PageRenderTime 56ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/administrator/components/com_modules/models/module.php

https://github.com/J2MTecnologia/joomla-3.x
PHP | 1118 lines | 658 code | 159 blank | 301 comment | 77 complexity | fdeee6979b5232a3e5df1288add30c4d MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * @package Joomla.Administrator
  4. * @subpackage com_modules
  5. *
  6. * @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE.txt
  8. */
  9. defined('_JEXEC') or die;
  10. /**
  11. * Module model.
  12. *
  13. * @package Joomla.Administrator
  14. * @subpackage com_modules
  15. * @since 1.6
  16. */
  17. class ModulesModelModule extends JModelAdmin
  18. {
  19. /**
  20. * @var string The prefix to use with controller messages.
  21. * @since 1.6
  22. */
  23. protected $text_prefix = 'COM_MODULES';
  24. /**
  25. * @var string The help screen key for the module.
  26. * @since 1.6
  27. */
  28. protected $helpKey = 'JHELP_EXTENSIONS_MODULE_MANAGER_EDIT';
  29. /**
  30. * @var string The help screen base URL for the module.
  31. * @since 1.6
  32. */
  33. protected $helpURL;
  34. /**
  35. * Method to auto-populate the model state.
  36. *
  37. * Note. Calling getState in this method will result in recursion.
  38. *
  39. * @return void
  40. *
  41. * @since 1.6
  42. */
  43. protected function populateState()
  44. {
  45. $app = JFactory::getApplication('administrator');
  46. // Load the User state.
  47. $pk = $app->input->getInt('id');
  48. if (!$pk)
  49. {
  50. if ($extensionId = (int) $app->getUserState('com_modules.add.module.extension_id'))
  51. {
  52. $this->setState('extension.id', $extensionId);
  53. }
  54. }
  55. $this->setState('module.id', $pk);
  56. // Load the parameters.
  57. $params = JComponentHelper::getParams('com_modules');
  58. $this->setState('params', $params);
  59. }
  60. /**
  61. * Method to perform batch operations on a set of modules.
  62. *
  63. * @param array $commands An array of commands to perform.
  64. * @param array $pks An array of item ids.
  65. * @param array $contexts An array of item contexts.
  66. *
  67. * @return boolean Returns true on success, false on failure.
  68. *
  69. * @since 1.7
  70. */
  71. public function batch($commands, $pks, $contexts)
  72. {
  73. // Sanitize user ids.
  74. $pks = array_unique($pks);
  75. JArrayHelper::toInteger($pks);
  76. // Remove any values of zero.
  77. if (array_search(0, $pks, true))
  78. {
  79. unset($pks[array_search(0, $pks, true)]);
  80. }
  81. if (empty($pks))
  82. {
  83. $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED'));
  84. return false;
  85. }
  86. $done = false;
  87. if (!empty($commands['position_id']))
  88. {
  89. $cmd = JArrayHelper::getValue($commands, 'move_copy', 'c');
  90. if (!empty($commands['position_id']))
  91. {
  92. if ($cmd == 'c')
  93. {
  94. $result = $this->batchCopy($commands['position_id'], $pks, $contexts);
  95. if (is_array($result))
  96. {
  97. $pks = $result;
  98. }
  99. else
  100. {
  101. return false;
  102. }
  103. }
  104. elseif ($cmd == 'm' && !$this->batchMove($commands['position_id'], $pks, $contexts))
  105. {
  106. return false;
  107. }
  108. $done = true;
  109. }
  110. }
  111. if (!empty($commands['assetgroup_id']))
  112. {
  113. if (!$this->batchAccess($commands['assetgroup_id'], $pks, $contexts))
  114. {
  115. return false;
  116. }
  117. $done = true;
  118. }
  119. if (!empty($commands['language_id']))
  120. {
  121. if (!$this->batchLanguage($commands['language_id'], $pks, $contexts))
  122. {
  123. return false;
  124. }
  125. $done = true;
  126. }
  127. if (!$done)
  128. {
  129. $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION'));
  130. return false;
  131. }
  132. // Clear the cache
  133. $this->cleanCache();
  134. return true;
  135. }
  136. /**
  137. * Batch copy modules to a new position or current.
  138. *
  139. * @param integer $value The new value matching a module position.
  140. * @param array $pks An array of row IDs.
  141. * @param array $contexts An array of item contexts.
  142. *
  143. * @return boolean True if successful, false otherwise and internal error is set.
  144. *
  145. * @since 2.5
  146. */
  147. protected function batchCopy($value, $pks, $contexts)
  148. {
  149. // Set the variables
  150. $user = JFactory::getUser();
  151. $table = $this->getTable();
  152. $newIds = array();
  153. $i = 0;
  154. foreach ($pks as $pk)
  155. {
  156. if ($user->authorise('core.create', 'com_modules'))
  157. {
  158. $table->reset();
  159. $table->load($pk);
  160. // Set the new position
  161. if ($value == 'noposition')
  162. {
  163. $position = '';
  164. }
  165. elseif ($value == 'nochange')
  166. {
  167. $position = $table->position;
  168. }
  169. else
  170. {
  171. $position = $value;
  172. }
  173. $table->position = $position;
  174. // Alter the title if necessary
  175. $data = $this->generateNewTitle(0, $table->title, $table->position);
  176. $table->title = $data['0'];
  177. // Reset the ID because we are making a copy
  178. $table->id = 0;
  179. // Unpublish the new module
  180. $table->published = 0;
  181. if (!$table->store())
  182. {
  183. $this->setError($table->getError());
  184. return false;
  185. }
  186. // Get the new item ID
  187. $newId = $table->get('id');
  188. // Add the new ID to the array
  189. $newIds[$i] = $newId;
  190. $i++;
  191. // Now we need to handle the module assignments
  192. $db = $this->getDbo();
  193. $query = $db->getQuery(true)
  194. ->select($db->quoteName('menuid'))
  195. ->from($db->quoteName('#__modules_menu'))
  196. ->where($db->quoteName('moduleid') . ' = ' . $pk);
  197. $db->setQuery($query);
  198. $menus = $db->loadColumn();
  199. // Insert the new records into the table
  200. foreach ($menus as $menu)
  201. {
  202. $query->clear()
  203. ->insert($db->quoteName('#__modules_menu'))
  204. ->columns(array($db->quoteName('moduleid'), $db->quoteName('menuid')))
  205. ->values($newId . ', ' . $menu);
  206. $db->setQuery($query);
  207. $db->execute();
  208. }
  209. }
  210. else
  211. {
  212. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_CREATE'));
  213. return false;
  214. }
  215. }
  216. // Clean the cache
  217. $this->cleanCache();
  218. return $newIds;
  219. }
  220. /**
  221. * Batch move modules to a new position or current.
  222. *
  223. * @param integer $value The new value matching a module position.
  224. * @param array $pks An array of row IDs.
  225. * @param array $contexts An array of item contexts.
  226. *
  227. * @return boolean True if successful, false otherwise and internal error is set.
  228. *
  229. * @since 2.5
  230. */
  231. protected function batchMove($value, $pks, $contexts)
  232. {
  233. // Set the variables
  234. $user = JFactory::getUser();
  235. $table = $this->getTable();
  236. foreach ($pks as $pk)
  237. {
  238. if ($user->authorise('core.edit', 'com_modules'))
  239. {
  240. $table->reset();
  241. $table->load($pk);
  242. // Set the new position
  243. if ($value == 'noposition')
  244. {
  245. $position = '';
  246. }
  247. elseif ($value == 'nochange')
  248. {
  249. $position = $table->position;
  250. }
  251. else
  252. {
  253. $position = $value;
  254. }
  255. $table->position = $position;
  256. // Alter the title if necessary
  257. $data = $this->generateNewTitle(0, $table->title, $table->position);
  258. $table->title = $data['0'];
  259. // Unpublish the moved module
  260. $table->published = 0;
  261. if (!$table->store())
  262. {
  263. $this->setError($table->getError());
  264. return false;
  265. }
  266. }
  267. else
  268. {
  269. $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));
  270. return false;
  271. }
  272. }
  273. // Clean the cache
  274. $this->cleanCache();
  275. return true;
  276. }
  277. /**
  278. * Method to test whether a record can have its state edited.
  279. *
  280. * @param object $record A record object.
  281. *
  282. * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component.
  283. * @since 3.2
  284. */
  285. protected function canEditState($record)
  286. {
  287. $user = JFactory::getUser();
  288. // Check for existing module.
  289. if (!empty($record->id))
  290. {
  291. return $user->authorise('core.edit.state', 'com_modules.module.' . (int) $record->id);
  292. }
  293. // Default to component settings if module not known.
  294. else
  295. {
  296. return parent::canEditState('com_modules');
  297. }
  298. }
  299. /**
  300. * Method to delete rows.
  301. *
  302. * @param array &$pks An array of item ids.
  303. *
  304. * @return boolean Returns true on success, false on failure.
  305. *
  306. * @since 1.6
  307. * @throws Exception
  308. */
  309. public function delete(&$pks)
  310. {
  311. $pks = (array) $pks;
  312. $user = JFactory::getUser();
  313. $table = $this->getTable();
  314. // Iterate the items to delete each one.
  315. foreach ($pks as $pk)
  316. {
  317. if ($table->load($pk))
  318. {
  319. // Access checks.
  320. if (!$user->authorise('core.delete', 'com_modules.module.'.(int) $pk) || $table->published != -2)
  321. {
  322. JError::raiseWarning(403, JText::_('JERROR_CORE_DELETE_NOT_PERMITTED'));
  323. return;
  324. }
  325. if (!$table->delete($pk))
  326. {
  327. throw new Exception($table->getError());
  328. }
  329. else
  330. {
  331. // Delete the menu assignments
  332. $db = $this->getDbo();
  333. $query = $db->getQuery(true)
  334. ->delete('#__modules_menu')
  335. ->where('moduleid=' . (int) $pk);
  336. $db->setQuery($query);
  337. $db->execute();
  338. }
  339. // Clear module cache
  340. parent::cleanCache($table->module, $table->client_id);
  341. }
  342. else
  343. {
  344. throw new Exception($table->getError());
  345. }
  346. }
  347. // Clear modules cache
  348. $this->cleanCache();
  349. return true;
  350. }
  351. /**
  352. * Method to duplicate modules.
  353. *
  354. * @param array &$pks An array of primary key IDs.
  355. *
  356. * @return boolean True if successful.
  357. *
  358. * @since 1.6
  359. * @throws Exception
  360. */
  361. public function duplicate(&$pks)
  362. {
  363. $user = JFactory::getUser();
  364. $db = $this->getDbo();
  365. // Access checks.
  366. if (!$user->authorise('core.create', 'com_modules'))
  367. {
  368. throw new Exception(JText::_('JERROR_CORE_CREATE_NOT_PERMITTED'));
  369. }
  370. $table = $this->getTable();
  371. foreach ($pks as $pk)
  372. {
  373. if ($table->load($pk, true))
  374. {
  375. // Reset the id to create a new record.
  376. $table->id = 0;
  377. // Alter the title.
  378. $m = null;
  379. if (preg_match('#\((\d+)\)$#', $table->title, $m))
  380. {
  381. $table->title = preg_replace('#\(\d+\)$#', '(' . ($m[1] + 1) . ')', $table->title);
  382. }
  383. else
  384. {
  385. $table->title .= ' (2)';
  386. }
  387. // Unpublish duplicate module
  388. $table->published = 0;
  389. if (!$table->check() || !$table->store())
  390. {
  391. throw new Exception($table->getError());
  392. }
  393. $query = $db->getQuery(true)
  394. ->select($db->quoteName('menuid'))
  395. ->from($db->quoteName('#__modules_menu'))
  396. ->where($db->quoteName('moduleid') . ' = ' . (int) $pk);
  397. $this->_db->setQuery($query);
  398. $rows = $this->_db->loadColumn();
  399. foreach ($rows as $menuid)
  400. {
  401. $tuples[] = (int) $table->id . ',' . (int) $menuid;
  402. }
  403. }
  404. else
  405. {
  406. throw new Exception($table->getError());
  407. }
  408. }
  409. if (!empty($tuples))
  410. {
  411. // Module-Menu Mapping: Do it in one query
  412. $query = $db->getQuery(true)
  413. ->insert($db->quoteName('#__modules_menu'))
  414. ->columns($db->quoteName(array('moduleid', 'menuid')))
  415. ->values($tuples);
  416. $this->_db->setQuery($query);
  417. try
  418. {
  419. $this->_db->execute();
  420. }
  421. catch (RuntimeException $e)
  422. {
  423. return JError::raiseWarning(500, $e->getMessage());
  424. }
  425. }
  426. // Clear modules cache
  427. $this->cleanCache();
  428. return true;
  429. }
  430. /**
  431. * Method to change the title.
  432. *
  433. * @param integer $category_id The id of the category. Not used here.
  434. * @param string $title The title.
  435. * @param string $position The position.
  436. *
  437. * @return array Contains the modified title.
  438. *
  439. * @since 2.5
  440. */
  441. protected function generateNewTitle($category_id, $title, $position)
  442. {
  443. // Alter the title & alias
  444. $table = $this->getTable();
  445. while ($table->load(array('position' => $position, 'title' => $title)))
  446. {
  447. $title = JString::increment($title);
  448. }
  449. return array($title);
  450. }
  451. /**
  452. * Method to get the client object
  453. *
  454. * @return void
  455. *
  456. * @since 1.6
  457. */
  458. public function &getClient()
  459. {
  460. return $this->_client;
  461. }
  462. /**
  463. * Method to get the record form.
  464. *
  465. * @param array $data Data for the form.
  466. * @param boolean $loadData True if the form is to load its own data (default case), false if not.
  467. *
  468. * @return JForm A JForm object on success, false on failure
  469. *
  470. * @since 1.6
  471. */
  472. public function getForm($data = array(), $loadData = true)
  473. {
  474. // The folder and element vars are passed when saving the form.
  475. if (empty($data))
  476. {
  477. $item = $this->getItem();
  478. $clientId = $item->client_id;
  479. $module = $item->module;
  480. $id = $item->id;
  481. }
  482. else
  483. {
  484. $clientId = JArrayHelper::getValue($data, 'client_id');
  485. $module = JArrayHelper::getValue($data, 'module');
  486. $id = JArrayHelper::getValue($data, 'id');
  487. }
  488. // These variables are used to add data from the plugin XML files.
  489. $this->setState('item.client_id', $clientId);
  490. $this->setState('item.module', $module);
  491. // Get the form.
  492. $form = $this->loadForm('com_modules.module', 'module', array('control' => 'jform', 'load_data' => $loadData));
  493. if (empty($form))
  494. {
  495. return false;
  496. }
  497. $form->setFieldAttribute('position', 'client', $this->getState('item.client_id') == 0 ? 'site' : 'administrator');
  498. $user = JFactory::getUser();
  499. // Check for existing module
  500. // Modify the form based on Edit State access controls.
  501. if ($id != 0 && (!$user->authorise('core.edit.state', 'com_modules.module.'.(int) $id))
  502. || ($id == 0 && !$user->authorise('core.edit.state', 'com_modules'))
  503. )
  504. {
  505. // Disable fields for display.
  506. $form->setFieldAttribute('ordering', 'disabled', 'true');
  507. $form->setFieldAttribute('published', 'disabled', 'true');
  508. $form->setFieldAttribute('publish_up', 'disabled', 'true');
  509. $form->setFieldAttribute('publish_down', 'disabled', 'true');
  510. // Disable fields while saving.
  511. // The controller has already verified this is a record you can edit.
  512. $form->setFieldAttribute('ordering', 'filter', 'unset');
  513. $form->setFieldAttribute('published', 'filter', 'unset');
  514. $form->setFieldAttribute('publish_up', 'filter', 'unset');
  515. $form->setFieldAttribute('publish_down', 'filter', 'unset');
  516. }
  517. return $form;
  518. }
  519. /**
  520. * Method to get the data that should be injected in the form.
  521. *
  522. * @return mixed The data for the form.
  523. *
  524. * @since 1.6
  525. */
  526. protected function loadFormData()
  527. {
  528. $app = JFactory::getApplication();
  529. // Check the session for previously entered form data.
  530. $data = JFactory::getApplication()->getUserState('com_modules.edit.module.data', array());
  531. if (empty($data))
  532. {
  533. $data = $this->getItem();
  534. // This allows us to inject parameter settings into a new module.
  535. $params = $app->getUserState('com_modules.add.module.params');
  536. if (is_array($params))
  537. {
  538. $data->set('params', $params);
  539. }
  540. }
  541. $this->preprocessData('com_modules.module', $data);
  542. return $data;
  543. }
  544. /**
  545. * Method to get a single record.
  546. *
  547. * @param integer $pk The id of the primary key.
  548. *
  549. * @return mixed Object on success, false on failure.
  550. *
  551. * @since 1.6
  552. */
  553. public function getItem($pk = null)
  554. {
  555. $pk = (!empty($pk)) ? (int) $pk : (int) $this->getState('module.id');
  556. $db = $this->getDbo();
  557. if (!isset($this->_cache[$pk]))
  558. {
  559. $false = false;
  560. // Get a row instance.
  561. $table = $this->getTable();
  562. // Attempt to load the row.
  563. $return = $table->load($pk);
  564. // Check for a table object error.
  565. if ($return === false && $error = $table->getError())
  566. {
  567. $this->setError($error);
  568. return $false;
  569. }
  570. // Check if we are creating a new extension.
  571. if (empty($pk))
  572. {
  573. if ($extensionId = (int) $this->getState('extension.id'))
  574. {
  575. $query = $db->getQuery(true)
  576. ->select('element, client_id')
  577. ->from('#__extensions')
  578. ->where('extension_id = ' . $extensionId)
  579. ->where('type = ' . $db->quote('module'));
  580. $db->setQuery($query);
  581. try
  582. {
  583. $extension = $db->loadObject();
  584. }
  585. catch (RuntimeException $e)
  586. {
  587. $this->setError($e->getMessage);
  588. return false;
  589. }
  590. if (empty($extension))
  591. {
  592. $this->setError('COM_MODULES_ERROR_CANNOT_FIND_MODULE');
  593. return false;
  594. }
  595. // Extension found, prime some module values.
  596. $table->module = $extension->element;
  597. $table->client_id = $extension->client_id;
  598. }
  599. else
  600. {
  601. $app = JFactory::getApplication();
  602. $app->redirect(JRoute::_('index.php?option=com_modules&view=modules', false));
  603. return false;
  604. }
  605. }
  606. // Convert to the JObject before adding other data.
  607. $properties = $table->getProperties(1);
  608. $this->_cache[$pk] = JArrayHelper::toObject($properties, 'JObject');
  609. // Convert the params field to an array.
  610. $registry = new JRegistry;
  611. $registry->loadString($table->params);
  612. $this->_cache[$pk]->params = $registry->toArray();
  613. // Determine the page assignment mode.
  614. $query = $db->getQuery(true)
  615. ->select($db->quoteName('menuid'))
  616. ->from($db->quoteName('#__modules_menu'))
  617. ->where($db->quoteName('moduleid') . ' = ' . (int) $pk);
  618. $db->setQuery($query);
  619. $assigned = $db->loadColumn();
  620. if (empty($pk))
  621. {
  622. // If this is a new module, assign to all pages.
  623. $assignment = 0;
  624. }
  625. elseif (empty($assigned))
  626. {
  627. // For an existing module it is assigned to none.
  628. $assignment = '-';
  629. }
  630. else
  631. {
  632. if ($assigned[0] > 0)
  633. {
  634. $assignment = 1;
  635. }
  636. elseif ($assigned[0] < 0)
  637. {
  638. $assignment = -1;
  639. }
  640. else
  641. {
  642. $assignment = 0;
  643. }
  644. }
  645. $this->_cache[$pk]->assigned = $assigned;
  646. $this->_cache[$pk]->assignment = $assignment;
  647. // Get the module XML.
  648. $client = JApplicationHelper::getClientInfo($table->client_id);
  649. $path = JPath::clean($client->path . '/modules/' . $table->module . '/' . $table->module . '.xml');
  650. if (file_exists($path))
  651. {
  652. $this->_cache[$pk]->xml = simplexml_load_file($path);
  653. }
  654. else
  655. {
  656. $this->_cache[$pk]->xml = null;
  657. }
  658. }
  659. return $this->_cache[$pk];
  660. }
  661. /**
  662. * Get the necessary data to load an item help screen.
  663. *
  664. * @return object An object with key, url, and local properties for loading the item help screen.
  665. *
  666. * @since 1.6
  667. */
  668. public function getHelp()
  669. {
  670. return (object) array('key' => $this->helpKey, 'url' => $this->helpURL);
  671. }
  672. /**
  673. * Returns a reference to the a Table object, always creating it.
  674. *
  675. * @param string $type The table type to instantiate
  676. * @param string $prefix A prefix for the table class name. Optional.
  677. * @param array $config Configuration array for model. Optional.
  678. *
  679. * @return JTable A database object
  680. *
  681. * @since 1.6
  682. */
  683. public function getTable($type = 'Module', $prefix = 'JTable', $config = array())
  684. {
  685. return JTable::getInstance($type, $prefix, $config);
  686. }
  687. /**
  688. * Prepare and sanitise the table prior to saving.
  689. *
  690. * @param JTable $table The database object
  691. *
  692. * @return void
  693. *
  694. * @since 1.6
  695. */
  696. protected function prepareTable($table)
  697. {
  698. $table->title = htmlspecialchars_decode($table->title, ENT_QUOTES);
  699. $table->position = trim($table->position);
  700. }
  701. /**
  702. * Method to preprocess the form
  703. *
  704. * @param JForm $form A form object.
  705. * @param mixed $data The data expected for the form.
  706. * @param string $group The name of the plugin group to import (defaults to "content").
  707. *
  708. * @return void
  709. *
  710. * @since 1.6
  711. * @throws Exception if there is an error loading the form.
  712. */
  713. protected function preprocessForm(JForm $form, $data, $group = 'content')
  714. {
  715. jimport('joomla.filesystem.path');
  716. $lang = JFactory::getLanguage();
  717. $clientId = $this->getState('item.client_id');
  718. $module = $this->getState('item.module');
  719. $client = JApplicationHelper::getClientInfo($clientId);
  720. $formFile = JPath::clean($client->path . '/modules/' . $module . '/' . $module . '.xml');
  721. // Load the core and/or local language file(s).
  722. $lang->load($module, $client->path, null, false, true)
  723. || $lang->load($module, $client->path . '/modules/' . $module, null, false, true);
  724. if (file_exists($formFile))
  725. {
  726. // Get the module form.
  727. if (!$form->loadFile($formFile, false, '//config'))
  728. {
  729. throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
  730. }
  731. // Attempt to load the xml file.
  732. if (!$xml = simplexml_load_file($formFile))
  733. {
  734. throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
  735. }
  736. // Get the help data from the XML file if present.
  737. $help = $xml->xpath('/extension/help');
  738. if (!empty($help))
  739. {
  740. $helpKey = trim((string) $help[0]['key']);
  741. $helpURL = trim((string) $help[0]['url']);
  742. $this->helpKey = $helpKey ? $helpKey : $this->helpKey;
  743. $this->helpURL = $helpURL ? $helpURL : $this->helpURL;
  744. }
  745. }
  746. // Load the default advanced params
  747. JForm::addFormPath(JPATH_ADMINISTRATOR . '/components/com_modules/models/forms');
  748. $form->loadFile('advanced', false);
  749. // Trigger the default form events.
  750. parent::preprocessForm($form, $data, $group);
  751. }
  752. /**
  753. * Loads ContentHelper for filters before validating data.
  754. *
  755. * @param object $form The form to validate against.
  756. * @param array $data The data to validate.
  757. * @param string $group The name of the group(defaults to null).
  758. *
  759. * @return mixed Array of filtered data if valid, false otherwise.
  760. *
  761. * @since 1.1
  762. */
  763. public function validate($form, $data, $group = null)
  764. {
  765. require_once JPATH_ADMINISTRATOR . '/components/com_content/helpers/content.php';
  766. return parent::validate($form, $data, $group);
  767. }
  768. /**
  769. * Method to save the form data.
  770. *
  771. * @param array $data The form data.
  772. *
  773. * @return boolean True on success.
  774. *
  775. * @since 1.6
  776. */
  777. public function save($data)
  778. {
  779. $dispatcher = JEventDispatcher::getInstance();
  780. $input = JFactory::getApplication()->input;
  781. $table = $this->getTable();
  782. $pk = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('module.id');
  783. $isNew = true;
  784. // Include the content modules for the onSave events.
  785. JPluginHelper::importPlugin('extension');
  786. // Load the row if saving an existing record.
  787. if ($pk > 0)
  788. {
  789. $table->load($pk);
  790. $isNew = false;
  791. }
  792. // Alter the title and published state for Save as Copy
  793. if ($input->get('task') == 'save2copy')
  794. {
  795. $orig_data = $input->post->get('jform', array(), 'array');
  796. $orig_table = clone($this->getTable());
  797. $orig_table->load((int) $orig_data['id']);
  798. if ($data['title'] == $orig_table->title)
  799. {
  800. $data['title'] .= ' ' . JText::_('JGLOBAL_COPY');
  801. $data['published'] = 0;
  802. }
  803. }
  804. // Bind the data.
  805. if (!$table->bind($data))
  806. {
  807. $this->setError($table->getError());
  808. return false;
  809. }
  810. // Prepare the row for saving
  811. $this->prepareTable($table);
  812. // Check the data.
  813. if (!$table->check())
  814. {
  815. $this->setError($table->getError());
  816. return false;
  817. }
  818. // Trigger the onExtensionBeforeSave event.
  819. $result = $dispatcher->trigger('onExtensionBeforeSave', array('com_modules.module', &$table, $isNew));
  820. if (in_array(false, $result, true))
  821. {
  822. $this->setError($table->getError());
  823. return false;
  824. }
  825. // Store the data.
  826. if (!$table->store())
  827. {
  828. $this->setError($table->getError());
  829. return false;
  830. }
  831. // Process the menu link mappings.
  832. $assignment = isset($data['assignment']) ? $data['assignment'] : 0;
  833. // Delete old module to menu item associations
  834. $db = $this->getDbo();
  835. $query = $db->getQuery(true)
  836. ->delete('#__modules_menu')
  837. ->where('moduleid = ' . (int) $table->id);
  838. $db->setQuery($query);
  839. try
  840. {
  841. $db->execute();
  842. }
  843. catch (RuntimeException $e)
  844. {
  845. $this->setError($e->getMessage());
  846. return false;
  847. }
  848. // If the assignment is numeric, then something is selected (otherwise it's none).
  849. if (is_numeric($assignment))
  850. {
  851. // Variable is numeric, but could be a string.
  852. $assignment = (int) $assignment;
  853. // Logic check: if no module excluded then convert to display on all.
  854. if ($assignment == -1 && empty($data['assigned']))
  855. {
  856. $assignment = 0;
  857. }
  858. // Check needed to stop a module being assigned to `All`
  859. // and other menu items resulting in a module being displayed twice.
  860. if ($assignment === 0)
  861. {
  862. // Assign new module to `all` menu item associations.
  863. $query->clear()
  864. ->insert('#__modules_menu')
  865. ->columns(array($db->quoteName('moduleid'), $db->quoteName('menuid')))
  866. ->values((int) $table->id . ', 0');
  867. $db->setQuery($query);
  868. try
  869. {
  870. $db->execute();
  871. }
  872. catch (RuntimeException $e)
  873. {
  874. $this->setError($e->getMessage());
  875. return false;
  876. }
  877. }
  878. elseif (!empty($data['assigned']))
  879. {
  880. // Get the sign of the number.
  881. $sign = $assignment < 0 ? -1 : 1;
  882. // Preprocess the assigned array.
  883. $tuples = array();
  884. foreach ($data['assigned'] as &$pk)
  885. {
  886. $tuples[] = '(' . (int) $table->id . ',' . (int) $pk * $sign . ')';
  887. }
  888. $this->_db->setQuery(
  889. 'INSERT INTO #__modules_menu (moduleid, menuid) VALUES ' .
  890. implode(',', $tuples)
  891. );
  892. try
  893. {
  894. $db->execute();
  895. }
  896. catch (RuntimeException $e)
  897. {
  898. $this->setError($e->getMessage());
  899. return false;
  900. }
  901. }
  902. }
  903. // Trigger the onExtensionAfterSave event.
  904. $dispatcher->trigger('onExtensionAfterSave', array('com_modules.module', &$table, $isNew));
  905. // Compute the extension id of this module in case the controller wants it.
  906. $query = $db->getQuery(true)
  907. ->select('extension_id')
  908. ->from('#__extensions AS e')
  909. ->join('LEFT', '#__modules AS m ON e.element = m.module')
  910. ->where('m.id = ' . (int) $table->id);
  911. $db->setQuery($query);
  912. try
  913. {
  914. $extensionId = $db->loadResult();
  915. }
  916. catch (RuntimeException $e)
  917. {
  918. JError::raiseWarning(500, $e->getMessage());
  919. return false;
  920. }
  921. $this->setState('module.extension_id', $extensionId);
  922. $this->setState('module.id', $table->id);
  923. // Clear modules cache
  924. $this->cleanCache();
  925. // Clean module cache
  926. parent::cleanCache($table->module, $table->client_id);
  927. return true;
  928. }
  929. /**
  930. * A protected method to get a set of ordering conditions.
  931. *
  932. * @param object $table A record object.
  933. *
  934. * @return array An array of conditions to add to add to ordering queries.
  935. *
  936. * @since 1.6
  937. */
  938. protected function getReorderConditions($table)
  939. {
  940. $condition = array();
  941. $condition[] = 'client_id = ' . (int) $table->client_id;
  942. $condition[] = 'position = ' . $this->_db->quote($table->position);
  943. return $condition;
  944. }
  945. /**
  946. * Custom clean cache method for different clients
  947. *
  948. * @param string $group The name of the plugin group to import (defaults to null).
  949. * @param integer $client_id The client ID. [optional]
  950. *
  951. * @return void
  952. *
  953. * @since 1.6
  954. */
  955. protected function cleanCache($group = null, $client_id = 0)
  956. {
  957. parent::cleanCache('com_modules', $this->getClient());
  958. }
  959. }