data-tools.php

Generic set of data tools
git clone git://git.finwo.net/lib/data-tools.php
Log | Files | Refs | README

ArrayQuery.php (5502B)


      1 <?php
      2 
      3 namespace Finwo\Datatools;
      4 
      5 use Finwo\PropertyAccessor\PropertyAccessor;
      6 
      7 class ArrayQuery
      8 {
      9     /**
     10      * @var array
     11      */
     12     protected $table = array();
     13 
     14     /**
     15      * @var array
     16      */
     17     protected $selects = array();
     18 
     19     /**
     20      * @var array
     21      */
     22     protected $filters = array();
     23 
     24     /**
     25      * @var string
     26      */
     27     protected $selectedField = '';
     28 
     29     /**
     30      * @var PropertyAccessor
     31      */
     32     protected $accessor;
     33 
     34     /**
     35      * @var integer
     36      */
     37     protected $skip = 0;
     38 
     39     /**
     40      * @var integer
     41      */
     42     protected $limit = -2;
     43 
     44     /**
     45      * @var array
     46      */
     47     protected $columnNames = array();
     48 
     49     /**
     50      * ArrayQuery constructor.
     51      *
     52      * @param array $data
     53      */
     54     public function __construct($data = array())
     55     {
     56         $this->table = $data;
     57     }
     58 
     59     /**
     60      * @param array $input
     61      *
     62      * @return ArrayQuery
     63      */
     64     public static function table($input = array())
     65     {
     66         return new ArrayQuery($input);
     67     }
     68 
     69     /**
     70      * @param $input
     71      *
     72      * @return ArrayQuery $this
     73      */
     74     public function select( $input )
     75     {
     76         if (
     77             is_callable($input) ||
     78             is_string($input)
     79         ) {
     80             $this->selects[] = $input;
     81         } elseif (is_array($input)) {
     82             foreach($input as $item) {
     83                 $this->select($item);
     84             }
     85         }
     86 
     87         return $this;
     88     }
     89 
     90     /**
     91      * @param $input
     92      *
     93      * @return $this
     94      */
     95     public function field( $input )
     96     {
     97         if(is_string($input)) {
     98             $this->selectedField = $input;
     99         }
    100 
    101         return $this;
    102     }
    103 
    104     /**
    105      * @param $input
    106      *
    107      * @return $this
    108      */
    109     public function equals( $input )
    110     {
    111         if(is_string($input)) {
    112             $this->filters[]= array(
    113                 'field' => $this->selectedField,
    114                 'type'  => 'equals',
    115                 'value' => $input,
    116             );
    117         }
    118 
    119         return $this;
    120     }
    121 
    122     /**
    123      * @param $input
    124      *
    125      * @return $this
    126      */
    127     public function validates( $input )
    128     {
    129         if(is_callable($input)) {
    130             $this->filters[]= array(
    131                 'field' => $this->selectedField,
    132                 'type'  => 'validate',
    133                 'value' => $input,
    134             );
    135 
    136         }
    137 
    138         return $this;
    139     }
    140 
    141     /**
    142      * @param $input
    143      *
    144      * @return $this
    145      */
    146     public function columnName( $input )
    147     {
    148         if (is_array($input)) {
    149             $this->columnNames = $input;
    150         }
    151 
    152         if (is_string($input)) {
    153             $this->columnNames[] = $input;
    154         }
    155 
    156         return $this;
    157     }
    158 
    159     /**
    160      * @param integer $input
    161      *
    162      * @return $this
    163      */
    164     public function skip( $input )
    165     {
    166         $this->skip = intval($input);
    167         return $this;
    168     }
    169 
    170     /**
    171      * @param integer $input
    172      *
    173      * @return $this
    174      */
    175     public function limit( $input )
    176     {
    177         $this->limit = intval($input);
    178         return $this;
    179     }
    180 
    181     /**
    182      * @return PropertyAccessor
    183      */
    184     protected function getAccessor()
    185     {
    186         if (is_null($this->accessor)) {
    187             $this->accessor = new PropertyAccessor();
    188         }
    189         return $this->accessor;
    190     }
    191 
    192     /**
    193      * @return array
    194      */
    195     public function execute()
    196     {
    197         $outputIndex = 0;
    198         $output = array();
    199 
    200         //loop through table
    201         foreach ($this->table as $row) {
    202 
    203             // handle limit
    204             if ( $this->limit-- == 0 ) {
    205                 break;
    206             }
    207 
    208             // reset the current row
    209             $columnIndex = 0;
    210             $outputRow   = array();
    211 
    212             // fetch columns
    213             foreach ($this->selects as $select) {
    214 
    215                 // allow associative column names
    216                 $colName = $columnIndex++;
    217                 if (isset($this->columnNames[$colName])) {
    218                     $colName = $this->columnNames[$colName];
    219                 }
    220 
    221                 // fetch & store value
    222                 $outputRow[$colName] = $this->executeSelect($row, $select);
    223             }
    224 
    225             // run through filters
    226             if ( $this->executeFilters($outputRow) ) {
    227 
    228                 // handle offset
    229                 if ( $this->skip-- > 0) {
    230                     continue;
    231                 }
    232 
    233                 // add row to output
    234                 $output[$outputIndex++] = $outputRow;
    235             } else {
    236                 $this->limit++;
    237             }
    238 
    239         }
    240 
    241         return $output;
    242     }
    243 
    244     protected function executeSelect($row, $select)
    245     {
    246         // Callable select statements
    247         if (is_callable($select)) {
    248             return call_user_func($select, $row);
    249         }
    250 
    251         // String selects
    252         if (is_string($select)) {
    253             return $this->getAccessor()->get($row, $select);
    254         }
    255 
    256         // Return empty column
    257         return null;
    258     }
    259 
    260     protected function executeFilters($row)
    261     {
    262         foreach ($this->filters as $filter) {
    263             switch($filter['type']) {
    264                 case 'equals':
    265                     if ($row[$filter['field']] !== $filter['value']) {
    266                         return false;
    267                     }
    268                     break;
    269                 case 'validate':
    270                     return call_user_func($filter['value'], $row[$filter['field']], $row);
    271                 default:
    272                     //unknown filter
    273                     break;
    274             }
    275 
    276         }
    277 
    278         return true;
    279     }
    280 }