Source for file module.php

Documentation is available at module.php

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

Documentation generated on Tue, 19 Nov 2013 15:08:47 +0100 by phpDocumentor 1.4.3