PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/library/spoon/datagrid/datagrid.php

http://github.com/forkcms/forkcms
PHP | 1996 lines | 784 code | 380 blank | 832 comment | 150 complexity | daadd373edda1ebe5cdedb26d8b93c57 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, MIT, AGPL-3.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * Spoon Library
  4. *
  5. * This source file is part of the Spoon Library. More information,
  6. * documentation and tutorials can be found @ http://www.spoon-library.com
  7. *
  8. * @package spoon
  9. * @subpackage datagrid
  10. *
  11. *
  12. * @author Davy Hellemans <davy@spoon-library.com>
  13. * @since 1.0.0
  14. */
  15. /**
  16. * This class is the base class used to generate datagrids from a range of sources.
  17. *
  18. * @package spoon
  19. * @subpackage datagrid
  20. *
  21. *
  22. * @author Davy Hellemans <davy@spoon-library.com>
  23. * @since 1.0.0
  24. */
  25. class SpoonDataGrid
  26. {
  27. /**
  28. * List of columns that may be sorted in, based on the query results
  29. *
  30. * @var array
  31. */
  32. private $allowedSortingColumns = array();
  33. /**
  34. * Html attributes
  35. *
  36. * @var array
  37. */
  38. private $attributes = array('datagrid' => array(),
  39. 'row' => array(),
  40. 'row_even' => array(),
  41. 'row_odd' => array(),
  42. 'footer' => array());
  43. /**
  44. * Table caption/description
  45. *
  46. * @var string
  47. */
  48. private $caption;
  49. /**
  50. * Array of column functions
  51. *
  52. * @var array
  53. */
  54. private $columnFunctions = array();
  55. /**
  56. * Array of column objects
  57. *
  58. * @var array
  59. */
  60. protected $columns = array();
  61. /**
  62. * Default compile directory
  63. *
  64. * @var string
  65. */
  66. private $compileDirectory;
  67. /**
  68. * Final output
  69. *
  70. * @var string
  71. */
  72. private $content;
  73. /**
  74. * Debug status
  75. *
  76. * @var bool
  77. */
  78. private $debug = false;
  79. /**
  80. * Offset start value
  81. *
  82. * @var int
  83. */
  84. private $offsetParameter;
  85. /**
  86. * Order start value
  87. *
  88. * @var string
  89. */
  90. private $orderParameter;
  91. /**
  92. * Separate results with pages
  93. *
  94. * @var bool
  95. */
  96. private $paging = true;
  97. /**
  98. * Default number of results per page
  99. *
  100. * @var int
  101. */
  102. private $pagingLimit = 30;
  103. /**
  104. * Class used to define paging
  105. *
  106. * @var SpoonDataGridPaging
  107. */
  108. private $pagingClass = 'SpoonDataGridPaging';
  109. /**
  110. * Parse status
  111. *
  112. * @var bool
  113. */
  114. private $parsed = false;
  115. /**
  116. * List of row functions
  117. *
  118. * @var array
  119. */
  120. private $rowFunctions = array();
  121. /**
  122. * Temporary output of the parsed row functions
  123. *
  124. * @var string
  125. */
  126. private $rowFunctionsParsed = array();
  127. /**
  128. * Default sorting column
  129. *
  130. * @var string
  131. */
  132. private $sortingColumn;
  133. /**
  134. * Sorting columns (cached when requested)
  135. *
  136. * @var array
  137. */
  138. private $sortingColumns = array();
  139. /**
  140. * Sorting icons
  141. *
  142. * @var array
  143. */
  144. private $sortingIcons = array( 'asc' => null,
  145. 'ascSelected' => null,
  146. 'desc' => null,
  147. 'descSelected' => null);
  148. /**
  149. * Sorting Labels
  150. *
  151. * @var array
  152. */
  153. private $sortingLabels = array( 'asc' => 'Sort ascending',
  154. 'ascSelected' => 'Sorted ascending',
  155. 'desc' => 'Sort descending',
  156. 'descSelected' => 'Sorted descending');
  157. /**
  158. * Default sorting method
  159. *
  160. * @var string
  161. */
  162. private $sortParameter;
  163. /**
  164. * Source of the datagrid
  165. *
  166. * @var SpoonDataGridSource
  167. */
  168. protected $source;
  169. /**
  170. * DataGrid summary
  171. *
  172. * @var string
  173. */
  174. private $summary;
  175. /**
  176. * Default or custom template
  177. *
  178. * @var string
  179. */
  180. private $template;
  181. /**
  182. * Template instance
  183. *
  184. * @var SpoonTemplate
  185. */
  186. protected $tpl;
  187. /**
  188. * Basic URL
  189. *
  190. * @var string
  191. */
  192. private $URL;
  193. /**
  194. * Class constructor.
  195. *
  196. * @param SpoonDatagridSource $source The data-source, which needs to extend from SpoonDatagridSource.
  197. * @param string[optional] $template The template that will be used to parse the datagrid.
  198. */
  199. public function __construct(SpoonDatagridSource $source, $template = null)
  200. {
  201. // set source
  202. $this->setSource($source);
  203. // set template
  204. if($template !== null) $this->setTemplate($template);
  205. // load template
  206. $this->tpl = new SpoonTemplate();
  207. // create default columns
  208. $this->createColumns();
  209. }
  210. /**
  211. * Adds a new column with a couple of options such as title, URL, image, ...
  212. *
  213. * @param string $name The name for this column, later used to refer to this column.
  214. * @param string[optional] $label The label that will be displayed in the header cell.
  215. * @param string[optional] $value The value you wish to display.
  216. * @param string[optional] $URL The URL to refer to.
  217. * @param string[optional] $title The title tag, in case you've provided a URL.
  218. * @param string[optional] $image The location to an image, used to fill the column.
  219. * @param int[optional] $sequence The sequence for this column, by default it will be added at the back.
  220. */
  221. public function addColumn($name, $label = null, $value = null, $URL = null, $title = null, $image = null, $sequence = null)
  222. {
  223. // redefine name
  224. $name = (string) $name;
  225. // column already exists
  226. if(isset($this->columns[$name])) throw new SpoonDatagridException('A column with the name "' . $name . '" already exists.');
  227. // redefine sequence
  228. if($sequence === null) $sequence = count($this->columns) + 1;
  229. // new column
  230. $this->columns[$name] = new SpoonDatagridColumn($name, $label, $value, $URL, $title, $image, $sequence);
  231. // add the class as an attribute to this column
  232. $this->columns[$name]->setAttributes(array('class' => $name));
  233. }
  234. /**
  235. * Builds the requested URL.
  236. *
  237. * @return string
  238. * @param int $offset The offset.
  239. * @param string $order The order-column.
  240. * @param string $sort The sorting-method.
  241. */
  242. private function buildURL($offset, $order, $sort)
  243. {
  244. return str_replace(array('[offset]', '[order]', '[sort]'), array($offset, $order, $sort), $this->URL);
  245. }
  246. /**
  247. * Clears the attributes.
  248. */
  249. public function clearAttributes()
  250. {
  251. $this->attributes['datagrid'] = array();
  252. }
  253. /**
  254. * Clears the attributes for a specific column.
  255. *
  256. * @param string $column The name of the column you want to clear the column attributes from.
  257. */
  258. public function clearColumnAttributes($column)
  259. {
  260. // has results
  261. if($this->source->getNumResults() > 0)
  262. {
  263. // column doesn't exist
  264. if(!isset($this->columns[(string) $column])) throw new SpoonDatagridException('The column "' . (string) $column . '" doesn\'t exist and therefor no attributes can be removed.');
  265. // exists
  266. $this->columns[(string) $column]->clearAttributes();
  267. }
  268. }
  269. /**
  270. * Clears the even row attributes.
  271. */
  272. public function clearEvenRowAttributes()
  273. {
  274. $this->attributes['row_even'] = array();
  275. }
  276. /**
  277. * clears the odd row attributes.
  278. */
  279. public function clearOddRowAttributes()
  280. {
  281. $this->attributes['row_odd'] = array();
  282. }
  283. /**
  284. * Clears the row attributes.
  285. */
  286. public function clearRowAttributes()
  287. {
  288. $this->attributes['row'] = array();
  289. }
  290. /**
  291. * Creates the default columns, based on the initially provided source.
  292. */
  293. private function createColumns()
  294. {
  295. // has results
  296. if($this->source->getNumResults() != 0)
  297. {
  298. // fetch the column names
  299. foreach($this->source->getColumns() as $column)
  300. {
  301. // add column
  302. $this->addColumn($column, $column, '[' . $column . ']', null, null, null, (count($this->columns) +1));
  303. // by default the column name will be added as a class
  304. $this->columns[$column]->setAttributes(array('class' => $column));
  305. // may be sorted on
  306. $this->allowedSortingColumns[] = $column;
  307. }
  308. }
  309. }
  310. /**
  311. * Shows the output & stops script execution.
  312. */
  313. public function display()
  314. {
  315. echo $this->getContent();
  316. exit;
  317. }
  318. /**
  319. * Generates the array with the order columns.
  320. */
  321. private function generateOrder()
  322. {
  323. // delete current cache of sortable columns
  324. $this->sortingColumns = array();
  325. // columns present
  326. if(count($this->columns) != 0)
  327. {
  328. // loop columns
  329. foreach($this->columns as $column)
  330. {
  331. // allowed sorting, sorting enabled specifically
  332. if(in_array($column->getName(), $this->allowedSortingColumns) && $column->getSorting())
  333. {
  334. // add to the list
  335. $this->sortingColumns[] = $column->getName();
  336. // default
  337. $default = $column->getName();
  338. }
  339. }
  340. // no default defined
  341. if($this->sortingColumn === null && isset($default)) $this->sortingColumn = $default;
  342. }
  343. }
  344. /**
  345. * Retrieve all the datagrid attributes.
  346. *
  347. * @return array
  348. */
  349. public function getAttributes()
  350. {
  351. return $this->attributes['datagrid'];
  352. }
  353. /**
  354. * Fetch the column object for a specific column.
  355. *
  356. * @return SpoonDatagridColumn
  357. * @param string $column The name of the column.
  358. */
  359. public function getColumn($column)
  360. {
  361. // has results
  362. if($this->source->getNumResults() > 0)
  363. {
  364. // column doesnt exist
  365. if(!isset($this->columns[$column])) throw new SpoonDatagridException('The column "' . $column . '" doesn\'t exist.');
  366. // exists
  367. return $this->columns[$column];
  368. }
  369. // fallback
  370. return new SpoonDatagridColumn($column);
  371. }
  372. /**
  373. * Fetch the list of columns in this datagrid.
  374. *
  375. * @return array
  376. */
  377. public function getColumns()
  378. {
  379. return $this->getColumnsSequence();
  380. }
  381. /**
  382. * Retrieve the columns sequence.
  383. *
  384. * @return array
  385. */
  386. private function getColumnsSequence()
  387. {
  388. // init var
  389. $columns = array();
  390. // loop all the columns
  391. foreach($this->columns as $column) $columns[$column->getSequence()] = $column->getName();
  392. // reindex
  393. return (!empty($columns)) ? SpoonFilter::arraySortKeys($columns) : $columns;
  394. }
  395. /**
  396. * Retrieve the parsed output.
  397. *
  398. * @return string
  399. */
  400. public function getContent()
  401. {
  402. // parse if needed
  403. if(!$this->parsed) $this->parse();
  404. // fetch content
  405. return $this->content;
  406. }
  407. /**
  408. * Fetch the debug status.
  409. *
  410. * @return bool
  411. */
  412. public function getDebug()
  413. {
  414. return $this->debug;
  415. }
  416. /**
  417. * Returns the html attributes based on an array.
  418. *
  419. * @return string
  420. * @param array[optional] $array The attributes to be converted into HTML-attributes.
  421. */
  422. private function getHTMLAttributes(array $array = array())
  423. {
  424. // output
  425. $html = '';
  426. // loop elements
  427. foreach($array as $label => $value) $html .= ' ' . $label . '="' . $value . '"';
  428. return $html;
  429. }
  430. /**
  431. * Retrieve the number of results for this datagrids' source.
  432. *
  433. * @return int
  434. */
  435. public function getNumResults()
  436. {
  437. return $this->source->getNumResults();
  438. }
  439. /**
  440. * Retrieve the offset value.
  441. *
  442. * @return int
  443. */
  444. public function getOffset()
  445. {
  446. // default offset
  447. $offset = null;
  448. // paging enabled
  449. if($this->paging)
  450. {
  451. // has results
  452. if($this->source->getNumResults() != 0)
  453. {
  454. // offset parameter defined
  455. if($this->offsetParameter !== null) $offset = $this->offsetParameter;
  456. // use default
  457. else $offset = (isset($_GET['offset'])) ? (int) $_GET['offset'] : 0;
  458. // offset cant be bigger than the number of results
  459. if($offset >= $this->source->getNumResults()) $offset = (int) $this->source->getNumResults() - $this->pagingLimit;
  460. // offset divided by the per page limit should have no rest
  461. if(($offset % $this->pagingLimit) != 0) $offset = 0;
  462. // offset minus the pagina limit may not go below zero
  463. if(($offset - $this->pagingLimit) < 0) $offset = 0;
  464. }
  465. // no results
  466. else $offset = 0;
  467. }
  468. return $offset;
  469. }
  470. /**
  471. * Retrieves the column that's currently being sorted on.
  472. *
  473. * @return string
  474. */
  475. public function getOrder()
  476. {
  477. // default value
  478. $order = null;
  479. // sorting enabled
  480. if($this->getSorting())
  481. {
  482. /**
  483. * First the list of columns that can be ordered on,
  484. * must be re-generated
  485. */
  486. $this->generateOrder();
  487. // order parameter defined
  488. if($this->orderParameter !== null) $order = $this->orderParameter;
  489. // defaut order
  490. else $order = (isset($_GET['order'])) ? (string) $_GET['order'] : null;
  491. // retrieve order
  492. $order = SpoonFilter::getValue($order, $this->sortingColumns, $this->sortingColumn);
  493. }
  494. return $order;
  495. }
  496. /**
  497. * Is paging enabled?
  498. *
  499. * @return bool
  500. */
  501. public function getPaging()
  502. {
  503. return $this->paging;
  504. }
  505. /**
  506. * Fetch name of the class that will be used to parse the paging.
  507. *
  508. * @return string
  509. */
  510. public function getPagingClass()
  511. {
  512. return $this->pagingClass;
  513. }
  514. /**
  515. * Fetch the number of items that will be shown on each page.
  516. *
  517. * @return int
  518. */
  519. public function getPagingLimit()
  520. {
  521. return ($this->paging) ? $this->pagingLimit : null;
  522. }
  523. /**
  524. * Retrieve the sorting method.
  525. *
  526. * @return string The sorting method, either asc or desc.
  527. */
  528. public function getSort()
  529. {
  530. // default sort
  531. $sort = ($this->sortParameter !== null) ? $this->sortParameter : null;
  532. // redefine
  533. $sort = (isset($_GET['sort'])) ? (string) $_GET['sort'] : $sort;
  534. // retrieve sort
  535. return SpoonFilter::getValue($sort, array('asc', 'desc'), 'asc');
  536. }
  537. /**
  538. * Retrieve the sorting status.
  539. *
  540. * @return bool
  541. */
  542. public function getSorting()
  543. {
  544. // generate order
  545. $this->generateOrder();
  546. // sorting columns exist?
  547. return (count($this->sortingColumns) != 0) ? true : false;
  548. }
  549. /**
  550. * Retrieve the datagrid source object.
  551. *
  552. * @return SpoonDatagridSource
  553. */
  554. public function getSource()
  555. {
  556. return $this->source;
  557. }
  558. /**
  559. * Fetch the template instance
  560. *
  561. * @return SpoonTemplate
  562. */
  563. public function getTemplate()
  564. {
  565. return $this->tpl;
  566. }
  567. /**
  568. * Retrieve the location of the template that will be used.
  569. *
  570. * @return string
  571. */
  572. private function getTemplatePath()
  573. {
  574. return ($this->template != null) ? $this->template : dirname(__FILE__) . '/datagrid.tpl';
  575. }
  576. /**
  577. * Retrieve the URL.
  578. *
  579. * @return string The URL that will be used, may contain variables with square brackets.
  580. */
  581. public function getURL()
  582. {
  583. return $this->URL;
  584. }
  585. /**
  586. * Parse the datagrid.
  587. */
  588. private function parse()
  589. {
  590. // has results
  591. if($this->source->getNumResults() > 0)
  592. {
  593. // fetch records
  594. $aRecords = $this->source->getData($this->getOffset(), $this->getPagingLimit(), $this->getOrder(), $this->getSort());
  595. // has results
  596. if(count($aRecords) != 0)
  597. {
  598. // compile directory
  599. $compileDirectory = ($this->compileDirectory !== null) ? $this->compileDirectory : dirname(realpath(__FILE__));
  600. $this->tpl->setCompileDirectory($compileDirectory);
  601. // only force compiling when debug is enabled
  602. if($this->debug) $this->tpl->setForceCompile(true);
  603. // table attributes
  604. $this->parseAttributes();
  605. // table summary
  606. $this->parseSummary();
  607. // caption/description
  608. $this->parseCaption();
  609. // header row
  610. $this->parseHeader();
  611. // actual rows
  612. $this->parseBody($aRecords);
  613. // pagination
  614. $this->parseFooter();
  615. // parse to buffer
  616. ob_start();
  617. $this->tpl->display($this->getTemplatePath());
  618. $this->content = ob_get_clean();
  619. }
  620. }
  621. // update parsed status
  622. $this->parsed = true;
  623. }
  624. /**
  625. * Parses the datagrid attributes.
  626. */
  627. private function parseAttributes()
  628. {
  629. $this->tpl->assign('attributes', $this->getHtmlAttributes($this->attributes['datagrid']));
  630. }
  631. /**
  632. * Parses the body.
  633. *
  634. * @param array $records The rows.
  635. */
  636. private function parseBody(array $records)
  637. {
  638. // init var
  639. $rows = array();
  640. // columns sequence
  641. $sequence = $this->getColumnsSequence();
  642. // loop records
  643. foreach($records as $i => &$record)
  644. {
  645. // replace possible variables
  646. $record = $this->parseRecord($record);
  647. // parse column functions
  648. $record = $this->parseColumnFunctions($record);
  649. // parse custom row functions
  650. $this->parseRowFunctions($record, $this->attributes['row']);
  651. // reset row
  652. $row = array('attributes' => '', 'columns' => array());
  653. // row attributes
  654. $row['attributes'] = str_replace($record['labels'], $record['values'], $this->getHtmlAttributes($this->attributes['row']));
  655. // add custom row functions
  656. if(!empty($this->rowFunctionsParsed))
  657. {
  658. // reset attributes
  659. $row['attributes'] = str_replace($record['labels'], $record['values'], $this->getHtmlAttributes($this->rowFunctionsParsed));
  660. // clear for the next row
  661. $this->rowFunctionsParsed = array();
  662. }
  663. // default row behaviour
  664. else $row['attributes'] = str_replace($record['labels'], $record['values'], $this->getHtmlAttributes($this->attributes['row']));
  665. // odd row attributes (reversed since the first $i = 0)
  666. if(!SpoonFilter::isOdd($i)) $cycleAttributes = str_replace($record['labels'], $record['values'], $this->getHtmlAttributes($this->attributes['row_odd']));
  667. // even row attributes
  668. else $cycleAttributes = str_replace($record['labels'], $record['values'], $this->getHtmlAttributes($this->attributes['row_even']));
  669. // no longer overwrite default attributes with odd/even attributes.
  670. if(!empty($row['attributes']))
  671. {
  672. $cycleData = array();
  673. $rowData = array();
  674. preg_match_all('/( (.*?)=\"(.*?)\")/', $row['attributes'], $rowData);
  675. preg_match_all('/( (.*?)=\"(.*?)\")/', $cycleAttributes, $cycleData);
  676. // go trough the attribute data to see if anything matches
  677. foreach($cycleData[2] as $cycleAttribute => $cycleValue)
  678. {
  679. if(in_array($cycleValue, $rowData[2]))
  680. {
  681. $rowData[3][$cycleAttribute] .= ' ' . $cycleData[3][$cycleAttribute];
  682. // remove the data so we can use the others to merge the arrays
  683. unset($cycleData[2][$cycleAttribute], $cycleData[3][$cycleAttribute]);
  684. }
  685. }
  686. // merge all the values, so we get everything we need
  687. $rowData[2] = array_merge($rowData[2], $cycleData[2]);
  688. $rowData[3] = array_merge($rowData[3], $cycleData[3]);
  689. // rebuild the data
  690. $row['attributes'] = $this->getHTMLAttributes(array_combine($rowData[2], $rowData[3]));
  691. }
  692. // no match, just assign the cycle attributes as the row attributes
  693. else $row['attributes'] = $cycleAttributes;
  694. // define the columns
  695. $columns = array();
  696. // loop columns
  697. foreach($sequence as $name)
  698. {
  699. // column
  700. $column = $this->columns[$name];
  701. // has overwrite enabled
  702. if($column->getOverwrite())
  703. {
  704. // fetch key
  705. $iKey = array_search('[' . $column->getName() . ']', $record['labels']);
  706. // parse the actual value
  707. $columnValue = $record['values'][$iKey];
  708. }
  709. // no overwrite status
  710. else
  711. {
  712. // default value
  713. $columnValue = '';
  714. // has an url
  715. if($column->getURL() !== null)
  716. {
  717. // open url tag
  718. $columnValue .= '<a href="' . str_replace($record['labels'], $record['values'], $column->getURL()) . '"';
  719. // add title
  720. $columnValue .= ' title="' . str_replace($record['labels'], $record['values'], $column->getURLTitle()) . '"';
  721. // confirm
  722. if($column->getConfirm() && $column->getConfirmMessage() !== null)
  723. {
  724. // default confirm
  725. if($column->getConfirmCustom() == '') $columnValue .= ' onclick="return confirm(\'' . str_replace($record['labels'], $record['values'], $column->getConfirmMessage()) . '\');"';
  726. // custom confirm
  727. else
  728. {
  729. // replace the message
  730. $tmpValue = str_replace('%message%', $column->getConfirmMessage(), $column->getConfirmCustom());
  731. // make vars available
  732. $tmpValue = str_replace($record['labels'], $record['values'], $tmpValue);
  733. // add id
  734. $columnValue .= ' ' . $tmpValue;
  735. }
  736. }
  737. // close start tag
  738. $columnValue .= '>';
  739. }
  740. // has an image
  741. if($column->getImage() !== null)
  742. {
  743. // open img tag
  744. $columnValue .= '<img src="' . str_replace($record['labels'], $record['values'], $column->getImage()) . '"';
  745. // add title & alt
  746. $columnValue .= ' alt="' . str_replace($record['labels'], $record['values'], $column->getImageTitle()) . '"';
  747. $columnValue .= ' title="' . str_replace($record['labels'], $record['values'], $column->getImageTitle()) . '"';
  748. // close img tag
  749. $columnValue .= ' />';
  750. }
  751. // regular value
  752. else
  753. {
  754. // fetch key
  755. $iKey = array_search('[' . $column->getName() . ']', $record['labels']);
  756. // parse value
  757. $columnValue .= $record['values'][$iKey];
  758. }
  759. // has an url (close the tag)
  760. if($column->getURL() !== null) $columnValue .= '</a>';
  761. }
  762. // fetch column attributes
  763. $columnAttributes = str_replace($record['labels'], $record['values'], $this->getHtmlAttributes($column->getAttributes()));
  764. // visible & iteration
  765. if(!$column->getHidden())
  766. {
  767. // add this column
  768. $columns[] = array('attributes' => $columnAttributes, 'value' => $columnValue);
  769. // add to custom list
  770. $row['column'][$name] = $columnValue;
  771. }
  772. }
  773. // add the columns to the rows
  774. $row['columns'] = $columns;
  775. // add the row
  776. $rows[] = $row;
  777. }
  778. // assign body
  779. $this->tpl->assign('rows', $rows);
  780. // assign the number of columns
  781. $this->tpl->assign('numColumns', count($rows[0]['columns']));
  782. }
  783. /**
  784. * Parses the caption tag.
  785. */
  786. private function parseCaption()
  787. {
  788. if($this->caption !== null) $this->tpl->assign('caption', $this->caption);
  789. }
  790. /**
  791. * Parses the column functions.
  792. *
  793. * @return array
  794. * @param array $record The column-data.
  795. */
  796. private function parseColumnFunctions($record)
  797. {
  798. // store old error reporting settings
  799. $currentErrorReporting = ini_get('error_reporting');
  800. // ignore warnings and notices
  801. error_reporting(E_WARNING | E_NOTICE);
  802. // loop functions
  803. foreach($this->columnFunctions as $function)
  804. {
  805. // no arguments given
  806. if($function['arguments'] == null) $value = call_user_func($function['function']);
  807. // array
  808. elseif(is_array($function['arguments']))
  809. {
  810. // replace arguments
  811. $function['arguments'] = str_replace($record['labels'], $record['values'], $function['arguments']);
  812. // execute function
  813. $value = call_user_func_array($function['function'], $function['arguments']);
  814. }
  815. // no null/array
  816. else $value = call_user_func($function['function'], str_replace($record['labels'], $record['values'], $function['arguments']));
  817. /**
  818. * Now that we have the return value of this method, we can
  819. * do the actual writeback to the column(s). If overwrite was
  820. * true, we're going to enable the overwrite of the writeback column(s)
  821. */
  822. // one column, that exists
  823. if(is_string($function['columns']) && isset($this->columns[$function['columns']]))
  824. {
  825. // fetch key
  826. $iKey = array_search('[' . $function['columns'] . ']', $record['labels']);
  827. // value was set
  828. if($iKey !== false)
  829. {
  830. // update value
  831. $record['values'][$iKey] = $value;
  832. // update overwrite
  833. if($function['overwrite']) $this->columns[$function['columns']]->setOverwrite(true);
  834. }
  835. }
  836. // write to multiple columns
  837. elseif(is_array($function['columns']) && count($function['columns']) != 0)
  838. {
  839. // loop target columns
  840. foreach($function['columns'] as $column)
  841. {
  842. // fetch key
  843. $iKey = array_search('[' . $column . ']', $record['labels']);
  844. // value was set
  845. if($iKey !== false)
  846. {
  847. // update value
  848. $record['values'][$iKey] = $value;
  849. // update overwrite
  850. if($function['overwrite']) $this->columns[$column]->setOverwrite(true);
  851. }
  852. }
  853. }
  854. }
  855. // restore error reporting
  856. error_reporting($currentErrorReporting);
  857. return $record;
  858. }
  859. /**
  860. * Parses the footer.
  861. */
  862. private function parseFooter()
  863. {
  864. // attributes
  865. $this->tpl->assign('footerAttributes', $this->getHtmlAttributes($this->attributes['footer']));
  866. // parse paging
  867. $this->parsePaging();
  868. }
  869. /**
  870. * Parses the header row.
  871. */
  872. private function parseHeader()
  873. {
  874. // init vars
  875. $header = array();
  876. // sequence
  877. $sequence = $this->getColumnsSequence();
  878. // sorting enabled?
  879. $sorting = $this->getSorting();
  880. // sortable columns
  881. $sortingColumns = array();
  882. foreach($sequence as $oColumn) if($this->columns[$oColumn]->getSorting()) $sortingColumns[] = $oColumn;
  883. // loop columns
  884. foreach($sequence as $name)
  885. {
  886. // define column
  887. $column = array();
  888. // column
  889. $oColumn = $this->columns[$name];
  890. // visible
  891. if(!$oColumn->getHidden())
  892. {
  893. // sorting globally enabled AND for this column
  894. if($sorting && in_array($name, $sortingColumns))
  895. {
  896. // init var
  897. $column['sorting'] = true;
  898. $column['noSorting'] = false;
  899. // sorted on this column?
  900. if($this->getOrder() == $name)
  901. {
  902. // sorted
  903. $column['sorted'] = true;
  904. $column['notSorted'] = false;
  905. // asc
  906. if($this->getSort() == 'asc')
  907. {
  908. $column['sortedAsc'] = true;
  909. $column['sortedDesc'] = false;
  910. }
  911. // desc
  912. else
  913. {
  914. $column['sortedAsc'] = false;
  915. $column['sortedDesc'] = true;
  916. }
  917. }
  918. /**
  919. * This column is sortable, but there's currently not being
  920. * sorted on this column.
  921. */
  922. elseif(in_array($name, $sortingColumns))
  923. {
  924. $column['sorted'] = false;
  925. $column['notSorted'] = true;
  926. }
  927. /**
  928. * URL's are parsed for the opposite column, as for the asc & desc version
  929. * for this column. If the sorting is currently not on this column
  930. * the default sorting method (mostly asc) will be used to define the opposite/default
  931. * sorting method.
  932. */
  933. // currently not sorting on this column
  934. if($this->getOrder() != $name) $sortingMethod = $this->columns[$name]->getSortingMethod();
  935. // sorted on this column ascending
  936. elseif($this->getSort() == 'asc') $sortingMethod = 'desc';
  937. // sorting on this column descending
  938. else $sortingMethod = 'asc';
  939. // build actual urls
  940. $column['sortingURL'] = $this->buildURL($this->getOffset(), $name, $sortingMethod);
  941. $column['sortingURLAsc'] = $this->buildURL($this->getOffset(), $name, 'asc');
  942. $column['sortingURLDesc'] = $this->buildURL($this->getOffset(), $name, 'desc');
  943. /**
  944. * There's no point in parsing the icon for this column if there's
  945. * not being sorted on this column.
  946. */
  947. /**
  948. * To define the default icon for sorting, we need to apply
  949. * the same rules as with the default url. See those comments for
  950. * the necessary details.
  951. */
  952. if($this->getOrder() != $name) $sortingIcon = $this->sortingIcons[$this->columns[$name]->getSortingMethod()];
  953. // sorted on this column asc/desc
  954. elseif($this->getSort() == 'asc') $sortingIcon = $this->sortingIcons['ascSelected'];
  955. else $sortingIcon = $this->sortingIcons['descSelected'];
  956. // asc & desc icons
  957. $column['sortingIcon'] = $sortingIcon;
  958. $column['sortingIconAsc'] = ($this->getSort() == 'asc') ? $this->sortingIcons['ascSelected'] : $this->sortingIcons['asc'];
  959. $column['sortingIconDesc'] = ($this->getSort() == 'desc') ? $this->sortingIcons['descSelected'] : $this->sortingIcons['desc'];
  960. // not sorted on this column
  961. if($this->getOrder() != $name) $sortingLabel = $this->sortingLabels[$this->columns[$name]->getSortingMethod()];
  962. // sorted on this column asc/desc
  963. elseif($this->getSort() == 'asc') $sortingLabel = $this->sortingLabels['ascSelected'];
  964. else $sortingLabel = $this->sortingLabels['descSelected'];
  965. // add sorting labels
  966. $column['sortingLabel'] = $sortingLabel;
  967. $column['sortingLabelAsc'] = $this->sortingLabels['asc'];
  968. $column['sortingLabelDesc'] = $this->sortingLabels['desc'];
  969. }
  970. // no sorting enabled for this column
  971. else
  972. {
  973. $column['sorting'] = false;
  974. $column['noSorting'] = true;
  975. }
  976. // parse vars
  977. $column['label'] = $oColumn->getLabel();
  978. // add attributes
  979. $column['attributes'] = $this->getHTMLAttributes($oColumn->getHeaderAttributes());
  980. // add to array
  981. $header[] = $column;
  982. }
  983. }
  984. // default headers
  985. $this->tpl->assign('headers', $header);
  986. }
  987. /**
  988. * Parses the paging.
  989. */
  990. private function parsePaging()
  991. {
  992. // enabled
  993. if($this->paging)
  994. {
  995. // offset, order & sort
  996. $this->tpl->assign(array('offset', 'order', 'sort'), array($this->getOffset(), $this->getOrder(), $this->getSort()));
  997. // number of results
  998. $this->tpl->assign('iResults', $this->source->getNumResults());
  999. // number of pages
  1000. $this->tpl->assign('iPages', ceil($this->source->getNumResults() / $this->pagingLimit));
  1001. // current page
  1002. $this->tpl->assign('iCurrentPage', ceil($this->getOffset() / $this->pagingLimit) + 1);
  1003. // number of items per page
  1004. $this->tpl->assign('iPerPage', $this->pagingLimit);
  1005. // parse paging
  1006. $content = call_user_func(array($this->pagingClass, 'getContent'), $this->URL, $this->getOffset(), $this->getOrder(), $this->getSort(), $this->source->getNumResults(), $this->pagingLimit, $this->debug, $this->compileDirectory);
  1007. // asign content
  1008. $this->tpl->assign('paging', $content);
  1009. }
  1010. }
  1011. /**
  1012. * Parses the record.
  1013. *
  1014. * @return array
  1015. * @param array $record The row-data.
  1016. */
  1017. private function parseRecord(array $record)
  1018. {
  1019. // init var
  1020. $array = array('labels' => array(), 'values' => array());
  1021. // create labels/values array
  1022. foreach($record as $label => $value)
  1023. {
  1024. $array['labels'][] = '[' . $label . ']';
  1025. $array['values'][] = $value;
  1026. }
  1027. // add offset?
  1028. if($this->paging)
  1029. {
  1030. $array['labels'][] = '[offset]';
  1031. $array['values'][] = $this->getOffset();
  1032. }
  1033. // sorting
  1034. if(count($this->sortingColumns) != 0)
  1035. {
  1036. $array['labels'][] = '[order]';
  1037. $array['labels'][] = '[sort]';
  1038. // --
  1039. $array['values'][] = $this->getOrder();
  1040. $array['values'][] = $this->getSort();
  1041. }
  1042. // loop the record fields
  1043. foreach($this->columns as $column)
  1044. {
  1045. // this column is an extra field, added in the datagrid
  1046. if(!in_array('[' . $column->getName() . ']', $array['labels']))
  1047. {
  1048. $array['values'][] = str_replace($array['labels'], $array['values'], $column->getValue());
  1049. $array['labels'][] = '[' . $column->getName() . ']';
  1050. }
  1051. }
  1052. return $array;
  1053. }
  1054. /**
  1055. * Parses the column functions.
  1056. *
  1057. * @param array $record The row-data.
  1058. * @param array[optional] $rowAttributes The attributes on the row.
  1059. */
  1060. private function parseRowFunctions($record, array $rowAttributes = null)
  1061. {
  1062. // store old error reporting settings
  1063. $currentErrorReporting = ini_get('error_reporting');
  1064. // ignore warnings and notices
  1065. error_reporting(E_WARNING | E_NOTICE);
  1066. // loop functions
  1067. foreach($this->rowFunctions as $function)
  1068. {
  1069. // no arguments given
  1070. if($function['arguments'] == null) $value = call_user_func($function['function'], $rowAttributes);
  1071. // array
  1072. elseif(is_array($function['arguments']))
  1073. {
  1074. // replace arguments
  1075. $function['arguments'] = str_replace($record['labels'], $record['values'], $function['arguments']);
  1076. $function['arguments'][] = $rowAttributes;
  1077. // execute function
  1078. $value = call_user_func_array($function['function'], $function['arguments']);
  1079. }
  1080. // no null/array
  1081. else $value = call_user_func($function['function'], str_replace($record['labels'], $record['values'], $function['arguments']), $rowAttributes);
  1082. /**
  1083. * Now that we have the return value we have to write the the
  1084. * custom row function cache. If overwrite was enabled, we're
  1085. * overwriting this, else we're adding to it!
  1086. */
  1087. if($function['overwrite']) $this->rowFunctionsParsed = $value;
  1088. else
  1089. {
  1090. // loop return values
  1091. foreach((array) $value as $key => $value)
  1092. {
  1093. if(isset($this->rowFunctionsParsed[$key])) $this->rowFunctionsParsed[$key] .= ' ' . $value;
  1094. else $this->rowFunctionsParsed[$key] = $value;
  1095. }
  1096. }
  1097. }
  1098. // restore error reporting
  1099. error_reporting($currentErrorReporting);
  1100. // cough it up
  1101. return $record;
  1102. }
  1103. /**
  1104. * Parses the summary.
  1105. */
  1106. private function parseSummary()
  1107. {
  1108. if($this->summary !== null) $this->tpl->assign('summary', $this->summary);
  1109. }
  1110. /**
  1111. * Set main datagrid attributes.
  1112. *
  1113. * @param array $attributes The attributes to set on the datagrid.
  1114. */
  1115. public function setAttributes(array $attributes)
  1116. {
  1117. foreach($attributes as $key => $value) $this->attributes['datagrid'][(string) $key] = (string) $value;
  1118. }
  1119. /**
  1120. * Sets the table caption or main description.
  1121. *
  1122. * @param string $value The value for the caption-element.
  1123. */
  1124. public function setCaption($value)
  1125. {
  1126. $this->caption = (string) $value;
  1127. }
  1128. /**
  1129. * Set one or more attributes for a specific column.
  1130. *
  1131. * @param string $column The column to apply the attributes on.
  1132. * @param array $attributes The attributes for a column.
  1133. */
  1134. public function setColumnAttributes($column, array $attributes)
  1135. {
  1136. // has results
  1137. if($this->source->getNumResults() > 0)
  1138. {
  1139. // column doesnt exist
  1140. if(!isset($this->columns[$column])) throw new SpoonDatagridException('The column "' . $column . '" doesn\'t exist, therefor no attributes can be added.');
  1141. // exists
  1142. else $this->columns[$column]->setAttributes($attributes);
  1143. }
  1144. }
  1145. /**
  1146. * Set a custom column confirm message.
  1147. *
  1148. * @param string $column The column to apply the confirmation on.
  1149. * @param string $message The message to use.
  1150. * @param string[optional] $custom Custom code you wish to use to confirm.
  1151. */
  1152. public function setColumnConfirm($column, $message, $custom = null)
  1153. {
  1154. // has results
  1155. if($this->source->getNumResults() > 0)
  1156. {
  1157. // column doesnt exist
  1158. if(!isset($this->columns[$column])) throw new SpoonDatagridException('The column "' . $column . '" doesn\'t exist, therefor no confirm message/script can be added.');
  1159. // exists
  1160. else $this->columns[$column]->setConfirm($message, $custom);
  1161. }
  1162. }
  1163. /**
  1164. * Sets the column function to be executed for every row.
  1165. *
  1166. * @param mixed $function The function to apply.
  1167. * @param mixed[optional] $arguments The arguments for the function.
  1168. * @param mixed $columns The columns wherein the result will appear.
  1169. * @param bool[optional] $overwrite Should the result overwrite the current value?
  1170. */
  1171. public function setColumnFunction($function, $arguments = null, $columns, $overwrite = false)
  1172. {
  1173. // has results
  1174. if($this->source->getNumResults() > 0)
  1175. {
  1176. // regular function
  1177. if(!is_array($function))
  1178. {
  1179. // function checks
  1180. if(!function_exists((string) $function)) throw new SpoonDatagridException('The function "' . (string) $function . '" doesn\'t exist.');
  1181. }
  1182. // class method
  1183. else
  1184. {
  1185. // method checks
  1186. if(count($function) != 2) throw new SpoonDatagridException('When providing a method for a column function it must be like array(\'class\', \'method\')');
  1187. // method doesn't exist
  1188. elseif(!is_callable(array($function[0], $function[1]))) throw new SpoonDatagridException('The method ' . (string) $function[0] . '::' . (string) $function[1] . ' does not exist.');
  1189. }
  1190. // add to function stack
  1191. $this->columnFunctions[] = array('function' => $function, 'arguments' => $arguments, 'columns' => $columns, 'overwrite' => (bool) $overwrite);
  1192. }
  1193. }
  1194. /**
  1195. * Set one or more attributes for a columns' header.
  1196. *
  1197. * @param string $column The column whereon the atrributes will be set.
  1198. * @param array $attributes The attributes for a column.
  1199. */
  1200. public function setColumnHeaderAttributes($column, array $attributes)
  1201. {
  1202. // has results
  1203. if($this->source->getNumResults() > 0)
  1204. {
  1205. // column doesnt exist
  1206. if(!isset($this->columns[$column])) throw new SpoonDatagridException('The column "' . $column . '" doesn\'t exist, therefor no attributes can be added to its header.');
  1207. // exists
  1208. else $this->columns[$column]->setHeaderAttributes($attributes);
  1209. }
  1210. }
  1211. /**
  1212. * Sets a single column hidden.
  1213. *
  1214. * @param string $column The column to hide/show.
  1215. * @param bool[optional] $on Should the column be hidden?
  1216. */
  1217. public function setColumnHidden($column, $on = true)
  1218. {
  1219. // has results
  1220. if($this->source->getNumResults() > 0)
  1221. {
  1222. // column doesn't exist
  1223. if(!isset($this->columns[(string) $column])) throw new SpoonDatagridException('The column "' . (string) $column . '" doesn\'t exist and therefor can\'t be set hidden.');
  1224. // exists
  1225. $this->columns[(string) $column]->setHidden($on);
  1226. }
  1227. }
  1228. /**
  1229. * Sets one or more columns hidden.
  1230. *
  1231. * @param array $columns An array with the columns to hide.
  1232. */
  1233. public function setColumnsHidden($columns)
  1234. {
  1235. // has results
  1236. if($this->source->getNumResults() > 0)
  1237. {
  1238. // array
  1239. if(is_array($columns)) foreach($columns as $column) $this->setColumnHidden((string) $column);
  1240. // multiple arguments
  1241. else
  1242. {
  1243. // set columns hidden
  1244. foreach(func_get_args() as $column) $this->setColumnHidden($column);
  1245. }
  1246. }
  1247. }
  1248. /**
  1249. * Set the default sorting method for a column.
  1250. *
  1251. * @param string $column The column to set the method for.
  1252. * @param string[optional] $sort The sorting method, possible values are: asc, desc.
  1253. */
  1254. public function setColumnSortingMethod($column, $sort = 'asc')
  1255. {
  1256. // has results
  1257. if($this->source->getNumResults() > 0)
  1258. {
  1259. // column doesn't exist
  1260. if(!isset($this->columns[(string) $column])) throw new SpoonDatagridException('The column "' . (string) $column . '" doesn\'t exist and therefor no default sorting method can be applied to it.');
  1261. // exists
  1262. $this->columns[(string) $column]->setSortingMethod($sort);
  1263. }
  1264. }
  1265. /**
  1266. * Sets the columns sequence.
  1267. *
  1268. * @param array $columns The columns in the correct sequence.
  1269. */
  1270. public function setColumnsSequence($columns)
  1271. {
  1272. // has results
  1273. if($this->source->getNumResults() > 0)
  1274. {
  1275. // array
  1276. if(is_array($columns)) call_user_func_array(array($this, 'setColumnsSequence'), $columns);
  1277. // multiple arguments
  1278. else
  1279. {
  1280. // current sequence
  1281. $sequences = $this->getColumnsSequence();
  1282. // fetch arguments
  1283. $arguments = func_get_args();
  1284. // build columns
  1285. $columns = (is_array($arguments[0])) ? $arguments[0] : $arguments;
  1286. // counter
  1287. $i = 1;
  1288. // loop colums
  1289. foreach($columns as $column)
  1290. {
  1291. // column exists
  1292. if(!isset($this->columns[(string) $column])) throw new SpoonDatagridException('The column "' . (string) $column . '" doesn\'t exist. Therefor its sequence can\'t be altered.');
  1293. // update sequence
  1294. $this->columns[(string) $column]->setSequence($i);
  1295. // remove from the original list
  1296. $iKey = (int) array_search((string) $column, $sequences);
  1297. unset($sequences[$iKey]);
  1298. // update counter
  1299. $i++;
  1300. }
  1301. // reset counter
  1302. $i = 1;
  1303. // add remaining columns
  1304. foreach($sequences as $sequence)
  1305. {
  1306. // update sequence
  1307. $this->columns[$sequence]->setSequence(count($columns) + $i);
  1308. // update counter
  1309. $i++;
  1310. }
  1311. }
  1312. }
  1313. }
  1314. /**
  1315. * Set the URL for a column.
  1316. *
  1317. * @param string $column The column wheron the URL will be applied.
  1318. * @param string $URL The URL.
  1319. * @param string[optional] $title The title for the URL.
  1320. */
  1321. public function setColumnURL($column, $URL, $title = null)
  1322. {
  1323. // has results
  1324. if($this->source->getNumResults() > 0)
  1325. {
  1326. // column doesn't exist
  1327. if(!isset($this->columns[(string) $column])) throw new SpoonDatagridException('The column "' . (string) $column . '" doesn\'t exist and therefor no URL can be applied.');
  1328. // exists
  1329. $this->columns[(string) $column]->setURL($URL, $title);
  1330. }
  1331. }
  1332. /**
  1333. * Sets the compile directory.
  1334. *
  1335. * @param string $path The path to the compile directory.
  1336. */
  1337. public function setCompileDirectory($path)
  1338. {
  1339. $this->compileDirectory = (string) $path;
  1340. }
  1341. /**
  1342. * Adjust the debug setting.
  1343. *
  1344. * @param bool[optional] $on Should we enable debug-mode.
  1345. */
  1346. public function setDebug($on = true)
  1347. {
  1348. $this->debug = (bool) $on;
  1349. }
  1350. /**
  1351. * Set the even row attributes.
  1352. *
  1353. * @param array $attributes The attributes for an even row.
  1354. */
  1355. public function setEvenRowAttributes(array $attributes)
  1356. {
  1357. if($this->source->getNumResults() > 0)
  1358. {
  1359. foreach($attributes as $key => $value)
  1360. {
  1361. $this->attributes['row_even'][(string) $key] = (string) $value;
  1362. }
  1363. }
  1364. }
  1365. /**
  1366. * Set the header labels.
  1367. *
  1368. * @param array $labels An array whith the labels where the key is the name of the column.
  1369. */
  1370. public function setHeaderLabels(array $labels)
  1371. {
  1372. // has results
  1373. if($this->source->getNumResults() > 0)
  1374. {
  1375. // loop the keys
  1376. foreach($labels as $column => $label)
  1377. {
  1378. // column doesn't exist
  1379. if(!isset($this->columns[$column])) throw new SpoonDatagridException('The column "' . $column . '" doesn\'t exist, therefor no label can be assigned to it.');
  1380. // exists
  1381. else $this->columns[$column]->setLabel($label);
  1382. }
  1383. }
  1384. }
  1385. /**
  1386. * Set the odd row attributes.
  1387. *
  1388. * @param array $attributes The attributes for an odd-row.
  1389. */
  1390. public function setOddRowAttributes(array $attributes)
  1391. {
  1392. if($this->source->getNumResults() > 0)
  1393. {
  1394. // add to the list
  1395. foreach($attributes as $key => $value) $this->attributes['row_odd'][(string) $key] = (string) $value;
  1396. }
  1397. }
  1398. /**
  1399. * Sets the value for offset. eg from the URL.
  1400. *
  1401. * @param int[optional] $value The value from the offset-parameter.
  1402. */
  1403. public function setOffsetParameter($value = null)
  1404. {
  1405. $this->offsetParameter = (int) $value;
  1406. }
  1407. /**
  1408. * Sets the value for the order. eg from the URL.
  1409. *
  1410. * @param string[optional] $value The value from the order-parameter.
  1411. */
  1412. public function setOrderParameter($value = null)
  1413. {
  1414. $this->orderParameter = (string) $value;
  1415. }
  1416. /**
  1417. * Allow/disallow showing the results on multiple pages.
  1418. *
  1419. * @param bool[optional] $on Is paging enabled?
  1420. */
  1421. public function setPaging($on = false)
  1422. {
  1423. $this->paging = (bool) $on;
  1424. }
  1425. /**
  1426. * Sets an alternative paging class.
  1427. *
  1428. * @param string $class The class that should be used for paging.
  1429. */
  1430. public function setPagingClass($class)
  1431. {
  1432. // class cant be found
  1433. if(!class_exists((string) $class)) throw new SpoonDatagridException('The class "' . (string) $class . '" you provided for the alternative paging can not be found.');
  1434. // class exists
  1435. else
  1436. {
  1437. // does not impmlement the interface
  1438. if(!in_array('iSpoonDatagridPaging', class_implements($class))) throw new SpoonDatagridException('The paging class you provided does not implement the "iSpoonDatagridPaging" interface');
  1439. // all is fine
  1440. else $this->pagingClass = $class;
  1441. }
  1442. }
  1443. /**
  1444. * Sets the number of results per page.
  1445. *
  1446. * @param int[optional] $limit The maximum number of rows when paging is enabled.
  1447. */
  1448. public function setPagingLimit($limit = 30)
  1449. {
  1450. $this->pagingLimit = abs((int) $limit);
  1451. }
  1452. /**
  1453. * Sets the row attributes.
  1454. *
  1455. * @param array $attributes The attributes for a row.
  1456. */
  1457. public function setRowAttributes(array $attributes)
  1458. {
  1459. foreach($attributes as $key => $value) $this->attributes['row'][(string) $key] = (string) $value;
  1460. }
  1461. /**
  1462. * Sets the row function to be executed for every row.
  1463. *
  1464. * @param mixed $function The function to apply.
  1465. * @param mixed[optional] $arguments The arguments to pass to the function.
  1466. * @param bool[optional] $overwrite Should the result overwrite the current value?
  1467. */
  1468. public function setRowFunction($function, $arguments = null, $overwrite = false)
  1469. {
  1470. // has results
  1471. if($this->source->getNumResults() > 0)
  1472. {
  1473. // regular function
  1474. if(!is_array($function))
  1475. {
  1476. // function checks
  1477. if(!function_exists((string) $function)) throw new SpoonDatagridException('The function "' . (string) $function . '" doesn\'t exist.');
  1478. }
  1479. // class method
  1480. else
  1481. {
  1482. // method checks
  1483. if(count($function) != 2) throw new SpoonDatagridException('When providing a method for a column function it must be like array(\'class\', \'method\')');
  1484. // method doesn't exist
  1485. elseif(!is_callable(array($function[0], $function[1]))) throw new SpoonDatagridException('The method ' . (string) $function[0] . '::' . (string) $function[1] . ' does not exist.');
  1486. }
  1487. // add to function stack
  1488. $this->rowFunctions[] = array('function' => $function, 'arguments' => $arguments, 'overwrite' => (bool) $overwrite);
  1489. }
  1490. }
  1491. /**
  1492. * Sets the columns that may be sorted on.
  1493. *
  1494. * @param array $columns The columns whereon sorting is enabled.
  1495. * @param string[optional] $default The column whereon will be sorted by default.
  1496. */
  1497. public function setSortingColumns(array $columns, $default = null)
  1498. {
  1499. // has results
  1500. if($this->source->getNumResults() > 0)
  1501. {
  1502. // loop columns
  1503. foreach($columns as $column)
  1504. {
  1505. // column doesn't exist
  1506. if(!isset($this->columns[(string) $column])) throw new SpoonDatagridException('The column "' . (string) $column . '" doesn\'t exist and therefor can\'t be sorted on.');
  1507. // column exists
  1508. else
  1509. {
  1510. // not sortable
  1511. if(!in_array((string) $column, $this->allowedSortingColumns)) throw new SpoonDatagridException('The column "' . (string) $column . '" can\'t be sorted on.');
  1512. // sortable
  1513. else
  1514. {
  1515. // enable sorting
  1516. $this->columns[(string) $column]->setSorting(true);
  1517. // set default sorting
  1518. if(!isset($defaultColumn)) $defaultColumn = (string) $column;
  1519. }
  1520. }
  1521. }
  1522. // default column set
  1523. if($default !== null && in_array($defaultColumn, $columns)) $defaultColumn = (string) $default;
  1524. // default column is not good
  1525. if(!in_array($defaultColumn, $this->allowedSortingColumns)) throw new SpoonDatagridException('The column "' . $defaultColumn . '" can\'t be set as the default sorting column, because it doesn\'t exist or may not be sorted on.');
  1526. // set default column
  1527. $this->sortingColumn = $defaultColumn;
  1528. }
  1529. }
  1530. /**
  1531. * Sets the sorting icons.
  1532. *
  1533. * @param string[optional] $asc The icon for ascending.
  1534. * @param string[optional] $ascSelected The icon when ascending sort is applied.
  1535. * @param string[optional] $desc The icon for descending.
  1536. * @param string[optional] $descSelected The icon when descending sort is applied.
  1537. */
  1538. public function setSortingIcons($asc = null, $ascSelected = null, $desc = null, $descSelected)
  1539. {
  1540. if($asc !== null) $this->sortingIcons['asc'] = (string) $asc;
  1541. if($ascSelected !== null) $this->sortingIcons['ascSelected'] = (string) $ascSelected;
  1542. if($desc !== null) $this->sortingIcons['desc'] = (string) $desc;
  1543. if($descSelected !== null) $this->sortingIcons['descSelected'] = (string) $descSelected;
  1544. }
  1545. /**
  1546. * Sets the sorting labels.
  1547. *
  1548. * @param string[optional] $asc The value for ascending.
  1549. * @param string[optional] $ascSelected The value when ascending sort is applied.
  1550. * @param string[optional] $desc The value for descending.
  1551. * @param string[optional] $descSelected The value when descending sort is applied.
  1552. */
  1553. public function setSortingLabels($asc = null, $ascSelected = null, $desc = null, $descSelected = null)
  1554. {
  1555. if($asc !== null) $this->sortingLabels['asc'] = (string) $asc;
  1556. if($ascSelected !== null) $this->sortingLabels['ascSelected'] = (string) $ascSelected;
  1557. if($desc !== null) $this->sortingLabels['desc'] = (string) $desc;
  1558. if($descSelected !== null) $this->sortingLabels['descSelected'] = (string) $descSelected;
  1559. }
  1560. /**
  1561. * Sets the value to sort.
  1562. *
  1563. * @param string[optional] $value The sorting-method.
  1564. */
  1565. public function setSortParameter($value = 'desc')
  1566. {
  1567. $this->sortParameter = SpoonFilter::getValue($value, array('asc', 'desc'), 'asc');
  1568. }
  1569. /**
  1570. * Sets the source for this datagrid.
  1571. *
  1572. * @param SpoonDatagridSource $source The source for the datagrid, it should implement SpoonDatagridSource.
  1573. */
  1574. private function setSource(SpoonDatagridSource $source)
  1575. {
  1576. $this->source = $source;
  1577. }
  1578. /**
  1579. * Sets the table summary.
  1580. *
  1581. * @param string $value The summary value.
  1582. */
  1583. public function setSummary($value)
  1584. {
  1585. $this->summary = (string) $value;
  1586. }
  1587. /**
  1588. * Sets the path to the template file.
  1589. *
  1590. * @param string $template The path to the template.
  1591. */
  1592. public function setTemplate($template)
  1593. {
  1594. $this->template = (string) $template;
  1595. }
  1596. /**
  1597. * Defines the default URL.
  1598. *
  1599. * @param string $URL The URL to use.
  1600. */
  1601. public function setURL($URL)
  1602. {
  1603. $this->URL = (string) $URL;
  1604. }
  1605. }
  1606. /**
  1607. * This exception is used to handle datagrid related exceptions.
  1608. *
  1609. * @package spoon
  1610. * @subpackage datagrid
  1611. *
  1612. *
  1613. * @author Davy Hellemans <davy@spoon-library.com>
  1614. * @since 0.1.1
  1615. */
  1616. class SpoonDatagridException extends SpoonException {}