PageRenderTime 57ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/backend/core/engine/datagrid.php

http://github.com/forkcms/forkcms
PHP | 915 lines | 402 code | 149 blank | 364 comment | 53 complexity | 39ef56b1ac11c7cb445e46482a67a333 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. * This file is part of Fork CMS.
  4. *
  5. * For the full copyright and license information, please view the license
  6. * file that was distributed with this source code.
  7. */
  8. /**
  9. * This is our extended version of SpoonDataGrid
  10. * This class will handle a lot of stuff for you, for example:
  11. * - it will set debugmode
  12. * - it will set the compile-directory
  13. * - ...
  14. *
  15. * @author Davy Hellemans <davy.hellemans@netlash.com>
  16. * @author Tijs Verkoyen <tijs@sumocoders.be>
  17. * @author Dieter Vanden Eynde <dieter@dieterve.be>
  18. * @author Jelmer Snoeck <jelmer.snoeck@netlash.com>
  19. */
  20. class BackendDataGrid extends SpoonDataGrid
  21. {
  22. /**
  23. * @param SpoonDataGridSource $source
  24. */
  25. public function __construct(SpoonDataGridSource $source)
  26. {
  27. parent::__construct($source);
  28. // set debugmode, this will force the recompile for the used templates
  29. $this->setDebug(SPOON_DEBUG);
  30. // set the compile-directory, so compiled templates will be in a folder that is writable
  31. $this->setCompileDirectory(BACKEND_CACHE_PATH . '/compiled_templates');
  32. // set attributes for the datagrid
  33. $this->setAttributes(array('class' => 'dataGrid', 'cellspacing' => 0, 'cellpadding' => 0, 'border' => 0));
  34. // id gets special treatment
  35. if(in_array('id', $this->getColumns()))
  36. {
  37. // hide the id by defaults
  38. $this->setColumnsHidden('id');
  39. // our JS needs to know an id, so we can highlight it
  40. $this->setRowAttributes(array('id' => 'row-[id]'));
  41. }
  42. // set default sorting options
  43. $this->setSortingOptions();
  44. // add classes on headers
  45. foreach($this->getColumns() as $column)
  46. {
  47. // set class
  48. $this->setColumnHeaderAttributes($column, array('class' => $column));
  49. // set default label
  50. $this->setHeaderLabels(array($column => SpoonFilter::ucfirst(BL::lbl(SpoonFilter::toCamelCase($column)))));
  51. }
  52. // set paging class
  53. $this->setPagingClass('BackendDataGridPaging');
  54. // set default template
  55. $this->setTemplate(BACKEND_CORE_PATH . '/layout/templates/datagrid.tpl');
  56. }
  57. /**
  58. * Adds a new column
  59. *
  60. * @param string $name The name for the new column.
  61. * @param string[optional] $label The label for the column.
  62. * @param string[optional] $value The value for the column.
  63. * @param string[optional] $URL The URL for the link inside the column.
  64. * @param string[optional] $title A title for the image inside the column.
  65. * @param string[optional] $image An URL to the image inside the column.
  66. * @param int[optional] $sequence The sequence for the column.
  67. */
  68. public function addColumn($name, $label = null, $value = null, $URL = null, $title = null, $image = null, $sequence = null)
  69. {
  70. // known actions that should have a button
  71. if(in_array($name, array('add', 'edit', 'delete', 'details', 'approve', 'mark_as_spam', 'install')))
  72. {
  73. // rebuild value, it should have special markup
  74. $value = '<a href="' . $URL . '" class="button icon icon' . SpoonFilter::toCamelCase($name) . ' linkButton">
  75. <span>' . $value . '</span>
  76. </a>';
  77. // reset URL
  78. $URL = null;
  79. }
  80. if(in_array($name, array('use_revision', 'use_draft')))
  81. {
  82. // rebuild value, it should have special markup
  83. $value = '<a href="' . $URL . '" class="button linkButton icon iconEdit icon' . SpoonFilter::toCamelCase($name) . '">
  84. <span>' . $value . '</span>
  85. </a>';
  86. // reset URL
  87. $URL = null;
  88. }
  89. // add the column
  90. parent::addColumn($name, $label, $value, $URL, $title, $image, $sequence);
  91. // known actions
  92. if(in_array($name, array('add', 'edit', 'delete', 'details', 'approve', 'mark_as_spam', 'install', 'use_revision', 'use_draft')))
  93. {
  94. // add special attributes for actions we know
  95. $this->setColumnAttributes($name, array('class' => 'action action' . SpoonFilter::toCamelCase($name)));
  96. }
  97. // set header attributes
  98. $this->setColumnHeaderAttributes($name, array('class' => $name));
  99. }
  100. /**
  101. * Adds a new column with a custom action button
  102. *
  103. * @param string $name The name for the new column.
  104. * @param string[optional] $label The label for the column.
  105. * @param string[optional] $value The value for the column.
  106. * @param string[optional] $URL The URL for the link inside the column.
  107. * @param string[optional] $title The title for the link inside the column.
  108. * @param array[optional] $anchorAttributes The attributes for the anchor inside the column.
  109. * @param string[optional] $image An URL to the image inside the column.
  110. * @param int[optional] $sequence The sequence for the column.
  111. */
  112. public function addColumnAction($name, $label = null, $value = null, $URL = null, $title = null, $anchorAttributes = null, $image = null, $sequence = null)
  113. {
  114. // reserve var for attributes
  115. $attributes = '';
  116. // no anchorAttributes set means we set the default class attribute for the anchor
  117. if(empty($anchorAttributes)) $anchorAttributes['class'] = 'button icon icon' . SpoonFilter::toCamelCase($name) . ' linkButton';
  118. // loop the attributes, build our attributes string
  119. foreach($anchorAttributes as $attribute => $attributeValue) $attributes .= ' ' . $attribute . '="' . $attributeValue . '"';
  120. // rebuild value
  121. $value = '<a href="' . $URL . '"' . $attributes . '>
  122. <span>' . $value . '</span>
  123. </a>';
  124. // add the column to the datagrid
  125. parent::addColumn($name, $label, $value, null, $title, $image, $sequence);
  126. // set column attributes
  127. $this->setColumnAttributes($name, array(
  128. 'class' => 'action action' . SpoonFilter::toCamelCase($name),
  129. 'style' => 'width: 10%;'
  130. ));
  131. // set header attributes
  132. $this->setColumnHeaderAttributes($name, array('class' => $name));
  133. }
  134. /**
  135. * Enable the grey out functionallity. This will see if we have a column that matches our set.
  136. * If so, it will call the BackendDatagridFunction with the type and value so we can parse the data.
  137. */
  138. public function enableGreyingOut()
  139. {
  140. $allowedColumns = array('hidden', 'visible', 'active', 'published');
  141. $allColumns = $this->getColumns();
  142. foreach($allowedColumns as $column)
  143. {
  144. // we have a match, set the row function
  145. if(array_search($column, $allColumns) !== false)
  146. {
  147. $this->setColumnHidden($column);
  148. $this->setRowFunction(array('BackendDatagridFunctions', 'greyOut'), array($column, '[' . $column . ']'), array($column));
  149. }
  150. }
  151. }
  152. /**
  153. * Enable drag and drop for the current datagrid
  154. */
  155. public function enableSequenceByDragAndDrop()
  156. {
  157. // add drag and drop-class
  158. $this->setAttributes(array('class' => 'dataGrid sequenceByDragAndDrop'));
  159. // disable paging
  160. $this->setPaging(false);
  161. // hide the sequence column
  162. $this->setColumnHidden('sequence');
  163. // add a column for the handle, so users have something to hold while draging
  164. $this->addColumn('dragAndDropHandle', null, '<span>' . BL::lbl('Move') . '</span>');
  165. // make sure the column with the handler is the first one
  166. $this->setColumnsSequence('dragAndDropHandle');
  167. // add a class on the handler column, so JS knows this is just a handler
  168. $this->setColumnAttributes('dragAndDropHandle', array('class' => 'dragAndDropHandle'));
  169. // our JS needs to know an id, so we can send the new order
  170. $this->setRowAttributes(array('data-id' => '[id]'));
  171. }
  172. /**
  173. * Retrieve the parsed output.
  174. *
  175. * @return string
  176. */
  177. public function getContent()
  178. {
  179. // mass action was set
  180. if($this->tpl->getAssignedValue('massAction') !== null) $this->tpl->assign('footer', true);
  181. // has paging & more than 1 page
  182. elseif($this->getPaging() && $this->getNumResults() > $this->getPagingLimit()) $this->tpl->assign('footer', true);
  183. // set the odd and even classes
  184. $this->setOddRowAttributes(array('class' => 'odd'));
  185. $this->setEvenRowAttributes(array('class' => 'even'));
  186. // enable greying out
  187. $this->enableGreyingOut();
  188. // execute parent
  189. return parent::getContent();
  190. }
  191. /**
  192. * Sets the active tab for this datagrid
  193. *
  194. * @param string $tab The name of the tab to show.
  195. */
  196. public function setActiveTab($tab)
  197. {
  198. $this->setURL('#' . $tab, true);
  199. }
  200. /**
  201. * Set a custom column confirm message.
  202. *
  203. * @param string $column The name of the column to set the confirm for.
  204. * @param string $message The message to use as a confirmmessage.
  205. * @param string[optional] $custom Unused parameter.
  206. * @param string[optional] $title The title for the column.
  207. * @param string[optional] $uniqueId A unique ID that will be uses.
  208. */
  209. public function setColumnConfirm($column, $message, $custom = null, $title = null, $uniqueId = '[id]')
  210. {
  211. $column = (string) $column;
  212. $message = (string) $message;
  213. $custom = (string) $custom;
  214. $title = ($title !== null) ? (string) $title : null;
  215. $uniqueId = (string) $uniqueId;
  216. // has results
  217. if($this->source->getNumResults() > 0)
  218. {
  219. // column doesnt exist
  220. if(!isset($this->columns[$column])) throw new SpoonDataGridException('The column "' . $column . '" doesn\'t exist, therefore no confirm message/script can be added.');
  221. // exists
  222. else
  223. {
  224. // get URL
  225. $URL = $this->columns[$column]->getURL();
  226. // URL provided?
  227. if($URL != '')
  228. {
  229. // grab current value
  230. $currentValue = $this->columns[$column]->getValue();
  231. // reset URL
  232. $this->columns[$column]->setURL(null);
  233. // set the value
  234. $this->columns[$column]->setValue('<a href="' . $URL . '" class="">' . $currentValue . '</a>');
  235. }
  236. // generate id
  237. $id = 'confirm-' . (string) $uniqueId;
  238. // set title if there wasn't one provided
  239. if($title === null) $title = SpoonFilter::ucfirst(BL::lbl('Delete') . '?');
  240. // grab current value
  241. $value = $this->columns[$column]->getValue();
  242. // add class for confirmation
  243. if(substr_count($value, '<a') > 0)
  244. {
  245. if(substr_count($value, 'class="') > 0) $value = str_replace('class="', 'data-message-id="' . $id . '" class="askConfirmation ', $value);
  246. else $value = str_replace('<a ', '<a data-message-id="' . $id . '" class="askConfirmation" ', $value);
  247. }
  248. // is it a link?
  249. else throw new BackendException('The column doesn\'t contain a link.');
  250. // append message
  251. $value .= '<div id="' . $id . '" title="' . $title . '" style="display: none;"><p>' . $message . '</p></div>';
  252. // reset value
  253. $this->columns[$column]->setValue($value);
  254. }
  255. }
  256. }
  257. /**
  258. * Sets the column function to be executed for every row
  259. *
  260. * @param mixed $function The function to execute.
  261. * @param mixed[optional] $arguments The arguments to pass to the function.
  262. * @param mixed $columns The column wherin the result will be printed.
  263. * @param bool[optional] $overwrite Should the orginal value be overwritten.
  264. */
  265. public function setColumnFunction($function, $arguments = null, $columns, $overwrite = true)
  266. {
  267. // call the parent
  268. parent::setColumnFunction($function, $arguments, $columns, $overwrite);
  269. // redefine columns
  270. $columns = (array) $columns;
  271. $attributes = null;
  272. // based on the function we should prepopulate the attributes array
  273. switch($function)
  274. {
  275. // timeAgo
  276. case array('BackendDataGridFunctions', 'getTimeAgo'):
  277. $attributes = array('class' => 'date');
  278. $headerAttributes = array('class' => 'date');
  279. break;
  280. }
  281. // add attributes if they are given
  282. if(!empty($attributes))
  283. {
  284. // loop and set attributes
  285. foreach($columns as $column) $this->setColumnAttributes($column, $attributes);
  286. }
  287. // add attributes if they are given
  288. if(!empty($headerAttributes))
  289. {
  290. // loop and set attributes
  291. foreach($columns as $column) $this->setColumnHeaderAttributes($column, $attributes);
  292. }
  293. }
  294. /**
  295. * Sets the dropdown for the mass action
  296. *
  297. * @param SpoonFormDropdown $actionDropDown A dropdown-instance.
  298. */
  299. public function setMassAction(SpoonFormDropdown $actionDropDown)
  300. {
  301. // buid HTML
  302. $HTML = '<p><label for="' . $actionDropDown->getAttribute('id') . '">' . SpoonFilter::ucfirst(BL::lbl('WithSelected')) . '</label></p>
  303. <p>
  304. ' . $actionDropDown->parse() . '
  305. </p>
  306. <div class="buttonHolder">
  307. <a href="#" class="submitButton button">
  308. <span>' . SpoonFilter::ucfirst(BL::lbl('Execute')) . '</span>
  309. </a>
  310. </div>';
  311. // assign parsed html
  312. $this->tpl->assign('massAction', $HTML);
  313. }
  314. /**
  315. * Sets the checkboxes for the mass action
  316. *
  317. * @param string $column The name for the column that will hold the checkboxes.
  318. * @param string $value The value for the checkbox.
  319. * @param array[optional] $excludedValues The values that should be excluded.
  320. * @param array[optional] $checkedValues The values that should be checked.
  321. */
  322. public function setMassActionCheckboxes($column, $value, array $excludedValues = null, array $checkedValues = null)
  323. {
  324. // build label and value
  325. $label = '<span class="checkboxHolder"><input type="checkbox" name="toggleChecks" value="toggleChecks" /></span>';
  326. $value = '<input type="checkbox" name="id[]" value="' . $value . '" class="inputCheckbox" />';
  327. // add the column
  328. $this->addColumn($column, $label, $value);
  329. // set as first column
  330. $this->setColumnsSequence($column);
  331. // excluded IDs found
  332. if(!empty($excludedValues))
  333. {
  334. // fetch the datagrid attributes
  335. $attributes = $this->getAttributes();
  336. // set if needed
  337. if(!isset($attributes['id'])) $this->setAttributes(array('id' => 'table_' . time()));
  338. // fetch the datagrid attributes
  339. $attributes = $this->getAttributes();
  340. // build array
  341. $excludedData['id'] = $attributes['id'];
  342. $excludedData['JSON'] = json_encode($excludedValues);
  343. // assign the stack to the datagrid template
  344. $this->tpl->assign('excludedCheckboxesData', $excludedData);
  345. }
  346. // checked IDs found
  347. if(!empty($checkedValues))
  348. {
  349. // fetch the datagrid attributes
  350. $attributes = $this->getAttributes();
  351. // set if needed
  352. if(!isset($attributes['id'])) $this->setAttributes(array('id' => 'table_' . time()));
  353. // fetch the datagrid attributes
  354. $attributes = $this->getAttributes();
  355. // build array
  356. $checkedData['id'] = $attributes['id'];
  357. $checkedData['JSON'] = json_encode($checkedValues);
  358. // assign the stack to the datagrid template
  359. $this->tpl->assign('checkedCheckboxesData', $checkedData);
  360. }
  361. }
  362. /**
  363. * Sets all the default settings needed when attempting to use sorting
  364. */
  365. private function setSortingOptions()
  366. {
  367. // default URL
  368. if(Spoon::exists('url')) $this->setURL(BackendModel::createURLForAction(null, null, null, array('offset' => '[offset]', 'order' => '[order]', 'sort' => '[sort]'), false));
  369. // sorting labels
  370. $this->setSortingLabels(BL::lbl('SortAscending'), BL::lbl('SortedAscending'), BL::lbl('SortDescending'), BL::lbl('SortedDescending'));
  371. }
  372. /**
  373. * Set a tooltip
  374. *
  375. * @param string $column The name of the column to set the tooltop for.
  376. * @param string $message The key for the message (will be parsed through BL::msg).
  377. */
  378. public function setTooltip($column, $message)
  379. {
  380. // get the column
  381. $instance = $this->getColumn($column);
  382. // build the value for the tooltip
  383. $value = BL::msg($message);
  384. // reset the label
  385. $instance->setLabel($instance->getLabel() . '<abbr class="help">?</abbr><span class="tooltip hidden" style="display: none;">' . $value . '</span>');
  386. }
  387. /**
  388. * Sets an URL, optionally only appending the provided piece
  389. *
  390. * @param string $URL The URL to set.
  391. * @param bool[optional] $append Should it be appended to the existing URL.
  392. */
  393. public function setURL($URL, $append = false)
  394. {
  395. if($append) parent::setURL(parent::getURL() . $URL);
  396. else parent::setURL($URL);
  397. }
  398. }
  399. /**
  400. * This is our implementation of iSpoonDatagGridPaging
  401. *
  402. * @author Tijs Verkoyen <tijs@sumocoders.be>
  403. * @author Davy Hellemans <davy.hellemans@netlash.com>
  404. */
  405. class BackendDataGridPaging implements iSpoonDataGridPaging
  406. {
  407. /**
  408. * Builds & returns the pagination
  409. *
  410. * @param string $URL
  411. * @param int $offset
  412. * @param string $order The name of the column to sort on.
  413. * @param string $sort The sorting method, possible values are: asc, desc.
  414. * @param int $numResults
  415. * @param int $numPerPage The items per page.
  416. * @param bool[optional] $debug
  417. * @param string[optional] $compileDirectory
  418. * @return string
  419. */
  420. public static function getContent($URL, $offset, $order, $sort, $numResults, $numPerPage, $debug = true, $compileDirectory = null)
  421. {
  422. // if there is just one page we don't need paging
  423. if($numResults < $numPerPage) return '';
  424. // load template
  425. $tpl = new SpoonTemplate();
  426. // compile directory
  427. if($compileDirectory !== null) $tpl->setCompileDirectory($compileDirectory);
  428. else $tpl->setCompileDirectory(dirname(__FILE__));
  429. // force compiling
  430. $tpl->setForceCompile((bool) $debug);
  431. // init vars
  432. $pagination = null;
  433. $showFirstPages = false;
  434. $showLastPages = false;
  435. // current page
  436. $currentPage = ceil($offset / $numPerPage) + 1;
  437. // number of pages
  438. $numPages = ceil($numResults / $numPerPage);
  439. // populate count fields
  440. $pagination['num_pages'] = $numPages;
  441. $pagination['current_page'] = $currentPage;
  442. // as long as we are below page 7 we should show all pages starting from 1
  443. if($currentPage < 8)
  444. {
  445. // init vars
  446. $pagesStart = 1;
  447. $pagesEnd = ($numPages >= 7) ? 7 : $numPages;
  448. // show last pages
  449. if($numPages > 8) $showLastPages = true;
  450. }
  451. // as long as we are 7 pages from the end we should show all pages till the end
  452. elseif($currentPage > ($numPages - 7))
  453. {
  454. // init vars
  455. $pagesStart = ($numPages == 9) ? ($numPages - 6) : ($numPages - 7);
  456. $pagesEnd = $numPages;
  457. // show first pages
  458. $showFirstPages = true;
  459. }
  460. // page 7
  461. else
  462. {
  463. // init vars
  464. $pagesStart = $currentPage - 2;
  465. $pagesEnd = $currentPage + 2;
  466. $showFirstPages = true;
  467. $showLastPages = true;
  468. }
  469. // show previous
  470. if($currentPage > 1)
  471. {
  472. // set
  473. $pagination['show_previous'] = true;
  474. $pagination['previous_url'] = str_replace(array('[offset]', '[order]', '[sort]'), array(($offset - $numPerPage), $order, $sort), $URL);
  475. }
  476. // show first pages?
  477. if($showFirstPages)
  478. {
  479. // init var
  480. $pagesFirstStart = 1;
  481. $pagesFirstEnd = 2;
  482. // loop pages
  483. for($i = $pagesFirstStart; $i <= $pagesFirstEnd; $i++)
  484. {
  485. // add
  486. $pagination['first'][] = array('url' => str_replace(array('[offset]', '[order]', '[sort]'), array((($numPerPage * $i) - $numPerPage), $order, $sort), $URL),
  487. 'label' => $i);
  488. }
  489. }
  490. // build array
  491. for($i = $pagesStart; $i <= $pagesEnd; $i++)
  492. {
  493. // init var
  494. $current = ($i == $currentPage);
  495. // add
  496. $pagination['pages'][] = array('url' => str_replace(array('[offset]', '[order]', '[sort]'), array((($numPerPage * $i) - $numPerPage), $order, $sort), $URL),
  497. 'label' => $i, 'current' => $current);
  498. }
  499. // show last pages?
  500. if($showLastPages)
  501. {
  502. // init var
  503. $pagesLastStart = $numPages - 1;
  504. $pagesLastEnd = $numPages;
  505. // loop pages
  506. for($i = $pagesLastStart; $i <= $pagesLastEnd; $i++)
  507. {
  508. // add
  509. $pagination['last'][] = array('url' => str_replace(array('[offset]', '[order]', '[sort]'), array((($numPerPage * $i) - $numPerPage), $order, $sort), $URL),
  510. 'label' => $i);
  511. }
  512. }
  513. // show next
  514. if($currentPage < $numPages)
  515. {
  516. // set
  517. $pagination['show_next'] = true;
  518. $pagination['next_url'] = str_replace(array('[offset]', '[order]', '[sort]'), array(($offset + $numPerPage), $order, $sort), $URL);
  519. }
  520. // multiple pages
  521. $pagination['multiple_pages'] = ($numPages == 1) ? false : true;
  522. // assign pagination
  523. $tpl->assign('pagination', $pagination);
  524. // assign labels
  525. $tpl->assign('previousLabel', BL::lbl('PreviousPage'));
  526. $tpl->assign('nextLabel', BL::lbl('NextPage'));
  527. $tpl->assign('goToLabel', BL::lbl('GoToPage'));
  528. return $tpl->getContent(BACKEND_CORE_PATH . '/layout/templates/datagrid_paging.tpl');
  529. }
  530. }
  531. /**
  532. * A datagrid with an array as source
  533. *
  534. * @author Davy Hellemans <davy.hellemans@netlash.com>
  535. */
  536. class BackendDataGridArray extends BackendDataGrid
  537. {
  538. /**
  539. * @param array $array The data.
  540. */
  541. public function __construct(array $array)
  542. {
  543. $source = new SpoonDataGridSourceArray($array);
  544. parent::__construct($source);
  545. }
  546. }
  547. /**
  548. * A datagrid with a DB-connection as source
  549. *
  550. * @author Davy Hellemans <davy.hellemans@netlash.com>
  551. */
  552. class BackendDataGridDB extends BackendDataGrid
  553. {
  554. /**
  555. * @param string $query The query to retrieve the data.
  556. * @param array[optional] $parameters The parameters to be used inside the query.
  557. * @param string[optional] $resultsQuery The optional count query, used to calculate the number of results.
  558. * @param array[optional] $resultsParameters Theh parameters to be used inside the results query.
  559. */
  560. public function __construct($query, $parameters = array(), $resultsQuery = null, $resultsParameters = array())
  561. {
  562. // results query?
  563. $results = ($resultsQuery !== null) ? array($resultsQuery, $resultsParameters) : null;
  564. // create a new source-object
  565. $source = new SpoonDataGridSourceDB(BackendModel::getDB(), array($query, (array) $parameters), $results);
  566. parent::__construct($source);
  567. }
  568. }
  569. /**
  570. * A set of commonly used functions that will be applied on rows or columns
  571. *
  572. * @author Tijs Verkoyen <tijs@sumocoders.be>
  573. */
  574. class BackendDataGridFunctions
  575. {
  576. /**
  577. * Formats plain text as HTML, links will be detected, paragraphs will be inserted
  578. *
  579. * @param string $var The data to cleanup.
  580. * @return string
  581. */
  582. public static function cleanupPlainText($var)
  583. {
  584. $var = (string) $var;
  585. // detect links
  586. $var = SpoonFilter::replaceURLsWithAnchors($var);
  587. // replace newlines
  588. $var = str_replace("\r", '', $var);
  589. $var = preg_replace('/(?<!.)(\r\n|\r|\n){3,}$/m', '', $var);
  590. // replace br's into p's
  591. $var = '<p>' . str_replace("\n", '</p><p>', $var) . '</p>';
  592. // cleanup
  593. $var = str_replace("\n", '', $var);
  594. $var = str_replace('<p></p>', '', $var);
  595. return $var;
  596. }
  597. /**
  598. * Format a number as a float
  599. *
  600. * @param float $number The number to format.
  601. * @param int[optional] $decimals The number of decimals.
  602. * @return string
  603. */
  604. public static function formatFloat($number, $decimals = 2)
  605. {
  606. $number = (float) $number;
  607. $decimals = (int) $decimals;
  608. return number_format($number, $decimals, '.', ' ');
  609. }
  610. /**
  611. * Format a date according the users' settings
  612. *
  613. * @param int $timestamp The UNIX-timestamp to format as a human readable date.
  614. * @return string
  615. */
  616. public static function getDate($timestamp)
  617. {
  618. $timestamp = (int) $timestamp;
  619. // if invalid timestamp return an empty string
  620. if($timestamp <= 0) return '';
  621. // get user setting for long dates
  622. $format = BackendAuthentication::getUser()->getSetting('date_format');
  623. // format the date according the user his settings
  624. return SpoonDate::getDate($format, $timestamp, BL::getInterfaceLanguage());
  625. }
  626. /**
  627. * Format a date as a long representation according the users' settings
  628. *
  629. * @param int $timestamp The UNIX-timestamp to format as a human readable date.
  630. * @return string
  631. */
  632. public static function getLongDate($timestamp)
  633. {
  634. $timestamp = (int) $timestamp;
  635. // if invalid timestamp return an empty string
  636. if($timestamp <= 0) return '';
  637. // get user setting for long dates
  638. $format = BackendAuthentication::getUser()->getSetting('datetime_format');
  639. // format the date according the user his settings
  640. return SpoonDate::getDate($format, $timestamp, BL::getInterfaceLanguage());
  641. }
  642. /**
  643. * Format a time according the users' settings
  644. *
  645. * @param int $timestamp The UNIX-timestamp to format as a human readable time.
  646. * @return string
  647. */
  648. public static function getTime($timestamp)
  649. {
  650. $timestamp = (int) $timestamp;
  651. // if invalid timestamp return an empty string
  652. if($timestamp <= 0) return '';
  653. // get user setting for long dates
  654. $format = BackendAuthentication::getUser()->getSetting('time_format');
  655. // format the date according the user his settings
  656. return SpoonDate::getDate($format, $timestamp, BL::getInterfaceLanguage());
  657. }
  658. /**
  659. * Get time ago as a string for use in a datagrid
  660. *
  661. * @param int $timestamp The UNIX-timestamp to convert in a time-ago-string.
  662. * @return string
  663. */
  664. public static function getTimeAgo($timestamp)
  665. {
  666. $timestamp = (int) $timestamp;
  667. // get user setting for long dates
  668. $format = BackendAuthentication::getUser()->getSetting('datetime_format');
  669. // get the time ago as a string
  670. $timeAgo = SpoonDate::getTimeAgo($timestamp, BL::getInterfaceLanguage(), $format);
  671. return '<abbr title="' . SpoonDate::getDate($format, $timestamp, BL::getInterfaceLanguage()) . '">' . $timeAgo . '</abbr>';
  672. }
  673. /**
  674. * Get the HTML for a user to use in a datagrid
  675. *
  676. * @param int $id The Id of the user.
  677. * @return string
  678. */
  679. public static function getUser($id)
  680. {
  681. $id = (int) $id;
  682. // create user instance
  683. $user = new BackendUser($id);
  684. // get settings
  685. $avatar = $user->getSetting('avatar', 'no-avatar.gif');
  686. $nickname = $user->getSetting('nickname');
  687. $allowed = BackendAuthentication::isAllowedAction('edit', 'users');
  688. // build html
  689. $html = '<div class="dataGridAvatar">' . "\n";
  690. $html .= ' <div class="avatar av24">' . "\n";
  691. if($allowed) $html .= ' <a href="' . BackendModel::createURLForAction('edit', 'users') . '&amp;id=' . $id . '">' . "\n";
  692. $html .= ' <img src="' . FRONTEND_FILES_URL . '/backend_users/avatars/32x32/' . $avatar . '" width="24" height="24" alt="' . $nickname . '" />' . "\n";
  693. if($allowed) $html .= ' </a>' . "\n";
  694. $html .= ' </div>';
  695. $html .= ' <p><a href="' . BackendModel::createURLForAction('edit', 'users') . '&amp;id=' . $id . '">' . $nickname . '</a></p>' . "\n";
  696. $html .= '</div>';
  697. return $html;
  698. }
  699. /**
  700. * This will grey out certain rows from comon columns. These columns are:
  701. *
  702. * 'visible', 'hidden', 'active', 'published'
  703. *
  704. * @param string $type The type of column. This is given since some columns can have different meanings than others.
  705. * @param string $value
  706. * @param array $attributes
  707. */
  708. public static function greyOut($type, $value, array $attributes = array())
  709. {
  710. // the base class
  711. $grayedOutClass = 'grayedOut';
  712. switch($type)
  713. {
  714. case 'visible':
  715. case 'active':
  716. case 'published':
  717. if($value == 'N') return array('class' => $grayedOutClass);
  718. break;
  719. case 'hidden':
  720. if($value == 'Y') return array('class' => $grayedOutClass);
  721. break;
  722. }
  723. return array();
  724. }
  725. /**
  726. * Returns an image tag
  727. *
  728. * @param string $path The path to the image.
  729. * @param string $image The filename of the image.
  730. * @param string[optional] $title The title (will be used as alt).
  731. * @return string
  732. */
  733. public static function showImage($path, $image, $title = '')
  734. {
  735. $path = (string) $path;
  736. $image = (string) $image;
  737. $title = (string) $title;
  738. return '<img src="' . $path . '/' . $image . '" alt="' . $title . '" />';
  739. }
  740. /**
  741. * Truncate a string
  742. *
  743. * @param string[optional] $string The string to truncate.
  744. * @param int $length The maximumlength for the string.
  745. * @param bool[optional] $useHellip Should a hellip be appended?
  746. * @return string
  747. */
  748. public static function truncate($string = null, $length, $useHellip = true)
  749. {
  750. // remove special chars
  751. $string = htmlspecialchars_decode($string);
  752. // less characters
  753. if(mb_strlen($string) <= $length) return SpoonFilter::htmlspecialchars($string);
  754. // more characters
  755. else
  756. {
  757. // hellip is seen as 1 char, so remove it from length
  758. if($useHellip) $length = $length - 1;
  759. // get the amount of requested characters
  760. $string = mb_substr($string, 0, $length);
  761. // add hellip
  762. if($useHellip) $string .= 'รข&#x20AC;?';
  763. return SpoonFilter::htmlspecialchars($string);
  764. }
  765. }
  766. }