Skip to content
Snippets Groups Projects
Select Git revision
  • 2df5804d3d034db26cef5a9ca8c584be3222c074
  • main default protected
  • studip-rector
  • ci-opt
  • course-members-export-as-word
  • data-vue-app
  • pipeline-improvements
  • webpack-optimizations
  • rector
  • icon-renewal
  • http-client-and-factories
  • jsonapi-atomic-operations
  • vueify-messages
  • tic-2341
  • 135-translatable-study-areas
  • extensible-sorm-action-parameters
  • sorm-configuration-trait
  • jsonapi-mvv-routes
  • docblocks-for-magic-methods
19 results

StudipArrayObject.class.php

Blame
  • Forked from Stud.IP / Stud.IP
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    StudipArrayObject.class.php 10.22 KiB
    <?php
    /**
     * StudipArrayObject
     *
     * This ArrayObject is a rewrite of the implementation to fix
     * issues with php's implementation of ArrayObject regarding cyclic references
     * based on Zend\Stdlib\ArrayObject\PhpReferenceCompatibility
     *
     * @author      André Noack <noack@data-quest.de>
     *
     * Zend Framework (http://framework.zend.com/)
     *
     * @link      http://github.com/zendframework/zf2 for the canonical source repository
     * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
     * @license   http://framework.zend.com/license/new-bsd New BSD License
     */
    class StudipArrayObject implements IteratorAggregate, ArrayAccess, Serializable, Countable
    {
        /**
         * Properties of the object have their normal functionality
         * when accessed as list (var_dump, foreach, etc.).
         */
        const STD_PROP_LIST = 1;
    
        /**
         * Entries can be accessed as properties (read and write).
         */
        const ARRAY_AS_PROPS = 2;
    
        /**
         * @var array
         */
        protected $storage;
    
        /**
         * @var int
         */
        protected $flag;
    
        /**
         * @var string
         */
        protected $iteratorClass;
    
        /**
         * @var array
         */
        protected $protectedProperties;
    
        /**
         * Constructor
         *
         * @param array  $input
         * @param int    $flags
         * @param string $iteratorClass
         */
        public function __construct($input = [], $flags = self::STD_PROP_LIST, $iteratorClass = 'ArrayIterator')
        {
            $this->setFlags($flags);
            $this->storage = $input;
            $this->setIteratorClass($iteratorClass);
            $this->protectedProperties = array_keys(get_object_vars($this));
        }
    
        /**
         * Returns whether the requested key exists
         *
         * @param  mixed $key
         * @return bool
         */
        public function __isset($key)
        {
            if ($this->flag == self::ARRAY_AS_PROPS) {
                return $this->offsetExists($key);
            }
    
            $this->validateKeyUsage($key);
    
            return isset($this->$key);
        }
    
        /**
         * Sets the value at the specified key to value
         *
         * @param  mixed $key
         * @param  mixed $value
         * @return void
         */
        public function __set($key, $value)
        {
            if ($this->flag == self::ARRAY_AS_PROPS) {
                $this->offsetSet($key, $value);
                return;
            }
    
            $this->validateKeyUsage($key);
    
            $this->$key = $value;
        }
    
        /**
         * Unsets the value at the specified key
         *
         * @param  mixed $key
         * @return void
         */
        public function __unset($key)
        {
            if ($this->flag == self::ARRAY_AS_PROPS) {
                $this->offsetUnset($key);
                return;
            }
    
            $this->validateKeyUsage($key);
    
            unset($this->$key);
        }
    
        /**
         * Returns the value at the specified key
         *
         * @param  mixed $key
         * @return mixed
         */
        public function __get($key)
        {
            if ($this->flag == self::ARRAY_AS_PROPS) {
                $ret = $this->offsetGet($key);
                return $ret;
            }
    
            $this->validateKeyUsage($key);
    
            return $this->$key;
        }
    
        /**
         * Called when serializing an ArrayObject
         */
        public function __serialize(): array
        {
            return get_object_vars($this);
        }
    
        /**
         * Called when unserializing an ArrayObject
         */
        public function __unserialize(array $data): void
        {
            foreach ($data as $k => $v) {
                switch ($k) {
                    case 'flag':
                        $this->setFlags($v);
                        break;
                    case 'storage':
                        $this->exchangeArray($v);
                        break;
                    case 'iteratorClass':
                        $this->setIteratorClass($v);
                        break;
                    case 'protectedProperties':
                        break;
                    default:
                        $this->__set($k, $v);
                }
            }
        }
    
        /**
         * Appends the value
         *
         * @param  mixed $value
         * @return void
         */
        public function append($value)
        {
            $this->storage[] = $value;
        }
    
        /**
         * Sort the entries by value
         *
         * @return void
         */
        public function asort()
        {
            asort($this->storage);
        }
    
        /**
         * Get the number of public properties in the ArrayObject
         */
        public function count(): int
        {
            return count($this->storage);
        }
    
        /**
         * Exchange the array for another one.
         *
         * @param  array|ArrayObject $data
         * @return array
         */
        public function exchangeArray($data)
        {
            if (!is_array($data) && !is_object($data)) {
                throw new InvalidArgumentException('Passed variable is not an array or object, using empty array instead');
            }
    
            if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject)) {
                $data = $data->getArrayCopy();
            }
            if (!is_array($data)) {
                $data = (array) $data;
            }
    
            $storage = $this->storage;
    
            $this->storage = $data;
    
            return $storage;
        }
    
        /**
         * Creates a copy of the ArrayObject.
         *
         * @return array
         */
        public function getArrayCopy()
        {
            return $this->storage;
        }
    
        /**
         * Gets the behavior flags.
         *
         * @return int
         */
        public function getFlags()
        {
            return $this->flag;
        }
    
        /**
         * Create a new iterator from an ArrayObject instance
         */
        public function getIterator(): Traversable
        {
            $class = $this->iteratorClass;
    
            return new $class($this->storage);
        }
    
        /**
         * Gets the iterator classname for the ArrayObject.
         *
         * @return string
         */
        public function getIteratorClass()
        {
            return $this->iteratorClass;
        }
    
        /**
         * Sort the entries by key
         *
         * @return void
         */
        public function ksort()
        {
            ksort($this->storage);
        }
    
        /**
         * Sort an array using a case insensitive "natural order" algorithm
         *
         * @return void
         */
        public function natcasesort()
        {
            natcasesort($this->storage);
        }
    
        /**
         * Sort entries using a "natural order" algorithm
         *
         * @return void
         */
        public function natsort()
        {
            natsort($this->storage);
        }
    
        /**
         * Returns whether the requested key exists
         *
         * @param  mixed $key
         */
        public function offsetExists($key): bool
        {
            return isset($this->storage[$key]);
        }
    
        /**
         * Returns the value at the specified key
         *
         * @param  mixed $key
         */
        public function offsetGet($key): mixed
        {
            $ret = null;
            if (!$this->offsetExists($key)) {
                return $ret;
            }
            $ret = $this->storage[$key];
    
            return $ret;
        }
    
        /**
         * Sets the value at the specified key to value
         *
         * @param  mixed $key
         * @param  mixed $value
         */
        public function offsetSet($key, $value): void
        {
            if (is_null($key)) {
                $this->append($value);
                return;
            }
            $this->storage[$key] = $value;
        }
    
        /**
         * Unsets the value at the specified key
         *
         * @param  mixed $key
         */
        public function offsetUnset($key): void
        {
            if ($this->offsetExists($key)) {
                unset($this->storage[$key]);
            }
        }
    
        /**
         * Serialize an ArrayObject
         *
         * @return string
         */
        public function serialize()
        {
            return serialize(get_object_vars($this));
        }
    
        /**
         * Sets the behavior flags
         *
         * @param  int  $flags
         * @return void
         */
        public function setFlags($flags)
        {
            $this->flag = $flags;
        }
    
        /**
         * Sets the iterator classname for the ArrayObject
         *
         * @param  string $class
         * @return void
         */
        public function setIteratorClass($class)
        {
            if (class_exists($class)) {
                $this->iteratorClass = $class;
    
                return ;
            }
    
            if (mb_strpos($class, '\\') === 0) {
                $class = '\\' . $class;
                if (class_exists($class)) {
                    $this->iteratorClass = $class;
    
                    return ;
                }
            }
    
            throw new InvalidArgumentException('The iterator class does not exist');
        }
    
        /**
         * Sort the entries with a user-defined comparison function and maintain key association
         *
         * @param  callable $function
         * @return void
         */
        public function uasort($function)
        {
            if (is_callable($function)) {
                uasort($this->storage, $function);
            }
        }
    
        /**
         * Sort the entries by keys using a user-defined comparison function
         *
         * @param  callable $function
         * @return void
         */
        public function uksort($function)
        {
            if (is_callable($function)) {
                uksort($this->storage, $function);
            }
        }
    
        /**
         * Unserialize an ArrayObject
         *
         * @param  string $data
         * @return void
         */
        public function unserialize($data)
        {
            $ar = unserialize($data);
            $this->setFlags($ar['flag']);
            $this->exchangeArray($ar['storage']);
            $this->setIteratorClass($ar['iteratorClass']);
            foreach ($ar as $k => $v) {
                switch ($k) {
                    case 'flag':
                        $this->setFlags($v);
                        break;
                    case 'storage':
                        $this->exchangeArray($v);
                        break;
                    case 'iteratorClass':
                        $this->setIteratorClass($v);
                        break;
                    case 'protectedProperties':
                        break;
                    default:
                        $this->__set($k, $v);
                }
            }
        }
    
        /**
         * Validates whether the given key is a protected property.
         *
         * @param  string $key The key to validate
         * @throws InvalidArgumentException when key is invalid
         */
        protected function validateKeyUsage($key)
        {
            if (in_array($key, $this->protectedProperties)) {
                throw new InvalidArgumentException("{$key} is a protected property, use a different key");
            }
        }
    
        /**
         * Returns whether the given value is in the underlying array.
         */
        public function contains($value): bool
        {
            return in_array($value, $this->storage);
        }
    }