Hawk - PHP documentation
  • Namespace
  • Class
  • Tree

Namespaces

  • Hawk
    • View
      • Plugins

Classes

  • Hawk\App
  • Hawk\ButtonInput
  • Hawk\Cache
  • Hawk\CheckboxInput
  • Hawk\ColorInput
  • Hawk\Conf
  • Hawk\Controller
  • Hawk\Crypto
  • Hawk\DatabaseSessionHandler
  • Hawk\DatetimeInput
  • Hawk\DB
  • Hawk\DBExample
  • Hawk\DeleteInput
  • Hawk\Dialogbox
  • Hawk\EmailInput
  • Hawk\ErrorHandler
  • Hawk\Event
  • Hawk\FileInput
  • Hawk\FileSystem
  • Hawk\FloatInput
  • Hawk\Form
  • Hawk\FormFieldset
  • Hawk\FormInput
  • Hawk\GenericModel
  • Hawk\GifImage
  • Hawk\HawkApi
  • Hawk\HawkUpdater
  • Hawk\HiddenInput
  • Hawk\HtmlInput
  • Hawk\HTTPRequest
  • Hawk\Icon
  • Hawk\Image
  • Hawk\IntegerInput
  • Hawk\ItemList
  • Hawk\ItemListField
  • Hawk\JpegImage
  • Hawk\Lang
  • Hawk\Language
  • Hawk\LeftSidebarTab
  • Hawk\Less
  • Hawk\Logger
  • Hawk\Mail
  • Hawk\MenuItem
  • Hawk\Model
  • Hawk\NoSidebarTab
  • Hawk\NumberInput
  • Hawk\ObjectInput
  • Hawk\Option
  • Hawk\Panel
  • Hawk\PasswordInput
  • Hawk\Permission
  • Hawk\Plugin
  • Hawk\PluginInstaller
  • Hawk\PngImage
  • Hawk\ProfileQuestion
  • Hawk\ProfileQuestionValue
  • Hawk\RadioInput
  • Hawk\Request
  • Hawk\Response
  • Hawk\RightSidebarTab
  • Hawk\Role
  • Hawk\RolePermission
  • Hawk\Route
  • Hawk\Router
  • Hawk\SelectInput
  • Hawk\Session
  • Hawk\Singleton
  • Hawk\SubmitInput
  • Hawk\Tabs
  • Hawk\TextareaInput
  • Hawk\TextInput
  • Hawk\Theme
  • Hawk\TimeInput
  • Hawk\Upload
  • Hawk\User
  • Hawk\View
  • Hawk\View\Plugins\Accordion
  • Hawk\View\Plugins\Button
  • Hawk\View\Plugins\Form
  • Hawk\View\Plugins\Icon
  • Hawk\View\Plugins\Import
  • Hawk\View\Plugins\Panel
  • Hawk\View\Plugins\Tabs
  • Hawk\View\Plugins\Text
  • Hawk\View\Plugins\Uri
  • Hawk\View\Plugins\Widget
  • Hawk\ViewPlugin
  • Hawk\Widget
  • Hawk\WysiwygInput

Traits

  • Hawk\Utils

Exceptions

  • Hawk\AppStopException
  • Hawk\DBExampleException
  • Hawk\DBException
  • Hawk\FileSystemException
  • Hawk\HawkApiException
  • Hawk\ImageException
  • Hawk\MailException
  • Hawk\UploadException
  • Hawk\ViewException
  1 <?php
  2 /**
  3  * ItemList.php
  4  *
  5  * @author  Elvyrra SAS
  6  * @license http://rem.mit-license.org/ MIT
  7  */
  8 
  9 namespace Hawk;
 10 
 11 /**
 12  * This class is used to generate and display smart lists, getting data from the database or a given array
 13  *
 14  * @package List
 15  */
 16 class ItemList {
 17     use Utils;
 18 
 19     // Class constants
 20     const DEFAULT_MODEL       = '\StdClass';
 21     const ALL_LINES           = 'all';
 22     const DEFAULT_LINE_CHOICE = 20;
 23 
 24     /**
 25      * The possible choices for the number of lines to display
 26      */
 27     public static $lineChoice = array(10, 20, 50, 100);
 28 
 29     /**
 30      * The list id
 31      *
 32      * @var string
 33      */
 34     public $id,
 35 
 36     /**
 37      * The list control buttons
 38      *
 39      * @var array
 40      */
 41     $controls = array(),
 42 
 43     /**
 44      * The list fields. This corresponds to the properties of each column in the list
 45      *
 46      * @var array
 47      */
 48     $fields = array(),
 49 
 50     /**
 51      * The user researches in the list
 52      *
 53      * @var array
 54      */
 55     $searches = array(),
 56 
 57     /**
 58      * The user sorts
 59      *
 60      * @var array
 61      */
 62     $sorts = array(),
 63 
 64     /**
 65      * The binded values for the SQL queries
 66      *
 67      * @var array
 68      */
 69     $binds = array(),
 70 
 71     /**
 72      * The number of lines to display
 73      *
 74      * @var int
 75      */
 76     $lines = self::DEFAULT_LINE_CHOICE,
 77 
 78     /**
 79      * The page number to display
 80      *
 81      * @var int
 82      */
 83     $page = 1,
 84 
 85     /**
 86      * The URI called to refresh the list
 87      *
 88      * @var string
 89      */
 90     $action,
 91 
 92     /**
 93      * The model used to get the data in the database
 94      *
 95      * @var string
 96      */
 97     $model = self::DEFAULT_MODEL,
 98 
 99     /**
100      * The table where to get the data if "model" is not set
101      *
102      * @var string
103      */
104     $table,
105 
106     /**
107      * The default reference field, used to index the list result table
108      *
109      * @var string
110      */
111     $reference,
112 
113     /**
114      * The list filter
115      *
116      * @var string
117      */
118     $filter,
119 
120     /**
121      * The default db instance name
122      *
123      * @var string
124      */
125     $dbname = MAINDB,
126 
127     /**
128      * The raw data to display in the list (overrides table, model, dbname and reference properties)
129      *
130      * @var array
131      */
132     $data = null,
133 
134     /**
135      * The fields group in the search query
136      *
137      * @var array
138      */
139     $group = array(),
140 
141     /**
142      * The id of the selected line
143      *
144      * @var mixed
145      */
146     $selected = null,
147 
148     /**
149      * The class to apply to the list lines
150      *
151      * @var string|function
152      */
153     $lineClass = null,
154 
155     /**
156      * Defines if the navigation bar of the list must be displayed
157      *
158      * @var bool
159      */
160     $navigation = true,
161 
162     /**
163      * If set to true, the columns headers are not displayed
164      *
165      * @var bool
166      */
167     $noHeader = false,
168 
169     /**
170      * If not empty, define the CSS selector of the node where to display the list refreshing result
171      *
172      * @var string
173      */
174     $target = '',
175 
176     /**
177      * Define the message to display if no result are found for the list
178      *
179      * @var string
180      */
181     $emptyMessage,
182 
183 
184     /**
185      * The whole list (list + navigation bar) view filename
186      *
187      * @var string
188      */
189     $tpl,
190 
191     /**
192      * The navigation bar view filename
193      *
194      * @var string
195      */
196     $navigationBarTpl,
197 
198     /**
199      * The list view filename
200      *
201      * @var string
202      */
203     $listTpl,
204 
205     /**
206      * The result view filename
207      *
208      * @var string
209      */
210     $resultTpl;
211 
212 
213     /**
214      * The DB instance used to make the database queries to get the list results
215      *
216      * @var DB
217      */
218     private $dbo,
219 
220     /**
221      * Define if the list refreshing or displayed for the first time
222      *
223      * @var boolean
224      */
225     $refresh = false;
226 
227 
228     /**
229      * Constructor
230      *
231      * @param arary $params The parameter of the list
232      */
233     public function __construct($params) {
234         // Default values
235         $this->emptyMessage = Lang::get('main.list-no-result');
236         $this->action = getenv('REQUEST_URI');
237         $this->refresh = !!App::request()->getParams('refresh');
238 
239         // Get the values from the parameters array
240         $this->map($params);
241 
242         if($this->data === null) {
243             if(!class_exists($this->model)) {
244                 $trace       = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
245                 $reflection  = new \ReflectionClass($trace[1]['class']);
246                 $this->model = $reflection->getNamespaceName().'\\'.$this->model;
247             }
248 
249             if($this->model == self::DEFAULT_MODEL) {
250                 if(!isset($this->table)) {
251                     throw new \Exception('ItemList contructor expects property "table" or "model" to be set');
252                 }
253 
254                 if(!isset($this->reference)) {
255                     $this->reference = 'id';
256                 }
257             }
258             else {
259                 $model = $this->model;
260 
261                 if(!isset($this->reference)) {
262                     $this->reference = $model::getPrimaryColumn();
263                 }
264 
265                 if(!isset($this->table)) {
266                     $this->table = $model::getTable();
267                 }
268 
269                 $this->dbname = $model::getDbName();
270             }
271 
272             $this->refAlias = is_array($this->reference) ? reset($this->reference) : $this->reference;
273             $this->refField = is_array($this->reference) ? reset(array_keys($this->reference)) : $this->reference;
274 
275             $this->dbo = DB::get($this->dbname);
276         }
277 
278         // initialize controls
279         foreach($this->controls as &$button) {
280             if(!empty($button['template'])) {
281                 switch($button['template']) {
282                     case 'refresh' :
283                         $button = array(
284                         'icon'    => 'refresh',
285                         'type'    => 'button',
286                         'onclick' => 'app.lists["'.$this->id.'"].refresh();',
287                         );
288                         break;
289 
290                     case 'print' :
291                         $button = array(
292                         'icon'    => 'print',
293                         'type'    => 'button',
294                         'onclick' => 'app.lists["'.$this->id.'"].print();',
295                         );
296                         break;
297                 }
298             }
299         }
300 
301         // Get the filters sent by POST or registered in COOKIES
302         $parameters = array(
303             'searches',
304             'sorts',
305             'lines',
306             'page',
307         );
308 
309         if(App::request()->getHeaders('X-List-Filter-'.$this->id)) {
310             App::session()->getUser()->setOption('main.list-'.$this->id, App::request()->getHeaders('X-List-Filter-'.$this->id));
311         }
312 
313         $this->userParam = json_decode(App::session()->getUser()->getOptions('main.list-'.$this->id), true);
314 
315         foreach($parameters as $name) {
316             if(isset($this->userParam[$name])) {
317                 $this->$name = $this->userParam[$name];
318             }
319         }
320 
321         // initialize fields default values
322         foreach($this->fields as $name => &$field) {
323             $field = new ItemListField($name, $field, $this);
324             if(isset($this->searches[$name])) {
325                 $field->searchValue = $this->searches[$name];
326             }
327 
328             if(!empty($this->sorts[$name])) {
329                 $field->sortValue = $this->sorts[$name];
330             }
331         }
332 
333         $event = new Event('list.'.$this->id.'.instanciated', array('list' => $this));
334         $event->trigger();
335 
336     }
337 
338 
339     /**
340      * Get the data to display
341      *
342      * @return array The data to display
343      */
344     public function get() {
345         if(isset($this->data) && is_array($this->data)) {
346             return $this->getFromArray($this->data);
347         }
348         else if($this->model && $this->table) {
349             return $this->getFromDatabase();
350         }
351 
352     }
353 
354 
355     /**
356      * Get the data from the database
357      *
358      * @return array The data taken from the databases
359      */
360     private function getFromDatabase() {
361         $fields = array();
362 
363         $where = array();
364         if(!empty($this->filter)) {
365             if($this->filter instanceof DBExample) {
366                 $where[] = $this->filter->parse($this->binds);
367             }
368             else if(is_array($this->filter)) {
369                 $where[]     = $this->filter[0];
370                 $this->binds = $this->filter[1];
371             }
372             else{
373                 $where[] = $this->filter;
374             }
375         }
376 
377         // insert the reference if not present in the fields
378         if(!isset($this->fields[$this->refAlias])) {
379             $this->fields[$this->refAlias] = new ItemListField(
380                 $this->refAlias,
381                 array(
382                     'field'  => $this->refField,
383                     'hidden' => true,
384                 ),
385                 $this
386             );
387         }
388 
389         // Prepare the fields to research
390         $searches = array();
391         foreach($this->fields as $name => &$field){
392             if(!$field->independant) {
393                 $fields[$this->dbo->formatField($field->field)] = $this->dbo->formatField($name);
394 
395                 // Get the pattern condition
396                 $sql = $field->getSearchCondition($this->binds);
397                 if($sql) {
398                     $where[] = $sql;
399                 }
400             }
401         }
402 
403         try{
404             $where = implode(' AND ', $where);
405 
406             $model = $this->model;
407             $this->recordNumber = $this->dbo->count($this->table, $where, $this->binds, $this->refField, $this->group);
408 
409             // Get the number of the page
410             if($this->lines == self::ALL_LINES) {
411                 $this->lines = $this->recordNumber;
412             }
413 
414             if($this->page > 1 && $this->page > ceil($this->recordNumber / $this->lines)) {
415                 $this->page = (ceil($this->recordNumber / $this->lines) > 0) ? ceil($this->recordNumber / $this->lines) : 1;
416             }
417 
418             $this->start = (($this->page - 1) * $this->lines);
419 
420             // Get the data from the database
421             $request = array(
422                 'fields'  => $fields,
423                 'from'    => $this->table,
424                 'where'   => $where,
425                 'binds'   => $this->binds,
426                 'orderby' => $this->sorts,
427                 'group'   => $this->group,
428                 'start'   => $this->start,
429                 'limit'   => $this->lines,
430                 'index'   => $this->refAlias,
431                 'return'  => $this->model,
432             );
433 
434             $this->results = $this->dbo->select($request);
435 
436             return $this->results;
437         }
438         catch(DBException $e){
439             exit(DEBUG_MODE ? $e->getMessage() : Lang::get('main.list-error'));
440         }
441 
442     }
443 
444 
445     /**
446      * Get the data of the list from a given array
447      *
448      * @param array $data The array where to take the data to display
449      */
450     private function getFromArray($data)
451     {
452         foreach($this->fields as $name => &$field){
453             $pattern = isset($this->searches[$name]) ? $this->searches[$name] : null;
454             if($pattern) {
455                 $data = array_filter(
456                     $data,
457                     function ($line) use ($pattern, $name) {
458                         return stripos($line[$name], $pattern) !== false;
459                     }
460                 );
461             }
462 
463             $sort = isset($this->sorts[$name]) ? $this->sorts[$name] : null;
464             if($sort) {
465                 usort(
466                     $data,
467                     function ($a, $b) use ($sort, $name) {
468                         if($sort > 0) {
469                             return $a[$name] < $b[$name];
470                         }
471                         else{
472                             return $b[$name] < $a[$name];
473                         }
474                     }
475                 );
476             }
477         }
478 
479         $this->recordNumber = count($data);
480 
481         if($this->page > ceil($this->recordNumber / $this->lines) && $this->page > 1) {
482             $this->page = (ceil($this->recordNumber / $this->lines) > 0) ? ceil($this->recordNumber / $this->lines) : 1;
483         }
484 
485         $this->start   = (($this->page - 1) * $this->lines);
486         $this->results = array_slice(
487             array_map(
488                 function ($line) {
489                     return (object) $line;
490                 },
491                 $data
492             ),
493             $this->start,
494             $this->lines
495         );
496 
497         return $this->results;
498 
499     }
500 
501 
502     /**
503      * Set the list data
504      *
505      * @param array $data The data to set
506      */
507     public function set($data) {
508         $this->getFromArray($data);
509 
510     }
511 
512 
513     /**
514      * Get the list views files
515      */
516     private function getViews() {
517         if(empty($this->tpl)) {
518             $this->tpl = Theme::getSelected()->getView('item-list/container.tpl');
519         }
520 
521         if(empty($this->navigationBarTpl)) {
522             $this->navigationBarTpl = Theme::getSelected()->getView('item-list/navigation-bar.tpl');
523         }
524 
525         if(empty($this->listTpl)) {
526             $this->listTpl = Theme::getSelected()->getView('item-list/list.tpl');
527         }
528 
529         if(empty($this->resultTpl)) {
530             $this->resultTpl = Theme::getSelected()->getView('item-list/result.tpl');
531         }
532 
533     }
534 
535 
536     /**
537      * Display the list (alias)
538      *
539      * @return string The HTML result of displaying
540      */
541     public function __toString() {
542         return $this->display();
543 
544     }
545 
546 
547     /**
548      * Display the list
549      *
550      * @return string The HTML result of displaying
551      */
552     public function display() {
553         try{
554             // Get the data to display
555             $this->get();
556 
557             // Get the total number of pages
558             $pages = (ceil($this->recordNumber / $this->lines) > 0) ? ceil($this->recordNumber / $this->lines) : 1;
559 
560             // At least one result to display
561             $data  = array();
562             $param = array();
563             if(is_array($this->results)) {
564                 foreach($this->results as $id => $line){
565                     $data[$id]  = array();
566                     $param[$id] = array('class' => '');
567 
568                     if($this->selected === $id) {
569                         $param[$id]['class'] .= 'selected ';
570                     }
571 
572                     if($this->lineClass) {
573                         $function = $this->lineClass;
574                         $param[$id]['class'] .= $function($line);
575                     }
576 
577                     foreach($this->fields as $name => $field){
578                         $data[$id][$name] = $field->displayCell($id);
579                     }
580                 }
581             }
582 
583             // Get the list views files
584             $this->getViews();
585 
586             return
587             View::make($this->refresh ? $this->resultTpl : $this->tpl, array(
588                 'list' => $this,
589                 'data' => $data,
590                 'linesParameters' => $param,
591                 'pages' => $pages,
592             )) .
593             View::make(Plugin::get('main')->getView('list.js.tpl'), array(
594                 'list' => $this,
595                 'pages' => $pages
596             ));
597         }
598         catch(\Exception $e){
599             App::errorHandler()->exception($e);
600         }
601     }
602 
603 
604     /**
605      * Check if the list is refreshing or displayed for the first time
606      */
607     public function isRefreshing() {
608         return $this->refresh;
609     }
610 }
611 
Hawk - PHP documentation API documentation generated by ApiGen