[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Microdata/ -> Microdata.php (source)

   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  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer