[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Joomla! Content Management System 5 * 6 * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10 namespace Joomla\CMS\Table; 11 12 use Joomla\CMS\Factory; 13 use Joomla\Database\DatabaseDriver; 14 use Joomla\Database\ParameterType; 15 16 // phpcs:disable PSR1.Files.SideEffects 17 \defined('JPATH_PLATFORM') or die; 18 // phpcs:enable PSR1.Files.SideEffects 19 20 /** 21 * Content History table. 22 * 23 * @since 3.2 24 */ 25 class ContentHistory extends Table 26 { 27 /** 28 * Array of object fields to unset from the data object before calculating SHA1 hash. This allows us to detect a meaningful change 29 * in the database row using the hash. This can be read from the #__content_types content_history_options column. 30 * 31 * @var array 32 * @since 3.2 33 */ 34 public $ignoreChanges = array(); 35 36 /** 37 * Array of object fields to convert to integers before calculating SHA1 hash. Some values are stored differently 38 * when an item is created than when the item is changed and saved. This works around that issue. 39 * This can be read from the #__content_types content_history_options column. 40 * 41 * @var array 42 * @since 3.2 43 */ 44 public $convertToInt = array(); 45 46 /** 47 * Constructor 48 * 49 * @param DatabaseDriver $db A database connector object 50 * 51 * @since 3.1 52 */ 53 public function __construct(DatabaseDriver $db) 54 { 55 parent::__construct('#__history', 'version_id', $db); 56 $this->ignoreChanges = array( 57 'modified_by', 58 'modified_user_id', 59 'modified', 60 'modified_time', 61 'checked_out', 62 'checked_out_time', 63 'version', 64 'hits', 65 'path', 66 ); 67 $this->convertToInt = array('publish_up', 'publish_down', 'ordering', 'featured'); 68 } 69 70 /** 71 * Overrides Table::store to set modified hash, user id, and save date. 72 * 73 * @param boolean $updateNulls True to update fields even if they are null. 74 * 75 * @return boolean True on success. 76 * 77 * @since 3.2 78 */ 79 public function store($updateNulls = false) 80 { 81 $this->set('character_count', \strlen($this->get('version_data'))); 82 $typeTable = Table::getInstance('ContentType', 'JTable', array('dbo' => $this->getDbo())); 83 $typeAlias = explode('.', $this->item_id); 84 array_pop($typeAlias); 85 $typeTable->load(array('type_alias' => implode('.', $typeAlias))); 86 87 if (!isset($this->sha1_hash)) { 88 $this->set('sha1_hash', $this->getSha1($this->get('version_data'), $typeTable)); 89 } 90 91 // Modify author and date only when not toggling Keep Forever 92 if ($this->get('keep_forever') === null) { 93 $this->set('editor_user_id', Factory::getUser()->id); 94 $this->set('save_date', Factory::getDate()->toSql()); 95 } 96 97 return parent::store($updateNulls); 98 } 99 100 /** 101 * Utility method to get the hash after removing selected values. This lets us detect changes other than 102 * modified date (which will change on every save). 103 * 104 * @param mixed $jsonData Either an object or a string with json-encoded data 105 * @param ContentType $typeTable Table object with data for this content type 106 * 107 * @return string SHA1 hash on success. Empty string on failure. 108 * 109 * @since 3.2 110 */ 111 public function getSha1($jsonData, ContentType $typeTable) 112 { 113 $object = \is_object($jsonData) ? $jsonData : json_decode($jsonData); 114 115 if (isset($typeTable->content_history_options) && \is_object(json_decode($typeTable->content_history_options))) { 116 $options = json_decode($typeTable->content_history_options); 117 $this->ignoreChanges = $options->ignoreChanges ?? $this->ignoreChanges; 118 $this->convertToInt = $options->convertToInt ?? $this->convertToInt; 119 } 120 121 foreach ($this->ignoreChanges as $remove) { 122 if (property_exists($object, $remove)) { 123 unset($object->$remove); 124 } 125 } 126 127 // Convert integers, booleans, and nulls to strings to get a consistent hash value 128 foreach ($object as $name => $value) { 129 if (\is_object($value)) { 130 // Go one level down for JSON column values 131 foreach ($value as $subName => $subValue) { 132 $object->$subName = \is_int($subValue) || \is_bool($subValue) || $subValue === null ? (string) $subValue : $subValue; 133 } 134 } else { 135 $object->$name = \is_int($value) || \is_bool($value) || $value === null ? (string) $value : $value; 136 } 137 } 138 139 // Work around empty values 140 foreach ($this->convertToInt as $convert) { 141 if (isset($object->$convert)) { 142 $object->$convert = (int) $object->$convert; 143 } 144 } 145 146 if (isset($object->review_time)) { 147 $object->review_time = (int) $object->review_time; 148 } 149 150 return sha1(json_encode($object)); 151 } 152 153 /** 154 * Utility method to get a matching row based on the hash value and id columns. 155 * This lets us check to make sure we don't save duplicate versions. 156 * 157 * @return string SHA1 hash on success. Empty string on failure. 158 * 159 * @since 3.2 160 */ 161 public function getHashMatch() 162 { 163 $db = $this->_db; 164 $itemId = $this->get('item_id'); 165 $sha1Hash = $this->get('sha1_hash'); 166 $query = $db->getQuery(true); 167 $query->select('*') 168 ->from($db->quoteName('#__history')) 169 ->where($db->quoteName('item_id') . ' = :item_id') 170 ->where($db->quoteName('sha1_hash') . ' = :sha1_hash') 171 ->bind(':item_id', $itemId, ParameterType::STRING) 172 ->bind(':sha1_hash', $sha1Hash); 173 174 $query->setLimit(1); 175 $db->setQuery($query); 176 177 return $db->loadObject(); 178 } 179 180 /** 181 * Utility method to remove the oldest versions of an item, saving only the most recent versions. 182 * 183 * @param integer $maxVersions The maximum number of versions to save. All others will be deleted. 184 * 185 * @return boolean true on success, false on failure. 186 * 187 * @since 3.2 188 */ 189 public function deleteOldVersions($maxVersions) 190 { 191 $result = true; 192 193 // Get the list of version_id values we want to save 194 $db = $this->_db; 195 $itemId = $this->get('item_id'); 196 $query = $db->getQuery(true); 197 $query->select($db->quoteName('version_id')) 198 ->from($db->quoteName('#__history')) 199 ->where($db->quoteName('item_id') . ' = :item_id') 200 ->where($db->quoteName('keep_forever') . ' != 1') 201 ->bind(':item_id', $itemId, ParameterType::STRING) 202 ->order($db->quoteName('save_date') . ' DESC '); 203 204 $query->setLimit((int) $maxVersions); 205 $db->setQuery($query); 206 $idsToSave = $db->loadColumn(0); 207 208 // Don't process delete query unless we have at least the maximum allowed versions 209 if (\count($idsToSave) === (int) $maxVersions) { 210 // Delete any rows not in our list and and not flagged to keep forever. 211 $query = $db->getQuery(true); 212 $query->delete($db->quoteName('#__history')) 213 ->where($db->quoteName('item_id') . ' = :item_id') 214 ->whereNotIn($db->quoteName('version_id'), $idsToSave) 215 ->where($db->quoteName('keep_forever') . ' != 1') 216 ->bind(':item_id', $itemId, ParameterType::STRING); 217 $db->setQuery($query); 218 $result = (bool) $db->execute(); 219 } 220 221 return $result; 222 } 223 }
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 |