Source for file article.php

Documentation is available at article.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Administrator
  4.  * @subpackage  com_content
  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. require_once JPATH_COMPONENT_ADMINISTRATOR '/helpers/content.php';
  13.  
  14. /**
  15.  * Item Model for an Article.
  16.  *
  17.  * @package     Joomla.Administrator
  18.  * @subpackage  com_content
  19.  * @since       1.6
  20.  */
  21. {
  22.     /**
  23.      * @var        string    The prefix to use with controller messages.
  24.      * @since   1.6
  25.      */
  26.     protected $text_prefix = 'COM_CONTENT';
  27.  
  28.     /**
  29.      * The type alias for this content type (for example, 'com_content.article').
  30.      *
  31.      * @var      string 
  32.      * @since    3.2
  33.      */
  34.     public $typeAlias = 'com_content.article';
  35.  
  36.     /**
  37.      * Batch copy items to a new category or current.
  38.      *
  39.      * @param   integer  $value     The new category.
  40.      * @param   array    $pks       An array of row IDs.
  41.      * @param   array    $contexts  An array of item contexts.
  42.      *
  43.      * @return  mixed  An array of new IDs on success, boolean false on failure.
  44.      *
  45.      * @since   11.1
  46.      */
  47.     protected function batchCopy($value$pks$contexts)
  48.     {
  49.         $categoryId = (int) $value;
  50.  
  51.         $i 0;
  52.  
  53.         if (!parent::checkCategoryId($categoryId))
  54.         {
  55.             return false;
  56.         }
  57.  
  58.         // Parent exists so we let's proceed
  59.         while (!empty($pks))
  60.         {
  61.             // Pop the first ID off the stack
  62.             $pk array_shift($pks);
  63.  
  64.             $this->table->reset();
  65.  
  66.             // Check that the row actually exists
  67.             if (!$this->table->load($pk))
  68.             {
  69.                 if ($error $this->table->getError())
  70.                 {
  71.                     // Fatal error
  72.                     $this->setError($error);
  73.  
  74.                     return false;
  75.                 }
  76.                 else
  77.                 {
  78.                     // Not fatal error
  79.                     $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND'$pk));
  80.                     continue;
  81.                 }
  82.             }
  83.  
  84.             // Alter the title & alias
  85.             $data $this->generateNewTitle($categoryId$this->table->alias$this->table->title);
  86.             $this->table->title $data['0'];
  87.             $this->table->alias $data['1'];
  88.  
  89.             // Reset the ID because we are making a copy
  90.             $this->table->id 0;
  91.  
  92.             // New category ID
  93.             $this->table->catid $categoryId;
  94.  
  95.             // TODO: Deal with ordering?
  96.             //$table->ordering    = 1;
  97.  
  98.             // Get the featured state
  99.             $featured $this->table->featured;
  100.  
  101.             // Check the row.
  102.             if (!$this->table->check())
  103.             {
  104.                 $this->setError($table->getError());
  105.                 return false;
  106.             }
  107.  
  108.             parent::createTagsHelper($this->tagsObserver$this->type$pk$this->typeAlias$this->table);
  109.  
  110.             // Store the row.
  111.             if (!$this->table->store())
  112.             {
  113.                 $this->setError($table->getError());
  114.                 return false;
  115.             }
  116.  
  117.             // Get the new item ID
  118.             $newId $this->table->get('id');
  119.  
  120.             // Add the new ID to the array
  121.             $newIds[$i$newId;
  122.             $i++;
  123.  
  124.             // Check if the article was featured and update the #__content_frontpage table
  125.             if ($featured == 1)
  126.             {
  127.                 $db $this->getDbo();
  128.                 $query $db->getQuery(true)
  129.                     ->insert($db->quoteName('#__content_frontpage'))
  130.                     ->values($newId ', 0');
  131.                 $db->setQuery($query);
  132.                 $db->execute();
  133.             }
  134.         }
  135.  
  136.         // Clean the cache
  137.         $this->cleanCache();
  138.  
  139.         return $newIds;
  140.     }
  141.  
  142.     /**
  143.      * Method to test whether a record can be deleted.
  144.      *
  145.      * @param   object    $record    A record object.
  146.      *
  147.      * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
  148.      * @since   1.6
  149.      */
  150.     protected function canDelete($record)
  151.     {
  152.         if (!empty($record->id))
  153.         {
  154.             if ($record->state != -2)
  155.             {
  156.                 return;
  157.             }
  158.             $user JFactory::getUser();
  159.             return $user->authorise('core.delete''com_content.article.' . (int) $record->id);
  160.         }
  161.     }
  162.  
  163.     /**
  164.      * Method to test whether a record can have its state edited.
  165.      *
  166.      * @param   object    $record    A record object.
  167.      *
  168.      * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
  169.      * @since   1.6
  170.      */
  171.     protected function canEditState($record)
  172.     {
  173.         $user JFactory::getUser();
  174.  
  175.         // Check for existing article.
  176.         if (!empty($record->id))
  177.         {
  178.             return $user->authorise('core.edit.state''com_content.article.' . (int) $record->id);
  179.         }
  180.         // New article, so check against the category.
  181.         elseif (!empty($record->catid))
  182.         {
  183.             return $user->authorise('core.edit.state''com_content.category.' . (int) $record->catid);
  184.         }
  185.         // Default to component settings if neither article nor category known.
  186.         else
  187.         {
  188.             return parent::canEditState('com_content');
  189.         }
  190.     }
  191.  
  192.     /**
  193.      * Prepare and sanitise the table data prior to saving.
  194.      *
  195.      * @param   JTable    A JTable object.
  196.      *
  197.      * @return  void 
  198.      * @since   1.6
  199.      */
  200.     protected function prepareTable($table)
  201.     {
  202.         // Set the publish date to now
  203.         $db $this->getDbo();
  204.         if ($table->state == && (int) $table->publish_up == 0)
  205.         {
  206.             $table->publish_up JFactory::getDate()->toSql();
  207.         }
  208.  
  209.         if ($table->state == && intval($table->publish_down== 0)
  210.         {
  211.             $table->publish_down $db->getNullDate();
  212.         }
  213.  
  214.         // Increment the content version number.
  215.         $table->version++;
  216.  
  217.         // Reorder the articles within the category so the new article is first
  218.         if (empty($table->id))
  219.         {
  220.             $table->reorder('catid = ' . (int) $table->catid ' AND state >= 0');
  221.         }
  222.     }
  223.  
  224.     /**
  225.      * Returns a Table object, always creating it.
  226.      *
  227.      * @param   type      The table type to instantiate
  228.      * @param   string    A prefix for the table class name. Optional.
  229.      * @param   array     Configuration array for model. Optional.
  230.      *
  231.      * @return  JTable    A database object
  232.      */
  233.     public function getTable($type 'Content'$prefix 'JTable'$config array())
  234.     {
  235.         return JTable::getInstance($type$prefix$config);
  236.     }
  237.  
  238.     /**
  239.      * Method to get a single record.
  240.      *
  241.      * @param   integer    The id of the primary key.
  242.      *
  243.      * @return  mixed  Object on success, false on failure.
  244.      */
  245.     public function getItem($pk null)
  246.     {
  247.         if ($item parent::getItem($pk))
  248.         {
  249.             // Convert the params field to an array.
  250.             $registry new JRegistry;
  251.             $registry->loadString($item->attribs);
  252.             $item->attribs $registry->toArray();
  253.  
  254.             // Convert the metadata field to an array.
  255.             $registry new JRegistry;
  256.             $registry->loadString($item->metadata);
  257.             $item->metadata $registry->toArray();
  258.  
  259.             // Convert the images field to an array.
  260.             $registry new JRegistry;
  261.             $registry->loadString($item->images);
  262.             $item->images $registry->toArray();
  263.  
  264.             // Convert the urls field to an array.
  265.             $registry new JRegistry;
  266.             $registry->loadString($item->urls);
  267.             $item->urls $registry->toArray();
  268.  
  269.             $item->articletext trim($item->fulltext!= '' $item->introtext "<hr id=\"system-readmore\" />" $item->fulltext $item->introtext;
  270.  
  271.             if (!empty($item->id))
  272.             {
  273.                 $item->tags new JHelperTags;
  274.                 $item->tags->getTagIds($item->id'com_content.article');
  275.             }
  276.         }
  277.  
  278.         // Load associated content items
  279.         $app JFactory::getApplication();
  280.         $assoc JLanguageAssociations::isEnabled();
  281.  
  282.         if ($assoc)
  283.         {
  284.             $item->associations array();
  285.  
  286.             if ($item->id != null)
  287.             {
  288.                 $associations JLanguageAssociations::getAssociations('com_content''#__content''com_content.item'$item->id);
  289.  
  290.                 foreach ($associations as $tag => $association)
  291.                 {
  292.                     $item->associations[$tag$association->id;
  293.                 }
  294.             }
  295.         }
  296.  
  297.         return $item;
  298.     }
  299.  
  300.     /**
  301.      * Method to get the record form.
  302.      *
  303.      * @param   array      $data        Data for the form.
  304.      * @param   boolean    $loadData    True if the form is to load its own data (default case), false if not.
  305.      *
  306.      * @return  mixed  A JForm object on success, false on failure
  307.      * @since   1.6
  308.      */
  309.     public function getForm($data array()$loadData true)
  310.     {
  311.         // Get the form.
  312.         $form $this->loadForm('com_content.article''article'array('control' => 'jform''load_data' => $loadData));
  313.         if (empty($form))
  314.         {
  315.             return false;
  316.         }
  317.         $jinput JFactory::getApplication()->input;
  318.  
  319.         // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first.
  320.         if ($jinput->get('a_id'))
  321.         {
  322.             $id $jinput->get('a_id'0);
  323.         }
  324.         // The back end uses id so we use that the rest of the time and set it to 0 by default.
  325.         else
  326.         {
  327.             $id $jinput->get('id'0);
  328.         }
  329.         // Determine correct permissions to check.
  330.         if ($this->getState('article.id'))
  331.         {
  332.             $id $this->getState('article.id');
  333.             // Existing record. Can only edit in selected categories.
  334.             $form->setFieldAttribute('catid''action''core.edit');
  335.             // Existing record. Can only edit own articles in selected categories.
  336.             $form->setFieldAttribute('catid''action''core.edit.own');
  337.         }
  338.         else
  339.         {
  340.             // New record. Can only create in selected categories.
  341.             $form->setFieldAttribute('catid''action''core.create');
  342.         }
  343.  
  344.         $user JFactory::getUser();
  345.  
  346.         // Check for existing article.
  347.         // Modify the form based on Edit State access controls.
  348.         if ($id != && (!$user->authorise('core.edit.state''com_content.article.' . (int) $id))
  349.             || ($id == && !$user->authorise('core.edit.state''com_content'))
  350.         )
  351.         {
  352.             // Disable fields for display.
  353.             $form->setFieldAttribute('featured''disabled''true');
  354.             $form->setFieldAttribute('ordering''disabled''true');
  355.             $form->setFieldAttribute('publish_up''disabled''true');
  356.             $form->setFieldAttribute('publish_down''disabled''true');
  357.             $form->setFieldAttribute('state''disabled''true');
  358.  
  359.             // Disable fields while saving.
  360.             // The controller has already verified this is an article you can edit.
  361.             $form->setFieldAttribute('featured''filter''unset');
  362.             $form->setFieldAttribute('ordering''filter''unset');
  363.             $form->setFieldAttribute('publish_up''filter''unset');
  364.             $form->setFieldAttribute('publish_down''filter''unset');
  365.             $form->setFieldAttribute('state''filter''unset');
  366.         }
  367.  
  368.         // Prevent messing with article language and category when editing existing article with associations
  369.         $app JFactory::getApplication();
  370.         $assoc JLanguageAssociations::isEnabled();
  371.  
  372.         if ($app->isSite(&& $assoc && $this->getState('article.id'))
  373.         {
  374.             $form->setFieldAttribute('language''readonly''true');
  375.             $form->setFieldAttribute('catid''readonly''true');
  376.             $form->setFieldAttribute('language''filter''unset');
  377.             $form->setFieldAttribute('catid''filter''unset');
  378.         }
  379.  
  380.         return $form;
  381.     }
  382.  
  383.     /**
  384.      * Method to get the data that should be injected in the form.
  385.      *
  386.      * @return  mixed  The data for the form.
  387.      * @since   1.6
  388.      */
  389.     protected function loadFormData()
  390.     {
  391.         // Check the session for previously entered form data.
  392.         $app JFactory::getApplication();
  393.         $data $app->getUserState('com_content.edit.article.data'array());
  394.  
  395.         if (empty($data))
  396.         {
  397.             $data $this->getItem();
  398.  
  399.             // Prime some default values.
  400.             if ($this->getState('article.id'== 0)
  401.             {
  402.                 $data->set('catid'$app->input->getInt('catid'$app->getUserState('com_content.articles.filter.category_id')));
  403.             }
  404.         }
  405.  
  406.         $this->preprocessData('com_content.article'$data);
  407.  
  408.         return $data;
  409.     }
  410.  
  411.     /**
  412.      * Method to save the form data.
  413.      *
  414.      * @param   array  The form data.
  415.      *
  416.      * @return  boolean  True on success.
  417.      * @since   1.6
  418.      */
  419.     public function save($data)
  420.     {
  421.         $app JFactory::getApplication();
  422.  
  423.         if (isset($data['images']&& is_array($data['images']))
  424.         {
  425.             $registry new JRegistry;
  426.             $registry->loadArray($data['images']);
  427.             $data['images'= (string) $registry;
  428.         }
  429.  
  430.         if (isset($data['urls']&& is_array($data['urls']))
  431.         {
  432.  
  433.             foreach ($data['urls'as $i => $url)
  434.             {
  435.                 if ($url != false && ($i == 'urla' || $i == 'urlb' || $i == 'urlc'))
  436.                 {
  437.                     $data['urls'][$iJStringPunycode::urlToPunycode($url);
  438.                 }
  439.  
  440.             }
  441.             $registry new JRegistry;
  442.             $registry->loadArray($data['urls']);
  443.             $data['urls'= (string) $registry;
  444.         }
  445.  
  446.         // Alter the title for save as copy
  447.         if ($app->input->get('task'== 'save2copy')
  448.         {
  449.             list($title$alias$this->generateNewTitle($data['catid']$data['alias']$data['title']);
  450.             $data['title'$title;
  451.             $data['alias'$alias;
  452.             $data['state'0;
  453.         }
  454.  
  455.         if (parent::save($data))
  456.         {
  457.  
  458.             if (isset($data['featured']))
  459.             {
  460.                 $this->featured($this->getState($this->getName('.id')$data['featured']);
  461.             }
  462.  
  463.             $assoc JLanguageAssociations::isEnabled();
  464.             if ($assoc)
  465.             {
  466.                 $id = (int) $this->getState($this->getName('.id');
  467.                 $item $this->getItem($id);
  468.  
  469.                 // Adding self to the association
  470.                 $associations $data['associations'];
  471.  
  472.                 foreach ($associations as $tag => $id)
  473.                 {
  474.                     if (empty($id))
  475.                     {
  476.                         unset($associations[$tag]);
  477.                     }
  478.                 }
  479.  
  480.                 // Detecting all item menus
  481.                 $all_language $item->language == '*';
  482.  
  483.                 if ($all_language && !empty($associations))
  484.                 {
  485.                     JError::raiseNotice(403JText::_('COM_CONTENT_ERROR_ALL_LANGUAGE_ASSOCIATED'));
  486.                 }
  487.  
  488.                 $associations[$item->language$item->id;
  489.  
  490.                 // Deleting old association for these items
  491.                 $db JFactory::getDbo();
  492.                 $query $db->getQuery(true)
  493.                     ->delete('#__associations')
  494.                     ->where('context=' $db->quote('com_content.item'))
  495.                     ->where('id IN (' implode(','$associations')');
  496.                 $db->setQuery($query);
  497.                 $db->execute();
  498.  
  499.                 if ($error $db->getErrorMsg())
  500.                 {
  501.                     $this->setError($error);
  502.                     return false;
  503.                 }
  504.  
  505.                 if (!$all_language && count($associations))
  506.                 {
  507.                     // Adding new association for these items
  508.                     $key md5(json_encode($associations));
  509.                     $query->clear()
  510.                         ->insert('#__associations');
  511.  
  512.                     foreach ($associations as $id)
  513.                     {
  514.                         $query->values($id ',' $db->quote('com_content.item'',' $db->quote($key));
  515.                     }
  516.  
  517.                     $db->setQuery($query);
  518.                     $db->execute();
  519.  
  520.                     if ($error $db->getErrorMsg())
  521.                     {
  522.                         $this->setError($error);
  523.                         return false;
  524.                     }
  525.                 }
  526.             }
  527.  
  528.             return true;
  529.         }
  530.  
  531.         return false;
  532.     }
  533.  
  534.     /**
  535.      * Method to toggle the featured setting of articles.
  536.      *
  537.      * @param   array    The ids of the items to toggle.
  538.      * @param   integer  The value to toggle to.
  539.      *
  540.      * @return  boolean  True on success.
  541.      */
  542.     public function featured($pks$value 0)
  543.     {
  544.         // Sanitize the ids.
  545.         $pks = (array) $pks;
  546.         JArrayHelper::toInteger($pks);
  547.  
  548.         if (empty($pks))
  549.         {
  550.             $this->setError(JText::_('COM_CONTENT_NO_ITEM_SELECTED'));
  551.             return false;
  552.         }
  553.  
  554.         $table $this->getTable('Featured''ContentTable');
  555.  
  556.         try
  557.         {
  558.             $db $this->getDbo();
  559.             $query $db->getQuery(true)
  560.                         ->update($db->quoteName('#__content'))
  561.                         ->set('featured = ' . (int) $value)
  562.                         ->where('id IN (' implode(','$pks')');
  563.             $db->setQuery($query);
  564.             $db->execute();
  565.  
  566.             if ((int) $value == 0)
  567.             {
  568.                 // Adjust the mapping table.
  569.                 // Clear the existing features settings.
  570.                 $query $db->getQuery(true)
  571.                             ->delete($db->quoteName('#__content_frontpage'))
  572.                             ->where('content_id IN (' implode(','$pks')');
  573.                 $db->setQuery($query);
  574.                 $db->execute();
  575.             }
  576.             else
  577.             {
  578.                 // first, we find out which of our new featured articles are already featured.
  579.                 $query $db->getQuery(true)
  580.                     ->select('f.content_id')
  581.                     ->from('#__content_frontpage AS f')
  582.                     ->where('content_id IN (' implode(','$pks')');
  583.                 //echo $query;
  584.                 $db->setQuery($query);
  585.  
  586.                 $old_featured $db->loadColumn();
  587.  
  588.                 // we diff the arrays to get a list of the articles that are newly featured
  589.                 $new_featured array_diff($pks$old_featured);
  590.  
  591.                 // Featuring.
  592.                 $tuples array();
  593.                 foreach ($new_featured as $pk)
  594.                 {
  595.                     $tuples[$pk ', 0';
  596.                 }
  597.                 if (count($tuples))
  598.                 {
  599.                     $db $this->getDbo();
  600.                     $columns array('content_id''ordering');
  601.                     $query $db->getQuery(true)
  602.                         ->insert($db->quoteName('#__content_frontpage'))
  603.                         ->columns($db->quoteName($columns))
  604.                         ->values($tuples);
  605.                     $db->setQuery($query);
  606.                     $db->execute();
  607.                 }
  608.             }
  609.         }
  610.         catch (Exception $e)
  611.         {
  612.             $this->setError($e->getMessage());
  613.             return false;
  614.         }
  615.  
  616.         $table->reorder();
  617.  
  618.         $this->cleanCache();
  619.  
  620.         return true;
  621.     }
  622.  
  623.     /**
  624.      * A protected method to get a set of ordering conditions.
  625.      *
  626.      * @param   object    record object.
  627.      *
  628.      * @return  array  An array of conditions to add to add to ordering queries.
  629.      * @since   1.6
  630.      */
  631.     protected function getReorderConditions($table)
  632.     {
  633.         $condition array();
  634.         $condition['catid = ' . (int) $table->catid;
  635.         return $condition;
  636.     }
  637.  
  638.     /**
  639.      * Auto-populate the model state.
  640.      *
  641.      * Note. Calling getState in this method will result in recursion.
  642.      *
  643.      * @return  void 
  644.      * @since    3.0
  645.      */
  646.     protected function preprocessForm(JForm $form$data$group 'content')
  647.     {
  648.         // Association content items
  649.         $app JFactory::getApplication();
  650.         $assoc JLanguageAssociations::isEnabled();
  651.         if ($assoc)
  652.         {
  653.             $languages JLanguageHelper::getLanguages('lang_code');
  654.  
  655.             // force to array (perhaps move to $this->loadFormData())
  656.             $data = (array) $data;
  657.  
  658.             $addform new SimpleXMLElement('<form />');
  659.             $fields $addform->addChild('fields');
  660.             $fields->addAttribute('name''associations');
  661.             $fieldset $fields->addChild('fieldset');
  662.             $fieldset->addAttribute('name''item_associations');
  663.             $fieldset->addAttribute('description''COM_CONTENT_ITEM_ASSOCIATIONS_FIELDSET_DESC');
  664.             $add false;
  665.             foreach ($languages as $tag => $language)
  666.             {
  667.                 if (empty($data['language']|| $tag != $data['language'])
  668.                 {
  669.                     $add true;
  670.                     $field $fieldset->addChild('field');
  671.                     $field->addAttribute('name'$tag);
  672.                     $field->addAttribute('type''modal_article');
  673.                     $field->addAttribute('language'$tag);
  674.                     $field->addAttribute('label'$language->title);
  675.                     $field->addAttribute('translate_label''false');
  676.                     $field->addAttribute('edit''true');
  677.                     $field->addAttribute('clear''true');
  678.                 }
  679.             }
  680.             if ($add)
  681.             {
  682.                 $form->load($addformfalse);
  683.             }
  684.         }
  685.  
  686.         parent::preprocessForm($form$data$group);
  687.     }
  688.  
  689.     /**
  690.      * Custom clean the cache of com_content and content modules
  691.      *
  692.      * @since   1.6
  693.      */
  694.     protected function cleanCache($group null$client_id 0)
  695.     {
  696.         parent::cleanCache('com_content');
  697.         parent::cleanCache('mod_articles_archive');
  698.         parent::cleanCache('mod_articles_categories');
  699.         parent::cleanCache('mod_articles_category');
  700.         parent::cleanCache('mod_articles_latest');
  701.         parent::cleanCache('mod_articles_news');
  702.         parent::cleanCache('mod_articles_popular');
  703.     }
  704. }

Documentation generated on Tue, 19 Nov 2013 14:53:58 +0100 by phpDocumentor 1.4.3