[ 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\Microdata; 11 12 // phpcs:disable PSR1.Files.SideEffects 13 \defined('JPATH_PLATFORM') or die; 14 // phpcs:enable PSR1.Files.SideEffects 15 16 /** 17 * Joomla Platform class for interacting with Microdata semantics. 18 * 19 * @since 3.2 20 */ 21 class Microdata 22 { 23 /** 24 * Array with all available Types and Properties from the http://schema.org vocabulary 25 * 26 * @var array 27 * @since 3.2 28 */ 29 protected static $types = null; 30 31 /** 32 * The Type 33 * 34 * @var string 35 * @since 3.2 36 */ 37 protected $type = null; 38 39 /** 40 * The Property 41 * 42 * @var string 43 * @since 3.2 44 */ 45 protected $property = null; 46 47 /** 48 * The Human content 49 * 50 * @var string 51 * @since 3.2 52 */ 53 protected $content = null; 54 55 /** 56 * The Machine content 57 * 58 * @var string 59 * @since 3.2 60 */ 61 protected $machineContent = null; 62 63 /** 64 * The Fallback Type 65 * 66 * @var string 67 * @since 3.2 68 */ 69 protected $fallbackType = null; 70 71 /** 72 * The Fallback Property 73 * 74 * @var string 75 * @since 3.2 76 */ 77 protected $fallbackProperty = null; 78 79 /** 80 * Used for checking if the library output is enabled or disabled 81 * 82 * @var boolean 83 * @since 3.2 84 */ 85 protected $enabled = true; 86 87 /** 88 * Initialize the class and setup the default $Type 89 * 90 * @param string $type Optional, fallback to 'Thing' Type 91 * @param boolean $flag Enable or disable the library output 92 * 93 * @since 3.2 94 */ 95 public function __construct($type = '', $flag = true) 96 { 97 if ($this->enabled = (bool) $flag) { 98 // Fallback to 'Thing' Type 99 if (!$type) { 100 $type = 'Thing'; 101 } 102 103 $this->setType($type); 104 } 105 } 106 107 /** 108 * Load all available Types and Properties from the http://schema.org vocabulary contained in the types.json file 109 * 110 * @return void 111 * 112 * @since 3.2 113 */ 114 protected static function loadTypes() 115 { 116 // Load the JSON 117 if (!static::$types) { 118 $path = __DIR__ . '/types.json'; 119 static::$types = json_decode(file_get_contents($path), true); 120 } 121 } 122 123 /** 124 * Reset all params 125 * 126 * @return void 127 * 128 * @since 3.2 129 */ 130 protected function resetParams() 131 { 132 $this->content = null; 133 $this->machineContent = null; 134 $this->property = null; 135 $this->fallbackProperty = null; 136 $this->fallbackType = null; 137 } 138 139 /** 140 * Enable or Disable the library output 141 * 142 * @param boolean $flag Enable or disable the library output 143 * 144 * @return Microdata Instance of $this 145 * 146 * @since 3.2 147 */ 148 public function enable($flag = true) 149 { 150 $this->enabled = (bool) $flag; 151 152 return $this; 153 } 154 155 /** 156 * Return 'true' if the library output is enabled 157 * 158 * @return boolean 159 * 160 * @since 3.2 161 */ 162 public function isEnabled() 163 { 164 return $this->enabled; 165 } 166 167 /** 168 * Set a new http://schema.org Type 169 * 170 * @param string $type The $Type to be setup 171 * 172 * @return Microdata Instance of $this 173 * 174 * @since 3.2 175 */ 176 public function setType($type) 177 { 178 if (!$this->enabled) { 179 return $this; 180 } 181 182 // Sanitize the Type 183 $this->type = static::sanitizeType($type); 184 185 // If the given $Type isn't available, fallback to 'Thing' Type 186 if (!static::isTypeAvailable($this->type)) { 187 $this->type = 'Thing'; 188 } 189 190 return $this; 191 } 192 193 /** 194 * Return the current $Type name 195 * 196 * @return string 197 * 198 * @since 3.2 199 */ 200 public function getType() 201 { 202 return $this->type; 203 } 204 205 /** 206 * Setup a $Property 207 * 208 * @param string $property The Property 209 * 210 * @return Microdata Instance of $this 211 * 212 * @since 3.2 213 */ 214 public function property($property) 215 { 216 if (!$this->enabled) { 217 return $this; 218 } 219 220 // Sanitize the $Property 221 $property = static::sanitizeProperty($property); 222 223 // Control if the $Property exists in the given $Type and setup it, otherwise leave it 'NULL' 224 if (static::isPropertyInType($this->type, $property)) { 225 $this->property = $property; 226 } 227 228 return $this; 229 } 230 231 /** 232 * Return the current $Property name 233 * 234 * @return string 235 * 236 * @since 3.2 237 */ 238 public function getProperty() 239 { 240 return $this->property; 241 } 242 243 /** 244 * Setup a Human content or content for the Machines 245 * 246 * @param string $content The human content or machine content to be used 247 * @param string $machineContent The machine content 248 * 249 * @return Microdata Instance of $this 250 * 251 * @since 3.2 252 */ 253 public function content($content, $machineContent = null) 254 { 255 $this->content = $content; 256 $this->machineContent = $machineContent; 257 258 return $this; 259 } 260 261 /** 262 * Return the current $content 263 * 264 * @return string 265 * 266 * @since 3.2 267 */ 268 public function getContent() 269 { 270 return $this->content; 271 } 272 273 /** 274 * Return the current $machineContent 275 * 276 * @return string 277 * 278 * @since 3.3 279 */ 280 public function getMachineContent() 281 { 282 return $this->machineContent; 283 } 284 285 /** 286 * Setup a Fallback Type and Property 287 * 288 * @param string $type The Fallback Type 289 * @param string $property The Fallback Property 290 * 291 * @return Microdata Instance of $this 292 * 293 * @since 3.2 294 */ 295 public function fallback($type, $property) 296 { 297 if (!$this->enabled) { 298 return $this; 299 } 300 301 // Sanitize the $Type 302 $this->fallbackType = static::sanitizeType($type); 303 304 // If the given $Type isn't available, fallback to 'Thing' Type 305 if (!static::isTypeAvailable($this->fallbackType)) { 306 $this->fallbackType = 'Thing'; 307 } 308 309 // Control if the $Property exist in the given $Type and setup it, otherwise leave it 'NULL' 310 if (static::isPropertyInType($this->fallbackType, $property)) { 311 $this->fallbackProperty = $property; 312 } else { 313 $this->fallbackProperty = null; 314 } 315 316 return $this; 317 } 318 319 /** 320 * Return the current $fallbackType 321 * 322 * @return string 323 * 324 * @since 3.2 325 */ 326 public function getFallbackType() 327 { 328 return $this->fallbackType; 329 } 330 331 /** 332 * Return the current $fallbackProperty 333 * 334 * @return string 335 * 336 * @since 3.2 337 */ 338 public function getFallbackProperty() 339 { 340 return $this->fallbackProperty; 341 } 342 343 /** 344 * This function handles the display logic. 345 * It checks if the Type, Property are available, if not check for a Fallback, 346 * then reset all params for the next use and return the HTML. 347 * 348 * @param string $displayType Optional, 'inline', available options ['inline'|'span'|'div'|meta] 349 * @param boolean $emptyOutput Return an empty string if the library output is disabled and there is a $content value 350 * 351 * @return string 352 * 353 * @since 3.2 354 */ 355 public function display($displayType = '', $emptyOutput = false) 356 { 357 // Initialize the HTML to output 358 $html = ($this->content !== null && !$emptyOutput) ? $this->content : ''; 359 360 // Control if the library output is enabled, otherwise return the $content or an empty string 361 if (!$this->enabled) { 362 // Reset params 363 $this->resetParams(); 364 365 return $html; 366 } 367 368 // If the $property is wrong for the current $Type check if a Fallback is available, otherwise return an empty HTML 369 if ($this->property) { 370 // Process and return the HTML the way the user expects to 371 if ($displayType) { 372 switch ($displayType) { 373 case 'span': 374 $html = static::htmlSpan($html, $this->property); 375 break; 376 377 case 'div': 378 $html = static::htmlDiv($html, $this->property); 379 break; 380 381 case 'meta': 382 $html = $this->machineContent ?? $html; 383 $html = static::htmlMeta($html, $this->property); 384 break; 385 386 default: 387 // Default $displayType = 'inline' 388 $html = static::htmlProperty($this->property); 389 break; 390 } 391 } else { 392 /* 393 * Process and return the HTML in an automatic way, 394 * with the $Property expected Types and display everything in the right way, 395 * check if the $Property is 'normal', 'nested' or must be rendered in a metadata tag 396 */ 397 switch (static::getExpectedDisplayType($this->type, $this->property)) { 398 case 'nested': 399 // Retrieve the expected 'nested' Type of the $Property 400 $nestedType = static::getExpectedTypes($this->type, $this->property); 401 $nestedProperty = ''; 402 403 // If there is a Fallback Type then probably it could be the expectedType 404 if (\in_array($this->fallbackType, $nestedType)) { 405 $nestedType = $this->fallbackType; 406 407 if ($this->fallbackProperty) { 408 $nestedProperty = $this->fallbackProperty; 409 } 410 } else { 411 $nestedType = $nestedType[0]; 412 } 413 414 // Check if a $content is available, otherwise fallback to an 'inline' display type 415 if ($this->content !== null) { 416 if ($nestedProperty) { 417 $html = static::htmlSpan( 418 $this->content, 419 $nestedProperty 420 ); 421 } 422 423 $html = static::htmlSpan( 424 $html, 425 $this->property, 426 $nestedType, 427 true 428 ); 429 } else { 430 $html = static::htmlProperty($this->property) . ' ' . static::htmlScope($nestedType); 431 432 if ($nestedProperty) { 433 $html .= ' ' . static::htmlProperty($nestedProperty); 434 } 435 } 436 437 break; 438 439 case 'meta': 440 // Check if a $content is available, otherwise fallback to an 'inline' display type 441 if ($this->content !== null) { 442 $html = $this->machineContent ?? $this->content; 443 $html = static::htmlMeta($html, $this->property) . $this->content; 444 } else { 445 $html = static::htmlProperty($this->property); 446 } 447 448 break; 449 450 default: 451 /* 452 * Default expected display type = 'normal' 453 * Check if a $content is available, 454 * otherwise fallback to an 'inline' display type 455 */ 456 if ($this->content !== null) { 457 $html = static::htmlSpan($this->content, $this->property); 458 } else { 459 $html = static::htmlProperty($this->property); 460 } 461 462 break; 463 } 464 } 465 } elseif ($this->fallbackProperty) { 466 // Process and return the HTML the way the user expects to 467 if ($displayType) { 468 switch ($displayType) { 469 case 'span': 470 $html = static::htmlSpan($html, $this->fallbackProperty, $this->fallbackType); 471 break; 472 473 case 'div': 474 $html = static::htmlDiv($html, $this->fallbackProperty, $this->fallbackType); 475 break; 476 477 case 'meta': 478 $html = $this->machineContent ?? $html; 479 $html = static::htmlMeta($html, $this->fallbackProperty, $this->fallbackType); 480 break; 481 482 default: 483 // Default $displayType = 'inline' 484 $html = static::htmlScope($this->fallbackType) . ' ' . static::htmlProperty($this->fallbackProperty); 485 break; 486 } 487 } else { 488 /* 489 * Process and return the HTML in an automatic way, 490 * with the $Property expected Types and display everything in the right way, 491 * check if the Property is 'nested' or must be rendered in a metadata tag 492 */ 493 switch (static::getExpectedDisplayType($this->fallbackType, $this->fallbackProperty)) { 494 case 'meta': 495 // Check if a $content is available, otherwise fallback to an 'inline' display Type 496 if ($this->content !== null) { 497 $html = $this->machineContent ?? $this->content; 498 $html = static::htmlMeta($html, $this->fallbackProperty, $this->fallbackType); 499 } else { 500 $html = static::htmlScope($this->fallbackType) . ' ' . static::htmlProperty($this->fallbackProperty); 501 } 502 503 break; 504 505 default: 506 /* 507 * Default expected display type = 'normal' 508 * Check if a $content is available, 509 * otherwise fallback to an 'inline' display Type 510 */ 511 if ($this->content !== null) { 512 $html = static::htmlSpan($this->content, $this->fallbackProperty); 513 $html = static::htmlSpan($html, '', $this->fallbackType); 514 } else { 515 $html = static::htmlScope($this->fallbackType) . ' ' . static::htmlProperty($this->fallbackProperty); 516 } 517 518 break; 519 } 520 } 521 } elseif (!$this->fallbackProperty && $this->fallbackType !== null) { 522 $html = static::htmlScope($this->fallbackType); 523 } 524 525 // Reset params 526 $this->resetParams(); 527 528 return $html; 529 } 530 531 /** 532 * Return the HTML of the current Scope 533 * 534 * @return string 535 * 536 * @since 3.2 537 */ 538 public function displayScope() 539 { 540 // Control if the library output is enabled, otherwise return the $content or empty string 541 if (!$this->enabled) { 542 return ''; 543 } 544 545 return static::htmlScope($this->type); 546 } 547 548 /** 549 * Return the sanitized $Type 550 * 551 * @param string $type The Type to sanitize 552 * 553 * @return string 554 * 555 * @since 3.2 556 */ 557 public static function sanitizeType($type) 558 { 559 return ucfirst(trim($type)); 560 } 561 562 /** 563 * Return the sanitized $Property 564 * 565 * @param string $property The Property to sanitize 566 * 567 * @return string 568 * 569 * @since 3.2 570 */ 571 public static function sanitizeProperty($property) 572 { 573 return lcfirst(trim($property)); 574 } 575 576 /** 577 * Return an array with all available Types and Properties from the http://schema.org vocabulary 578 * 579 * @return array 580 * 581 * @since 3.2 582 */ 583 public static function getTypes() 584 { 585 static::loadTypes(); 586 587 return static::$types; 588 } 589 590 /** 591 * Return an array with all available Types from the http://schema.org vocabulary 592 * 593 * @return array 594 * 595 * @since 3.2 596 */ 597 public static function getAvailableTypes() 598 { 599 static::loadTypes(); 600 601 return array_keys(static::$types); 602 } 603 604 /** 605 * Return the expected Types of the given Property 606 * 607 * @param string $type The Type to process 608 * @param string $property The Property to process 609 * 610 * @return array 611 * 612 * @since 3.2 613 */ 614 public static function getExpectedTypes($type, $property) 615 { 616 static::loadTypes(); 617 618 $tmp = static::$types[$type]['properties']; 619 620 // Check if the $Property is in the $Type 621 if (isset($tmp[$property])) { 622 return $tmp[$property]['expectedTypes']; 623 } 624 625 // Check if the $Property is inherit 626 $extendedType = static::$types[$type]['extends']; 627 628 // Recursive 629 if (!empty($extendedType)) { 630 return static::getExpectedTypes($extendedType, $property); 631 } 632 633 return array(); 634 } 635 636 /** 637 * Return the expected display type: [normal|nested|meta] 638 * In which way to display the Property: 639 * normal -> itemprop="name" 640 * nested -> itemprop="director" itemscope itemtype="https://schema.org/Person" 641 * meta -> `<meta itemprop="datePublished" content="1991-05-01">` 642 * 643 * @param string $type The Type where to find the Property 644 * @param string $property The Property to process 645 * 646 * @return string 647 * 648 * @since 3.2 649 */ 650 protected static function getExpectedDisplayType($type, $property) 651 { 652 $expectedTypes = static::getExpectedTypes($type, $property); 653 654 // Retrieve the first expected type 655 $type = $expectedTypes[0]; 656 657 // Check if it's a 'meta' display 658 if ($type === 'Date' || $type === 'DateTime' || $property === 'interactionCount') { 659 return 'meta'; 660 } 661 662 // Check if it's a 'normal' display 663 if ($type === 'Text' || $type === 'URL' || $type === 'Boolean' || $type === 'Number') { 664 return 'normal'; 665 } 666 667 // Otherwise it's a 'nested' display 668 return 'nested'; 669 } 670 671 /** 672 * Recursive function, control if the given Type has the given Property 673 * 674 * @param string $type The Type where to check 675 * @param string $property The Property to check 676 * 677 * @return boolean 678 * 679 * @since 3.2 680 */ 681 public static function isPropertyInType($type, $property) 682 { 683 if (!static::isTypeAvailable($type)) { 684 return false; 685 } 686 687 // Control if the $Property exists, and return 'true' 688 if (\array_key_exists($property, static::$types[$type]['properties'])) { 689 return true; 690 } 691 692 // Recursive: Check if the $Property is inherit 693 $extendedType = static::$types[$type]['extends']; 694 695 if (!empty($extendedType)) { 696 return static::isPropertyInType($extendedType, $property); 697 } 698 699 return false; 700 } 701 702 /** 703 * Control if the given Type class is available 704 * 705 * @param string $type The Type to check 706 * 707 * @return boolean 708 * 709 * @since 3.2 710 */ 711 public static function isTypeAvailable($type) 712 { 713 static::loadTypes(); 714 715 return \array_key_exists($type, static::$types); 716 } 717 718 /** 719 * Return Microdata semantics in a `<meta>` tag with content for machines. 720 * 721 * @param string $content The machine content to display 722 * @param string $property The Property 723 * @param string $scope Optional, the Type scope to display 724 * @param boolean $invert Optional, default = false, invert the $scope with the $property 725 * 726 * @return string 727 * 728 * @since 3.2 729 */ 730 public static function htmlMeta($content, $property, $scope = '', $invert = false) 731 { 732 return static::htmlTag('meta', $content, $property, $scope, $invert); 733 } 734 735 /** 736 * Return Microdata semantics in a `<span>` tag. 737 * 738 * @param string $content The human content 739 * @param string $property Optional, the human content to display 740 * @param string $scope Optional, the Type scope to display 741 * @param boolean $invert Optional, default = false, invert the $scope with the $property 742 * 743 * @return string 744 * 745 * @since 3.2 746 */ 747 public static function htmlSpan($content, $property = '', $scope = '', $invert = false) 748 { 749 return static::htmlTag('span', $content, $property, $scope, $invert); 750 } 751 752 /** 753 * Return Microdata semantics in a `<div>` tag. 754 * 755 * @param string $content The human content 756 * @param string $property Optional, the human content to display 757 * @param string $scope Optional, the Type scope to display 758 * @param boolean $invert Optional, default = false, invert the $scope with the $property 759 * 760 * @return string 761 * 762 * @since 3.2 763 */ 764 public static function htmlDiv($content, $property = '', $scope = '', $invert = false) 765 { 766 return static::htmlTag('div', $content, $property, $scope, $invert); 767 } 768 769 /** 770 * Return Microdata semantics in a specified tag. 771 * 772 * @param string $tag The HTML tag 773 * @param string $content The human content 774 * @param string $property Optional, the human content to display 775 * @param string $scope Optional, the Type scope to display 776 * @param boolean $invert Optional, default = false, invert the $scope with the $property 777 * 778 * @return string 779 * 780 * @since 3.3 781 */ 782 public static function htmlTag($tag, $content, $property = '', $scope = '', $invert = false) 783 { 784 // Control if the $Property has already the 'itemprop' prefix 785 if (!empty($property) && stripos($property, 'itemprop') !== 0) { 786 $property = static::htmlProperty($property); 787 } 788 789 // Control if the $Scope have already the 'itemscope' prefix 790 if (!empty($scope) && stripos($scope, 'itemscope') !== 0) { 791 $scope = static::htmlScope($scope); 792 } 793 794 // Depending on the case, the $scope must precede the $property, or otherwise 795 if ($invert) { 796 $tmp = implode(' ', array($property, $scope)); 797 } else { 798 $tmp = implode(' ', array($scope, $property)); 799 } 800 801 $tmp = trim($tmp); 802 $tmp = ($tmp) ? ' ' . $tmp : ''; 803 804 // Control if it is an empty element without a closing tag 805 if ($tag === 'meta') { 806 return "<meta$tmp content='$content'>"; 807 } 808 809 return '<' . $tag . $tmp . '>' . $content . '</' . $tag . '>'; 810 } 811 812 /** 813 * Return the HTML Scope 814 * 815 * @param string $scope The Scope to process 816 * 817 * @return string 818 * 819 * @since 3.2 820 */ 821 public static function htmlScope($scope) 822 { 823 return "itemscope itemtype='https://schema.org/" . static::sanitizeType($scope) . "'"; 824 } 825 826 /** 827 * Return the HTML Property 828 * 829 * @param string $property The Property to process 830 * 831 * @return string 832 * 833 * @since 3.2 834 */ 835 public static function htmlProperty($property) 836 { 837 return "itemprop='$property'"; 838 } 839 }
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 |