Advertisement
czaroentoro

SSP Class Moified with Join

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