original_string: public function getRelated($source, $relationName, $query=null, $meta=null)
      {
          if (!$source) { return; }
  
          $sourceIsArray = false;
  
          $test = $source;
          if (is_array($test) || $test instanceof \Traversable) {
              $sourceIsArray = true;
              $test = $test[0];
          }
  
          if (!$meta) {
              if ($query instanceof Meta) {
                  list ($meta, $query) = [$query, null];
              } else {
                  $meta = $this->mapper->getMeta(get_class($test));
              }
          }
          else {
              $meta = $meta instanceof Meta ? $meta : $this->mapper->getMeta($meta);
          }
  
          if (!isset($meta->relations[$relationName])) {
              throw new Exception("Unknown relation $relationName on {$meta->class}");
          }
          
          $relation = $meta->relations[$relationName];
          $relator = $this->getRelator($relation);
          
          if ($query) {
              // need to support both Query\Criteria and Query\Select
              // this is a cheeky hack - the API doesn't declare support for
              // Select in Relators because it carries promises of things like 
              // 'fields' and whatnot that we'll never be able to satisfy. 
              // That whole hierarchy needs to be cleaned
              // up into a bunch of traits so we can have RelatorCriteria or something.
              $query = $query instanceof Query\Criteria ? $query : Query\Select::fromParamArgs([$query]);
              $stack = $query->stack;
          }
          else {
              $stack = [];
          }
  
          $stack[$meta->class] = true;
          if ($sourceIsArray) {
              return $relator->getRelatedForList($meta, $source, $relation, $query ?: null, $stack);
          } else {
              return $relator->getRelated($meta, $source, $relation, $query ?: null, $stack);
          }
      }
code: public function getRelated($source, $relationName, $query=null, $meta=null)
      {
          if (!$source) { return; }
  
          $sourceIsArray = false;
  
          $test = $source;
          if (is_array($test) || $test instanceof \Traversable) {
              $sourceIsArray = true;
              $test = $test[0];
          }
  
          if (!$meta) {
              if ($query instanceof Meta) {
                  list ($meta, $query) = [$query, null];
              } else {
                  $meta = $this->mapper->getMeta(get_class($test));
              }
          }
          else {
              $meta = $meta instanceof Meta ? $meta : $this->mapper->getMeta($meta);
          }
  
          if (!isset($meta->relations[$relationName])) {
              throw new Exception("Unknown relation $relationName on {$meta->class}");
          }
          
          $relation = $meta->relations[$relationName];
          $relator = $this->getRelator($relation);
          
          if ($query) {
              // need to support both Query\Criteria and Query\Select
              // this is a cheeky hack - the API doesn't declare support for
              // Select in Relators because it carries promises of things like 
              // 'fields' and whatnot that we'll never be able to satisfy. 
              // That whole hierarchy needs to be cleaned
              // up into a bunch of traits so we can have RelatorCriteria or something.
              $query = $query instanceof Query\Criteria ? $query : Query\Select::fromParamArgs([$query]);
              $stack = $query->stack;
          }
          else {
              $stack = [];
          }
  
          $stack[$meta->class] = true;
          if ($sourceIsArray) {
              return $relator->getRelatedForList($meta, $source, $relation, $query ?: null, $stack);
          } else {
              return $relator->getRelated($meta, $source, $relation, $query ?: null, $stack);
          }
      }
code_tokens: public function getRelated ( $ source , $ relationName , $ query = null , $ meta = null ) { if ( ! $ source ) { return ; } $ sourceIsArray = false ; $ test = $ source ; if ( is_array ( $ test ) || $ test instanceof \ Traversable ) { $ sourceIsArray = true ; $ test = $ test [ 0 ] ; } if ( ! $ meta ) { if ( $ query instanceof Meta ) { list ( $ meta , $ query ) = [ $ query , null ] ; } else { $ meta = $ this -> mapper -> getMeta ( get_class ( $ test ) ) ; } } else { $ meta = $ meta instanceof Meta ? $ meta : $ this -> mapper -> getMeta ( $ meta ) ; } if ( ! isset ( $ meta -> relations [ $ relationName ] ) ) { throw new Exception ( "Unknown relation $relationName on {$meta->class}" ) ; } $ relation = $ meta -> relations [ $ relationName ] ; $ relator = $ this -> getRelator ( $ relation ) ; if ( $ query ) { // need to support both Query\Criteria and Query\Select // this is a cheeky hack - the API doesn't declare support for // Select in Relators because it carries promises of things like  // 'fields' and whatnot that we'll never be able to satisfy.  // That whole hierarchy needs to be cleaned // up into a bunch of traits so we can have RelatorCriteria or something. $ query = $ query instanceof Query \ Criteria ? $ query : Query \ Select :: fromParamArgs ( [ $ query ] ) ; $ stack = $ query -> stack ; } else { $ stack = [ ] ; } $ stack [ $ meta -> class ] = true ; if ( $ sourceIsArray ) { return $ relator -> getRelatedForList ( $ meta , $ source , $ relation , $ query ? : null , $ stack ) ; } else { return $ relator -> getRelated ( $ meta , $ source , $ relation , $ query ? : null , $ stack ) ; } }
docstring: Get related objects from the database
  
  Supports the following signatures:
  
  - getRelated( object|array $source , string $relationName )
  - getRelated( object|array $source , string $relationName , $query )
  - getRelated( object|array $source , string $relationName , Meta $meta )
  - getRelated( object|array $source , string $relationName , $query, Meta $meta )
  
  @return object[]
docstring_tokens: Get related objects from the database