[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/administrator/components/com_contenthistory/src/Helper/ -> ContenthistoryHelper.php (source)

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Administrator
   5   * @subpackage  com_contenthistory
   6   *
   7   * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
   8   * @license     GNU General Public License version 2 or later; see LICENSE.txt
   9   */
  10  
  11  namespace Joomla\Component\Contenthistory\Administrator\Helper;
  12  
  13  use Joomla\CMS\Factory;
  14  use Joomla\CMS\Filesystem\File;
  15  use Joomla\CMS\Filesystem\Folder;
  16  use Joomla\CMS\Filesystem\Path;
  17  use Joomla\CMS\Language\Text;
  18  use Joomla\CMS\Table\ContentHistory;
  19  use Joomla\CMS\Table\ContentType;
  20  use Joomla\CMS\Table\Table;
  21  use Joomla\Database\ParameterType;
  22  
  23  // phpcs:disable PSR1.Files.SideEffects
  24  \defined('_JEXEC') or die;
  25  // phpcs:enable PSR1.Files.SideEffects
  26  
  27  /**
  28   * Categories helper.
  29   *
  30   * @since  3.2
  31   */
  32  class ContenthistoryHelper
  33  {
  34      /**
  35       * Method to put all field names, including nested ones, in a single array for easy lookup.
  36       *
  37       * @param   \stdClass  $object  Standard class object that may contain one level of nested objects.
  38       *
  39       * @return  array  Associative array of all field names, including ones in a nested object.
  40       *
  41       * @since   3.2
  42       */
  43      public static function createObjectArray($object)
  44      {
  45          $result = array();
  46  
  47          if ($object === null) {
  48              return $result;
  49          }
  50  
  51          foreach ($object as $name => $value) {
  52              $result[$name] = $value;
  53  
  54              if (is_object($value)) {
  55                  foreach ($value as $subName => $subValue) {
  56                      $result[$subName] = $subValue;
  57                  }
  58              }
  59          }
  60  
  61          return $result;
  62      }
  63  
  64      /**
  65       * Method to decode JSON-encoded fields in a standard object. Used to unpack JSON strings in the content history data column.
  66       *
  67       * @param   string  $jsonString  JSON String to convert to an object.
  68       *
  69       * @return  \stdClass  Object with any JSON-encoded fields unpacked.
  70       *
  71       * @since   3.2
  72       */
  73      public static function decodeFields($jsonString)
  74      {
  75          $object = json_decode($jsonString);
  76  
  77          if (is_object($object)) {
  78              foreach ($object as $name => $value) {
  79                  if ($subObject = json_decode($value)) {
  80                      $object->$name = $subObject;
  81                  }
  82              }
  83          }
  84  
  85          return $object;
  86      }
  87  
  88      /**
  89       * Method to get field labels for the fields in the JSON-encoded object.
  90       * First we see if we can find translatable labels for the fields in the object.
  91       * We translate any we can find and return an array in the format object->name => label.
  92       *
  93       * @param   \stdClass    $object      Standard class object in the format name->value.
  94       * @param   ContentType  $typesTable  Table object with content history options.
  95       *
  96       * @return  \stdClass  Contains two associative arrays.
  97       *                    $formValues->labels in the format name => label (for example, 'id' => 'Article ID').
  98       *                    $formValues->values in the format name => value (for example, 'state' => 'Published'.
  99       *                    This translates the text from the selected option in the form.
 100       *
 101       * @since   3.2
 102       */
 103      public static function getFormValues($object, ContentType $typesTable)
 104      {
 105          $labels = array();
 106          $values = array();
 107          $expandedObjectArray = static::createObjectArray($object);
 108          static::loadLanguageFiles($typesTable->type_alias);
 109  
 110          if ($formFile = static::getFormFile($typesTable)) {
 111              if ($xml = simplexml_load_file($formFile)) {
 112                  // Now we need to get all of the labels from the form
 113                  $fieldArray = $xml->xpath('//field');
 114                  $fieldArray = array_merge($fieldArray, $xml->xpath('//fields'));
 115  
 116                  foreach ($fieldArray as $field) {
 117                      if ($label = (string) $field->attributes()->label) {
 118                          $labels[(string) $field->attributes()->name] = Text::_($label);
 119                      }
 120                  }
 121  
 122                  // Get values for any list type fields
 123                  $listFieldArray = $xml->xpath('//field[@type="list" or @type="radio"]');
 124  
 125                  foreach ($listFieldArray as $field) {
 126                      $name = (string) $field->attributes()->name;
 127  
 128                      if (isset($expandedObjectArray[$name])) {
 129                          $optionFieldArray = $field->xpath('option[@value="' . $expandedObjectArray[$name] . '"]');
 130  
 131                          $valueText = null;
 132  
 133                          if (is_array($optionFieldArray) && count($optionFieldArray)) {
 134                              $valueText = trim((string) $optionFieldArray[0]);
 135                          }
 136  
 137                          $values[(string) $field->attributes()->name] = Text::_($valueText);
 138                      }
 139                  }
 140              }
 141          }
 142  
 143          $result = new \stdClass();
 144          $result->labels = $labels;
 145          $result->values = $values;
 146  
 147          return $result;
 148      }
 149  
 150      /**
 151       * Method to get the XML form file for this component. Used to get translated field names for history preview.
 152       *
 153       * @param   ContentType  $typesTable  Table object with content history options.
 154       *
 155       * @return  mixed  \JModel object if successful, false if no model found.
 156       *
 157       * @since   3.2
 158       */
 159      public static function getFormFile(ContentType $typesTable)
 160      {
 161          // First, see if we have a file name in the $typesTable
 162          $options = json_decode($typesTable->content_history_options);
 163  
 164          if (is_object($options) && isset($options->formFile) && File::exists(JPATH_ROOT . '/' . $options->formFile)) {
 165              $result = JPATH_ROOT . '/' . $options->formFile;
 166          } else {
 167              $aliasArray = explode('.', $typesTable->type_alias);
 168              $component = ($aliasArray[1] == 'category') ? 'com_categories' : $aliasArray[0];
 169              $path  = Folder::makeSafe(JPATH_ADMINISTRATOR . '/components/' . $component . '/models/forms/');
 170              array_shift($aliasArray);
 171              $file = File::makeSafe(implode('.', $aliasArray) . '.xml');
 172              $result = File::exists($path . $file) ? $path . $file : false;
 173          }
 174  
 175          return $result;
 176      }
 177  
 178      /**
 179       * Method to query the database using values from lookup objects.
 180       *
 181       * @param   \stdClass  $lookup  The std object with the values needed to do the query.
 182       * @param   mixed      $value   The value used to find the matching title or name. Typically the id.
 183       *
 184       * @return  mixed  Value from database (for example, name or title) on success, false on failure.
 185       *
 186       * @since   3.2
 187       */
 188      public static function getLookupValue($lookup, $value)
 189      {
 190          $result = false;
 191  
 192          if (isset($lookup->sourceColumn) && isset($lookup->targetTable) && isset($lookup->targetColumn) && isset($lookup->displayColumn)) {
 193              $db    = Factory::getDbo();
 194              $value = (int) $value;
 195              $query = $db->getQuery(true);
 196              $query->select($db->quoteName($lookup->displayColumn))
 197                  ->from($db->quoteName($lookup->targetTable))
 198                  ->where($db->quoteName($lookup->targetColumn) . ' = :value')
 199                  ->bind(':value', $value, ParameterType::INTEGER);
 200              $db->setQuery($query);
 201  
 202              try {
 203                  $result = $db->loadResult();
 204              } catch (\Exception $e) {
 205                  // Ignore any errors and just return false
 206                  return false;
 207              }
 208          }
 209  
 210          return $result;
 211      }
 212  
 213      /**
 214       * Method to remove fields from the object based on values entered in the #__content_types table.
 215       *
 216       * @param   \stdClass    $object     Object to be passed to view layout file.
 217       * @param   ContentType  $typeTable  Table object with content history options.
 218       *
 219       * @return  \stdClass  object with hidden fields removed.
 220       *
 221       * @since   3.2
 222       */
 223      public static function hideFields($object, ContentType $typeTable)
 224      {
 225          if ($options = json_decode($typeTable->content_history_options)) {
 226              if (isset($options->hideFields) && is_array($options->hideFields)) {
 227                  foreach ($options->hideFields as $field) {
 228                      unset($object->$field);
 229                  }
 230              }
 231          }
 232  
 233          return $object;
 234      }
 235  
 236      /**
 237       * Method to load the language files for the component whose history is being viewed.
 238       *
 239       * @param   string  $typeAlias  The type alias, for example 'com_content.article'.
 240       *
 241       * @return  void
 242       *
 243       * @since   3.2
 244       */
 245      public static function loadLanguageFiles($typeAlias)
 246      {
 247          $aliasArray = explode('.', $typeAlias);
 248  
 249          if (is_array($aliasArray) && count($aliasArray) == 2) {
 250              $component = ($aliasArray[1] == 'category') ? 'com_categories' : $aliasArray[0];
 251              $lang = Factory::getLanguage();
 252  
 253              /**
 254               * Loading language file from the administrator/language directory then
 255               * loading language file from the administrator/components/extension/language directory
 256               */
 257              $lang->load($component, JPATH_ADMINISTRATOR)
 258              || $lang->load($component, Path::clean(JPATH_ADMINISTRATOR . '/components/' . $component));
 259  
 260              // Force loading of backend global language file
 261              $lang->load('joomla', Path::clean(JPATH_ADMINISTRATOR));
 262          }
 263      }
 264  
 265      /**
 266       * Method to create object to pass to the layout. Format is as follows:
 267       * field is std object with name, value.
 268       *
 269       * Value can be a std object with name, value pairs.
 270       *
 271       * @param   \stdClass  $object      The std object from the JSON string. Can be nested 1 level deep.
 272       * @param   \stdClass  $formValues  Standard class of label and value in an associative array.
 273       *
 274       * @return  \stdClass  Object with translated labels where available
 275       *
 276       * @since   3.2
 277       */
 278      public static function mergeLabels($object, $formValues)
 279      {
 280          $result = new \stdClass();
 281  
 282          if ($object === null) {
 283              return $result;
 284          }
 285  
 286          $labelsArray = $formValues->labels;
 287          $valuesArray = $formValues->values;
 288  
 289          foreach ($object as $name => $value) {
 290              $result->$name = new \stdClass();
 291              $result->$name->name = $name;
 292              $result->$name->value = $valuesArray[$name] ?? $value;
 293              $result->$name->label = $labelsArray[$name] ?? $name;
 294  
 295              if (is_object($value)) {
 296                  $subObject = new \stdClass();
 297  
 298                  foreach ($value as $subName => $subValue) {
 299                      $subObject->$subName = new \stdClass();
 300                      $subObject->$subName->name = $subName;
 301                      $subObject->$subName->value = $valuesArray[$subName] ?? $subValue;
 302                      $subObject->$subName->label = $labelsArray[$subName] ?? $subName;
 303                      $result->$name->value = $subObject;
 304                  }
 305              }
 306          }
 307  
 308          return $result;
 309      }
 310  
 311      /**
 312       * Method to prepare the object for the preview and compare views.
 313       *
 314       * @param   ContentHistory  $table  Table object loaded with data.
 315       *
 316       * @return  \stdClass  Object ready for the views.
 317       *
 318       * @since   3.2
 319       */
 320      public static function prepareData(ContentHistory $table)
 321      {
 322          $object = static::decodeFields($table->version_data);
 323          $typesTable = Table::getInstance('ContentType', 'Joomla\\CMS\\Table\\');
 324          $typeAlias = explode('.', $table->item_id);
 325          array_pop($typeAlias);
 326          $typesTable->load(array('type_alias' => implode('.', $typeAlias)));
 327          $formValues = static::getFormValues($object, $typesTable);
 328          $object = static::mergeLabels($object, $formValues);
 329          $object = static::hideFields($object, $typesTable);
 330          $object = static::processLookupFields($object, $typesTable);
 331  
 332          return $object;
 333      }
 334  
 335      /**
 336       * Method to process any lookup values found in the content_history_options column for this table.
 337       * This allows category title and user name to be displayed instead of the id column.
 338       *
 339       * @param   \stdClass    $object      The std object from the JSON string. Can be nested 1 level deep.
 340       * @param   ContentType  $typesTable  Table object loaded with data.
 341       *
 342       * @return  \stdClass  Object with lookup values inserted.
 343       *
 344       * @since   3.2
 345       */
 346      public static function processLookupFields($object, ContentType $typesTable)
 347      {
 348          if ($options = json_decode($typesTable->content_history_options)) {
 349              if (isset($options->displayLookup) && is_array($options->displayLookup)) {
 350                  foreach ($options->displayLookup as $lookup) {
 351                      $sourceColumn = $lookup->sourceColumn ?? false;
 352                      $sourceValue = $object->$sourceColumn->value ?? false;
 353  
 354                      if ($sourceColumn && $sourceValue && ($lookupValue = static::getLookupValue($lookup, $sourceValue))) {
 355                          $object->$sourceColumn->value = $lookupValue;
 356                      }
 357                  }
 358              }
 359          }
 360  
 361          return $object;
 362      }
 363  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer