yii\mongodb\file\Download::substr PHP Method

substr() public method

Return part of a file.
public substr ( integer $start, integer $length ) : string | false
$start integer reading start position. If non-negative, the returned string will start at the start'th position in file, counting from zero. If negative, the returned string will start at the start'th character from the end of file.
$length integer number of bytes to read. If given and is positive, the string returned will contain at most length characters beginning from start (depending on the length of file). If given and is negative, then that many characters will be omitted from the end of file (after the start position has been calculated when a start is negative).
return string | false the extracted part of file or `false` on failure
    public function substr($start, $length)
    {
        $document = $this->getDocument();
        if ($start < 0) {
            $start = max($document['length'] + $start, 0);
        }
        if ($start > $document['length']) {
            return false;
        }
        if ($length < 0) {
            $length = $document['length'] - $start + $length;
            if ($length < 0) {
                return false;
            }
        }
        $chunkSize = $document['chunkSize'];
        $startChunkNumber = floor($start / $chunkSize);
        $chunkIterator = $this->getChunkIterator();
        if (!$chunkIterator->valid()) {
            // invalid iterator state - recreate iterator
            // unable to use `rewind` due to error "Cursors cannot rewind after starting iteration"
            $chunkIterator = $this->getChunkIterator(true);
        }
        if ($chunkIterator->key() > $startChunkNumber) {
            // unable to go back by iterator
            // unable to use `rewind` due to error "Cursors cannot rewind after starting iteration"
            $chunkIterator = $this->getChunkIterator(true);
        }
        $result = '';
        $chunkDataOffset = $start - $startChunkNumber * $chunkSize;
        while ($chunkIterator->valid()) {
            if ($chunkIterator->key() >= $startChunkNumber) {
                $chunk = $chunkIterator->current();
                $data = $chunk['data']->getData();
                $readLength = min($chunkSize - $chunkDataOffset, $length);
                $result .= StringHelper::byteSubstr($data, $chunkDataOffset, $readLength);
                $length -= $readLength;
                if ($length <= 0) {
                    break;
                }
                $chunkDataOffset = 0;
            }
            $chunkIterator->next();
        }
        return $result;
    }