[ 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_finder 6 * 7 * @copyright (C) 2011 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\Finder\Administrator\Indexer; 12 13 use Joomla\CMS\Factory; 14 use Joomla\CMS\Tree\NodeInterface; 15 use Joomla\Component\Finder\Administrator\Table\MapTable; 16 17 // phpcs:disable PSR1.Files.SideEffects 18 \defined('_JEXEC') or die; 19 // phpcs:enable PSR1.Files.SideEffects 20 21 /** 22 * Taxonomy base class for the Finder indexer package. 23 * 24 * @since 2.5 25 */ 26 class Taxonomy 27 { 28 /** 29 * An internal cache of taxonomy data. 30 * 31 * @var object[] 32 * @since 4.0.0 33 */ 34 public static $taxonomies = array(); 35 36 /** 37 * An internal cache of branch data. 38 * 39 * @var object[] 40 * @since 4.0.0 41 */ 42 public static $branches = array(); 43 44 /** 45 * An internal cache of taxonomy node data for inserting it. 46 * 47 * @var object[] 48 * @since 2.5 49 */ 50 public static $nodes = array(); 51 52 /** 53 * Method to add a branch to the taxonomy tree. 54 * 55 * @param string $title The title of the branch. 56 * @param integer $state The published state of the branch. [optional] 57 * @param integer $access The access state of the branch. [optional] 58 * 59 * @return integer The id of the branch. 60 * 61 * @since 2.5 62 * @throws \RuntimeException on database error. 63 */ 64 public static function addBranch($title, $state = 1, $access = 1) 65 { 66 $node = new \stdClass(); 67 $node->title = $title; 68 $node->state = $state; 69 $node->access = $access; 70 $node->parent_id = 1; 71 $node->language = ''; 72 73 return self::storeNode($node, 1); 74 } 75 76 /** 77 * Method to add a node to the taxonomy tree. 78 * 79 * @param string $branch The title of the branch to store the node in. 80 * @param string $title The title of the node. 81 * @param integer $state The published state of the node. [optional] 82 * @param integer $access The access state of the node. [optional] 83 * @param string $language The language of the node. [optional] 84 * 85 * @return integer The id of the node. 86 * 87 * @since 2.5 88 * @throws \RuntimeException on database error. 89 */ 90 public static function addNode($branch, $title, $state = 1, $access = 1, $language = '') 91 { 92 // Get the branch id, insert it if it does not exist. 93 $branchId = static::addBranch($branch); 94 95 $node = new \stdClass(); 96 $node->title = $title; 97 $node->state = $state; 98 $node->access = $access; 99 $node->parent_id = $branchId; 100 $node->language = $language; 101 102 return self::storeNode($node, $branchId); 103 } 104 105 /** 106 * Method to add a nested node to the taxonomy tree. 107 * 108 * @param string $branch The title of the branch to store the node in. 109 * @param NodeInterface $node The source-node of the taxonomy node. 110 * @param integer $state The published state of the node. [optional] 111 * @param integer $access The access state of the node. [optional] 112 * @param string $language The language of the node. [optional] 113 * @param integer $branchId ID of a branch if known. [optional] 114 * 115 * @return integer The id of the node. 116 * 117 * @since 4.0.0 118 */ 119 public static function addNestedNode($branch, NodeInterface $node, $state = 1, $access = 1, $language = '', $branchId = null) 120 { 121 if (!$branchId) { 122 // Get the branch id, insert it if it does not exist. 123 $branchId = static::addBranch($branch); 124 } 125 126 $parent = $node->getParent(); 127 128 if ($parent && $parent->title != 'ROOT') { 129 $parentId = self::addNestedNode($branch, $parent, $state, $access, $language, $branchId); 130 } else { 131 $parentId = $branchId; 132 } 133 134 $temp = new \stdClass(); 135 $temp->title = $node->title; 136 $temp->state = $state; 137 $temp->access = $access; 138 $temp->parent_id = $parentId; 139 $temp->language = $language; 140 141 return self::storeNode($temp, $parentId); 142 } 143 144 /** 145 * A helper method to store a node in the taxonomy 146 * 147 * @param object $node The node data to include 148 * @param integer $parentId The parent id of the node to add. 149 * 150 * @return integer The id of the inserted node. 151 * 152 * @since 4.0.0 153 * @throws \RuntimeException 154 */ 155 protected static function storeNode($node, $parentId) 156 { 157 // Check to see if the node is in the cache. 158 if (isset(static::$nodes[$parentId . ':' . $node->title])) { 159 return static::$nodes[$parentId . ':' . $node->title]->id; 160 } 161 162 // Check to see if the node is in the table. 163 $db = Factory::getDbo(); 164 $query = $db->getQuery(true) 165 ->select('*') 166 ->from($db->quoteName('#__finder_taxonomy')) 167 ->where($db->quoteName('parent_id') . ' = ' . $db->quote($parentId)) 168 ->where($db->quoteName('title') . ' = ' . $db->quote($node->title)) 169 ->where($db->quoteName('language') . ' = ' . $db->quote($node->language)); 170 171 $db->setQuery($query); 172 173 // Get the result. 174 $result = $db->loadObject(); 175 176 // Check if the database matches the input data. 177 if ((bool) $result && $result->state == $node->state && $result->access == $node->access) { 178 // The data matches, add the item to the cache. 179 static::$nodes[$parentId . ':' . $node->title] = $result; 180 181 return static::$nodes[$parentId . ':' . $node->title]->id; 182 } 183 184 /* 185 * The database did not match the input. This could be because the 186 * state has changed or because the node does not exist. Let's figure 187 * out which case is true and deal with it. 188 * @todo: use factory? 189 */ 190 $nodeTable = new MapTable($db); 191 192 if (empty($result)) { 193 // Prepare the node object. 194 $nodeTable->title = $node->title; 195 $nodeTable->state = (int) $node->state; 196 $nodeTable->access = (int) $node->access; 197 $nodeTable->language = $node->language; 198 $nodeTable->setLocation((int) $parentId, 'last-child'); 199 } else { 200 // Prepare the node object. 201 $nodeTable->id = (int) $result->id; 202 $nodeTable->title = $result->title; 203 $nodeTable->state = (int) ($node->state > 0 ? $node->state : $result->state); 204 $nodeTable->access = (int) $result->access; 205 $nodeTable->language = $node->language; 206 $nodeTable->setLocation($result->parent_id, 'last-child'); 207 } 208 209 // Check the data. 210 if (!$nodeTable->check()) { 211 $error = $nodeTable->getError(); 212 213 if ($error instanceof \Exception) { 214 // \Joomla\CMS\Table\NestedTable sets errors of exceptions, so in this case we can pass on more 215 // information 216 throw new \RuntimeException( 217 $error->getMessage(), 218 $error->getCode(), 219 $error 220 ); 221 } 222 223 // Standard string returned. Probably from the \Joomla\CMS\Table\Table class 224 throw new \RuntimeException($error, 500); 225 } 226 227 // Store the data. 228 if (!$nodeTable->store()) { 229 $error = $nodeTable->getError(); 230 231 if ($error instanceof \Exception) { 232 // \Joomla\CMS\Table\NestedTable sets errors of exceptions, so in this case we can pass on more 233 // information 234 throw new \RuntimeException( 235 $error->getMessage(), 236 $error->getCode(), 237 $error 238 ); 239 } 240 241 // Standard string returned. Probably from the \Joomla\CMS\Table\Table class 242 throw new \RuntimeException($error, 500); 243 } 244 245 $nodeTable->rebuildPath($nodeTable->id); 246 247 // Add the node to the cache. 248 static::$nodes[$parentId . ':' . $nodeTable->title] = (object) $nodeTable->getProperties(); 249 250 return static::$nodes[$parentId . ':' . $nodeTable->title]->id; 251 } 252 253 /** 254 * Method to add a map entry between a link and a taxonomy node. 255 * 256 * @param integer $linkId The link to map to. 257 * @param integer $nodeId The node to map to. 258 * 259 * @return boolean True on success. 260 * 261 * @since 2.5 262 * @throws \RuntimeException on database error. 263 */ 264 public static function addMap($linkId, $nodeId) 265 { 266 // Insert the map. 267 $db = Factory::getDbo(); 268 269 $query = $db->getQuery(true) 270 ->select($db->quoteName('link_id')) 271 ->from($db->quoteName('#__finder_taxonomy_map')) 272 ->where($db->quoteName('link_id') . ' = ' . (int) $linkId) 273 ->where($db->quoteName('node_id') . ' = ' . (int) $nodeId); 274 $db->setQuery($query); 275 $db->execute(); 276 $id = (int) $db->loadResult(); 277 278 if (!$id) { 279 $map = new \stdClass(); 280 $map->link_id = (int) $linkId; 281 $map->node_id = (int) $nodeId; 282 $db->insertObject('#__finder_taxonomy_map', $map); 283 } 284 285 return true; 286 } 287 288 /** 289 * Method to get the title of all taxonomy branches. 290 * 291 * @return array An array of branch titles. 292 * 293 * @since 2.5 294 * @throws \RuntimeException on database error. 295 */ 296 public static function getBranchTitles() 297 { 298 $db = Factory::getDbo(); 299 300 // Set user variables 301 $groups = implode(',', Factory::getUser()->getAuthorisedViewLevels()); 302 303 // Create a query to get the taxonomy branch titles. 304 $query = $db->getQuery(true) 305 ->select($db->quoteName('title')) 306 ->from($db->quoteName('#__finder_taxonomy')) 307 ->where($db->quoteName('parent_id') . ' = 1') 308 ->where($db->quoteName('state') . ' = 1') 309 ->where($db->quoteName('access') . ' IN (' . $groups . ')'); 310 311 // Get the branch titles. 312 $db->setQuery($query); 313 314 return $db->loadColumn(); 315 } 316 317 /** 318 * Method to find a taxonomy node in a branch. 319 * 320 * @param string $branch The branch to search. 321 * @param string $title The title of the node. 322 * 323 * @return mixed Integer id on success, null on no match. 324 * 325 * @since 2.5 326 * @throws \RuntimeException on database error. 327 */ 328 public static function getNodeByTitle($branch, $title) 329 { 330 $db = Factory::getDbo(); 331 332 // Set user variables 333 $groups = implode(',', Factory::getUser()->getAuthorisedViewLevels()); 334 335 // Create a query to get the node. 336 $query = $db->getQuery(true) 337 ->select('t1.*') 338 ->from($db->quoteName('#__finder_taxonomy') . ' AS t1') 339 ->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS t2 ON t2.id = t1.parent_id') 340 ->where('t1.access IN (' . $groups . ')') 341 ->where('t1.state = 1') 342 ->where('t1.title LIKE ' . $db->quote($db->escape($title) . '%')) 343 ->where('t2.access IN (' . $groups . ')') 344 ->where('t2.state = 1') 345 ->where('t2.title = ' . $db->quote($branch)); 346 347 // Get the node. 348 $query->setLimit(1); 349 $db->setQuery($query); 350 351 return $db->loadObject(); 352 } 353 354 /** 355 * Method to remove map entries for a link. 356 * 357 * @param integer $linkId The link to remove. 358 * 359 * @return boolean True on success. 360 * 361 * @since 2.5 362 * @throws \RuntimeException on database error. 363 */ 364 public static function removeMaps($linkId) 365 { 366 // Delete the maps. 367 $db = Factory::getDbo(); 368 $query = $db->getQuery(true) 369 ->delete($db->quoteName('#__finder_taxonomy_map')) 370 ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); 371 $db->setQuery($query); 372 $db->execute(); 373 374 return true; 375 } 376 377 /** 378 * Method to remove orphaned taxonomy maps 379 * 380 * @return integer The number of deleted rows. 381 * 382 * @since 4.2.0 383 * @throws \RuntimeException on database error. 384 */ 385 public static function removeOrphanMaps() 386 { 387 // Delete all orphaned maps 388 $db = Factory::getDbo(); 389 $query2 = $db->getQuery(true) 390 ->select($db->quoteName('link_id')) 391 ->from($db->quoteName('#__finder_links')); 392 $query = $db->getQuery(true) 393 ->delete($db->quoteName('#__finder_taxonomy_map')) 394 ->where($db->quoteName('link_id') . ' NOT IN (' . $query2 . ')'); 395 $db->setQuery($query); 396 $db->execute(); 397 $count = $db->getAffectedRows(); 398 399 return $count; 400 } 401 402 /** 403 * Method to remove orphaned taxonomy nodes and branches. 404 * 405 * @return integer The number of deleted rows. 406 * 407 * @since 2.5 408 * @throws \RuntimeException on database error. 409 */ 410 public static function removeOrphanNodes() 411 { 412 // Delete all orphaned nodes. 413 $affectedRows = 0; 414 $db = Factory::getDbo(); 415 $nodeTable = new MapTable($db); 416 $query = $db->getQuery(true); 417 418 $query->select($db->quoteName('t.id')) 419 ->from($db->quoteName('#__finder_taxonomy', 't')) 420 ->join('LEFT', $db->quoteName('#__finder_taxonomy_map', 'm') . ' ON ' . $db->quoteName('m.node_id') . '=' . $db->quoteName('t.id')) 421 ->where($db->quoteName('t.parent_id') . ' > 1 ') 422 ->where('t.lft + 1 = t.rgt') 423 ->where($db->quoteName('m.link_id') . ' IS NULL'); 424 425 do { 426 $db->setQuery($query); 427 $nodes = $db->loadColumn(); 428 429 foreach ($nodes as $node) { 430 $nodeTable->delete($node); 431 $affectedRows++; 432 } 433 } while ($nodes); 434 435 return $affectedRows; 436 } 437 438 /** 439 * Get a taxonomy based on its id or all taxonomies 440 * 441 * @param integer $id Id of the taxonomy 442 * 443 * @return object|array A taxonomy object or an array of all taxonomies 444 * 445 * @since 4.0.0 446 */ 447 public static function getTaxonomy($id = 0) 448 { 449 if (!count(self::$taxonomies)) { 450 $db = Factory::getDbo(); 451 $query = $db->getQuery(true); 452 453 $query->select(array('id','parent_id','lft','rgt','level','path','title','alias','state','access','language')) 454 ->from($db->quoteName('#__finder_taxonomy')) 455 ->order($db->quoteName('lft')); 456 457 $db->setQuery($query); 458 self::$taxonomies = $db->loadObjectList('id'); 459 } 460 461 if ($id == 0) { 462 return self::$taxonomies; 463 } 464 465 if (isset(self::$taxonomies[$id])) { 466 return self::$taxonomies[$id]; 467 } 468 469 return false; 470 } 471 472 /** 473 * Get a taxonomy branch object based on its title or all branches 474 * 475 * @param string $title Title of the branch 476 * 477 * @return object|array The object with the branch data or an array of all branches 478 * 479 * @since 4.0.0 480 */ 481 public static function getBranch($title = '') 482 { 483 if (!count(self::$branches)) { 484 $taxonomies = self::getTaxonomy(); 485 486 foreach ($taxonomies as $t) { 487 if ($t->level == 1) { 488 self::$branches[$t->title] = $t; 489 } 490 } 491 } 492 493 if ($title == '') { 494 return self::$branches; 495 } 496 497 if (isset(self::$branches[$title])) { 498 return self::$branches[$title]; 499 } 500 501 return false; 502 } 503 }
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 |