PHP Classes

File: src/InputFilter.php

Recommend this page to a friend!
  Packages of Scott Arciszewski   Ionizer PHP Filter Input   src/InputFilter.php   Download  
File: src/InputFilter.php
Role: Class source
Content type: text/plain
Description: Class source
Class: Ionizer PHP Filter Input
Filter input values by chaining filter objects
Author: By
Last change:
Date: 5 years ago
Size: 5,139 bytes
 

Contents

Class file image Download
<?php
declare(strict_types=1);
namespace ParagonIE\Ionizer;

use ParagonIE\ConstantTime\Binary;
use ParagonIE\Ionizer\Contract\FilterInterface;

/**
 * Class InputFilter
 * @package ParagonIE\Ionizer
 */
class InputFilter implements FilterInterface
{
    /**
     * @var string|int|float|bool|array|null
     */
    protected $default;

    /**
     * @var string
     */
    protected $type = '';

    /**
     * @var string (for debugging purposes)
     */
    protected $index = '';

    /**
     * @var callable[]
     */
    protected $callbacks = [];

    /**
     * @var string[]
     */
    protected $thisCallbacks = [];

    /**
     * Sets the expected input type (e.g. string, boolean)
     *
     * @param string $typeIndicator
     * @return FilterInterface
     */
    public function setType(string $typeIndicator): FilterInterface
    {
        $this->type = $typeIndicator;
        return $this;
    }

    /**
     * Throw an InvalidDataException is this field is not defined/populated.
     * Use in a callback.
     *
     * $filter->addCallback([InputFilter::class, 'required']);
     *
     * @param mixed|null $data
     * @return mixed
     * @throws InvalidDataException
     */
    public static function required($data = null)
    {
        if (\is_null($data)) {
            throw new InvalidDataException('This is not an optional field.');
        }
        return $data;
    }

    /**
     * Set the default value (not applicable to booleans)
     *
     * @param string|int|float|bool|array|null $value
     * @return FilterInterface
     */
    public function setDefault($value): FilterInterface
    {
        $this->default = $value;
        return $this;
    }

    /**
     * Add a callback to this filter (supports more than one)
     *
     * @param callable $func
     * @return FilterInterface
     */
    public function addCallback(callable $func): FilterInterface
    {
        $this->callbacks[] = $func;
        return $this;
    }

    /**
     * Add a callback to this filter (supports more than one)
     *
     * @param string $func
     * @return FilterInterface
     */
    public function addThisCallback(string $func): FilterInterface
    {
        if (!\method_exists($this, $func)) {
            throw new \Error('Method ' . $func . ' does not exist on class ' . \get_class($this));
        }
        $this->thisCallbacks[] = $func;
        return $this;
    }

    /**
     * Process data using the filter rules.
     *
     * @param mixed $data
     * @return mixed
     * @throws InvalidDataException
     * @throws \TypeError
     */
    public function process($data = null)
    {
        /** @var string|int|float|bool|array|null $data */
        $data = $this->applyCallbacks($data, 0);
        /** @var string|int|float|bool|array|null $data */
        $data = $this->applyThisCallbacks($data, 0);
        if ($data === null) {
            /** @var string|int|float|bool|array|null $data */
            $data = $this->default;
        }

        // For type strictness:
        switch ($this->type) {
            case 'array':
                /** @var array $data */
                return (array) $data;
            case 'bool':
                /** @var bool $data */
                return (bool) $data;
            case 'float':
                /** @var float $data */
                return (float) $data;
            case 'int':
                /** @var int $data */
                return (int) $data;
            case 'string':
                /** @var string $data */
                return (string) $data;
            default:
                return $data;
        }
    }

    /**
     * Apply all of the callbacks for this filter.
     *
     * @param mixed $data
     * @param int $offset
     * @return mixed
     * @throws InvalidDataException
     */
    public function applyCallbacks($data = null, int $offset = 0)
    {
        if (empty($data)) {
            if ($this->type === 'bool') {
                return false;
            }
            return $this->default;
        }
        if ($offset >= \count($this->callbacks)) {
            return $data;
        }
        $func = $this->callbacks[$offset];
        /** @var string|int|float|bool|array|null $data */
        $data = $func($data);
        return $this->applyCallbacks($data, $offset + 1);
    }
    /**
     * Apply all of the callbacks for this filter.
     *
     * @param mixed $data
     * @param int $offset
     * @return mixed
     * @throws InvalidDataException
     */
    public function applyThisCallbacks($data = null, int $offset = 0)
    {
        if ($offset >= \count($this->thisCallbacks)) {
            return $data;
        }
        /** @var string $func */
        $func = $this->thisCallbacks[$offset];
        /** @var string|int|float|bool|array|null $data */
        $data = $this->$func($data);
        return $this->applyCallbacks($data, $offset + 1);
    }

    /**
     * @param string $index
     * @return FilterInterface
     */
    public function setIndex(string $index): FilterInterface
    {
        $this->index = $index;
        return $this;
    }
}