diff --git a/administrator/components/com_menus/models/item.php b/administrator/components/com_menus/models/item.php index ca66ab2d721fe..17a36cb2b18f7 100644 --- a/administrator/components/com_menus/models/item.php +++ b/administrator/components/com_menus/models/item.php @@ -48,9 +48,10 @@ class MenusModelItem extends JModelAdmin /** * Method to test whether a record can be deleted. * - * @param object A record object. + * @param object $record A record object. * * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * * @since 1.6 */ protected function canDelete($record) @@ -59,13 +60,37 @@ protected function canDelete($record) { if ($record->published != -2) { - return; + return false; } return parent::canDelete($record); } } + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + + if (!empty($record->id)) + { + return $user->authorise('core.edit.state', 'com_menus.item.' . (int) $record->id); + } + // Default to component settings if menu item not known. + else + { + return parent::canEditState($record); + } + } + /** * Method to perform batch operations on an item or a set of items. * @@ -92,6 +117,7 @@ public function batch($commands, $pks, $contexts) if (empty($pks)) { $this->setError(JText::_('COM_MENUS_NO_ITEM_SELECTED')); + return false; } @@ -104,6 +130,7 @@ public function batch($commands, $pks, $contexts) if ($cmd == 'c') { $result = $this->batchCopy($commands['menu_id'], $pks, $contexts); + if (is_array($result)) { $pks = $result; @@ -117,6 +144,7 @@ public function batch($commands, $pks, $contexts) { return false; } + $done = true; } @@ -143,6 +171,7 @@ public function batch($commands, $pks, $contexts) if (!$done) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; } @@ -181,6 +210,7 @@ protected function batchCopy($value, $pks, $contexts) { // Fatal error $this->setError($error); + return false; } else @@ -198,15 +228,18 @@ protected function batchCopy($value, $pks, $contexts) if (!$parentId = $table->getRootId()) { $this->setError($db->getErrorMsg()); + return false; } } // Check that user has create permission for menus $user = JFactory::getUser(); + if (!$user->authorise('core.create', 'com_menus')) { $this->setError(JText::_('COM_MENUS_BATCH_MENU_ITEM_CANNOT_CREATE')); + return false; } @@ -225,6 +258,7 @@ protected function batchCopy($value, $pks, $contexts) catch (RuntimeException $e) { $this->setError($e->getMessage()); + return false; } @@ -243,6 +277,7 @@ protected function batchCopy($value, $pks, $contexts) { // Fatal error $this->setError($error); + return false; } else @@ -287,7 +322,7 @@ protected function batchCopy($value, $pks, $contexts) $table->setLocation($table->parent_id, 'last-child'); // TODO: Deal with ordering? - //$table->ordering = 1; + // $table->ordering = 1; $table->level = null; $table->lft = null; $table->rgt = null; @@ -302,12 +337,14 @@ protected function batchCopy($value, $pks, $contexts) if (!$table->check()) { $this->setError($table->getError()); + return false; } // Store the row. if (!$table->store()) { $this->setError($table->getError()); + return false; } @@ -327,6 +364,7 @@ protected function batchCopy($value, $pks, $contexts) if (!$table->rebuild()) { $this->setError($table->getError()); + return false; } @@ -334,6 +372,7 @@ protected function batchCopy($value, $pks, $contexts) if (!$table->rebuildPath($table->id)) { $this->setError($table->getError()); + return false; } @@ -388,15 +427,18 @@ protected function batchMove($value, $pks, $contexts) // Check that user has create and edit permission for menus $user = JFactory::getUser(); + if (!$user->authorise('core.create', 'com_menus')) { $this->setError(JText::_('COM_MENUS_BATCH_MENU_ITEM_CANNOT_CREATE')); + return false; } if (!$user->authorise('core.edit', 'com_menus')) { $this->setError(JText::_('COM_MENUS_BATCH_MENU_ITEM_CANNOT_EDIT')); + return false; } @@ -413,6 +455,7 @@ protected function batchMove($value, $pks, $contexts) { // Fatal error $this->setError($error); + return false; } else @@ -445,6 +488,7 @@ protected function batchMove($value, $pks, $contexts) if (!$table->check()) { $this->setError($table->getError()); + return false; } @@ -452,6 +496,7 @@ protected function batchMove($value, $pks, $contexts) if (!$table->store()) { $this->setError($table->getError()); + return false; } @@ -459,6 +504,7 @@ protected function batchMove($value, $pks, $contexts) if (!$table->rebuildPath()) { $this->setError($table->getError()); + return false; } } @@ -484,6 +530,7 @@ protected function batchMove($value, $pks, $contexts) catch (RuntimeException $e) { $this->setError($e->getMessage()); + return false; } } @@ -497,10 +544,11 @@ protected function batchMove($value, $pks, $contexts) /** * Method to check if you can save a record. * - * @param array $data An array of input data. - * @param string $key The name of the key for the primary key. + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. * * @return boolean + * * @since 1.6 */ protected function canSave($data = array(), $key = 'id') @@ -511,9 +559,11 @@ protected function canSave($data = array(), $key = 'id') /** * Method to get the row form. * - * @param array $data Data for the form. - * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * * @return mixed A JForm object on success, false on failure + * * @since 1.6 */ public function getForm($data = array(), $loadData = true) @@ -523,6 +573,7 @@ public function getForm($data = array(), $loadData = true) { $item = $this->getItem(); $this->setState('item.link', $item->link); + // The type should already be set. } else @@ -559,6 +610,7 @@ public function getForm($data = array(), $loadData = true) * Method to get the data that should be injected in the form. * * @return mixed The data for the form. + * * @since 1.6 */ protected function loadFormData() @@ -575,6 +627,7 @@ protected function loadFormData() * Get the necessary data to load an item help screen. * * @return object An object with key, url, and local properties for loading the item help screen. + * * @since 1.6 */ public function getHelp() @@ -585,9 +638,10 @@ public function getHelp() /** * Method to get a menu item. * - * @param integer $pk An optional id of the object to get, otherwise the id from the model state is used. + * @param integer $pk An optional id of the object to get, otherwise the id from the model state is used. * * @return mixed Menu item data object on success, false on failure. + * * @since 1.6 */ public function getItem($pk = null) @@ -604,6 +658,7 @@ public function getItem($pk = null) if ($error = $table->getError()) { $this->setError($error); + return false; } @@ -718,6 +773,7 @@ public function getItem($pk = null) // Load associated menu items $app = JFactory::getApplication(); $assoc = JLanguageAssociations::isEnabled(); + if ($assoc) { if ($pk != null) @@ -729,6 +785,7 @@ public function getItem($pk = null) $result->associations = array(); } } + $result->menuordering = $pk; return $result; @@ -738,6 +795,7 @@ public function getItem($pk = null) * Get the list of modules not in trash. * * @return mixed An array of module records (id, title, position), or false on error. + * * @since 1.6 */ public function getModules() @@ -745,9 +803,11 @@ public function getModules() $db = $this->getDbo(); $query = $db->getQuery(true); - // Join on the module-to-menu mapping table. - // We are only interested if the module is displayed on ALL or THIS menu item (or the inverse ID number). - //sqlsrv changes for modulelink to menu manager + /** + * Join on the module-to-menu mapping table. + * We are only interested if the module is displayed on ALL or THIS menu item (or the inverse ID number). + * sqlsrv changes for modulelink to menu manager + */ $query->select('a.id, a.title, a.position, a.published, map.menuid') ->from('#__modules AS a') ->join('LEFT', sprintf('#__modules_menu AS map ON map.moduleid = a.id AND map.menuid IN (0, %1$d, -%1$d)', $this->getState('item.id'))) @@ -769,6 +829,7 @@ public function getModules() catch (RuntimeException $e) { $this->setError($e->getMessage()); + return false; } @@ -779,9 +840,10 @@ public function getModules() * A protected method to get the where clause for the reorder * This ensures that the row will be moved relative to a row with the same menutype * - * @param JTableMenu $table instance + * @param JTableMenu $table instance * * @return array An array of conditions to add to add to ordering queries. + * * @since 1.6 */ protected function getReorderConditions($table) @@ -792,11 +854,12 @@ protected function getReorderConditions($table) /** * Returns a Table object, always creating it * - * @param type $type The table type to instantiate - * @param string $prefix A prefix for the table class name. Optional. - * @param array $config Configuration array for model. Optional. + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object * - * @return JTable A database object * @since 1.6 */ public function getTable($type = 'Menu', $prefix = 'MenusTable', $config = array()) @@ -810,6 +873,7 @@ public function getTable($type = 'Menu', $prefix = 'MenusTable', $config = array * Note. Calling getState in this method will result in recursion. * * @return void + * * @since 1.6 */ protected function populateState() @@ -824,21 +888,26 @@ protected function populateState() { $parentId = $app->input->getInt('parent_id'); } + $this->setState('item.parent_id', $parentId); $menuType = $app->getUserState('com_menus.edit.item.menutype'); + if ($app->input->getString('menutype', false)) { $menuType = $app->input->getString('menutype', 'mainmenu'); } + $this->setState('item.menutype', $menuType); if (!($type = $app->getUserState('com_menus.edit.item.type'))) { $type = $app->input->get('type'); + // Note a new menu item will have no field type. // The field is required so the user has to change it. } + $this->setState('item.type', $type); if ($link = $app->getUserState('com_menus.edit.item.link')) @@ -852,12 +921,16 @@ protected function populateState() } /** - * @param object $form A form object. - * @param mixed $data The data expected for the form. + * Merge the form with additional fields from various possible sources. + * + * @param object $form A form object. + * @param mixed $data The data expected for the form. + * @param string $group The name of the plugin group to import (defaults to "content"). * * @return void + * * @since 1.6 - * @throws Exception if there is an error in the form event. + * @throws Exception if there is an error in the form event. */ protected function preprocessForm(JForm $form, $data, $group = 'content') { @@ -868,7 +941,6 @@ protected function preprocessForm(JForm $form, $data, $group = 'content') // Initialise form with component view params if available. if ($type == 'component') { - $link = htmlspecialchars_decode($link); // Parse the link arguments. @@ -878,6 +950,7 @@ protected function preprocessForm(JForm $form, $data, $group = 'content') // Confirm that the option is defined. $option = ''; $base = ''; + if (isset($args['option'])) { // The option determines the base path to work with. @@ -887,6 +960,7 @@ protected function preprocessForm(JForm $form, $data, $group = 'content') // Confirm a view is defined. $formFile = false; + if (isset($args['view'])) { $view = $args['view']; @@ -921,6 +995,7 @@ protected function preprocessForm(JForm $form, $data, $group = 'content') { $temp = explode(':', $layout); $templatePath = JPATH::clean(JPATH_SITE . '/templates/' . $temp[0] . '/html/' . $option . '/' . $view . '/' . $temp[1] . '.xml'); + if (is_file($templatePath)) { $formFile = $templatePath; @@ -948,6 +1023,7 @@ protected function preprocessForm(JForm $form, $data, $group = 'content') { // Now check for a component manifest file $path = JPath::clean($base . '/metadata.xml'); + if (is_file($path)) { $formFile = $path; @@ -1001,21 +1077,12 @@ protected function preprocessForm(JForm $form, $data, $group = 'content') $this->helpLocal = (($helpLoc == 'true') || ($helpLoc == '1') || ($helpLoc == 'local')) ? true : false; } - // Now load the component params. - // TODO: Work out why 'fixing' this breaks JForm - if ($isNew = false) - { - $path = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $option . '/config.xml'); - } - else - { - $path = 'null'; - } + $path = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $option . '/config.xml'); if (is_file($path)) { // Add the component params last of all to the existing form. - if (!$form->load($path, true, '/config')) + if (!$form->loadFile($path, true, '/config')) { throw new Exception(JText::_('JERROR_LOADFILE_FAILED')); } @@ -1042,6 +1109,7 @@ protected function preprocessForm(JForm $form, $data, $group = 'content') $fieldset->addAttribute('name', 'item_associations'); $fieldset->addAttribute('description', 'COM_MENUS_ITEM_ASSOCIATIONS_FIELDSET_DESC'); $add = false; + foreach ($languages as $tag => $language) { if ($tag != $data['language']) @@ -1057,6 +1125,7 @@ protected function preprocessForm(JForm $form, $data, $group = 'content') $option->addAttribute('value', ''); } } + if ($add) { $form->load($addform, false); @@ -1071,6 +1140,7 @@ protected function preprocessForm(JForm $form, $data, $group = 'content') * Method rebuild the entire nested set tree. * * @return boolean False on failure or error, true otherwise. + * * @since 1.6 */ public function rebuild() @@ -1083,6 +1153,7 @@ public function rebuild() if (!$table->rebuild()) { $this->setError($table->getError()); + return false; } @@ -1133,9 +1204,10 @@ public function rebuild() /** * Method to save the form data. * - * @param array $data The form data. + * @param array $data The form data. * * @return boolean True on success. + * * @since 1.6 */ public function save($data) @@ -1150,11 +1222,11 @@ public function save($data) $table->load($pk); $isNew = false; } + if (!$isNew) { if ($table->parent_id == $data['parent_id']) { - // If first is chosen make the item the first child of the selected parent. if ($data['menuordering'] == -1) { @@ -1193,6 +1265,7 @@ public function save($data) if (!$table->bind($data)) { $this->setError($table->getError()); + return false; } @@ -1210,6 +1283,7 @@ public function save($data) if (!$table->check()) { $this->setError($table->getError()); + return false; } @@ -1217,6 +1291,7 @@ public function save($data) if (!$table->store()) { $this->setError($table->getError()); + return false; } @@ -1224,6 +1299,7 @@ public function save($data) if (!$table->rebuildPath($table->id)) { $this->setError($table->getError()); + return false; } @@ -1233,10 +1309,12 @@ public function save($data) // Load associated menu items $app = JFactory::getApplication(); $assoc = JLanguageAssociations::isEnabled(); + if ($assoc) { // Adding self to the association $associations = $data['associations']; + foreach ($associations as $tag => $id) { if (empty($id)) @@ -1247,6 +1325,7 @@ public function save($data) // Detecting all item menus $all_language = $table->language == '*'; + if ($all_language && !empty($associations)) { JError::raiseNotice(403, JText::_('COM_MENUS_ERROR_ALL_LANGUAGE_ASSOCIATED')); @@ -1269,6 +1348,7 @@ public function save($data) catch (RuntimeException $e) { $this->setError($e->getMessage()); + return false; } @@ -1278,10 +1358,12 @@ public function save($data) $key = md5(json_encode($associations)); $query->clear() ->insert('#__associations'); + foreach ($associations as $id) { $query->values($id . ',' . $db->quote('com_menus.item') . ',' . $db->quote($key)); } + $db->setQuery($query); try @@ -1291,6 +1373,7 @@ public function save($data) catch (RuntimeException $e) { $this->setError($e->getMessage()); + return false; } } @@ -1317,10 +1400,11 @@ public function save($data) * First we save the new order values in the lft values of the changed ids. * Then we invoke the table rebuild to implement the new ordering. * - * @param array $idArray id's of rows to be reordered - * @param array $lft_array lft values of rows to be reordered + * @param array $idArray id's of rows to be reordered + * @param array $lft_array lft values of rows to be reordered * * @return boolean false on failuer or error, true otherwise + * * @since 1.6 */ public function saveorder($idArray = null, $lft_array = null) @@ -1331,6 +1415,7 @@ public function saveorder($idArray = null, $lft_array = null) if (!$table->saveorder($idArray, $lft_array)) { $this->setError($table->getError()); + return false; } @@ -1343,10 +1428,11 @@ public function saveorder($idArray = null, $lft_array = null) /** * Method to change the home state of one or more items. * - * @param array $pks A list of the primary keys to change. - * @param integer $value The value of the home state. + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the home state. * * @return boolean True on success. + * * @since 1.6 */ public function setHome(&$pks, $value = 1) @@ -1375,6 +1461,7 @@ public function setHome(&$pks, $value = 1) else { $table->home = $value; + if ($table->language == '*') { $table->published = 1; @@ -1403,6 +1490,7 @@ public function setHome(&$pks, $value = 1) else { unset($pks[$i]); + if (!$onehome) { $onehome = true; @@ -1421,8 +1509,8 @@ public function setHome(&$pks, $value = 1) /** * Method to change the published state of one or more records. * - * @param array &$pks A list of the primary keys to change. - * @param integer $value The value of the published state. + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. * * @return boolean True on success. * @@ -1475,12 +1563,14 @@ protected function generateNewTitle($parent_id, $alias, $title) { // Alter the title & alias $table = $this->getTable(); + while ($table->load(array('alias' => $alias, 'parent_id' => $parent_id))) { if ($title == $table->title) { $title = JString::increment($title); } + $alias = JString::increment($alias, 'dash'); } @@ -1490,6 +1580,11 @@ protected function generateNewTitle($parent_id, $alias, $title) /** * Custom clean cache method * + * @param mixed $group Not used. + * @param integer $client_id Not used. + * + * @return void + * * @since 1.6 */ protected function cleanCache($group = null, $client_id = 0)