[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |