/** * is the variable a data container that we can read from? * * @param mixed $item * the item to check * @return boolean * TRUE if the item is a data container * FALSE otherwise */ public static function check($item) { if (IsAssignable::check($item) || IsIndexable::check($item)) { return true; } return false; }
/** * throws exceptions if $item is not an assignable data type * * @param mixed $item * the container to check * @param string $exception * the class to use when throwing an exception * @return void */ public static function check($item, $exception = E4xx_UnsupportedType::class) { // make sure we have a string if (!IsAssignable::check($item)) { throw new $exception(SimpleType::from($item)); } }
/** * does it make sense to attempt to merge the contents of $theirs into * $ours? * * @param mixed $ours * where we want to merge to * @param mixed $theirs * where we want to merge from * @return boolean * true if merging makes sense * false otherwise */ public static function into($ours, $theirs) { // we can't merge non-arrays, non-objects if (!IsTraversable::check($theirs) && !IsAssignable::check($theirs)) { return false; } // if we have arrays or databag-type objects, we're good if (IsIndexable::check($ours) || IsAssignable::check($ours)) { return true; } // if we get here, then $ours is a complex object, which // we do not know how to merge // // or it is a scalar, which doesn't support merging at all return false; }
/** * merge their data into our array * * @param array &$ours * the array that we want to merge into * @param array|object $theirs * the data that we want to merge from * @return void */ public static function from(&$ours, $theirs) { if (IsAssignable::check($theirs)) { return self::fromObject($ours, $theirs); } if (IsTraversable::check($theirs)) { return self::fromArray($ours, $theirs); } // at this point, we want to append onto the end of $ours $ours[] = $theirs; }
/** * merge their data into one of our data's properties * * @param mixed $ours * the data that we want to merge into * @param string $property * the property to merge into * @param mixed $value * the data that we want to merge from * @return void */ public static function of(&$ours, $property, $value) { if (IsIndexable::check($ours)) { return self::ofArray($ours, $property, $value); } if (IsAssignable::check($ours)) { return self::ofObject($ours, $property, $value); } throw new E4xx_UnsupportedType(SimpleType::from($ours)); }
/** * merge their data into our data, using dot.notation.support to * find the point where the merge starts * * @param object $ours * the object that we want to merge into * @param string $path * the dot.notation.support path to where the merge should start * @param mixed $value * the data that we want to merge from * @param array|callable|string|null * if $path goes beyond what exists in $ours, how do we want to * extend $ours? * @return void */ public static function into(&$ours, $path, $value, $extendingItem = null) { if (IsAssignable::check($ours)) { return self::intoObject($ours, $path, $value, $extendingItem); } if (IsIndexable::check($ours)) { return self::intoArray($ours, $path, $value, $extendingItem); } throw new E4xx_UnsupportedType(SimpleType::from($ours)); }
/** * extract a value from a container, using dot.notation.support * * @param mixed $item * the container to extract from * @param string $path * the dot.notation.support path to walk * @return mixed * whatever we find when we walk the path */ public static function from($item, $path) { // robustness! RequireReadableContainer::check($item, E4xx_UnsupportedType::class); if (IsAssignable::check($item)) { return self::fromObject($item, $path); } return self::fromArray($item, $path); }
/** * get a child from part of our container tree, optionally extending * the container if needed * * @param array|object &$container * the container we want to get the child from * @param string $part * the name of the child that we want * @param array|callable|string|null $extendingItem * if we need to extend the container, this is what we use to * do the extension * @return mixed */ private static function &getChildFromPart(&$container, $part, $extendingItem = null) { if (IsAssignable::check($container)) { return self::getPartFromObject($container, $part, $extendingItem); } // if we get here, this must be an array $retval =& self::getPartFromArray($container, $part, $extendingItem); return $retval; }
/** * merge their data into our object * * @param object $ours * the object that we want to merge into * @param array|object $theirs * the data that we want to merge from * @return void */ public static function from($ours, $theirs) { if (IsAssignable::check($theirs)) { return self::fromObject($ours, $theirs); } if (IsTraversable::check($theirs)) { return self::fromArray($ours, $theirs); } // cannot merge anything that reaches here! throw new E4xx_UnsupportedType(SimpleType::from($ours)); }
/** * should we overwrite $ours->$property with the value of $theirs? * * @param object $ours * the object where $property may exist * @param string $property * the property on $ours whose fate we are deciding * @param mixed $theirs * the data we want to assign to the property * @return boolean * TRUE if we should overwrite the property's existing value * with $value * TRUE if $property currently has no value * FALSE if we should merge $value into the property's exist * value */ public static function intoObject($ours, $property, $theirs) { // robustness! if (!IsAssignable::check($ours)) { throw new E4xx_UnsupportedType(SimpleType::from($ours)); } return self::checkObject($ours, $property, $theirs); }