PageRenderTime 30ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/legacy/model/admin.php

http://github.com/joomla/joomla-platform
PHP | 1166 lines | 647 code | 196 blank | 323 comment | 83 complexity | ba7919b480b294de633165d4181d6c6c MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * @package Joomla.Legacy
  4. * @subpackage Model
  5. *
  6. * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. /**
  11. * Prototype admin model.
  12. *
  13. * @package Joomla.Legacy
  14. * @subpackage Model
  15. * @since 12.2
  16. * @deprecated 13.3
  17. */
  18. abstract class JModelAdmin extends JModelForm
  19. {
  20. /**
  21. * The prefix to use with controller messages.
  22. *
  23. * @var string
  24. * @since 12.2
  25. */
  26. protected $text_prefix = null;
  27. /**
  28. * The event to trigger after deleting the data.
  29. *
  30. * @var string
  31. * @since 12.2
  32. */
  33. protected $event_after_delete = null;
  34. /**
  35. * The event to trigger after saving the data.
  36. *
  37. * @var string
  38. * @since 12.2
  39. */
  40. protected $event_after_save = null;
  41. /**
  42. * The event to trigger before deleting the data.
  43. *
  44. * @var string
  45. * @since 12.2
  46. */
  47. protected $event_before_delete = null;
  48. /**
  49. * The event to trigger before saving the data.
  50. *
  51. * @var string
  52. * @since 12.2
  53. */
  54. protected $event_before_save = null;
  55. /**
  56. * The event to trigger after changing the published state of the data.
  57. *
  58. * @var string
  59. * @since 12.2
  60. */
  61. protected $event_change_state = null;
  62. /**
  63. * Constructor.
  64. *
  65. * @param array $config An optional associative array of configuration settings.
  66. *
  67. * @see JModelLegacy
  68. * @since 12.2
  69. */
  70. public function __construct($config = array())
  71. {
  72. parent::__construct($config);
  73. if (isset($config['event_after_delete']))
  74. {
  75. $this->event_after_delete = $config['event_after_delete'];
  76. }
  77. elseif (empty($this->event_after_delete))
  78. {
  79. $this->event_after_delete = 'onContentAfterDelete';
  80. }
  81. if (isset($config['event_after_save']))
  82. {
  83. $this->event_after_save = $config['event_after_save'];
  84. }
  85. elseif (empty($this->event_after_save))
  86. {
  87. $this->event_after_save = 'onContentAfterSave';
  88. }
  89. if (isset($config['event_before_delete']))
  90. {
  91. $this->event_before_delete = $config['event_before_delete'];
  92. }
  93. elseif (empty($this->event_before_delete))
  94. {
  95. $this->event_before_delete = 'onContentBeforeDelete';
  96. }
  97. if (isset($config['event_before_save']))
  98. {
  99. $this->event_before_save = $config['event_before_save'];
  100. }
  101. elseif (empty($this->event_before_save))
  102. {
  103. $this->event_before_save = 'onContentBeforeSave';
  104. }
  105. if (isset($config['event_change_state']))
  106. {
  107. $this->event_change_state = $config['event_change_state'];
  108. }
  109. elseif (empty($this->event_change_state))
  110. {
  111. $this->event_change_state = 'onContentChangeState';
  112. }
  113. // Guess the JText message prefix. Defaults to the option.
  114. if (isset($config['text_prefix']))
  115. {
  116. $this->text_prefix = strtoupper($config['text_prefix']);
  117. }
  118. elseif (empty($this->text_prefix))
  119. {
  120. $this->text_prefix = strtoupper($this->option);
  121. }
  122. }
  123. /**
  124. * Method to perform batch operations on an item or a set of items.
  125. *
  126. * @param array $commands An array of commands to perform.
  127. * @param array $pks An array of item ids.
  128. * @param array $contexts An array of item contexts.
  129. *
  130. * @return boolean Returns true on success, false on failure.
  131. *
  132. * @since 12.2
  133. */
  134. public function batch($commands, $pks, $contexts)
  135. {
  136. // Sanitize user ids.
  137. $pks = array_unique($pks);
  138. JArrayHelper::toInteger($pks);
  139. // Remove any values of zero.
  140. if (array_search(0, $pks, true))
  141. {
  142. unset($pks[array_search(0, $pks, true)]);
  143. }
  144. if (empty($pks))
  145. {
  146. $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED'));
  147. return false;
  148. }
  149. $done = false;
  150. if (!empty($commands['category_id']))
  151. {
  152. $cmd = JArrayHelper::getValue($commands, 'move_copy', 'c');
  153. if ($cmd == 'c')
  154. {
  155. $result = $this->batchCopy($commands['category_id'], $pks, $contexts);
  156. if (is_array($result))
  157. {
  158. $pks = $result;
  159. }
  160. else
  161. {
  162. return false;
  163. }
  164. }
  165. elseif ($cmd == 'm' && !$this->batchMove($commands['category_id'], $pks, $contexts))
  166. {
  167. return false;
  168. }
  169. $done = true;
  170. }
  171. if (!empty($commands['assetgroup_id']))
  172. {
  173. if (!$this->batchAccess($commands['assetgroup_id'], $pks, $contexts))
  174. {
  175. return false;
  176. }
  177. $done = true;
  178. }
  179. if (!empty($commands['language_id']))
  180. {
  181. if (!$this->batchLanguage($commands['language_id'], $pks, $contexts))
  182. {
  183. return false;
  184. }
  185. $done = true;
  186. }
  187. if (!$done)
  188. {
  189. $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION'));
  190. return false;
  191. }
  192. // Clear the cache
  193. $this->cleanCache();
  194. return true;
  195. }
  196. /**
  197. * Batch access level changes for a group of rows.
  198. *
  199. * @param integer $value The new value matching an Asset Group ID.
  200. * @param array $pks An array of row IDs.
  201. * @param array $contexts An array of item contexts.
  202. *
  203. * @return boolean True if successful, false otherwise and internal error is set.
  204. *
  205. * @since 12.2
  206. */
  207. protected function batchAccess($value, $pks, $contexts)
  208. {
  209. // Set the variables
  210. $user = JFactory::getUser();
  211. $table = $this->getTable();
  212. foreach ($pks as $pk)
  213. {
  214. if ($user->authorise('core.edit', $contexts[$pk]))
  215. {
  216. $table->reset();
  217. $table->load($pk);
  218. $table->access = (int) $value;
  219. if (!$table->store())
  220. {
  221. $this->setError($table->getError());
  222. return false;
  223. }
  224. }
  225. else
  226. {
  227. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));
  228. return false;
  229. }
  230. }
  231. // Clean the cache
  232. $this->cleanCache();
  233. return true;
  234. }
  235. /**
  236. * Batch copy items to a new category or current.
  237. *
  238. * @param integer $value The new category.
  239. * @param array $pks An array of row IDs.
  240. * @param array $contexts An array of item contexts.
  241. *
  242. * @return mixed An array of new IDs on success, boolean false on failure.
  243. *
  244. * @since 12.2
  245. */
  246. protected function batchCopy($value, $pks, $contexts)
  247. {
  248. $categoryId = (int) $value;
  249. $table = $this->getTable();
  250. $i = 0;
  251. // Check that the category exists
  252. if ($categoryId)
  253. {
  254. $categoryTable = JTable::getInstance('Category');
  255. if (!$categoryTable->load($categoryId))
  256. {
  257. if ($error = $categoryTable->getError())
  258. {
  259. // Fatal error
  260. $this->setError($error);
  261. return false;
  262. }
  263. else
  264. {
  265. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND'));
  266. return false;
  267. }
  268. }
  269. }
  270. if (empty($categoryId))
  271. {
  272. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND'));
  273. return false;
  274. }
  275. // Check that the user has create permission for the component
  276. $extension = JFactory::getApplication()->input->get('option', '');
  277. $user = JFactory::getUser();
  278. if (!$user->authorise('core.create', $extension . '.category.' . $categoryId))
  279. {
  280. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_CREATE'));
  281. return false;
  282. }
  283. // Parent exists so we let's proceed
  284. while (!empty($pks))
  285. {
  286. // Pop the first ID off the stack
  287. $pk = array_shift($pks);
  288. $table->reset();
  289. // Check that the row actually exists
  290. if (!$table->load($pk))
  291. {
  292. if ($error = $table->getError())
  293. {
  294. // Fatal error
  295. $this->setError($error);
  296. return false;
  297. }
  298. else
  299. {
  300. // Not fatal error
  301. $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk));
  302. continue;
  303. }
  304. }
  305. // Alter the title & alias
  306. $data = $this->generateNewTitle($categoryId, $table->alias, $table->title);
  307. $table->title = $data['0'];
  308. $table->alias = $data['1'];
  309. // Reset the ID because we are making a copy
  310. $table->id = 0;
  311. // New category ID
  312. $table->catid = $categoryId;
  313. // TODO: Deal with ordering?
  314. // $table->ordering = 1;
  315. // Check the row.
  316. if (!$table->check())
  317. {
  318. $this->setError($table->getError());
  319. return false;
  320. }
  321. // Store the row.
  322. if (!$table->store())
  323. {
  324. $this->setError($table->getError());
  325. return false;
  326. }
  327. // Get the new item ID
  328. $newId = $table->get('id');
  329. // Add the new ID to the array
  330. $newIds[$i] = $newId;
  331. $i++;
  332. }
  333. // Clean the cache
  334. $this->cleanCache();
  335. return $newIds;
  336. }
  337. /**
  338. * Batch language changes for a group of rows.
  339. *
  340. * @param string $value The new value matching a language.
  341. * @param array $pks An array of row IDs.
  342. * @param array $contexts An array of item contexts.
  343. *
  344. * @return boolean True if successful, false otherwise and internal error is set.
  345. *
  346. * @since 11.3
  347. */
  348. protected function batchLanguage($value, $pks, $contexts)
  349. {
  350. // Set the variables
  351. $user = JFactory::getUser();
  352. $table = $this->getTable();
  353. foreach ($pks as $pk)
  354. {
  355. if ($user->authorise('core.edit', $contexts[$pk]))
  356. {
  357. $table->reset();
  358. $table->load($pk);
  359. $table->language = $value;
  360. if (!$table->store())
  361. {
  362. $this->setError($table->getError());
  363. return false;
  364. }
  365. }
  366. else
  367. {
  368. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));
  369. return false;
  370. }
  371. }
  372. // Clean the cache
  373. $this->cleanCache();
  374. return true;
  375. }
  376. /**
  377. * Batch move items to a new category
  378. *
  379. * @param integer $value The new category ID.
  380. * @param array $pks An array of row IDs.
  381. * @param array $contexts An array of item contexts.
  382. *
  383. * @return boolean True if successful, false otherwise and internal error is set.
  384. *
  385. * @since 12.2
  386. */
  387. protected function batchMove($value, $pks, $contexts)
  388. {
  389. $categoryId = (int) $value;
  390. $table = $this->getTable();
  391. // Check that the category exists
  392. if ($categoryId)
  393. {
  394. $categoryTable = JTable::getInstance('Category');
  395. if (!$categoryTable->load($categoryId))
  396. {
  397. if ($error = $categoryTable->getError())
  398. {
  399. // Fatal error
  400. $this->setError($error);
  401. return false;
  402. }
  403. else
  404. {
  405. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND'));
  406. return false;
  407. }
  408. }
  409. }
  410. if (empty($categoryId))
  411. {
  412. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND'));
  413. return false;
  414. }
  415. // Check that user has create and edit permission for the component
  416. $extension = JFactory::getApplication()->input->get('option', '');
  417. $user = JFactory::getUser();
  418. if (!$user->authorise('core.create', $extension . '.category.' . $categoryId))
  419. {
  420. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_CREATE'));
  421. return false;
  422. }
  423. // Parent exists so we let's proceed
  424. foreach ($pks as $pk)
  425. {
  426. if (!$user->authorise('core.edit', $contexts[$pk]))
  427. {
  428. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));
  429. return false;
  430. }
  431. // Check that the row actually exists
  432. if (!$table->load($pk))
  433. {
  434. if ($error = $table->getError())
  435. {
  436. // Fatal error
  437. $this->setError($error);
  438. return false;
  439. }
  440. else
  441. {
  442. // Not fatal error
  443. $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk));
  444. continue;
  445. }
  446. }
  447. // Set the new category ID
  448. $table->catid = $categoryId;
  449. // Check the row.
  450. if (!$table->check())
  451. {
  452. $this->setError($table->getError());
  453. return false;
  454. }
  455. // Store the row.
  456. if (!$table->store())
  457. {
  458. $this->setError($table->getError());
  459. return false;
  460. }
  461. }
  462. // Clean the cache
  463. $this->cleanCache();
  464. return true;
  465. }
  466. /**
  467. * Method to test whether a record can be deleted.
  468. *
  469. * @param object $record A record object.
  470. *
  471. * @return boolean True if allowed to delete the record. Defaults to the permission for the component.
  472. *
  473. * @since 12.2
  474. */
  475. protected function canDelete($record)
  476. {
  477. $user = JFactory::getUser();
  478. return $user->authorise('core.delete', $this->option);
  479. }
  480. /**
  481. * Method to test whether a record can be deleted.
  482. *
  483. * @param object $record A record object.
  484. *
  485. * @return boolean True if allowed to change the state of the record. Defaults to the permission for the component.
  486. *
  487. * @since 12.2
  488. */
  489. protected function canEditState($record)
  490. {
  491. $user = JFactory::getUser();
  492. return $user->authorise('core.edit.state', $this->option);
  493. }
  494. /**
  495. * Method override to check-in a record or an array of record
  496. *
  497. * @param mixed $pks The ID of the primary key or an array of IDs
  498. *
  499. * @return mixed Boolean false if there is an error, otherwise the count of records checked in.
  500. *
  501. * @since 12.2
  502. */
  503. public function checkin($pks = array())
  504. {
  505. $pks = (array) $pks;
  506. $table = $this->getTable();
  507. $count = 0;
  508. if (empty($pks))
  509. {
  510. $pks = array((int) $this->getState($this->getName() . '.id'));
  511. }
  512. // Check in all items.
  513. foreach ($pks as $pk)
  514. {
  515. if ($table->load($pk))
  516. {
  517. if ($table->checked_out > 0)
  518. {
  519. if (!parent::checkin($pk))
  520. {
  521. return false;
  522. }
  523. $count++;
  524. }
  525. }
  526. else
  527. {
  528. $this->setError($table->getError());
  529. return false;
  530. }
  531. }
  532. return $count;
  533. }
  534. /**
  535. * Method override to check-out a record.
  536. *
  537. * @param integer $pk The ID of the primary key.
  538. *
  539. * @return boolean True if successful, false if an error occurs.
  540. *
  541. * @since 12.2
  542. */
  543. public function checkout($pk = null)
  544. {
  545. $pk = (!empty($pk)) ? $pk : (int) $this->getState($this->getName() . '.id');
  546. return parent::checkout($pk);
  547. }
  548. /**
  549. * Method to delete one or more records.
  550. *
  551. * @param array &$pks An array of record primary keys.
  552. *
  553. * @return boolean True if successful, false if an error occurs.
  554. *
  555. * @since 12.2
  556. */
  557. public function delete(&$pks)
  558. {
  559. $dispatcher = JEventDispatcher::getInstance();
  560. $pks = (array) $pks;
  561. $table = $this->getTable();
  562. // Include the content plugins for the on delete events.
  563. JPluginHelper::importPlugin('content');
  564. // Iterate the items to delete each one.
  565. foreach ($pks as $i => $pk)
  566. {
  567. if ($table->load($pk))
  568. {
  569. if ($this->canDelete($table))
  570. {
  571. $context = $this->option . '.' . $this->name;
  572. // Trigger the onContentBeforeDelete event.
  573. $result = $dispatcher->trigger($this->event_before_delete, array($context, $table));
  574. if (in_array(false, $result, true))
  575. {
  576. $this->setError($table->getError());
  577. return false;
  578. }
  579. if (!$table->delete($pk))
  580. {
  581. $this->setError($table->getError());
  582. return false;
  583. }
  584. // Trigger the onContentAfterDelete event.
  585. $dispatcher->trigger($this->event_after_delete, array($context, $table));
  586. }
  587. else
  588. {
  589. // Prune items that you can't change.
  590. unset($pks[$i]);
  591. $error = $this->getError();
  592. if ($error)
  593. {
  594. JLog::add($error, JLog::WARNING, 'jerror');
  595. return false;
  596. }
  597. else
  598. {
  599. JLog::add(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), JLog::WARNING, 'jerror');
  600. return false;
  601. }
  602. }
  603. }
  604. else
  605. {
  606. $this->setError($table->getError());
  607. return false;
  608. }
  609. }
  610. // Clear the component's cache
  611. $this->cleanCache();
  612. return true;
  613. }
  614. /**
  615. * Method to change the title & alias.
  616. *
  617. * @param integer $category_id The id of the category.
  618. * @param string $alias The alias.
  619. * @param string $title The title.
  620. *
  621. * @return array Contains the modified title and alias.
  622. *
  623. * @since 12.2
  624. */
  625. protected function generateNewTitle($category_id, $alias, $title)
  626. {
  627. // Alter the title & alias
  628. $table = $this->getTable();
  629. while ($table->load(array('alias' => $alias, 'catid' => $category_id)))
  630. {
  631. $title = JString::increment($title);
  632. $alias = JString::increment($alias, 'dash');
  633. }
  634. return array($title, $alias);
  635. }
  636. /**
  637. * Method to get a single record.
  638. *
  639. * @param integer $pk The id of the primary key.
  640. *
  641. * @return mixed Object on success, false on failure.
  642. *
  643. * @since 12.2
  644. */
  645. public function getItem($pk = null)
  646. {
  647. $pk = (!empty($pk)) ? $pk : (int) $this->getState($this->getName() . '.id');
  648. $table = $this->getTable();
  649. if ($pk > 0)
  650. {
  651. // Attempt to load the row.
  652. $return = $table->load($pk);
  653. // Check for a table object error.
  654. if ($return === false && $table->getError())
  655. {
  656. $this->setError($table->getError());
  657. return false;
  658. }
  659. }
  660. // Convert to the JObject before adding other data.
  661. $properties = $table->getProperties(1);
  662. $item = JArrayHelper::toObject($properties, 'JObject');
  663. if (property_exists($item, 'params'))
  664. {
  665. $registry = new JRegistry;
  666. $registry->loadString($item->params);
  667. $item->params = $registry->toArray();
  668. }
  669. return $item;
  670. }
  671. /**
  672. * A protected method to get a set of ordering conditions.
  673. *
  674. * @param JTable $table A JTable object.
  675. *
  676. * @return array An array of conditions to add to ordering queries.
  677. *
  678. * @since 12.2
  679. */
  680. protected function getReorderConditions($table)
  681. {
  682. return array();
  683. }
  684. /**
  685. * Stock method to auto-populate the model state.
  686. *
  687. * @return void
  688. *
  689. * @since 12.2
  690. */
  691. protected function populateState()
  692. {
  693. $table = $this->getTable();
  694. $key = $table->getKeyName();
  695. // Get the pk of the record from the request.
  696. $pk = JFactory::getApplication()->input->getInt($key);
  697. $this->setState($this->getName() . '.id', $pk);
  698. // Load the parameters.
  699. $value = JComponentHelper::getParams($this->option);
  700. $this->setState('params', $value);
  701. }
  702. /**
  703. * Prepare and sanitise the table data prior to saving.
  704. *
  705. * @param JTable $table A reference to a JTable object.
  706. *
  707. * @return void
  708. *
  709. * @since 12.2
  710. */
  711. protected function prepareTable(JTable $table)
  712. {
  713. // Derived class will provide its own implementation if required.
  714. }
  715. /**
  716. * Method to change the published state of one or more records.
  717. *
  718. * @param array &$pks A list of the primary keys to change.
  719. * @param integer $value The value of the published state.
  720. *
  721. * @return boolean True on success.
  722. *
  723. * @since 12.2
  724. */
  725. public function publish(&$pks, $value = 1)
  726. {
  727. $dispatcher = JEventDispatcher::getInstance();
  728. $user = JFactory::getUser();
  729. $table = $this->getTable();
  730. $pks = (array) $pks;
  731. // Ensure that we do not receive an empty array
  732. if (empty($pks))
  733. {
  734. return true;
  735. }
  736. // Include the content plugins for the change of state event.
  737. JPluginHelper::importPlugin('content');
  738. // Access checks.
  739. foreach ($pks as $i => $pk)
  740. {
  741. $table->reset();
  742. if ($table->load($pk))
  743. {
  744. if (!$this->canEditState($table))
  745. {
  746. // Prune items that you can't change.
  747. unset($pks[$i]);
  748. JLog::add(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), JLog::WARNING, 'jerror');
  749. return false;
  750. }
  751. }
  752. }
  753. // Attempt to change the state of the records.
  754. if (!$table->publish($pks, $value, $user->get('id')))
  755. {
  756. $this->setError($table->getError());
  757. return false;
  758. }
  759. $context = $this->option . '.' . $this->name;
  760. // Trigger the onContentChangeState event.
  761. $result = $dispatcher->trigger($this->event_change_state, array($context, $pks, $value));
  762. if (in_array(false, $result, true))
  763. {
  764. $this->setError($table->getError());
  765. return false;
  766. }
  767. // Clear the component's cache
  768. $this->cleanCache();
  769. return true;
  770. }
  771. /**
  772. * Method to adjust the ordering of a row.
  773. *
  774. * Returns NULL if the user did not have edit
  775. * privileges for any of the selected primary keys.
  776. *
  777. * @param integer $pks The ID of the primary key to move.
  778. * @param integer $delta Increment, usually +1 or -1
  779. *
  780. * @return mixed False on failure or error, true on success, null if the $pk is empty (no items selected).
  781. *
  782. * @since 12.2
  783. */
  784. public function reorder($pks, $delta = 0)
  785. {
  786. $table = $this->getTable();
  787. $pks = (array) $pks;
  788. $result = true;
  789. $allowed = true;
  790. foreach ($pks as $i => $pk)
  791. {
  792. $table->reset();
  793. if ($table->load($pk) && $this->checkout($pk))
  794. {
  795. // Access checks.
  796. if (!$this->canEditState($table))
  797. {
  798. // Prune items that you can't change.
  799. unset($pks[$i]);
  800. $this->checkin($pk);
  801. JLog::add(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), JLog::WARNING, 'jerror');
  802. $allowed = false;
  803. continue;
  804. }
  805. $where = array();
  806. $where = $this->getReorderConditions($table);
  807. if (!$table->move($delta, $where))
  808. {
  809. $this->setError($table->getError());
  810. unset($pks[$i]);
  811. $result = false;
  812. }
  813. $this->checkin($pk);
  814. }
  815. else
  816. {
  817. $this->setError($table->getError());
  818. unset($pks[$i]);
  819. $result = false;
  820. }
  821. }
  822. if ($allowed === false && empty($pks))
  823. {
  824. $result = null;
  825. }
  826. // Clear the component's cache
  827. if ($result == true)
  828. {
  829. $this->cleanCache();
  830. }
  831. return $result;
  832. }
  833. /**
  834. * Method to save the form data.
  835. *
  836. * @param array $data The form data.
  837. *
  838. * @return boolean True on success, False on error.
  839. *
  840. * @since 12.2
  841. */
  842. public function save($data)
  843. {
  844. $dispatcher = JEventDispatcher::getInstance();
  845. $table = $this->getTable();
  846. $key = $table->getKeyName();
  847. $pk = (!empty($data[$key])) ? $data[$key] : (int) $this->getState($this->getName() . '.id');
  848. $isNew = true;
  849. // Include the content plugins for the on save events.
  850. JPluginHelper::importPlugin('content');
  851. // Allow an exception to be thrown.
  852. try
  853. {
  854. // Load the row if saving an existing record.
  855. if ($pk > 0)
  856. {
  857. $table->load($pk);
  858. $isNew = false;
  859. }
  860. // Bind the data.
  861. if (!$table->bind($data))
  862. {
  863. $this->setError($table->getError());
  864. return false;
  865. }
  866. // Prepare the row for saving
  867. $this->prepareTable($table);
  868. // Check the data.
  869. if (!$table->check())
  870. {
  871. $this->setError($table->getError());
  872. return false;
  873. }
  874. // Trigger the onContentBeforeSave event.
  875. $result = $dispatcher->trigger($this->event_before_save, array($this->option . '.' . $this->name, $table, $isNew));
  876. if (in_array(false, $result, true))
  877. {
  878. $this->setError($table->getError());
  879. return false;
  880. }
  881. // Store the data.
  882. if (!$table->store())
  883. {
  884. $this->setError($table->getError());
  885. return false;
  886. }
  887. // Clean the cache.
  888. $this->cleanCache();
  889. // Trigger the onContentAfterSave event.
  890. $dispatcher->trigger($this->event_after_save, array($this->option . '.' . $this->name, $table, $isNew));
  891. }
  892. catch (Exception $e)
  893. {
  894. $this->setError($e->getMessage());
  895. return false;
  896. }
  897. $pkName = $table->getKeyName();
  898. if (isset($table->$pkName))
  899. {
  900. $this->setState($this->getName() . '.id', $table->$pkName);
  901. }
  902. $this->setState($this->getName() . '.new', $isNew);
  903. return true;
  904. }
  905. /**
  906. * Saves the manually set order of records.
  907. *
  908. * @param array $pks An array of primary key ids.
  909. * @param integer $order +1 or -1
  910. *
  911. * @return mixed
  912. *
  913. * @since 12.2
  914. */
  915. public function saveorder($pks = null, $order = null)
  916. {
  917. $table = $this->getTable();
  918. $conditions = array();
  919. if (empty($pks))
  920. {
  921. return JError::raiseWarning(500, JText::_($this->text_prefix . '_ERROR_NO_ITEMS_SELECTED'));
  922. }
  923. // Update ordering values
  924. foreach ($pks as $i => $pk)
  925. {
  926. $table->load((int) $pk);
  927. // Access checks.
  928. if (!$this->canEditState($table))
  929. {
  930. // Prune items that you can't change.
  931. unset($pks[$i]);
  932. JLog::add(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), JLog::WARNING, 'jerror');
  933. }
  934. elseif ($table->ordering != $order[$i])
  935. {
  936. $table->ordering = $order[$i];
  937. if (!$table->store())
  938. {
  939. $this->setError($table->getError());
  940. return false;
  941. }
  942. // Remember to reorder within position and client_id
  943. $condition = $this->getReorderConditions($table);
  944. $found = false;
  945. foreach ($conditions as $cond)
  946. {
  947. if ($cond[1] == $condition)
  948. {
  949. $found = true;
  950. break;
  951. }
  952. }
  953. if (!$found)
  954. {
  955. $key = $table->getKeyName();
  956. $conditions[] = array($table->$key, $condition);
  957. }
  958. }
  959. }
  960. // Execute reorder for each category.
  961. foreach ($conditions as $cond)
  962. {
  963. $table->load($cond[0]);
  964. $table->reorder($cond[1]);
  965. }
  966. // Clear the component's cache
  967. $this->cleanCache();
  968. return true;
  969. }
  970. }