Advertisement
dropbox1349

entire code

Oct 30th, 2015
391
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 14.36 KB | None | 0 0
  1. <?php
  2.  
  3. /*
  4.  * Helper functions for building a DataTables server-side processing SQL query
  5.  *
  6.  * The static functions in this class are just helper functions to help build
  7.  * the SQL used in the DataTables demo server-side processing scripts. These
  8.  * functions obviously do not represent all that can be done with server-side
  9.  * processing, they are intentionally simple to show how it works. More complex
  10.  * server-side processing operations will likely require a custom script.
  11.  *
  12.  * See http://datatables.net/usage/server-side for full details on the server-
  13.  * side processing requirements of DataTables.
  14.  *
  15.  * @license MIT - http://datatables.net/license_mit
  16.  */
  17.  
  18.  
  19. // REMOVE THIS BLOCK - used for DataTables test environment only!
  20. $file = $_SERVER['DOCUMENT_ROOT'].'/datatables/mysql.php';
  21. if ( is_file( $file ) ) {
  22.     include( $file );
  23. }
  24.  
  25.  
  26. class SSP {
  27.     /**
  28.      * Create the data output array for the DataTables rows
  29.      *
  30.      *  @param  array $columns Column information array
  31.      *  @param  array $data    Data from the SQL get
  32.      *  @return array          Formatted data in a row based format
  33.      */
  34.     static function data_output ( $columns, $data )
  35.     {
  36.         $out = array();
  37.  
  38.         for ( $i=0, $ien=count($data) ; $i<$ien ; $i++ ) {
  39.             $row = array();
  40.  
  41.             for ( $j=0, $jen=count($columns) ; $j<$jen ; $j++ ) {
  42.                 $column = $columns[$j];
  43.  
  44.                 // Is there a formatter?
  45.                 if ( isset( $column['formatter'] ) ) {
  46.                     $row[ $column['dt'] ] = $column['formatter']( $data[$i][ $column['db'] ], $data[$i] );
  47.                 }
  48.                 else {
  49.                     $row[ $column['dt'] ] = $data[$i][ $columns[$j]['db'] ];
  50.                 }
  51.             }
  52.  
  53.             $out[] = $row;
  54.         }
  55.  
  56.         return $out;
  57.     }
  58.  
  59.  
  60.     /**
  61.      * Database connection
  62.      *
  63.      * Obtain an PHP PDO connection from a connection details array
  64.      *
  65.      *  @param  array $conn SQL connection details. The array should have
  66.      *    the following properties
  67.      *     * host - host name
  68.      *     * db   - database name
  69.      *     * user - user name
  70.      *     * pass - user password
  71.      *  @return resource PDO connection
  72.      */
  73.     static function db ( $conn )
  74.     {
  75.         if ( is_array( $conn ) ) {
  76.             return self::sql_connect( $conn );
  77.         }
  78.  
  79.         return $conn;
  80.     }
  81.  
  82.  
  83.     /**
  84.      * Paging
  85.      *
  86.      * Construct the LIMIT clause for server-side processing SQL query
  87.      *
  88.      *  @param  array $request Data sent to server by DataTables
  89.      *  @param  array $columns Column information array
  90.      *  @return string SQL limit clause
  91.      */
  92.     static function limit ( $request, $columns )
  93.     {
  94.         $limit = '';
  95.  
  96.         if ( isset($request['start']) && $request['length'] != -1 ) {
  97.             $limit = "LIMIT ".intval($request['start']).", ".intval($request['length']);
  98.         }
  99.  
  100.         return $limit;
  101.     }
  102.  
  103.  
  104.     /**
  105.      * Ordering
  106.      *
  107.      * Construct the ORDER BY clause for server-side processing SQL query
  108.      *
  109.      *  @param  array $request Data sent to server by DataTables
  110.      *  @param  array $columns Column information array
  111.      *  @return string SQL order by clause
  112.      */
  113.     static function order ( $request, $columns )
  114.     {
  115.         $order = '';
  116.  
  117.         if ( isset($request['order']) && count($request['order']) ) {
  118.             $orderBy = array();
  119.             $dtColumns = self::pluck( $columns, 'dt' );
  120.  
  121.             for ( $i=0, $ien=count($request['order']) ; $i<$ien ; $i++ ) {
  122.                 // Convert the column index into the column data property
  123.                 $columnIdx = intval($request['order'][$i]['column']);
  124.                 $requestColumn = $request['columns'][$columnIdx];
  125.  
  126.                 $columnIdx = array_search( $requestColumn['data'], $dtColumns );
  127.                 $column = $columns[ $columnIdx ];
  128.  
  129.                 if ( $requestColumn['orderable'] == 'true' ) {
  130.                     $dir = $request['order'][$i]['dir'] === 'asc' ?
  131.                         'ASC' :
  132.                         'DESC';
  133.  
  134.                     $orderBy[] = '`'.$column['db'].'` '.$dir;
  135.                 }
  136.             }
  137.  
  138.             $order = 'ORDER BY '.implode(', ', $orderBy);
  139.         }
  140.  
  141.         return $order;
  142.     }
  143.  
  144.  
  145.     /**
  146.      * Searching / Filtering
  147.      *
  148.      * Construct the WHERE clause for server-side processing SQL query.
  149.      *
  150.      * NOTE this does not match the built-in DataTables filtering which does it
  151.      * word by word on any field. It's possible to do here performance on large
  152.      * databases would be very poor
  153.      *
  154.      *  @param  array $request Data sent to server by DataTables
  155.      *  @param  array $columns Column information array
  156.      *  @param  array $bindings Array of values for PDO bindings, used in the
  157.      *    sql_exec() function
  158.      *  @return string SQL where clause
  159.      */
  160.      
  161.     static function filter ( $request, $columns, &$bindings )
  162.     {
  163.         $globalSearch = array();
  164.         $columnSearch = array();
  165.         $dtColumns = self::pluck( $columns, 'dt' );
  166.  
  167.         if ( isset($request['search']) && $request['search']['value'] != '' ) {
  168.             $str = $request['search']['value'];
  169.  
  170.             for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) {
  171.                 $requestColumn = $request['columns'][$i];
  172.                 $columnIdx = array_search( $requestColumn['data'], $dtColumns );
  173.                 $column = $columns[ $columnIdx ];
  174.  
  175.                 if ( $requestColumn['searchable'] == 'true' ) {
  176.    $str = str_replace(" ","|",$str);
  177.    $binding = self::bind( $bindings, $str, PDO::PARAM_STR );
  178.    $globalSearch[] = "".$column['db']." REGEXP ".$binding;
  179. }
  180.             }
  181.         }
  182.  
  183.         // Individual column filtering
  184.         for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) {
  185.             $requestColumn = $request['columns'][$i];
  186.             $columnIdx = array_search( $requestColumn['data'], $dtColumns );
  187.             $column = $columns[ $columnIdx ];
  188.  
  189.             $str = $requestColumn['search']['value'];
  190.  
  191.             if ( $requestColumn['searchable'] == 'true' &&
  192.              $str != '' ) {
  193.                 $binding = self::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
  194.                 $columnSearch[] = "`".$column['db']."` LIKE ".$binding;
  195.             }
  196.         }
  197.  
  198.         // Combine the filters into a single string
  199.         $where = '';
  200.  
  201.         if ( count( $globalSearch ) ) {
  202.             $where = '('.implode(' OR ', $globalSearch).')';
  203.         }
  204.  
  205.         if ( count( $columnSearch ) ) {
  206.             $where = $where === '' ?
  207.                 implode(' AND ', $columnSearch) :
  208.                 $where .' AND '. implode(' AND ', $columnSearch);
  209.         }
  210.  
  211.         if ( $where !== '' ) {
  212.             $where = 'WHERE '.$where;
  213.         }
  214.  
  215.         return $where;
  216.     }
  217.  
  218.  
  219.     /**
  220.      * Perform the SQL queries needed for an server-side processing requested,
  221.      * utilising the helper functions of this class, limit(), order() and
  222.      * filter() among others. The returned array is ready to be encoded as JSON
  223.      * in response to an SSP request, or can be modified if needed before
  224.      * sending back to the client.
  225.      *
  226.      *  @param  array $request Data sent to server by DataTables
  227.      *  @param  array|PDO $conn PDO connection resource or connection parameters array
  228.      *  @param  string $table SQL table to query
  229.      *  @param  string $primaryKey Primary key of the table
  230.      *  @param  array $columns Column information array
  231.      *  @return array          Server-side processing response array
  232.      */
  233.     static function simple ( $request, $conn, $table, $primaryKey, $columns )
  234.     {
  235.         $bindings = array();
  236.         $db = self::db( $conn );
  237.  
  238.         // Build the SQL query string from the request
  239.         $limit = self::limit( $request, $columns );
  240.         $order = self::order( $request, $columns );
  241.         $where = self::filter( $request, $columns, $bindings );
  242.  
  243.         // Main query to actually get the data
  244.         $data = self::sql_exec( $db, $bindings,
  245.             "SELECT SQL_CALC_FOUND_ROWS `".implode("`, `", self::pluck($columns, 'db'))."`
  246.              FROM `$table`
  247.              $where
  248.              $order
  249.              $limit"
  250.         );
  251.  
  252.         // Data set length after filtering
  253.         $resFilterLength = self::sql_exec( $db,
  254.             "SELECT FOUND_ROWS()"
  255.         );
  256.         $recordsFiltered = $resFilterLength[0][0];
  257.  
  258.         // Total data set length
  259.         $resTotalLength = self::sql_exec( $db,
  260.             "SELECT COUNT(`{$primaryKey}`)
  261.              FROM   `$table`"
  262.         );
  263.         $recordsTotal = $resTotalLength[0][0];
  264.  
  265.  
  266.         /*
  267.          * Output
  268.          */
  269.         return array(
  270.             "draw"            => intval( $request['draw'] ),
  271.             "recordsTotal"    => intval( $recordsTotal ),
  272.             "recordsFiltered" => intval( $recordsFiltered ),
  273.             "data"            => self::data_output( $columns, $data )
  274.         );
  275.     }
  276.  
  277.  
  278.     /**
  279.      * The difference between this method and the `simple` one, is that you can
  280.      * apply additional `where` conditions to the SQL queries. These can be in
  281.      * one of two forms:
  282.      *
  283.      * * 'Result condition' - This is applied to the result set, but not the
  284.      *   overall paging information query - i.e. it will not effect the number
  285.      *   of records that a user sees they can have access to. This should be
  286.      *   used when you want apply a filtering condition that the user has sent.
  287.      * * 'All condition' - This is applied to all queries that are made and
  288.      *   reduces the number of records that the user can access. This should be
  289.      *   used in conditions where you don't want the user to ever have access to
  290.      *   particular records (for example, restricting by a login id).
  291.      *
  292.      *  @param  array $request Data sent to server by DataTables
  293.      *  @param  array|PDO $conn PDO connection resource or connection parameters array
  294.      *  @param  string $table SQL table to query
  295.      *  @param  string $primaryKey Primary key of the table
  296.      *  @param  array $columns Column information array
  297.      *  @param  string $whereResult WHERE condition to apply to the result set
  298.      *  @param  string $whereAll WHERE condition to apply to all queries
  299.      *  @return array          Server-side processing response array
  300.      */
  301.     static function complex ( $request, $conn, $table, $primaryKey, $columns, $whereResult=null, $whereAll=null )
  302.     {
  303.         $bindings = array();
  304.         $db = self::db( $conn );
  305.         $localWhereResult = array();
  306.         $localWhereAll = array();
  307.         $whereAllSql = '';
  308.  
  309.         // Build the SQL query string from the request
  310.         $limit = self::limit( $request, $columns );
  311.         $order = self::order( $request, $columns );
  312.         $where = self::filter( $request, $columns, $bindings );
  313.  
  314.         $whereResult = self::_flatten( $whereResult );
  315.         $whereAll = self::_flatten( $whereAll );
  316.  
  317.         if ( $whereResult ) {
  318.             $where = $where ?
  319.                 $where .' AND '.$whereResult :
  320.                 'WHERE '.$whereResult;
  321.         }
  322.  
  323.         if ( $whereAll ) {
  324.             $where = $where ?
  325.                 $where .' AND '.$whereAll :
  326.                 'WHERE '.$whereAll;
  327.  
  328.             $whereAllSql = 'WHERE '.$whereAll;
  329.         }
  330.  
  331.         // Main query to actually get the data
  332.         $data = self::sql_exec( $db, $bindings,
  333.             "SELECT SQL_CALC_FOUND_ROWS `".implode("`, `", self::pluck($columns, 'db'))."`
  334.              FROM `$table`
  335.              $where
  336.              $order
  337.              $limit"
  338.         );
  339.  
  340.         // Data set length after filtering
  341.         $resFilterLength = self::sql_exec( $db,
  342.             "SELECT FOUND_ROWS()"
  343.         );
  344.         $recordsFiltered = $resFilterLength[0][0];
  345.  
  346.         // Total data set length
  347.         $resTotalLength = self::sql_exec( $db, $bindings,
  348.             "SELECT COUNT(`{$primaryKey}`)
  349.              FROM   `$table` ".
  350.             $whereAllSql
  351.         );
  352.         $recordsTotal = $resTotalLength[0][0];
  353.  
  354.         /*
  355.          * Output
  356.          */
  357.         return array(
  358.             "draw"            => intval( $request['draw'] ),
  359.             "recordsTotal"    => intval( $recordsTotal ),
  360.             "recordsFiltered" => intval( $recordsFiltered ),
  361.             "data"            => self::data_output( $columns, $data )
  362.         );
  363.     }
  364.  
  365.  
  366.     /**
  367.      * Connect to the database
  368.      *
  369.      * @param  array $sql_details SQL server connection details array, with the
  370.      *   properties:
  371.      *     * host - host name
  372.      *     * db   - database name
  373.      *     * user - user name
  374.      *     * pass - user password
  375.      * @return resource Database connection handle
  376.      */
  377.     static function sql_connect ( $sql_details )
  378.     {
  379.         try {
  380.             $db = @new PDO(
  381.                 "mysql:host={$sql_details['host']};dbname={$sql_details['db']}",
  382.                 $sql_details['user'],
  383.                 $sql_details['pass'],
  384.                 array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION )
  385.             );
  386.         }
  387.         catch (PDOException $e) {
  388.             self::fatal(
  389.                 "An error occurred while connecting to the database. ".
  390.                 "The error reported by the server was: ".$e->getMessage()
  391.             );
  392.         }
  393.  
  394.         return $db;
  395.     }
  396.  
  397.  
  398.     /**
  399.      * Execute an SQL query on the database
  400.      *
  401.      * @param  resource $db  Database handler
  402.      * @param  array    $bindings Array of PDO binding values from bind() to be
  403.      *   used for safely escaping strings. Note that this can be given as the
  404.      *   SQL query string if no bindings are required.
  405.      * @param  string   $sql SQL query to execute.
  406.      * @return array         Result from the query (all rows)
  407.      */
  408.     static function sql_exec ( $db, $bindings, $sql=null )
  409.     {
  410.         // Argument shifting
  411.         if ( $sql === null ) {
  412.             $sql = $bindings;
  413.         }
  414.  
  415.         $stmt = $db->prepare( $sql );
  416.         //echo $sql;
  417.  
  418.         // Bind parameters
  419.         if ( is_array( $bindings ) ) {
  420.             for ( $i=0, $ien=count($bindings) ; $i<$ien ; $i++ ) {
  421.                 $binding = $bindings[$i];
  422.                 $stmt->bindValue( $binding['key'], $binding['val'], $binding['type'] );
  423.             }
  424.         }
  425.  
  426.         // Execute
  427.         try {
  428.             $stmt->execute();
  429.         }
  430.         catch (PDOException $e) {
  431.             self::fatal( "An SQL error occurred: ".$e->getMessage() );
  432.         }
  433.  
  434.         // Return all
  435.         return $stmt->fetchAll();
  436.     }
  437.  
  438.  
  439.     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  440.      * Internal methods
  441.      */
  442.  
  443.     /**
  444.      * Throw a fatal error.
  445.      *
  446.      * This writes out an error message in a JSON string which DataTables will
  447.      * see and show to the user in the browser.
  448.      *
  449.      * @param  string $msg Message to send to the client
  450.      */
  451.     static function fatal ( $msg )
  452.     {
  453.         echo json_encode( array(
  454.             "error" => $msg
  455.         ) );
  456.  
  457.         exit(0);
  458.     }
  459.  
  460.     /**
  461.      * Create a PDO binding key which can be used for escaping variables safely
  462.      * when executing a query with sql_exec()
  463.      *
  464.      * @param  array &$a    Array of bindings
  465.      * @param  *      $val  Value to bind
  466.      * @param  int    $type PDO field type
  467.      * @return string       Bound key to be used in the SQL where this parameter
  468.      *   would be used.
  469.      */
  470.     static function bind ( &$a, $val, $type )
  471.     {
  472.         $key = ':binding_'.count( $a );
  473.  
  474.         $a[] = array(
  475.             'key' => $key,
  476.             'val' => $val,
  477.             'type' => $type
  478.         );
  479.  
  480.         return $key;
  481.     }
  482.  
  483.  
  484.     /**
  485.      * Pull a particular property from each assoc. array in a numeric array,
  486.      * returning and array of the property values from each item.
  487.      *
  488.      *  @param  array  $a    Array to get data from
  489.      *  @param  string $prop Property to read
  490.      *  @return array        Array of property values
  491.      */
  492.     static function pluck ( $a, $prop )
  493.     {
  494.         $out = array();
  495.  
  496.         for ( $i=0, $len=count($a) ; $i<$len ; $i++ ) {
  497.             $out[] = $a[$i][$prop];
  498.         }
  499.  
  500.         return $out;
  501.     }
  502.  
  503.  
  504.     /**
  505.      * Return a string from an array or a string
  506.      *
  507.      * @param  array|string $a Array to join
  508.      * @param  string $join Glue for the concatenation
  509.      * @return string Joined string
  510.      */
  511.     static function _flatten ( $a, $join = ' AND ' )
  512.     {
  513.         if ( ! $a ) {
  514.             return '';
  515.         }
  516.         else if ( $a && is_array($a) ) {
  517.             return implode( $join, $a );
  518.         }
  519.         return $a;
  520.     }
  521. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement