Source for file item.php

Documentation is available at item.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Administrator
  4.  * @subpackage  com_menus
  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.txt
  8.  */
  9.  
  10. defined('_JEXEC'or die;
  11.  
  12. jimport('joomla.filesystem.path');
  13. require_once JPATH_COMPONENT '/helpers/menus.php';
  14.  
  15. /**
  16.  * Menu Item Model for Menus.
  17.  *
  18.  * @package     Joomla.Administrator
  19.  * @subpackage  com_menus
  20.  * @since       1.6
  21.  */
  22. class MenusModelItem extends JModelAdmin
  23. {
  24.     /**
  25.      * @var        string    The prefix to use with controller messages.
  26.      * @since   1.6
  27.      */
  28.     protected $text_prefix = 'COM_MENUS_ITEM';
  29.  
  30.     /**
  31.      * @var        string    The help screen key for the menu item.
  32.      * @since   1.6
  33.      */
  34.     protected $helpKey = 'JHELP_MENUS_MENU_ITEM_MANAGER_EDIT';
  35.  
  36.     /**
  37.      * @var        string    The help screen base URL for the menu item.
  38.      * @since   1.6
  39.      */
  40.     protected $helpURL;
  41.  
  42.     /**
  43.      * @var        boolean    True to use local lookup for the help screen.
  44.      * @since   1.6
  45.      */
  46.     protected $helpLocal = false;
  47.  
  48.     /**
  49.      * Method to test whether a record can be deleted.
  50.      *
  51.      * @param   object    record object.
  52.      *
  53.      * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
  54.      * @since   1.6
  55.      */
  56.     protected function canDelete($record)
  57.     {
  58.         if (!empty($record->id))
  59.         {
  60.             if ($record->published != -2)
  61.             {
  62.                 return;
  63.             }
  64.             $user JFactory::getUser();
  65.  
  66.             return $user->authorise('core.delete''com_menus.item.' . (int) $record->id);
  67.         }
  68.     }
  69.  
  70.     /**
  71.      * Method to test whether a record can have its state edited.
  72.      *
  73.      * @param   object    record object.
  74.      *
  75.      * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
  76.      * @since   1.6
  77.      */
  78.     protected function canEditState($record)
  79.     {
  80.         $user JFactory::getUser();
  81.  
  82.         if (!empty($record->id))
  83.         {
  84.             return $user->authorise('core.edit.state''com_menus.item.' . (int) $record->id);
  85.         }
  86.         // Default to component settings if menu item not known.
  87.         else
  88.         {
  89.             return parent::canEditState($record);
  90.         }
  91.     }
  92.  
  93.     /**
  94.      * Method to perform batch operations on an item or a set of items.
  95.      *
  96.      * @param   array  $commands  An array of commands to perform.
  97.      * @param   array  $pks       An array of item ids.
  98.      * @param   array  $contexts  An array of item contexts.
  99.      *
  100.      * @return  boolean  Returns true on success, false on failure.
  101.      *
  102.      * @since   1.6
  103.      */
  104.     public function batch($commands$pks$contexts)
  105.     {
  106.         // Sanitize user ids.
  107.         $pks array_unique($pks);
  108.         JArrayHelper::toInteger($pks);
  109.  
  110.         // Remove any values of zero.
  111.         if (array_search(0$pkstrue))
  112.         {
  113.             unset($pks[array_search(0$pkstrue)]);
  114.         }
  115.  
  116.         if (empty($pks))
  117.         {
  118.             $this->setError(JText::_('COM_MENUS_NO_ITEM_SELECTED'));
  119.             return false;
  120.         }
  121.  
  122.         $done false;
  123.  
  124.         if (!empty($commands['menu_id']))
  125.         {
  126.             $cmd JArrayHelper::getValue($commands'move_copy''c');
  127.  
  128.             if ($cmd == 'c')
  129.             {
  130.                 $result $this->batchCopy($commands['menu_id']$pks$contexts);
  131.                 if (is_array($result))
  132.                 {
  133.                     $pks $result;
  134.                 }
  135.                 else
  136.                 {
  137.                     return false;
  138.                 }
  139.             }
  140.             elseif ($cmd == 'm' && !$this->batchMove($commands['menu_id']$pks$contexts))
  141.             {
  142.                 return false;
  143.             }
  144.             $done true;
  145.         }
  146.  
  147.         if (!empty($commands['assetgroup_id']))
  148.         {
  149.             if (!$this->batchAccess($commands['assetgroup_id']$pks$contexts))
  150.             {
  151.                 return false;
  152.             }
  153.  
  154.             $done true;
  155.         }
  156.  
  157.         if (!empty($commands['language_id']))
  158.         {
  159.             if (!$this->batchLanguage($commands['language_id']$pks$contexts))
  160.             {
  161.                 return false;
  162.             }
  163.  
  164.             $done true;
  165.         }
  166.  
  167.         if (!$done)
  168.         {
  169.             $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION'));
  170.             return false;
  171.         }
  172.  
  173.         return true;
  174.     }
  175.  
  176.     /**
  177.      * Batch copy menu items to a new menu or parent.
  178.      *
  179.      * @param   integer  $value     The new menu or sub-item.
  180.      * @param   array    $pks       An array of row IDs.
  181.      * @param   array    $contexts  An array of item contexts.
  182.      *
  183.      * @return  mixed  An array of new IDs on success, boolean false on failure.
  184.      *
  185.      * @since   1.6
  186.      */
  187.     protected function batchCopy($value$pks$contexts)
  188.     {
  189.         // $value comes as {menutype}.{parent_id}
  190.         $parts explode('.'$value);
  191.         $menuType $parts[0];
  192.         $parentId = (int) JArrayHelper::getValue($parts10);
  193.  
  194.         $table $this->getTable();
  195.         $db $this->getDbo();
  196.         $query $db->getQuery(true);
  197.         $i 0;
  198.  
  199.         // Check that the parent exists
  200.         if ($parentId)
  201.         {
  202.             if (!$table->load($parentId))
  203.             {
  204.                 if ($error $table->getError())
  205.                 {
  206.                     // Fatal error
  207.                     $this->setError($error);
  208.                     return false;
  209.                 }
  210.                 else
  211.                 {
  212.                     // Non-fatal error
  213.                     $this->setError(JText::_('JGLOBAL_BATCH_MOVE_PARENT_NOT_FOUND'));
  214.                     $parentId 0;
  215.                 }
  216.             }
  217.         }
  218.  
  219.         // If the parent is 0, set it to the ID of the root item in the tree
  220.         if (empty($parentId))
  221.         {
  222.             if (!$parentId $table->getRootId())
  223.             {
  224.                 $this->setError($db->getErrorMsg());
  225.                 return false;
  226.             }
  227.         }
  228.  
  229.         // Check that user has create permission for menus
  230.         $user JFactory::getUser();
  231.         if (!$user->authorise('core.create''com_menus'))
  232.         {
  233.             $this->setError(JText::_('COM_MENUS_BATCH_MENU_ITEM_CANNOT_CREATE'));
  234.             return false;
  235.         }
  236.  
  237.         // We need to log the parent ID
  238.         $parents array();
  239.  
  240.         // Calculate the emergency stop count as a precaution against a runaway loop bug
  241.         $query->select('COUNT(id)')
  242.             ->from($db->quoteName('#__menu'));
  243.         $db->setQuery($query);
  244.  
  245.         try
  246.         {
  247.             $count $db->loadResult();
  248.         }
  249.         catch (RuntimeException $e)
  250.         {
  251.             $this->setError($e->getMessage());
  252.             return false;
  253.         }
  254.  
  255.         // Parent exists so we let's proceed
  256.         while (!empty($pks&& $count 0)
  257.         {
  258.             // Pop the first id off the stack
  259.             $pk array_shift($pks);
  260.  
  261.             $table->reset();
  262.  
  263.             // Check that the row actually exists
  264.             if (!$table->load($pk))
  265.             {
  266.                 if ($error $table->getError())
  267.                 {
  268.                     // Fatal error
  269.                     $this->setError($error);
  270.                     return false;
  271.                 }
  272.                 else
  273.                 {
  274.                     // Not fatal error
  275.                     $this->setError(JText::sprintf('JGLOBAL_BATCH_MOVE_ROW_NOT_FOUND'$pk));
  276.                     continue;
  277.                 }
  278.             }
  279.  
  280.             // Copy is a bit tricky, because we also need to copy the children
  281.             $query->clear()
  282.                 ->select('id')
  283.                 ->from($db->quoteName('#__menu'))
  284.                 ->where('lft > ' . (int) $table->lft)
  285.                 ->where('rgt < ' . (int) $table->rgt);
  286.             $db->setQuery($query);
  287.             $childIds $db->loadColumn();
  288.  
  289.             // Add child ID's to the array only if they aren't already there.
  290.             foreach ($childIds as $childId)
  291.             {
  292.                 if (!in_array($childId$pks))
  293.                 {
  294.                     array_push($pks$childId);
  295.                 }
  296.             }
  297.  
  298.             // Make a copy of the old ID and Parent ID
  299.             $oldId $table->id;
  300.             $oldParentId $table->parent_id;
  301.  
  302.             // Reset the id because we are making a copy.
  303.             $table->id 0;
  304.  
  305.             // If we a copying children, the Old ID will turn up in the parents list
  306.             // otherwise it's a new top level item
  307.             $table->parent_id = isset($parents[$oldParentId]$parents[$oldParentId$parentId;
  308.             $table->menutype $menuType;
  309.  
  310.             // Set the new location in the tree for the node.
  311.             $table->setLocation($table->parent_id'last-child');
  312.  
  313.             // TODO: Deal with ordering?
  314.             //$table->ordering    = 1;
  315.             $table->level null;
  316.             $table->lft null;
  317.             $table->rgt null;
  318.             $table->home 0;
  319.  
  320.             // Alter the title & alias
  321.             list($title$alias$this->generateNewTitle($table->parent_id$table->alias$table->title);
  322.             $table->title $title;
  323.             $table->alias $alias;
  324.  
  325.             // Check the row.
  326.             if (!$table->check())
  327.             {
  328.                 $this->setError($table->getError());
  329.                 return false;
  330.             }
  331.             // Store the row.
  332.             if (!$table->store())
  333.             {
  334.                 $this->setError($table->getError());
  335.                 return false;
  336.             }
  337.  
  338.             // Get the new item ID
  339.             $newId $table->get('id');
  340.  
  341.             // Add the new ID to the array
  342.             $newIds[$i$newId;
  343.             $i++;
  344.  
  345.             // Now we log the old 'parent' to the new 'parent'
  346.             $parents[$oldId$table->id;
  347.             $count--;
  348.         }
  349.  
  350.         // Rebuild the hierarchy.
  351.         if (!$table->rebuild())
  352.         {
  353.             $this->setError($table->getError());
  354.             return false;
  355.         }
  356.  
  357.         // Rebuild the tree path.
  358.         if (!$table->rebuildPath($table->id))
  359.         {
  360.             $this->setError($table->getError());
  361.             return false;
  362.         }
  363.  
  364.         // Clean the cache
  365.         $this->cleanCache();
  366.  
  367.         return $newIds;
  368.     }
  369.  
  370.     /**
  371.      * Batch move menu items to a new menu or parent.
  372.      *
  373.      * @param   integer  $value     The new menu or sub-item.
  374.      * @param   array    $pks       An array of row IDs.
  375.      * @param   array    $contexts  An array of item contexts.
  376.      *
  377.      * @return  boolean  True on success.
  378.      *
  379.      * @since   1.6
  380.      */
  381.     protected function batchMove($value$pks$contexts)
  382.     {
  383.         // $value comes as {menutype}.{parent_id}
  384.         $parts explode('.'$value);
  385.         $menuType $parts[0];
  386.         $parentId = (int) JArrayHelper::getValue($parts10);
  387.  
  388.         $table $this->getTable();
  389.         $db $this->getDbo();
  390.         $query $db->getQuery(true);
  391.  
  392.         // Check that the parent exists.
  393.         if ($parentId)
  394.         {
  395.             if (!$table->load($parentId))
  396.             {
  397.                 if ($error $table->getError())
  398.                 {
  399.                     // Fatal error
  400.                     $this->setError($error);
  401.  
  402.                     return false;
  403.                 }
  404.                 else
  405.                 {
  406.                     // Non-fatal error
  407.                     $this->setError(JText::_('JGLOBAL_BATCH_MOVE_PARENT_NOT_FOUND'));
  408.                     $parentId 0;
  409.                 }
  410.             }
  411.         }
  412.  
  413.         // Check that user has create and edit permission for menus
  414.         $user JFactory::getUser();
  415.         if (!$user->authorise('core.create''com_menus'))
  416.         {
  417.             $this->setError(JText::_('COM_MENUS_BATCH_MENU_ITEM_CANNOT_CREATE'));
  418.             return false;
  419.         }
  420.  
  421.         if (!$user->authorise('core.edit''com_menus'))
  422.         {
  423.             $this->setError(JText::_('COM_MENUS_BATCH_MENU_ITEM_CANNOT_EDIT'));
  424.             return false;
  425.         }
  426.  
  427.         // We are going to store all the children and just moved the menutype
  428.         $children array();
  429.  
  430.         // Parent exists so we let's proceed
  431.         foreach ($pks as $pk)
  432.         {
  433.             // Check that the row actually exists
  434.             if (!$table->load($pk))
  435.             {
  436.                 if ($error $table->getError())
  437.                 {
  438.                     // Fatal error
  439.                     $this->setError($error);
  440.                     return false;
  441.                 }
  442.                 else
  443.                 {
  444.                     // Not fatal error
  445.                     $this->setError(JText::sprintf('JGLOBAL_BATCH_MOVE_ROW_NOT_FOUND'$pk));
  446.                     continue;
  447.                 }
  448.             }
  449.  
  450.             // Set the new location in the tree for the node.
  451.             $table->setLocation($parentId'last-child');
  452.  
  453.             // Set the new Parent Id
  454.             $table->parent_id $parentId;
  455.  
  456.             // Check if we are moving to a different menu
  457.             if ($menuType != $table->menutype)
  458.             {
  459.                 // Add the child node ids to the children array.
  460.                 $query->clear()
  461.                     ->select($db->quoteName('id'))
  462.                     ->from($db->quoteName('#__menu'))
  463.                     ->where($db->quoteName('lft'' BETWEEN ' . (int) $table->lft ' AND ' . (int) $table->rgt);
  464.                 $db->setQuery($query);
  465.                 $children array_merge($children(array) $db->loadColumn());
  466.             }
  467.  
  468.             // Check the row.
  469.             if (!$table->check())
  470.             {
  471.                 $this->setError($table->getError());
  472.                 return false;
  473.             }
  474.  
  475.             // Store the row.
  476.             if (!$table->store())
  477.             {
  478.                 $this->setError($table->getError());
  479.                 return false;
  480.             }
  481.  
  482.             // Rebuild the tree path.
  483.             if (!$table->rebuildPath())
  484.             {
  485.                 $this->setError($table->getError());
  486.                 return false;
  487.             }
  488.         }
  489.  
  490.         // Process the child rows
  491.         if (!empty($children))
  492.         {
  493.             // Remove any duplicates and sanitize ids.
  494.             $children array_unique($children);
  495.             JArrayHelper::toInteger($children);
  496.  
  497.             // Update the menutype field in all nodes where necessary.
  498.             $query->clear()
  499.                 ->update($db->quoteName('#__menu'))
  500.                 ->set($db->quoteName('menutype'' = ' $db->quote($menuType))
  501.                 ->where($db->quoteName('id'' IN (' implode(','$children')');
  502.             $db->setQuery($query);
  503.  
  504.             try
  505.             {
  506.                 $db->execute();
  507.             }
  508.             catch (RuntimeException $e)
  509.             {
  510.                 $this->setError($e->getMessage());
  511.                 return false;
  512.             }
  513.         }
  514.  
  515.         // Clean the cache
  516.         $this->cleanCache();
  517.  
  518.         return true;
  519.     }
  520.  
  521.     /**
  522.      * Method to check if you can save a record.
  523.      *
  524.      * @param   array     $data    An array of input data.
  525.      * @param   string    $key     The name of the key for the primary key.
  526.      *
  527.      * @return  boolean 
  528.      * @since   1.6
  529.      */
  530.     protected function canSave($data array()$key 'id')
  531.     {
  532.         return JFactory::getUser()->authorise('core.edit'$this->option);
  533.     }
  534.  
  535.     /**
  536.      * Method to get the row form.
  537.      *
  538.      * @param   array      $data        Data for the form.
  539.      * @param   boolean    $loadData    True if the form is to load its own data (default case), false if not.
  540.      * @return  mixed  A JForm object on success, false on failure
  541.      * @since   1.6
  542.      */
  543.     public function getForm($data array()$loadData true)
  544.     {
  545.         // The folder and element vars are passed when saving the form.
  546.         if (empty($data))
  547.         {
  548.             $item $this->getItem();
  549.             $this->setState('item.link'$item->link);
  550.             // The type should already be set.
  551.         }
  552.         else
  553.         {
  554.             $this->setState('item.link'JArrayHelper::getValue($data'link'));
  555.             $this->setState('item.type'JArrayHelper::getValue($data'type'));
  556.         }
  557.  
  558.         // Get the form.
  559.         $form $this->loadForm('com_menus.item''item'array('control' => 'jform''load_data' => $loadData)true);
  560.  
  561.         if (empty($form))
  562.         {
  563.             return false;
  564.         }
  565.  
  566.         // Modify the form based on access controls.
  567.         if (!$this->canEditState((object) $data))
  568.         {
  569.             // Disable fields for display.
  570.             $form->setFieldAttribute('menuordering''disabled''true');
  571.             $form->setFieldAttribute('published''disabled''true');
  572.  
  573.             // Disable fields while saving.
  574.             // The controller has already verified this is an article you can edit.
  575.             $form->setFieldAttribute('menuordering''filter''unset');
  576.             $form->setFieldAttribute('published''filter''unset');
  577.         }
  578.  
  579.         return $form;
  580.     }
  581.  
  582.     /**
  583.      * Method to get the data that should be injected in the form.
  584.      *
  585.      * @return  mixed  The data for the form.
  586.      * @since   1.6
  587.      */
  588.     protected function loadFormData()
  589.     {
  590.         // Check the session for previously entered form data.
  591.         $data array_merge((array) $this->getItem()(array) JFactory::getApplication()->getUserState('com_menus.edit.item.data'array()));
  592.  
  593.         $this->preprocessData('com_menus.item'$data);
  594.  
  595.         return $data;
  596.     }
  597.  
  598.     /**
  599.      * Get the necessary data to load an item help screen.
  600.      *
  601.      * @return  object  An object with key, url, and local properties for loading the item help screen.
  602.      * @since   1.6
  603.      */
  604.     public function getHelp()
  605.     {
  606.         return (object) array('key' => $this->helpKey'url' => $this->helpURL'local' => $this->helpLocal);
  607.     }
  608.  
  609.     /**
  610.      * Method to get a menu item.
  611.      *
  612.      * @param   integer    $pk    An optional id of the object to get, otherwise the id from the model state is used.
  613.      *
  614.      * @return  mixed  Menu item data object on success, false on failure.
  615.      * @since   1.6
  616.      */
  617.     public function getItem($pk null)
  618.     {
  619.         $pk (!empty($pk)) $pk : (int) $this->getState('item.id');
  620.  
  621.         // Get a level row instance.
  622.         $table $this->getTable();
  623.  
  624.         // Attempt to load the row.
  625.         $table->load($pk);
  626.  
  627.         // Check for a table object error.
  628.         if ($error $table->getError())
  629.         {
  630.             $this->setError($error);
  631.             return false;
  632.         }
  633.  
  634.         // Prime required properties.
  635.  
  636.         if ($type $this->getState('item.type'))
  637.         {
  638.             $table->type $type;
  639.         }
  640.  
  641.         if (empty($table->id))
  642.         {
  643.             $table->parent_id $this->getState('item.parent_id');
  644.             $table->menutype $this->getState('item.menutype');
  645.             $table->params '{}';
  646.         }
  647.  
  648.         // If the link has been set in the state, possibly changing link type.
  649.         if ($link $this->getState('item.link'))
  650.         {
  651.             // Check if we are changing away from the actual link type.
  652.             if (MenusHelper::getLinkKey($table->link!= MenusHelper::getLinkKey($link))
  653.             {
  654.                 $table->link $link;
  655.             }
  656.         }
  657.  
  658.         switch ($table->type)
  659.         {
  660.             case 'alias':
  661.                 $table->component_id 0;
  662.                 $args array();
  663.  
  664.                 parse_str(parse_url($table->linkPHP_URL_QUERY)$args);
  665.                 break;
  666.  
  667.             case 'separator':
  668.             case 'heading':
  669.                 $table->link '';
  670.                 $table->component_id 0;
  671.                 break;
  672.  
  673.             case 'url':
  674.                 $table->component_id 0;
  675.  
  676.                 parse_str(parse_url($table->linkPHP_URL_QUERY));
  677.                 break;
  678.  
  679.             case 'component':
  680.             default:
  681.                 // Enforce a valid type.
  682.                 $table->type 'component';
  683.  
  684.                 // Ensure the integrity of the component_id field is maintained, particularly when changing the menu item type.
  685.                 $args array();
  686.                 parse_str(parse_url($table->linkPHP_URL_QUERY)$args);
  687.  
  688.                 if (isset($args['option']))
  689.                 {
  690.                     // Load the language file for the component.
  691.                     $lang JFactory::getLanguage();
  692.                     $lang->load($args['option']JPATH_ADMINISTRATORnullfalsetrue)
  693.                         || $lang->load($args['option']JPATH_ADMINISTRATOR '/components/' $args['option']nullfalsetrue);
  694.  
  695.                     // Determine the component id.
  696.                     $component JComponentHelper::getComponent($args['option']);
  697.  
  698.                     if (isset($component->id))
  699.                     {
  700.                         $table->component_id $component->id;
  701.                     }
  702.                 }
  703.                 break;
  704.         }
  705.  
  706.         // We have a valid type, inject it into the state for forms to use.
  707.         $this->setState('item.type'$table->type);
  708.  
  709.         // Convert to the JObject before adding the params.
  710.         $properties $table->getProperties(1);
  711.         $result JArrayHelper::toObject($properties);
  712.  
  713.         // Convert the params field to an array.
  714.         $registry new JRegistry;
  715.         $registry->loadString($table->params);
  716.         $result->params $registry->toArray();
  717.  
  718.         // Merge the request arguments in to the params for a component.
  719.         if ($table->type == 'component')
  720.         {
  721.             // Note that all request arguments become reserved parameter names.
  722.             $result->request $args;
  723.             $result->params array_merge($result->params$args);
  724.         }
  725.  
  726.         if ($table->type == 'alias')
  727.         {
  728.             // Note that all request arguments become reserved parameter names.
  729.             $args array();
  730.             parse_str(parse_url($table->linkPHP_URL_QUERY)$args);
  731.             $result->params array_merge($result->params$args);
  732.         }
  733.  
  734.         if ($table->type == 'url')
  735.         {
  736.             // Note that all request arguments become reserved parameter names.
  737.             $args array();
  738.             parse_str(parse_url($table->linkPHP_URL_QUERY)$args);
  739.             $result->params array_merge($result->params$args);
  740.         }
  741.  
  742.         // Load associated menu items
  743.         $app JFactory::getApplication();
  744.         $assoc JLanguageAssociations::isEnabled();
  745.         if ($assoc)
  746.         {
  747.             if ($pk != null)
  748.             {
  749.                 $result->associations MenusHelper::getAssociations($pk);
  750.             }
  751.             else
  752.             {
  753.                 $result->associations array();
  754.             }
  755.         }
  756.         $result->menuordering $pk;
  757.  
  758.         return $result;
  759.     }
  760.  
  761.     /**
  762.      * Get the list of modules not in trash.
  763.      *
  764.      * @return  mixed  An array of module records (id, title, position), or false on error.
  765.      * @since   1.6
  766.      */
  767.     public function getModules()
  768.     {
  769.         $db $this->getDbo();
  770.         $query $db->getQuery(true);
  771.  
  772.         // Join on the module-to-menu mapping table.
  773.         // We are only interested if the module is displayed on ALL or THIS menu item (or the inverse ID number).
  774.         //sqlsrv changes for modulelink to menu manager
  775.         $query->select('a.id, a.title, a.position, a.published, map.menuid')
  776.             ->from('#__modules AS a')
  777.             ->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')))
  778.             ->select('(SELECT COUNT(*) FROM #__modules_menu WHERE moduleid = a.id AND menuid < 0) AS ' $db->quoteName('except'));
  779.  
  780.         // Join on the asset groups table.
  781.         $query->select('ag.title AS access_title')
  782.             ->join('LEFT''#__viewlevels AS ag ON ag.id = a.access')
  783.             ->where('a.published >= 0')
  784.             ->where('a.client_id = 0')
  785.             ->order('a.position, a.ordering');
  786.  
  787.         $db->setQuery($query);
  788.  
  789.         try
  790.         {
  791.             $result $db->loadObjectList();
  792.         }
  793.         catch (RuntimeException $e)
  794.         {
  795.             $this->setError($e->getMessage());
  796.             return false;
  797.         }
  798.  
  799.         return $result;
  800.     }
  801.  
  802.     /**
  803.      * A protected method to get the where clause for the reorder
  804.      * This ensures that the row will be moved relative to a row with the same menutype
  805.      *
  806.      * @param   JTableMenu $table instance
  807.      *
  808.      * @return  array  An array of conditions to add to add to ordering queries.
  809.      * @since   1.6
  810.      */
  811.     protected function getReorderConditions($table)
  812.     {
  813.         return 'menutype = ' $this->_db->quote($table->menutype);
  814.     }
  815.  
  816.     /**
  817.      * Returns a Table object, always creating it
  818.      *
  819.      * @param   type      $type      The table type to instantiate
  820.      * @param   string    $prefix    A prefix for the table class name. Optional.
  821.      * @param   array     $config    Configuration array for model. Optional.
  822.      *
  823.      * @return  JTable    A database object
  824.      * @since   1.6
  825.      */
  826.     public function getTable($type 'Menu'$prefix 'MenusTable'$config array())
  827.     {
  828.         return JTable::getInstance($type$prefix$config);
  829.     }
  830.  
  831.     /**
  832.      * Auto-populate the model state.
  833.      *
  834.      * Note. Calling getState in this method will result in recursion.
  835.      *
  836.      * @return  void 
  837.      * @since   1.6
  838.      */
  839.     protected function populateState()
  840.     {
  841.         $app JFactory::getApplication('administrator');
  842.  
  843.         // Load the User state.
  844.         $pk $app->input->getInt('id');
  845.         $this->setState('item.id'$pk);
  846.  
  847.         if (!($parentId $app->getUserState('com_menus.edit.item.parent_id')))
  848.         {
  849.             $parentId $app->input->getInt('parent_id');
  850.         }
  851.         $this->setState('item.parent_id'$parentId);
  852.  
  853.         $menuType $app->getUserState('com_menus.edit.item.menutype');
  854.         if ($app->input->getString('menutype'false))
  855.         {
  856.             $menuType $app->input->getString('menutype''mainmenu');
  857.         }
  858.         $this->setState('item.menutype'$menuType);
  859.  
  860.         if (!($type $app->getUserState('com_menus.edit.item.type')))
  861.         {
  862.             $type $app->input->get('type');
  863.             // Note a new menu item will have no field type.
  864.             // The field is required so the user has to change it.
  865.         }
  866.         $this->setState('item.type'$type);
  867.  
  868.         if ($link $app->getUserState('com_menus.edit.item.link'))
  869.         {
  870.             $this->setState('item.link'$link);
  871.         }
  872.  
  873.         // Load the parameters.
  874.         $params JComponentHelper::getParams('com_menus');
  875.         $this->setState('params'$params);
  876.     }
  877.  
  878.     /**
  879.      * @param   object    $form    A form object.
  880.      * @param   mixed     $data    The data expected for the form.
  881.      *
  882.      * @return  void 
  883.      * @since   1.6
  884.      * @throws    Exception if there is an error in the form event.
  885.      */
  886.     protected function preprocessForm(JForm $form$data$group 'content')
  887.     {
  888.         $link $this->getState('item.link');
  889.         $type $this->getState('item.type');
  890.         $formFile false;
  891.  
  892.         // Initialise form with component view params if available.
  893.         if ($type == 'component')
  894.         {
  895.  
  896.             $link htmlspecialchars_decode($link);
  897.  
  898.             // Parse the link arguments.
  899.             $args array();
  900.             parse_str(parse_url(htmlspecialchars_decode($link)PHP_URL_QUERY)$args);
  901.  
  902.             // Confirm that the option is defined.
  903.             $option '';
  904.             $base '';
  905.             if (isset($args['option']))
  906.             {
  907.                 // The option determines the base path to work with.
  908.                 $option $args['option'];
  909.                 $base JPATH_SITE '/components/' $option;
  910.             }
  911.  
  912.             // Confirm a view is defined.
  913.             $formFile false;
  914.             if (isset($args['view']))
  915.             {
  916.                 $view $args['view'];
  917.  
  918.                 // Determine the layout to search for.
  919.                 if (isset($args['layout']))
  920.                 {
  921.                     $layout $args['layout'];
  922.                 }
  923.                 else
  924.                 {
  925.                     $layout 'default';
  926.                 }
  927.  
  928.                 $formFile false;
  929.  
  930.                 // Check for the layout XML file. Use standard xml file if it exists.
  931.                 $tplFolders array(
  932.                         $base '/views/' $view '/tmpl',
  933.                         $base '/view/' $view '/tmpl'
  934.                 );
  935.                 $path JPath::find($tplFolders$layout '.xml');
  936.  
  937.                 if (is_file($path))
  938.                 {
  939.                     $formFile $path;
  940.                 }
  941.  
  942.                 // If custom layout, get the xml file from the template folder
  943.                 // template folder is first part of file name -- template:folder
  944.                 if (!$formFile && (strpos($layout':'0))
  945.                 {
  946.                     $temp explode(':'$layout);
  947.                     $templatePath JPATH::clean(JPATH_SITE '/templates/' $temp[0'/html/' $option '/' $view '/' $temp[1'.xml');
  948.                     if (is_file($templatePath))
  949.                     {
  950.                         $formFile $templatePath;
  951.                     }
  952.                 }
  953.             }
  954.  
  955.             // Now check for a view manifest file
  956.             if (!$formFile)
  957.             {
  958.                 if (isset($view))
  959.                 {
  960.                     $metadataFolders array(
  961.                             $base '/view/' $view,
  962.                             $base '/views/' $view
  963.                     );
  964.                     $metaPath JPath::find($metadataFolders'metadata.xml');
  965.  
  966.                     if (is_file($path JPath::clean($metaPath)))
  967.                     {
  968.                         $formFile $path;
  969.                     }
  970.                 }
  971.                 else
  972.                 {
  973.                     // Now check for a component manifest file
  974.                     $path JPath::clean($base '/metadata.xml');
  975.                     if (is_file($path))
  976.                     {
  977.                         $formFile $path;
  978.                     }
  979.                 }
  980.             }
  981.         }
  982.  
  983.         if ($formFile)
  984.         {
  985.             // If an XML file was found in the component, load it first.
  986.             // We need to qualify the full path to avoid collisions with component file names.
  987.  
  988.             if ($form->loadFile($formFiletrue'/metadata'== false)
  989.             {
  990.                 throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
  991.             }
  992.  
  993.             // Attempt to load the xml file.
  994.             if (!$xml simplexml_load_file($formFile))
  995.             {
  996.                 throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
  997.             }
  998.  
  999.             // Get the help data from the XML file if present.
  1000.             $help $xml->xpath('/metadata/layout/help');
  1001.         }
  1002.         else
  1003.         {
  1004.             // We don't have a component. Load the form XML to get the help path
  1005.             $xmlFile JPath::find(JPATH_ROOT '/administrator/components/com_menus/models/forms''item_' $type '.xml');
  1006.  
  1007.             // Attempt to load the xml file.
  1008.             if ($xmlFile && !$xml simplexml_load_file($xmlFile))
  1009.             {
  1010.                 throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
  1011.             }
  1012.  
  1013.             // Get the help data from the XML file if present.
  1014.             $help $xml->xpath('/form/help');
  1015.         }
  1016.  
  1017.         if (!empty($help))
  1018.         {
  1019.             $helpKey trim((string) $help[0]['key']);
  1020.             $helpURL trim((string) $help[0]['url']);
  1021.             $helpLoc trim((string) $help[0]['local']);
  1022.  
  1023.             $this->helpKey = $helpKey $helpKey $this->helpKey;
  1024.             $this->helpURL = $helpURL $helpURL $this->helpURL;
  1025.             $this->helpLocal = (($helpLoc == 'true'|| ($helpLoc == '1'|| ($helpLoc == 'local')) true false;
  1026.         }
  1027.  
  1028.         // Now load the component params.
  1029.         // TODO: Work out why 'fixing' this breaks JForm
  1030.         if ($isNew false)
  1031.         {
  1032.             $path JPath::clean(JPATH_ADMINISTRATOR '/components/' $option '/config.xml');
  1033.         }
  1034.         else
  1035.         {
  1036.             $path 'null';
  1037.         }
  1038.  
  1039.         if (is_file($path))
  1040.         {
  1041.             // Add the component params last of all to the existing form.
  1042.             if (!$form->load($pathtrue'/config'))
  1043.             {
  1044.                 throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
  1045.             }
  1046.         }
  1047.  
  1048.         // Load the specific type file
  1049.         if (!$form->loadFile('item_' $typefalsefalse))
  1050.         {
  1051.             throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
  1052.         }
  1053.  
  1054.         // Association menu items
  1055.         $app JFactory::getApplication();
  1056.         $assoc JLanguageAssociations::isEnabled();
  1057.  
  1058.         if ($assoc)
  1059.         {
  1060.             $languages JLanguageHelper::getLanguages('lang_code');
  1061.  
  1062.             $addform new SimpleXMLElement('<form />');
  1063.             $fields $addform->addChild('fields');
  1064.             $fields->addAttribute('name''associations');
  1065.             $fieldset $fields->addChild('fieldset');
  1066.             $fieldset->addAttribute('name''item_associations');
  1067.             $fieldset->addAttribute('description''COM_MENUS_ITEM_ASSOCIATIONS_FIELDSET_DESC');
  1068.             $add false;
  1069.             foreach ($languages as $tag => $language)
  1070.             {
  1071.                 if ($tag != $data['language'])
  1072.                 {
  1073.                     $add true;
  1074.                     $field $fieldset->addChild('field');
  1075.                     $field->addAttribute('name'$tag);
  1076.                     $field->addAttribute('type''menuitem');
  1077.                     $field->addAttribute('language'$tag);
  1078.                     $field->addAttribute('label'$language->title);
  1079.                     $field->addAttribute('translate_label''false');
  1080.                     $option $field->addChild('option''COM_MENUS_ITEM_FIELD_ASSOCIATION_NO_VALUE');
  1081.                     $option->addAttribute('value''');
  1082.                 }
  1083.             }
  1084.             if ($add)
  1085.             {
  1086.                 $form->load($addformfalse);
  1087.             }
  1088.         }
  1089.  
  1090.         // Trigger the default form events.
  1091.         parent::preprocessForm($form$data$group);
  1092.     }
  1093.  
  1094.     /**
  1095.      * Method rebuild the entire nested set tree.
  1096.      *
  1097.      * @return  boolean  False on failure or error, true otherwise.
  1098.      * @since   1.6
  1099.      */
  1100.     public function rebuild()
  1101.     {
  1102.         // Initialiase variables.
  1103.         $db $this->getDbo();
  1104.         $query $db->getQuery(true);
  1105.         $table $this->getTable();
  1106.  
  1107.         if (!$table->rebuild())
  1108.         {
  1109.             $this->setError($table->getError());
  1110.             return false;
  1111.         }
  1112.  
  1113.         $query->select('id, params')
  1114.             ->from('#__menu')
  1115.             ->where('params NOT LIKE ' $db->quote('{%'))
  1116.             ->where('params <> ' $db->quote(''));
  1117.         $db->setQuery($query);
  1118.  
  1119.         try
  1120.         {
  1121.             $items $db->loadObjectList();
  1122.         }
  1123.         catch (RuntimeException $e)
  1124.         {
  1125.             return JError::raiseWarning(500$e->getMessage());
  1126.         }
  1127.  
  1128.         foreach ($items as &$item)
  1129.         {
  1130.             $registry new JRegistry;
  1131.             $registry->loadString($item->params);
  1132.             $params = (string) $registry;
  1133.  
  1134.             $query->clear();
  1135.             $query->update('#__menu')
  1136.                 ->set('params = ' $db->quote($params))
  1137.                 ->where('id = ' $item->id);
  1138.  
  1139.             try
  1140.             {
  1141.                 $db->setQuery($query)->execute();
  1142.             }
  1143.             catch (RuntimeException $e)
  1144.             {
  1145.                 return JError::raiseWarning(500$e->getMessage());
  1146.             }
  1147.  
  1148.             unset($registry);
  1149.         }
  1150.  
  1151.         // Clean the cache
  1152.         $this->cleanCache();
  1153.  
  1154.         return true;
  1155.     }
  1156.  
  1157.     /**
  1158.      * Method to save the form data.
  1159.      *
  1160.      * @param   array  $data    The form data.
  1161.      *
  1162.      * @return  boolean  True on success.
  1163.      * @since   1.6
  1164.      */
  1165.     public function save($data)
  1166.     {
  1167.         $pk (!empty($data['id'])) $data['id': (int) $this->getState('item.id');
  1168.         $isNew true;
  1169.         $table $this->getTable();
  1170.  
  1171.         // Load the row if saving an existing item.
  1172.         if ($pk 0)
  1173.         {
  1174.             $table->load($pk);
  1175.             $isNew false;
  1176.         }
  1177.         if (!$isNew)
  1178.         {
  1179.             if ($table->parent_id == $data['parent_id'])
  1180.             {
  1181.  
  1182.                 // If first is chosen make the item the first child of the selected parent.
  1183.                 if ($data['menuordering'== -1)
  1184.                 {
  1185.                     $table->setLocation($data['parent_id']'first-child');
  1186.                 }
  1187.                 // If last is chosen make it the last child of the selected parent.
  1188.                 elseif ($data['menuordering'== -2)
  1189.                 {
  1190.                     $table->setLocation($data['parent_id']'last-child');
  1191.                 }
  1192.                 // Don't try to put an item after itself. All other ones put after the selected item.
  1193.                 // $data['id'] is empty means it's a save as copy
  1194.                 elseif ($data['menuordering'&& $table->id != $data['menuordering'|| empty($data['id']))
  1195.                 {
  1196.                     $table->setLocation($data['menuordering']'after');
  1197.                 }
  1198.                 // Just leave it where it is if no change is made.
  1199.                 elseif ($data['menuordering'&& $table->id == $data['menuordering'])
  1200.                 {
  1201.                     unset($data['menuordering']);
  1202.                 }
  1203.             }
  1204.             // Set the new parent id if parent id not matched and put in last position
  1205.             else
  1206.             {
  1207.                 $table->setLocation($data['parent_id']'last-child');
  1208.             }
  1209.         }
  1210.         // We have a new item, so it is not a change.
  1211.         else
  1212.         {
  1213.             $table->setLocation($data['parent_id']'last-child');
  1214.         }
  1215.  
  1216.         // Bind the data.
  1217.         if (!$table->bind($data))
  1218.         {
  1219.             $this->setError($table->getError());
  1220.             return false;
  1221.         }
  1222.  
  1223.         // Alter the title & alias for save as copy.  Also, unset the home record.
  1224.         if (!$isNew && $data['id'== 0)
  1225.         {
  1226.             list($title$alias$this->generateNewTitle($table->parent_id$table->alias$table->title);
  1227.             $table->title $title;
  1228.             $table->alias $alias;
  1229.             $table->published 0;
  1230.             $table->home 0;
  1231.         }
  1232.  
  1233.         // Check the data.
  1234.         if (!$table->check())
  1235.         {
  1236.             $this->setError($table->getError());
  1237.             return false;
  1238.         }
  1239.  
  1240.         // Store the data.
  1241.         if (!$table->store())
  1242.         {
  1243.             $this->setError($table->getError());
  1244.             return false;
  1245.         }
  1246.  
  1247.         // Rebuild the tree path.
  1248.         if (!$table->rebuildPath($table->id))
  1249.         {
  1250.             $this->setError($table->getError());
  1251.             return false;
  1252.         }
  1253.  
  1254.         $this->setState('item.id'$table->id);
  1255.         $this->setState('item.menutype'$table->menutype);
  1256.  
  1257.         // Load associated menu items
  1258.         $app JFactory::getApplication();
  1259.         $assoc JLanguageAssociations::isEnabled();
  1260.         if ($assoc)
  1261.         {
  1262.             // Adding self to the association
  1263.             $associations $data['associations'];
  1264.             foreach ($associations as $tag => $id)
  1265.             {
  1266.                 if (empty($id))
  1267.                 {
  1268.                     unset($associations[$tag]);
  1269.                 }
  1270.             }
  1271.  
  1272.             // Detecting all item menus
  1273.             $all_language $table->language == '*';
  1274.             if ($all_language && !empty($associations))
  1275.             {
  1276.                 JError::raiseNotice(403JText::_('COM_MENUS_ERROR_ALL_LANGUAGE_ASSOCIATED'));
  1277.             }
  1278.  
  1279.             $associations[$table->language$table->id;
  1280.  
  1281.             // Deleting old association for these items
  1282.             $db JFactory::getDbo();
  1283.             $query $db->getQuery(true)
  1284.                 ->delete('#__associations')
  1285.                 ->where('context=' $db->quote('com_menus.item'))
  1286.                 ->where('id IN (' implode(','$associations')');
  1287.             $db->setQuery($query);
  1288.  
  1289.             try
  1290.             {
  1291.                 $db->execute();
  1292.             }
  1293.             catch (RuntimeException $e)
  1294.             {
  1295.                 $this->setError($e->getMessage());
  1296.                 return false;
  1297.             }
  1298.  
  1299.             if (!$all_language && count($associations1)
  1300.             {
  1301.                 // Adding new association for these items
  1302.                 $key md5(json_encode($associations));
  1303.                 $query->clear()
  1304.                     ->insert('#__associations');
  1305.                 foreach ($associations as $id)
  1306.                 {
  1307.                     $query->values($id ',' $db->quote('com_menus.item'',' $db->quote($key));
  1308.                 }
  1309.                 $db->setQuery($query);
  1310.  
  1311.                 try
  1312.                 {
  1313.                     $db->execute();
  1314.                 }
  1315.                 catch (RuntimeException $e)
  1316.                 {
  1317.                     $this->setError($e->getMessage());
  1318.                     return false;
  1319.                 }
  1320.             }
  1321.         }
  1322.  
  1323.         // Clean the cache
  1324.         $this->cleanCache();
  1325.  
  1326.         if (isset($data['link']))
  1327.         {
  1328.             $base JUri::base();
  1329.             $juri JUri::getInstance($base $data['link']);
  1330.             $option $juri->getVar('option');
  1331.  
  1332.             // Clean the cache
  1333.             parent::cleanCache($option);
  1334.         }
  1335.  
  1336.         return true;
  1337.     }
  1338.  
  1339.     /**
  1340.      * Method to save the reordered nested set tree.
  1341.      * First we save the new order values in the lft values of the changed ids.
  1342.      * Then we invoke the table rebuild to implement the new ordering.
  1343.      *
  1344.      * @param   array  $idArray      id's of rows to be reordered
  1345.      * @param   array  $lft_array    lft values of rows to be reordered
  1346.      *
  1347.      * @return  boolean false on failuer or error, true otherwise
  1348.      * @since   1.6
  1349.      */
  1350.     public function saveorder($idArray null$lft_array null)
  1351.     {
  1352.         // Get an instance of the table object.
  1353.         $table $this->getTable();
  1354.  
  1355.         if (!$table->saveorder($idArray$lft_array))
  1356.         {
  1357.             $this->setError($table->getError());
  1358.             return false;
  1359.         }
  1360.  
  1361.         // Clean the cache
  1362.         $this->cleanCache();
  1363.  
  1364.         return true;
  1365.     }
  1366.  
  1367.     /**
  1368.      * Method to change the home state of one or more items.
  1369.      *
  1370.      * @param   array    $pks      A list of the primary keys to change.
  1371.      * @param   integer  $value    The value of the home state.
  1372.      *
  1373.      * @return  boolean  True on success.
  1374.      * @since   1.6
  1375.      */
  1376.     public function setHome(&$pks$value 1)
  1377.     {
  1378.         $table $this->getTable();
  1379.         $pks = (array) $pks;
  1380.  
  1381.         $languages array();
  1382.         $onehome false;
  1383.  
  1384.         // Remember that we can set a home page for different languages,
  1385.         // so we need to loop through the primary key array.
  1386.         foreach ($pks as $i => $pk)
  1387.         {
  1388.             if ($table->load($pk))
  1389.             {
  1390.                 if (!array_key_exists($table->language$languages))
  1391.                 {
  1392.                     $languages[$table->languagetrue;
  1393.  
  1394.                     if ($table->home == $value)
  1395.                     {
  1396.                         unset($pks[$i]);
  1397.                         JError::raiseNotice(403JText::_('COM_MENUS_ERROR_ALREADY_HOME'));
  1398.                     }
  1399.                     else
  1400.                     {
  1401.                         $table->home $value;
  1402.                         if ($table->language == '*')
  1403.                         {
  1404.                             $table->published 1;
  1405.                         }
  1406.  
  1407.                         if (!$this->canSave($table))
  1408.                         {
  1409.                             // Prune items that you can't change.
  1410.                             unset($pks[$i]);
  1411.                             JError::raiseWarning(403JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'));
  1412.                         }
  1413.                         elseif (!$table->check())
  1414.                         {
  1415.                             // Prune the items that failed pre-save checks.
  1416.                             unset($pks[$i]);
  1417.                             JError::raiseWarning(403$table->getError());
  1418.                         }
  1419.                         elseif (!$table->store())
  1420.                         {
  1421.                             // Prune the items that could not be stored.
  1422.                             unset($pks[$i]);
  1423.                             JError::raiseWarning(403$table->getError());
  1424.                         }
  1425.                     }
  1426.                 }
  1427.                 else
  1428.                 {
  1429.                     unset($pks[$i]);
  1430.                     if (!$onehome)
  1431.                     {
  1432.                         $onehome true;
  1433.                         JError::raiseNotice(403JText::sprintf('COM_MENUS_ERROR_ONE_HOME'));
  1434.                     }
  1435.                 }
  1436.             }
  1437.         }
  1438.  
  1439.         // Clean the cache
  1440.         $this->cleanCache();
  1441.  
  1442.         return true;
  1443.     }
  1444.  
  1445.     /**
  1446.      * Method to change the published state of one or more records.
  1447.      *
  1448.      * @param   array       &$pks   A list of the primary keys to change.
  1449.      * @param   integer     $value  The value of the published state.
  1450.      *
  1451.      * @return  boolean  True on success.
  1452.      *
  1453.      * @since   1.6
  1454.      */
  1455.     public function publish(&$pks$value 1)
  1456.     {
  1457.         $table $this->getTable();
  1458.         $pks = (array) $pks;
  1459.  
  1460.         // Default menu item existence checks.
  1461.         if ($value != 1)
  1462.         {
  1463.             foreach ($pks as $i => $pk)
  1464.             {
  1465.                 if ($table->load($pk&& $table->home && $table->language == '*')
  1466.                 {
  1467.                     // Prune items that you can't change.
  1468.                     JError::raiseWarning(403JText::_('JLIB_DATABASE_ERROR_MENU_UNPUBLISH_DEFAULT_HOME'));
  1469.                     unset($pks[$i]);
  1470.                     break;
  1471.                 }
  1472.             }
  1473.         }
  1474.  
  1475.         // Clean the cache
  1476.         $this->cleanCache();
  1477.  
  1478.         // Ensure that previous checks doesn't empty the array
  1479.         if (empty($pks))
  1480.         {
  1481.             return true;
  1482.         }
  1483.  
  1484.         return parent::publish($pks$value);
  1485.     }
  1486.  
  1487.     /**
  1488.      * Method to change the title & alias.
  1489.      *
  1490.      * @param   integer  $parent_id  The id of the parent.
  1491.      * @param   string   $alias      The alias.
  1492.      * @param   string   $title      The title.
  1493.      *
  1494.      * @return  array  Contains the modified title and alias.
  1495.      *
  1496.      * @since   1.6
  1497.      */
  1498.     protected function generateNewTitle($parent_id$alias$title)
  1499.     {
  1500.         // Alter the title & alias
  1501.         $table $this->getTable();
  1502.         while ($table->load(array('alias' => $alias'parent_id' => $parent_id)))
  1503.         {
  1504.             if ($title == $table->title)
  1505.             {
  1506.                 $title JString::increment($title);
  1507.             }
  1508.             $alias JString::increment($alias'dash');
  1509.         }
  1510.  
  1511.         return array($title$alias);
  1512.     }
  1513.  
  1514.     /**
  1515.      * Custom clean cache method
  1516.      *
  1517.      * @since   1.6
  1518.      */
  1519.     protected function cleanCache($group null$client_id 0)
  1520.     {
  1521.         parent::cleanCache('com_modules');
  1522.         parent::cleanCache('mod_menu');
  1523.     }
  1524. }

Documentation generated on Tue, 19 Nov 2013 15:05:57 +0100 by phpDocumentor 1.4.3