/**
  * throws exceptions if $item is not a traversable 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 traversable type
     if (!IsTraversable::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;
 }
 /**
  * @covers ::getCachedResult
  * @covers ::getCacheKey
  * @covers ::check
  * @covers ::checkMixed
  */
 public function testReadsFromStaticCache()
 {
     // ----------------------------------------------------------------
     // setup your test
     // force a nonsense result into the cache
     $expectedResult = 100;
     $data = 3.1415927;
     InvokeMethod::onClass(IsTraversable::class, 'setCachedResult', [$data, $expectedResult]);
     // ----------------------------------------------------------------
     // perform the change
     $actualResult = IsTraversable::check($data);
     // ----------------------------------------------------------------
     // test the results
     $this->assertEquals($expectedResult, $actualResult);
 }
 /**
  * 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;
 }
 /**
  * descend inside a container, using dot.notation.support, and optionally
  * extending the container if the end of the dot.notation.path is missing
  *
  * @param  mixed &$item
  *         the container to dig into
  * @param  string $property
  *         the dot.notation.support path to descend
  * @param  array|callable|string|null $extendingItem
  *         if we need to extend, what data type do we extend using?
  * @return mixed
  */
 public static function &into(&$item, $property, $extendingItem = null)
 {
     if (IsAssignable::check($item)) {
         $retval =& self::intoObject($item, $property, $extendingItem);
         return $retval;
     }
     if (IsTraversable::check($item)) {
         $retval =& self::intoArray($item, $property, $extendingItem);
         return $retval;
     }
     throw new E4xx_UnsupportedType(SimpleType::from($item));
 }
 /**
  * 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));
 }
 /**
  * convert an array (or traversable object) into an array
  *
  * this will do a deep conversion
  *
  * @param  Traversable $data
  *         the data to convert
  * @return array
  */
 private static function fromTraversable($data)
 {
     // our return value
     $retval = [];
     // walk the array
     foreach ($data as $key => $value) {
         if (IsTraversable::check($value)) {
             // array, object - deep copy required
             $retval[$key] = self::from($value);
         } else {
             // it is either opaque, or a simple type
             $retval[$key] = $value;
         }
     }
     // all done
     return $retval;
 }