Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/cakephp/cakephp/src/View/Form/ArrayContext.php
<?php
/**
 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 * @link          https://cakephp.org CakePHP(tm) Project
 * @since         3.0.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 */
namespace Cake\View\Form;

use
Cake\Http\ServerRequest;
use
Cake\Utility\Hash;
use
Cake\Validation\Validator;

/**
 * Provides a basic array based context provider for FormHelper.
 *
 * This adapter is useful in testing or when you have forms backed by
 * simple array data structures.
 *
 * Important keys:
 *
 * - `defaults` The default values for fields. These values
 *   will be used when there is no request data set. Data should be nested following
 *   the dot separated paths you access your fields with.
 * - `required` A nested array of fields, relationships and boolean
 *   flags to indicate a field is required. The value can also be a string to be used
 *   as the required error message
 * - `schema` An array of data that emulate the column structures that
 *   Cake\Database\Schema\Schema uses. This array allows you to control
 *   the inferred type for fields and allows auto generation of attributes
 *   like maxlength, step and other HTML attributes. If you want
 *   primary key/id detection to work. Make sure you have provided a `_constraints`
 *   array that contains `primary`. See below for an example.
 * - `errors` An array of validation errors. Errors should be nested following
 *   the dot separated paths you access your fields with.
 *
 *  ### Example
 *
 *  ```
 *  $data = [
 *    'schema' => [
 *      'id' => ['type' => 'integer'],
 *      'title' => ['type' => 'string', 'length' => 255],
 *      '_constraints' => [
 *        'primary' => ['type' => 'primary', 'columns' => ['id']]
 *      ]
 *    ],
 *    'defaults' => [
 *      'id' => 1,
 *      'title' => 'First post!',
 *    ],
 *    'required' => [
 *      'id' => true, // will use default required message
 *      'title' => 'Please enter a title',
 *      'body' => false,
 *    ],
 *  ];
 *  ```
 */
class ArrayContext implements ContextInterface
{
   
/**
     * The request object.
     *
     * @var \Cake\Http\ServerRequest
     */
   
protected $_request;

   
/**
     * Context data for this object.
     *
     * @var array
     */
   
protected $_context;

   
/**
     * Constructor.
     *
     * @param \Cake\Http\ServerRequest $request The request object.
     * @param array $context Context info.
     */
   
public function __construct(ServerRequest $request, array $context)
    {
       
$this->_request = $request;
       
$context += [
           
'schema' => [],
           
'required' => [],
           
'defaults' => [],
           
'errors' => [],
        ];
       
$this->_context = $context;
    }

   
/**
     * Get the fields used in the context as a primary key.
     *
     * @return array
     */
   
public function primaryKey()
    {
        if (
            empty(
$this->_context['schema']['_constraints']) ||
            !
is_array($this->_context['schema']['_constraints'])
        ) {
            return [];
        }
        foreach (
$this->_context['schema']['_constraints'] as $data) {
            if (isset(
$data['type']) && $data['type'] === 'primary') {
                return isset(
$data['columns']) ? (array)$data['columns'] : [];
            }
        }

        return [];
    }

   
/**
     * {@inheritDoc}
     */
   
public function isPrimaryKey($field)
    {
       
$primaryKey = $this->primaryKey();

        return
in_array($field, $primaryKey, true);
    }

   
/**
     * Returns whether or not this form is for a create operation.
     *
     * For this method to return true, both the primary key constraint
     * must be defined in the 'schema' data, and the 'defaults' data must
     * contain a value for all fields in the key.
     *
     * @return bool
     */
   
public function isCreate()
    {
       
$primary = $this->primaryKey();
        foreach (
$primary as $column) {
            if (!empty(
$this->_context['defaults'][$column])) {
                return
false;
            }
        }

        return
true;
    }

   
/**
     * Get the current value for a given field.
     *
     * This method will coalesce the current request data and the 'defaults'
     * array.
     *
     * @param string $field A dot separated path to the field a value
     *   is needed for.
     * @param array $options Options:
     *   - `default`: Default value to return if no value found in request
     *     data or context record.
     *   - `schemaDefault`: Boolean indicating whether default value from
     *      context's schema should be used if it's not explicitly provided.
     * @return mixed
     */
   
public function val($field, $options = [])
    {
       
$options += [
           
'default' => null,
           
'schemaDefault' => true,
        ];

       
$val = $this->_request->getData($field);
        if (
$val !== null) {
            return
$val;
        }
        if (
$options['default'] !== null || !$options['schemaDefault']) {
            return
$options['default'];
        }
        if (empty(
$this->_context['defaults']) || !is_array($this->_context['defaults'])) {
            return
null;
        }

       
// Using Hash::check here incase the default value is actually null
       
if (Hash::check($this->_context['defaults'], $field)) {
            return
Hash::get($this->_context['defaults'], $field);
        }

        return
Hash::get($this->_context['defaults'], $this->stripNesting($field));
    }

   
/**
     * Check if a given field is 'required'.
     *
     * In this context class, this is simply defined by the 'required' array.
     *
     * @param string $field A dot separated path to check required-ness for.
     * @return bool
     */
   
public function isRequired($field)
    {
        return (bool)
$this->getRequiredMessage($field);
    }

   
/**
     * {@inheritDoc}
     */
   
public function getRequiredMessage($field)
    {
        if (!
is_array($this->_context['required'])) {
            return
null;
        }
       
$required = Hash::get($this->_context['required'], $field);
        if (
$required === null) {
           
$required = Hash::get($this->_context['required'], $this->stripNesting($field));
        }

        if (
$required === false) {
            return
null;
        }

        if (
$required === true) {
           
$required = __d('cake', 'This field is required');
        }

        return
$required;
    }

   
/**
     * Get field length from validation
     *
     * In this context class, this is simply defined by the 'length' array.
     *
     * @param string $field A dot separated path to check required-ness for.
     * @return int|null
     */
   
public function getMaxLength($field)
    {
        if (!
is_array($this->_context['schema'])) {
            return
null;
        }

        return
Hash::get($this->_context['schema'], "$field.length");
    }

   
/**
     * {@inheritDoc}
     */
   
public function fieldNames()
    {
       
$schema = $this->_context['schema'];
        unset(
$schema['_constraints'], $schema['_indexes']);

        return
array_keys($schema);
    }

   
/**
     * Get the abstract field type for a given field name.
     *
     * @param string $field A dot separated path to get a schema type for.
     * @return string|null An abstract data type or null.
     * @see \Cake\Database\Type
     */
   
public function type($field)
    {
        if (!
is_array($this->_context['schema'])) {
            return
null;
        }

       
$schema = Hash::get($this->_context['schema'], $field);
        if (
$schema === null) {
           
$schema = Hash::get($this->_context['schema'], $this->stripNesting($field));
        }

        return isset(
$schema['type']) ? $schema['type'] : null;
    }

   
/**
     * Get an associative array of other attributes for a field name.
     *
     * @param string $field A dot separated path to get additional data on.
     * @return array An array of data describing the additional attributes on a field.
     */
   
public function attributes($field)
    {
        if (!
is_array($this->_context['schema'])) {
            return [];
        }
       
$schema = Hash::get($this->_context['schema'], $field);
        if (
$schema === null) {
           
$schema = Hash::get($this->_context['schema'], $this->stripNesting($field));
        }
       
$whitelist = ['length' => null, 'precision' => null];

        return
array_intersect_key((array)$schema, $whitelist);
    }

   
/**
     * Check whether or not a field has an error attached to it
     *
     * @param string $field A dot separated path to check errors on.
     * @return bool Returns true if the errors for the field are not empty.
     */
   
public function hasError($field)
    {
        if (empty(
$this->_context['errors'])) {
            return
false;
        }

        return (bool)
Hash::check($this->_context['errors'], $field);
    }

   
/**
     * Get the errors for a given field
     *
     * @param string $field A dot separated path to check errors on.
     * @return array An array of errors, an empty array will be returned when the
     *    context has no errors.
     */
   
public function error($field)
    {
        if (empty(
$this->_context['errors'])) {
            return [];
        }

        return (array)
Hash::get($this->_context['errors'], $field);
    }

   
/**
     * Strips out any numeric nesting
     *
     * For example users.0.age will output as users.age
     *
     * @param string $field A dot separated path
     * @return string A string with stripped numeric nesting
     */
   
protected function stripNesting($field)
    {
        return
preg_replace('/\.\d*\./', '.', $field);
    }
}