1 <?php
  2 
  3   4   5   6   7   8   9  10 
 11 
 12 namespace Icybee\ManageBlock;
 13 
 14 use ICanBoogie\ActiveRecord\Query;
 15 
 16 use Brickrouge\DropdownMenu;
 17 use Brickrouge\Element;
 18 
 19  20  21  22  23  24  25  26  27 
 28 class Column extends \ICanBoogie\Object
 29 {
 30     const ORDER_ASC = 1;
 31     const ORDER_DESC = -1;
 32 
 33     public $id;
 34 
 35     public $title;
 36     public $class;
 37     public $filters;
 38     public $reset;
 39     public $orderable = false;
 40     public $order;
 41     public $default_order = self::ORDER_ASC;
 42     public $discreet = true;
 43 
 44     protected  = 'Icybee\ManageBlock\HeaderRenderer';
 45     protected $cell_renderer = 'Icybee\ManageBlock\CellRenderer';
 46 
 47     public $manager;
 48 
 49     public function __construct(\Icybee\ManageBlock $manager, $id, array $options=array())
 50     {
 51         
 52 
 53         if (method_exists($this, 'update_filters'))
 54         {
 55             throw new \Exception("The <q>update_filters()</q> method is deprecated, please use the <q>alter_filters()</q> method.");
 56         }
 57 
 58         if (method_exists($this, 'alter_query'))
 59         {
 60             throw new \Exception("The <q>alter_query()</q> method is deprecated, please use the <q>alter_query_with_filter()</q> method.");
 61         }
 62 
 63         
 64 
 65         $this->manager = $manager;
 66         $this->id = $id;
 67 
 68         $this->modify_options($options + $this->resolve_default_values());
 69     }
 70 
 71     
 72     protected function set_filtering()
 73     {
 74         throw new \InvalidArgumentException("The <q>filtering</q> property is deprecated. Use <q>is_filtering</q> or <q>filter_value</q>");
 75     }
 76 
 77     protected function set_label($value)
 78     {
 79         trigger_error("The <q>label</q> property is deprecated, use <q>title</q> instead.");
 80 
 81         $this->title = $value;
 82     }
 83 
 84     protected function get_label()
 85     {
 86         trigger_error("The <q>label</q> property is deprecated, use <q>title</q> instead.");
 87 
 88         return $this->title;
 89     }
 90 
 91      92  93  94  95 
 96     protected function get_is_filtering()
 97     {
 98         return $this->manager->is_filtering($this->id);
 99     }
100 
101     102 103 104 105 
106     protected function get_filter_value()
107     {
108         return $this->is_filtering ? $this->manager->options->filters[$this->id] : null;
109     }
110 
111     112 113 114 115 116 117 118 119 
120     public function t($native, array $args=array(), array $options=array())
121     {
122         return $this->manager->t($native, $args, $options);
123     }
124 
125     126 127 128 129 
130     protected function resolve_default_values()
131     {
132         $id = $this->id;
133         $fields = $this->manager->model->extended_schema['fields'];
134         $field = isset($fields[$id]) ? $fields[$id] : null;
135 
136         $orderable = true;
137         $default_order = 1;
138         $discreet = false;
139 
140         if ($field)
141         {
142             if (($field['type'] == 'integer' && (!empty($field['primary']) || !empty($field['indexed']))) || $field['type'] == 'boolean')
143             {
144                 $orderable = false;
145 
146                 if (!empty($field['indexed']))
147                 {
148                     $discreet = true;
149                 }
150             }
151 
152             if (in_array($field['type'], array('date', 'datetime', 'timestamp')))
153             {
154                 $default_order = -1;
155             }
156         }
157         else
158         {
159             $orderable = false;
160         }
161 
162         return array
163         (
164             'title' => $id,
165             'reset' => "?$id=",
166             'orderable' => $orderable,
167             'default_order' => $default_order
168         );
169     }
170 
171     172 173 174 175 176 177 
178     public function modify_options(array $options)
179     {
180         foreach ($options as $option => $value)
181         {
182             switch ($option)
183             {
184                 case 'label':
185                 case 'title':
186                 case 'class':
187                 case 'filters':
188                 case 'reset':
189                 case 'orderable':
190                 case 'order':
191                 case 'default_order':
192                 case 'discreet':
193                 case 'filtering':
194                 case 'header_renderer':
195                 case 'cell_renderer':
196                     $this->$option = $value;
197                     break;
198 
199                 case 'hook':
200 
201                     break;
202             }
203         }
204 
205         return $this;
206     }
207 
208     209 210 211 212 213 214 215 216 217 218 
219     public function alter_filters(array $filters, array $modifiers)
220     {
221         return $filters;
222     }
223 
224     225 226 227 228 229 230 231 232 233 234 
235     public function alter_query_with_filter(Query $query, $filter_value)
236     {
237         if ($filter_value)
238         {
239             $query->and(array($this->id => $filter_value));
240         }
241 
242         return $query;
243     }
244 
245     246 247 248 249 250 251 252 253 254 255 256 
257     public function alter_query_with_order(Query $query, $order_direction)
258     {
259         return $query->order("`$this->id` " . ($order_direction < 0 ? 'desc' : 'asc'));
260     }
261 
262     263 264 265 266 267 268 269 270 271 
272     public function alter_records(array $records)
273     {
274         return $records;
275     }
276 
277     278 279 280 281 
282     protected function get_options()
283     {
284         if (empty($this->filters['options']))
285         {
286             return;
287         }
288 
289         $options = array();
290 
291         foreach ($this->filters['options'] as $qs => $label)
292         {
293             if ($qs[0] == '=')
294             {
295                 $qs = $this->id . $qs;
296             }
297 
298             $options['?' . $qs] = $this->manager->t($label);
299         }
300 
301         return $options;
302     }
303 
304     305 306 
307     public function render_options()
308     {
309         $options = $this->get_options();
310 
311         if (!$options)
312         {
313             return;
314         }
315 
316         if ($this->is_filtering)
317         {
318             $options = array_merge
319             (
320                 array
321                 (
322                     $this->reset => $this->t('Display all'),
323                     false
324                 ),
325 
326                 $options
327             );
328         }
329 
330         $menu = new DropdownMenu
331         (
332             array
333             (
334                 DropdownMenu::OPTIONS => $options,
335 
336                 'value' => $this->filter_value
337             )
338         );
339 
340         return <<<EOT
341 <div class="dropdown navbar"><a href="#" data-toggle="dropdown"><i class="icon-cog"></i></a>$menu</div>
342 EOT;
343     }
344 
345     346 347 348 349 
350     public function ()
351     {
352         $renderer = $this->header_renderer;
353 
354         if (!($renderer instanceof HeaderRenderer))
355         {
356             $this->header_renderer = $renderer = new $renderer($this);
357         }
358 
359         return $renderer();
360     }
361 
362     363 364 365 366 367 368 
369     public function render_cell($record)
370     {
371         $renderer = $this->cell_renderer;
372 
373         if (!($renderer instanceof CellRenderer))
374         {
375             $this->cell_renderer = $renderer = new $renderer($this);
376         }
377 
378         return $renderer($record, $this->id);
379     }
380 
381     382 383 384 385 386 387 
388     public function add_assets(\Brickrouge\Document $document)
389     {
390 
391     }
392 }
393 
394 395 396 
397 class 
398 {
399     protected $column;
400 
401     public function __construct(Column $column)
402     {
403         $this->column = $column;
404     }
405 
406     public function __invoke()
407     {
408         $column = $this->column;
409         $module = $this->column->manager->module;
410         $id = $column->id;
411         $title = $column->title;
412         $t = $this->column->manager->t;
413 
414         if ($title)
415         {
416             $title = $t($id, array(), array('scope' => 'column', 'default' => $title));
417         }
418 
419         if ($column->is_filtering)
420         {
421             $a_title = $t('View all');
422             $title = $title ?: ' ';
423 
424             return <<<EOT
425 <a href="{$column->reset}" title="{$a_title}"><span class="title">{$title}</span></a>
426 EOT;
427         }
428 
429         if ($title && $column->orderable)
430         {
431             $order = $column->order;
432             $order_reverse = ($order === null) ? $column->default_order : -$order;
433 
434             return new Element
435             (
436                 'a', array
437                 (
438                     Element::INNER_HTML => '<span class="title">' . $title . '</span>',
439 
440                     'title' => $t('Sort by: :identifier', array(':identifier' => $title)),
441                     'href' => "?order=$id:" . ($order_reverse < 0 ? 'desc' : 'asc'),
442                     'class' => $order ? ($order < 0 ? 'desc' : 'asc') : null
443                 )
444             );
445         }
446 
447         return $title;
448     }
449 }
450 
451 452 453 
454 class CellRenderer
455 {
456     protected $column;
457 
458     public function __construct(Column $column)
459     {
460         $this->column = $column;
461     }
462 
463     public function __invoke($record, $property)
464     {
465         return \Brickrouge\escape($record->$property);
466     }
467 
468     public function t($str, array $args=array(), array $options=array())
469     {
470         return $this->column->t($str, $args, $options);
471     }
472 }