[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Form/ -> FormHelper.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2010 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\Form;
  11  
  12  use Joomla\CMS\Filesystem\Path;
  13  use Joomla\String\Normalise;
  14  use Joomla\String\StringHelper;
  15  
  16  // phpcs:disable PSR1.Files.SideEffects
  17  \defined('JPATH_PLATFORM') or die;
  18  // phpcs:enable PSR1.Files.SideEffects
  19  
  20  /**
  21   * Form's helper class.
  22   * Provides a storage for filesystem's paths where Form's entities reside and methods for creating those entities.
  23   * Also stores objects with entities' prototypes for further reusing.
  24   *
  25   * @since  1.7.0
  26   */
  27  class FormHelper
  28  {
  29      /**
  30       * Array with paths where entities(field, rule, form) can be found.
  31       *
  32       * Array's structure:
  33       *
  34       * paths:
  35       * {ENTITY_NAME}:
  36       * - /path/1
  37       * - /path/2
  38       *
  39       * @var    array
  40       * @since  1.7.0
  41       */
  42      protected static $paths;
  43  
  44      /**
  45       * The class namespaces.
  46       *
  47       * @var   string
  48       * @since 3.8.0
  49       */
  50      protected static $prefixes = array('field' => array(), 'form' => array(), 'rule' => array(), 'filter' => array());
  51  
  52      /**
  53       * Static array of Form's entity objects for re-use.
  54       * Prototypes for all fields and rules are here.
  55       *
  56       * Array's structure:
  57       * entities:
  58       * {ENTITY_NAME}:
  59       * {KEY}: {OBJECT}
  60       *
  61       * @var    array
  62       * @since  1.7.0
  63       */
  64      protected static $entities = array('field' => array(), 'form' => array(), 'rule' => array(), 'filter' => array());
  65  
  66      /**
  67       * Method to load a form field object given a type.
  68       *
  69       * @param   string   $type  The field type.
  70       * @param   boolean  $new   Flag to toggle whether we should get a new instance of the object.
  71       *
  72       * @return  FormField|boolean  FormField object on success, false otherwise.
  73       *
  74       * @since   1.7.0
  75       */
  76      public static function loadFieldType($type, $new = true)
  77      {
  78          return self::loadType('field', $type, $new);
  79      }
  80  
  81      /**
  82       * Method to load a form rule object given a type.
  83       *
  84       * @param   string   $type  The rule type.
  85       * @param   boolean  $new   Flag to toggle whether we should get a new instance of the object.
  86       *
  87       * @return  FormRule|boolean  FormRule object on success, false otherwise.
  88       *
  89       * @since   1.7.0
  90       */
  91      public static function loadRuleType($type, $new = true)
  92      {
  93          return self::loadType('rule', $type, $new);
  94      }
  95  
  96      /**
  97       * Method to load a form filter object given a type.
  98       *
  99       * @param   string   $type  The rule type.
 100       * @param   boolean  $new   Flag to toggle whether we should get a new instance of the object.
 101       *
 102       * @return  FormFilterInterface|boolean  FormRule object on success, false otherwise.
 103       *
 104       * @since   4.0.0
 105       */
 106      public static function loadFilterType($type, $new = true)
 107      {
 108          return self::loadType('filter', $type, $new);
 109      }
 110  
 111      /**
 112       * Method to load a form entity object given a type.
 113       * Each type is loaded only once and then used as a prototype for other objects of same type.
 114       * Please, use this method only with those entities which support types (forms don't support them).
 115       *
 116       * @param   string   $entity  The entity.
 117       * @param   string   $type    The entity type.
 118       * @param   boolean  $new     Flag to toggle whether we should get a new instance of the object.
 119       *
 120       * @return  mixed  Entity object on success, false otherwise.
 121       *
 122       * @since   1.7.0
 123       */
 124      protected static function loadType($entity, $type, $new = true)
 125      {
 126          // Reference to an array with current entity's type instances
 127          $types = &self::$entities[$entity];
 128  
 129          $key = md5($type);
 130  
 131          // Return an entity object if it already exists and we don't need a new one.
 132          if (isset($types[$key]) && $new === false) {
 133              return $types[$key];
 134          }
 135  
 136          $class = self::loadClass($entity, $type);
 137  
 138          if ($class === false) {
 139              return false;
 140          }
 141  
 142          // Instantiate a new type object.
 143          $types[$key] = new $class();
 144  
 145          return $types[$key];
 146      }
 147  
 148      /**
 149       * Attempt to import the FormField class file if it isn't already imported.
 150       * You can use this method outside of Form for loading a field for inheritance or composition.
 151       *
 152       * @param   string  $type  Type of a field whose class should be loaded.
 153       *
 154       * @return  string|boolean  Class name on success or false otherwise.
 155       *
 156       * @since   1.7.0
 157       */
 158      public static function loadFieldClass($type)
 159      {
 160          return self::loadClass('field', $type);
 161      }
 162  
 163      /**
 164       * Attempt to import the FormRule class file if it isn't already imported.
 165       * You can use this method outside of Form for loading a rule for inheritance or composition.
 166       *
 167       * @param   string  $type  Type of a rule whose class should be loaded.
 168       *
 169       * @return  string|boolean  Class name on success or false otherwise.
 170       *
 171       * @since   1.7.0
 172       */
 173      public static function loadRuleClass($type)
 174      {
 175          return self::loadClass('rule', $type);
 176      }
 177  
 178      /**
 179       * Attempt to import the FormFilter class file if it isn't already imported.
 180       * You can use this method outside of Form for loading a filter for inheritance or composition.
 181       *
 182       * @param   string  $type  Type of a filter whose class should be loaded.
 183       *
 184       * @return  string|boolean  Class name on success or false otherwise.
 185       *
 186       * @since   4.0.0
 187       */
 188      public static function loadFilterClass($type)
 189      {
 190          return self::loadClass('filter', $type);
 191      }
 192  
 193      /**
 194       * Load a class for one of the form's entities of a particular type.
 195       * Currently, it makes sense to use this method for the "field" and "rule" entities
 196       * (but you can support more entities in your subclass).
 197       *
 198       * @param   string  $entity  One of the form entities (field or rule).
 199       * @param   string  $type    Type of an entity.
 200       *
 201       * @return  string|boolean  Class name on success or false otherwise.
 202       *
 203       * @since   1.7.0
 204       */
 205      protected static function loadClass($entity, $type)
 206      {
 207          // Check if there is a class in the registered namespaces
 208          foreach (self::addPrefix($entity) as $prefix) {
 209              // Treat underscores as namespace
 210              $name = Normalise::toSpaceSeparated($type);
 211              $name = str_ireplace(' ', '\\', ucwords($name));
 212  
 213              $subPrefix = '';
 214  
 215              if (strpos($name, '.')) {
 216                  list($subPrefix, $name) = explode('.', $name);
 217                  $subPrefix = ucfirst($subPrefix) . '\\';
 218              }
 219  
 220              // Compile the classname
 221              $class = rtrim($prefix, '\\') . '\\' . $subPrefix . ucfirst($name) . ucfirst($entity);
 222  
 223              // Check if the class exists
 224              if (class_exists($class)) {
 225                  return $class;
 226              }
 227          }
 228  
 229          $prefix = 'J';
 230  
 231          if (strpos($type, '.')) {
 232              list($prefix, $type) = explode('.', $type);
 233          }
 234  
 235          $class = StringHelper::ucfirst($prefix, '_') . 'Form' . StringHelper::ucfirst($entity, '_') . StringHelper::ucfirst($type, '_');
 236  
 237          if (class_exists($class)) {
 238              return $class;
 239          }
 240  
 241          // Get the field search path array.
 242          $paths = self::addPath($entity);
 243  
 244          // If the type is complex, add the base type to the paths.
 245          if ($pos = strpos($type, '_')) {
 246              // Add the complex type prefix to the paths.
 247              for ($i = 0, $n = \count($paths); $i < $n; $i++) {
 248                  // Derive the new path.
 249                  $path = $paths[$i] . '/' . strtolower(substr($type, 0, $pos));
 250  
 251                  // If the path does not exist, add it.
 252                  if (!\in_array($path, $paths)) {
 253                      $paths[] = $path;
 254                  }
 255              }
 256  
 257              // Break off the end of the complex type.
 258              $type = substr($type, $pos + 1);
 259          }
 260  
 261          // Try to find the class file.
 262          $type = strtolower($type) . '.php';
 263  
 264          foreach ($paths as $path) {
 265              $file = Path::find($path, $type);
 266  
 267              if (!$file) {
 268                  continue;
 269              }
 270  
 271              require_once $file;
 272  
 273              if (class_exists($class)) {
 274                  break;
 275              }
 276          }
 277  
 278          // Check for all if the class exists.
 279          return class_exists($class) ? $class : false;
 280      }
 281  
 282      /**
 283       * Method to add a path to the list of field include paths.
 284       *
 285       * @param   mixed  $new  A path or array of paths to add.
 286       *
 287       * @return  array  The list of paths that have been added.
 288       *
 289       * @since   1.7.0
 290       */
 291      public static function addFieldPath($new = null)
 292      {
 293          return self::addPath('field', $new);
 294      }
 295  
 296      /**
 297       * Method to add a path to the list of form include paths.
 298       *
 299       * @param   mixed  $new  A path or array of paths to add.
 300       *
 301       * @return  array  The list of paths that have been added.
 302       *
 303       * @since   1.7.0
 304       */
 305      public static function addFormPath($new = null)
 306      {
 307          return self::addPath('form', $new);
 308      }
 309  
 310      /**
 311       * Method to add a path to the list of rule include paths.
 312       *
 313       * @param   mixed  $new  A path or array of paths to add.
 314       *
 315       * @return  array  The list of paths that have been added.
 316       *
 317       * @since   1.7.0
 318       */
 319      public static function addRulePath($new = null)
 320      {
 321          return self::addPath('rule', $new);
 322      }
 323  
 324      /**
 325       * Method to add a path to the list of filter include paths.
 326       *
 327       * @param   mixed  $new  A path or array of paths to add.
 328       *
 329       * @return  array  The list of paths that have been added.
 330       *
 331       * @since   4.0.0
 332       */
 333      public static function addFilterPath($new = null)
 334      {
 335          return self::addPath('filter', $new);
 336      }
 337  
 338      /**
 339       * Method to add a path to the list of include paths for one of the form's entities.
 340       * Currently supported entities: field, rule and form. You are free to support your own in a subclass.
 341       *
 342       * @param   string  $entity  Form's entity name for which paths will be added.
 343       * @param   mixed   $new     A path or array of paths to add.
 344       *
 345       * @return  array  The list of paths that have been added.
 346       *
 347       * @since   1.7.0
 348       */
 349      protected static function addPath($entity, $new = null)
 350      {
 351          if (!isset(self::$paths[$entity])) {
 352              self::$paths[$entity] = [];
 353          }
 354  
 355          // Reference to an array with paths for current entity
 356          $paths = &self::$paths[$entity];
 357  
 358          // Force the new path(s) to an array.
 359          settype($new, 'array');
 360  
 361          // Add the new paths to the stack if not already there.
 362          foreach ($new as $path) {
 363              $path = \trim($path);
 364  
 365              if (!\in_array($path, $paths)) {
 366                  \array_unshift($paths, $path);
 367              }
 368          }
 369  
 370          return $paths;
 371      }
 372  
 373      /**
 374       * Method to add a namespace prefix to the list of field lookups.
 375       *
 376       * @param   mixed  $new  A namespaces or array of namespaces to add.
 377       *
 378       * @return  array  The list of namespaces that have been added.
 379       *
 380       * @since   3.8.0
 381       */
 382      public static function addFieldPrefix($new = null)
 383      {
 384          return self::addPrefix('field', $new);
 385      }
 386  
 387      /**
 388       * Method to add a namespace to the list of form lookups.
 389       *
 390       * @param   mixed  $new  A namespace or array of namespaces to add.
 391       *
 392       * @return  array  The list of namespaces that have been added.
 393       *
 394       * @since   3.8.0
 395       */
 396      public static function addFormPrefix($new = null)
 397      {
 398          return self::addPrefix('form', $new);
 399      }
 400  
 401      /**
 402       * Method to add a namespace to the list of rule lookups.
 403       *
 404       * @param   mixed  $new  A namespace or array of namespaces to add.
 405       *
 406       * @return  array  The list of namespaces that have been added.
 407       *
 408       * @since   3.8.0
 409       */
 410      public static function addRulePrefix($new = null)
 411      {
 412          return self::addPrefix('rule', $new);
 413      }
 414  
 415      /**
 416       * Method to add a namespace to the list of filter lookups.
 417       *
 418       * @param   mixed  $new  A namespace or array of namespaces to add.
 419       *
 420       * @return  array  The list of namespaces that have been added.
 421       *
 422       * @since   4.0.0
 423       */
 424      public static function addFilterPrefix($new = null)
 425      {
 426          return self::addPrefix('filter', $new);
 427      }
 428  
 429      /**
 430       * Method to add a namespace to the list of namespaces for one of the form's entities.
 431       * Currently supported entities: field, rule and form. You are free to support your own in a subclass.
 432       *
 433       * @param   string  $entity  Form's entity name for which paths will be added.
 434       * @param   mixed   $new     A namespace or array of namespaces to add.
 435       *
 436       * @return  array  The list of namespaces that have been added.
 437       *
 438       * @since   3.8.0
 439       */
 440      protected static function addPrefix($entity, $new = null)
 441      {
 442          // Reference to an array with namespaces for current entity
 443          $prefixes = &self::$prefixes[$entity];
 444  
 445          // Add the default entity's search namespace if not set.
 446          if (empty($prefixes)) {
 447              $prefixes[] = __NAMESPACE__ . '\\' . ucfirst($entity);
 448          }
 449  
 450          // Force the new namespace(s) to an array.
 451          settype($new, 'array');
 452  
 453          // Add the new paths to the stack if not already there.
 454          foreach ($new as $prefix) {
 455              $prefix = trim($prefix);
 456  
 457              if (\in_array($prefix, $prefixes)) {
 458                  continue;
 459              }
 460  
 461              array_unshift($prefixes, $prefix);
 462          }
 463  
 464          return $prefixes;
 465      }
 466  
 467      /**
 468       * Parse the show on conditions
 469       *
 470       * @param   string  $showOn       Show on conditions.
 471       * @param   string  $formControl  Form name.
 472       * @param   string  $group        The dot-separated form group path.
 473       *
 474       * @return  array   Array with show on conditions.
 475       *
 476       * @since   3.7.0
 477       */
 478      public static function parseShowOnConditions($showOn, $formControl = null, $group = null)
 479      {
 480          // Process the showon data.
 481          if (!$showOn) {
 482              return array();
 483          }
 484  
 485          $formPath = $formControl ?: '';
 486  
 487          if ($group) {
 488              $groups = explode('.', $group);
 489  
 490              // An empty formControl leads to invalid shown property
 491              // Use the 1st part of the group instead to avoid.
 492              if (empty($formPath) && isset($groups[0])) {
 493                  $formPath = $groups[0];
 494                  array_shift($groups);
 495              }
 496  
 497              foreach ($groups as $group) {
 498                  $formPath .= '[' . $group . ']';
 499              }
 500          }
 501  
 502          $showOnData  = array();
 503          $showOnParts = preg_split('#(\[AND\]|\[OR\])#', $showOn, -1, PREG_SPLIT_DELIM_CAPTURE);
 504          $op          = '';
 505  
 506          foreach ($showOnParts as $showOnPart) {
 507              if (($showOnPart === '[AND]') || $showOnPart === '[OR]') {
 508                  $op = trim($showOnPart, '[]');
 509                  continue;
 510              }
 511  
 512              $compareEqual     = strpos($showOnPart, '!:') === false;
 513              $showOnPartBlocks = explode(($compareEqual ? ':' : '!:'), $showOnPart, 2);
 514  
 515              $dotPos = strpos($showOnPartBlocks[0], '.');
 516  
 517              if ($dotPos === false) {
 518                  $field = $formPath ? $formPath . '[' . $showOnPartBlocks[0] . ']' : $showOnPartBlocks[0];
 519              } else {
 520                  if ($dotPos === 0) {
 521                      $fieldName = substr($showOnPartBlocks[0], 1);
 522                      $field     = $formControl ? $formControl . '[' . $fieldName . ']' : $fieldName;
 523                  } else {
 524                      if ($formControl) {
 525                          $field = $formControl . ('[' . str_replace('.', '][', $showOnPartBlocks[0]) . ']');
 526                      } else {
 527                          $groupParts = explode('.', $showOnPartBlocks[0]);
 528                          $field      = array_shift($groupParts) . '[' . join('][', $groupParts) . ']';
 529                      }
 530                  }
 531              }
 532  
 533              $showOnData[] = array(
 534                  'field'  => $field,
 535                  'values' => explode(',', $showOnPartBlocks[1]),
 536                  'sign'   => $compareEqual === true ? '=' : '!=',
 537                  'op'     => $op,
 538              );
 539  
 540              if ($op !== '') {
 541                  $op = '';
 542              }
 543          }
 544  
 545          return $showOnData;
 546      }
 547  }


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