* @git Joomla Component Builder * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace VDM\Joomla\Componentbuilder\Compiler\JoomlaThree; use Joomla\CMS\Factory; use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler; use VDM\Joomla\Utilities\JsonHelper; use VDM\Joomla\Utilities\ArrayHelper; use VDM\Joomla\Componentbuilder\Compiler\Config; use VDM\Joomla\Componentbuilder\Compiler\Interfaces\HistoryInterface; /** * Compiler History * * @since 3.2.0 */ final class History implements HistoryInterface { /** * History Item Object * * @var object|null * @since 3.2.0 */ protected ?object $tmp; /** * Compiler Config * * @var Config * @since 3.2.0 */ protected Config $config; /** * Database object to query local DB * * @since 3.2.0 */ protected $db; /** * Constructor * * @param Config|null $config The compiler config object. * * @since 3.2.0 */ public function __construct(?Config $config = null) { $this->config = $config ?: Compiler::_('Config'); $this->db = Factory::getDbo(); } /** * Get Item History object * * @param string $type The type of item * @param int $id The item ID * * @return ?object The history * @since 3.2.0 */ public function get(string $type, int $id): ?object { // quick class object to store old history object $this->tmp = null; // Create a new query object. $query = $this->db->getQuery(true); $query->select('h.*'); $query->from('#__ucm_history AS h'); $query->where( $this->db->quoteName('h.ucm_item_id') . ' = ' . (int) $id ); // Join over the content type for the type id $query->join( 'LEFT', '#__content_types AS ct ON ct.type_id = h.ucm_type_id' ); $query->where( 'ct.type_alias = ' . $this->db->quote( 'com_componentbuilder.' . $type ) ); $query->order('h.save_date DESC'); $this->db->setQuery($query, 0, 1); $this->db->execute(); if ($this->db->getNumRows()) { // new version of this item found // so we need to mark it as the last compiled version $newActive = $this->db->loadObject(); // set the new version watch $this->set($newActive, 1); } // Get last compiled verion $query = $this->db->getQuery(true); $query->select('h.*'); $query->from('#__ucm_history AS h'); $query->where( $this->db->quoteName('h.ucm_item_id') . ' = ' . (int) $id ); $query->where('h.keep_forever = 1'); $query->where('h.version_note LIKE ' . $this->db->quote('%component%')); // make sure it does not return the active version if (isset($newActive) && isset($newActive->version_id)) { $query->where('h.version_id != ' . (int) $newActive->version_id); } // Join over the content type for the type id $query->join( 'LEFT', '#__content_types AS ct ON ct.type_id = h.ucm_type_id' ); $query->where( 'ct.type_alias = ' . $this->db->quote( 'com_componentbuilder.' . $type ) ); $query->order('h.save_date DESC'); $this->db->setQuery($query); $this->db->execute(); if ($this->db->getNumRows()) { // the old active version was found // so we may need to do an SQL update // and unmark the old compiled version $oldActives = $this->db->loadObjectList(); foreach ($oldActives as $oldActive) { // remove old version watch $this->set($oldActive, 0); } } // return the last used history record or null. return $this->tmp; } /** * Set Item History Watch * * @param Object $object The history object * @param int $action The action to take * 0 = remove watch * 1 = add watch * * @return bool * @since 3.2.0 */ protected function set(object $object, int $action): bool { // check the note if (JsonHelper::check($object->version_note)) { $version_note = json_decode((string) $object->version_note, true); } else { $version_note = array('component' => []); } // set watch switch ($action) { case 0: // remove watch if (isset($version_note['component']) && ($key = array_search( $this->config->component_id, $version_note['component'] )) !== false) { // last version that was used to build/compile $this->tmp = json_decode((string) $object->version_data); // remove it from this component unset($version_note['component'][$key]); } else { // since it was not found, no need to update anything return true; } break; case 1: // add watch if (!in_array($this->config->component_id, $version_note['component'])) { $version_note['component'][] = $this->config->component_id; } else { // since it is there already, no need to update anything return true; } break; } // check if we need to still keep this locked if (isset($version_note['component']) && ArrayHelper::check($version_note['component'])) { // insure component ids are only added once per item $version_note['component'] = array_unique( $version_note['component'] ); // we may change this, little risky (but since JCB does not have history notes it should be okay for now) $object->version_note = json_encode($version_note); $object->keep_forever = '1'; } else { $object->version_note = ''; $object->keep_forever = '0'; } // run the update return $this->db->updateObject('#__ucm_history', $object, 'version_id'); } }