1<?php 2/** 3 * Joomla! Content Management System 4 * 5 * @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved. 6 * @license GNU General Public License version 2 or later; see LICENSE.txt 7 */ 8 9namespace Joomla\CMS\Table\Observer; 10 11defined('JPATH_PLATFORM') or die; 12 13/** 14 * Abstract class defining methods that can be 15 * implemented by an Observer class of a Table class (which is an Observable). 16 * Attaches $this Observer to the $table in the constructor. 17 * The classes extending this class should not be instantiated directly, as they 18 * are automatically instanciated by the \JObserverMapper 19 * 20 * @since 3.1.2 21 */ 22class Tags extends AbstractObserver 23{ 24 /** 25 * Helper object for managing tags 26 * 27 * @var \JHelperTags 28 * @since 3.1.2 29 */ 30 protected $tagsHelper; 31 32 /** 33 * The pattern for this table's TypeAlias 34 * 35 * @var string 36 * @since 3.1.2 37 */ 38 protected $typeAliasPattern = null; 39 40 /** 41 * Override for postStoreProcess param newTags, Set by setNewTags, used by onAfterStore and onBeforeStore 42 * 43 * @var array 44 * @since 3.1.2 45 */ 46 protected $newTags = false; 47 48 /** 49 * Override for postStoreProcess param replaceTags. Set by setNewTags, used by onAfterStore 50 * 51 * @var boolean 52 * @since 3.1.2 53 */ 54 protected $replaceTags = true; 55 56 /** 57 * Not public, so marking private and deprecated, but needed internally in parseTypeAlias for 58 * PHP < 5.4.0 as it's not passing context $this to closure function. 59 * 60 * @var Tags 61 * @since 3.1.2 62 * @deprecated Never use this 63 * @private 64 */ 65 public static $_myTableForPregreplaceOnly; 66 67 /** 68 * Creates the associated observer instance and attaches it to the $observableObject 69 * Creates the associated tags helper class instance 70 * $typeAlias can be of the form "{variableName}.type", automatically replacing {variableName} with table-instance variables variableName 71 * 72 * @param \JObservableInterface $observableObject The subject object to be observed 73 * @param array $params ( 'typeAlias' => $typeAlias ) 74 * 75 * @return Tags 76 * 77 * @since 3.1.2 78 */ 79 public static function createObserver(\JObservableInterface $observableObject, $params = array()) 80 { 81 $typeAlias = $params['typeAlias']; 82 83 $observer = new self($observableObject); 84 85 $observer->tagsHelper = new \JHelperTags; 86 $observer->typeAliasPattern = $typeAlias; 87 88 return $observer; 89 } 90 91 /** 92 * Pre-processor for $table->store($updateNulls) 93 * 94 * @param boolean $updateNulls The result of the load 95 * @param string $tableKey The key of the table 96 * 97 * @return void 98 * 99 * @since 3.1.2 100 */ 101 public function onBeforeStore($updateNulls, $tableKey) 102 { 103 $this->parseTypeAlias(); 104 105 if (empty($this->table->tagsHelper->tags)) 106 { 107 $this->tagsHelper->preStoreProcess($this->table); 108 } 109 else 110 { 111 $this->tagsHelper->preStoreProcess($this->table, (array) $this->table->tagsHelper->tags); 112 } 113 } 114 115 /** 116 * Post-processor for $table->store($updateNulls) 117 * You can change optional params newTags and replaceTags of tagsHelper with method setNewTagsToAdd 118 * 119 * @param boolean &$result The result of the load 120 * 121 * @return void 122 * 123 * @since 3.1.2 124 */ 125 public function onAfterStore(&$result) 126 { 127 if ($result) 128 { 129 if (empty($this->table->tagsHelper->tags)) 130 { 131 $result = $this->tagsHelper->postStoreProcess($this->table); 132 } 133 else 134 { 135 $result = $this->tagsHelper->postStoreProcess($this->table, $this->table->tagsHelper->tags); 136 } 137 138 // Restore default values for the optional params: 139 $this->newTags = array(); 140 $this->replaceTags = true; 141 } 142 } 143 144 /** 145 * Pre-processor for $table->delete($pk) 146 * 147 * @param mixed $pk An optional primary key value to delete. If not set the instance property value is used. 148 * 149 * @return void 150 * 151 * @since 3.1.2 152 * @throws \UnexpectedValueException 153 */ 154 public function onBeforeDelete($pk) 155 { 156 $this->parseTypeAlias(); 157 $this->tagsHelper->deleteTagData($this->table, $pk); 158 } 159 160 /** 161 * Sets the new tags to be added or to replace existing tags 162 * 163 * @param array $newTags New tags to be added to or replace current tags for an item 164 * @param boolean $replaceTags Replace tags (true) or add them (false) 165 * 166 * @return boolean 167 * 168 * @since 3.1.2 169 */ 170 public function setNewTags($newTags, $replaceTags) 171 { 172 $this->parseTypeAlias(); 173 174 return $this->tagsHelper->postStoreProcess($this->table, $newTags, $replaceTags); 175 } 176 177 /** 178 * Internal method 179 * Parses a TypeAlias of the form "{variableName}.type", replacing {variableName} with table-instance variables variableName 180 * Storing result into $this->tagsHelper->typeAlias 181 * 182 * @return void 183 * 184 * @since 3.1.2 185 */ 186 protected function parseTypeAlias() 187 { 188 // Needed for PHP < 5.4.0 as it's not passing context $this to closure function 189 static::$_myTableForPregreplaceOnly = $this->table; 190 191 $this->tagsHelper->typeAlias = preg_replace_callback('/{([^}]+)}/', 192 function($matches) 193 { 194 return Tags::$_myTableForPregreplaceOnly->{$matches[1]}; 195 }, 196 $this->typeAliasPattern 197 ); 198 } 199} 200