659 lines
16 KiB
PHP
659 lines
16 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Hoa
|
||
|
|
*
|
||
|
|
*
|
||
|
|
* @license
|
||
|
|
*
|
||
|
|
* New BSD License
|
||
|
|
*
|
||
|
|
* Copyright © 2007-2017, Hoa community. All rights reserved.
|
||
|
|
*
|
||
|
|
* Redistribution and use in source and binary forms, with or without
|
||
|
|
* modification, are permitted provided that the following conditions are met:
|
||
|
|
* * Redistributions of source code must retain the above copyright
|
||
|
|
* notice, this list of conditions and the following disclaimer.
|
||
|
|
* * Redistributions in binary form must reproduce the above copyright
|
||
|
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
|
* documentation and/or other materials provided with the distribution.
|
||
|
|
* * Neither the name of the Hoa nor the names of its contributors may be
|
||
|
|
* used to endorse or promote products derived from this software without
|
||
|
|
* specific prior written permission.
|
||
|
|
*
|
||
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
*/
|
||
|
|
|
||
|
|
namespace Psy\Readline\Hoa;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Class \Hoa\File\Finder.
|
||
|
|
*
|
||
|
|
* This class allows to find files easily by using filters and flags.
|
||
|
|
*/
|
||
|
|
class FileFinder implements \IteratorAggregate
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* SplFileInfo classname.
|
||
|
|
*/
|
||
|
|
protected $_splFileInfo = \SplFileInfo::class;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Paths where to look for.
|
||
|
|
*/
|
||
|
|
protected $_paths = [];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Max depth in recursion.
|
||
|
|
*/
|
||
|
|
protected $_maxDepth = -1;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Filters.
|
||
|
|
*/
|
||
|
|
protected $_filters = [];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Flags.
|
||
|
|
*/
|
||
|
|
protected $_flags = -1;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Types of files to handle.
|
||
|
|
*/
|
||
|
|
protected $_types = [];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* What comes first: parent or child?
|
||
|
|
*/
|
||
|
|
protected $_first = -1;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sorts.
|
||
|
|
*/
|
||
|
|
protected $_sorts = [];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Initialize.
|
||
|
|
*/
|
||
|
|
public function __construct()
|
||
|
|
{
|
||
|
|
$this->_flags = IteratorFileSystem::KEY_AS_PATHNAME
|
||
|
|
| IteratorFileSystem::CURRENT_AS_FILEINFO
|
||
|
|
| IteratorFileSystem::SKIP_DOTS;
|
||
|
|
$this->_first = \RecursiveIteratorIterator::SELF_FIRST;
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Select a directory to scan.
|
||
|
|
*/
|
||
|
|
public function in($paths): self
|
||
|
|
{
|
||
|
|
if (!\is_array($paths)) {
|
||
|
|
$paths = [$paths];
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach ($paths as $path) {
|
||
|
|
if (1 === \preg_match('/[\*\?\[\]]/', $path)) {
|
||
|
|
$iterator = new \CallbackFilterIterator(
|
||
|
|
new \GlobIterator(\rtrim($path, \DIRECTORY_SEPARATOR)),
|
||
|
|
function ($current) {
|
||
|
|
return $current->isDir();
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
foreach ($iterator as $fileInfo) {
|
||
|
|
$this->_paths[] = $fileInfo->getPathname();
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
$this->_paths[] = $path;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set max depth for recursion.
|
||
|
|
*/
|
||
|
|
public function maxDepth(int $depth): self
|
||
|
|
{
|
||
|
|
$this->_maxDepth = $depth;
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Include files in the result.
|
||
|
|
*/
|
||
|
|
public function files(): self
|
||
|
|
{
|
||
|
|
$this->_types[] = 'file';
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Include directories in the result.
|
||
|
|
*/
|
||
|
|
public function directories(): self
|
||
|
|
{
|
||
|
|
$this->_types[] = 'dir';
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Include links in the result.
|
||
|
|
*/
|
||
|
|
public function links(): self
|
||
|
|
{
|
||
|
|
$this->_types[] = 'link';
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Follow symbolink links.
|
||
|
|
*/
|
||
|
|
public function followSymlinks(bool $flag = true): self
|
||
|
|
{
|
||
|
|
if (true === $flag) {
|
||
|
|
$this->_flags ^= IteratorFileSystem::FOLLOW_SYMLINKS;
|
||
|
|
} else {
|
||
|
|
$this->_flags |= IteratorFileSystem::FOLLOW_SYMLINKS;
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Include files that match a regex.
|
||
|
|
* Example:
|
||
|
|
* $this->name('#\.php$#');.
|
||
|
|
*/
|
||
|
|
public function name(string $regex): self
|
||
|
|
{
|
||
|
|
$this->_filters[] = function (\SplFileInfo $current) use ($regex) {
|
||
|
|
return 0 !== \preg_match($regex, $current->getBasename());
|
||
|
|
};
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Exclude directories that match a regex.
|
||
|
|
* Example:
|
||
|
|
* $this->notIn('#^\.(git|hg)$#');.
|
||
|
|
*/
|
||
|
|
public function notIn(string $regex): self
|
||
|
|
{
|
||
|
|
$this->_filters[] = function (\SplFileInfo $current) use ($regex) {
|
||
|
|
foreach (\explode(\DIRECTORY_SEPARATOR, $current->getPathname()) as $part) {
|
||
|
|
if (0 !== \preg_match($regex, $part)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
};
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Include files that respect a certain size.
|
||
|
|
* The size is a string of the form:
|
||
|
|
* operator number unit
|
||
|
|
* where
|
||
|
|
* • operator could be: <, <=, >, >= or =;
|
||
|
|
* • number is a positive integer;
|
||
|
|
* • unit could be: b (default), Kb, Mb, Gb, Tb, Pb, Eb, Zb, Yb.
|
||
|
|
* Example:
|
||
|
|
* $this->size('>= 12Kb');.
|
||
|
|
*/
|
||
|
|
public function size(string $size): self
|
||
|
|
{
|
||
|
|
if (0 === \preg_match('#^(<|<=|>|>=|=)\s*(\d+)\s*((?:[KMGTPEZY])b)?$#', $size, $matches)) {
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
$number = (float) ($matches[2]);
|
||
|
|
$unit = $matches[3] ?? 'b';
|
||
|
|
$operator = $matches[1];
|
||
|
|
|
||
|
|
switch ($unit) {
|
||
|
|
case 'b':
|
||
|
|
break;
|
||
|
|
|
||
|
|
// kilo
|
||
|
|
case 'Kb':
|
||
|
|
$number <<= 10;
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
// mega.
|
||
|
|
case 'Mb':
|
||
|
|
$number <<= 20;
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
// giga.
|
||
|
|
case 'Gb':
|
||
|
|
$number <<= 30;
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
// tera.
|
||
|
|
case 'Tb':
|
||
|
|
$number *= 1099511627776;
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
// peta.
|
||
|
|
case 'Pb':
|
||
|
|
$number *= 1024 ** 5;
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
// exa.
|
||
|
|
case 'Eb':
|
||
|
|
$number *= 1024 ** 6;
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
// zetta.
|
||
|
|
case 'Zb':
|
||
|
|
$number *= 1024 ** 7;
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
// yota.
|
||
|
|
case 'Yb':
|
||
|
|
$number *= 1024 ** 8;
|
||
|
|
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
$filter = null;
|
||
|
|
|
||
|
|
switch ($operator) {
|
||
|
|
case '<':
|
||
|
|
$filter = function (\SplFileInfo $current) use ($number) {
|
||
|
|
return $current->getSize() < $number;
|
||
|
|
};
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
case '<=':
|
||
|
|
$filter = function (\SplFileInfo $current) use ($number) {
|
||
|
|
return $current->getSize() <= $number;
|
||
|
|
};
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
case '>':
|
||
|
|
$filter = function (\SplFileInfo $current) use ($number) {
|
||
|
|
return $current->getSize() > $number;
|
||
|
|
};
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
case '>=':
|
||
|
|
$filter = function (\SplFileInfo $current) use ($number) {
|
||
|
|
return $current->getSize() >= $number;
|
||
|
|
};
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
case '=':
|
||
|
|
$filter = function (\SplFileInfo $current) use ($number) {
|
||
|
|
return $current->getSize() === $number;
|
||
|
|
};
|
||
|
|
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->_filters[] = $filter;
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Whether we should include dots or not (respectively . and ..).
|
||
|
|
*/
|
||
|
|
public function dots(bool $flag = true): self
|
||
|
|
{
|
||
|
|
if (true === $flag) {
|
||
|
|
$this->_flags ^= IteratorFileSystem::SKIP_DOTS;
|
||
|
|
} else {
|
||
|
|
$this->_flags |= IteratorFileSystem::SKIP_DOTS;
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Include files that are owned by a certain owner.
|
||
|
|
*/
|
||
|
|
public function owner(int $owner): self
|
||
|
|
{
|
||
|
|
$this->_filters[] = function (\SplFileInfo $current) use ($owner) {
|
||
|
|
return $current->getOwner() === $owner;
|
||
|
|
};
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Format date.
|
||
|
|
* Date can have the following syntax:
|
||
|
|
* date
|
||
|
|
* since date
|
||
|
|
* until date
|
||
|
|
* If the date does not have the “ago” keyword, it will be added.
|
||
|
|
* Example: “42 hours” is equivalent to “since 42 hours” which is equivalent
|
||
|
|
* to “since 42 hours ago”.
|
||
|
|
*/
|
||
|
|
protected function formatDate(string $date, &$operator): int
|
||
|
|
{
|
||
|
|
$operator = -1;
|
||
|
|
|
||
|
|
if (0 === \preg_match('#\bago\b#', $date)) {
|
||
|
|
$date .= ' ago';
|
||
|
|
}
|
||
|
|
|
||
|
|
if (0 !== \preg_match('#^(since|until)\b(.+)$#', $date, $matches)) {
|
||
|
|
$time = \strtotime($matches[2]);
|
||
|
|
|
||
|
|
if ('until' === $matches[1]) {
|
||
|
|
$operator = 1;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
$time = \strtotime($date);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $time;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Include files that have been changed from a certain date.
|
||
|
|
* Example:
|
||
|
|
* $this->changed('since 13 days');.
|
||
|
|
*/
|
||
|
|
public function changed(string $date): self
|
||
|
|
{
|
||
|
|
$time = $this->formatDate($date, $operator);
|
||
|
|
|
||
|
|
if (-1 === $operator) {
|
||
|
|
$this->_filters[] = function (\SplFileInfo $current) use ($time) {
|
||
|
|
return $current->getCTime() >= $time;
|
||
|
|
};
|
||
|
|
} else {
|
||
|
|
$this->_filters[] = function (\SplFileInfo $current) use ($time) {
|
||
|
|
return $current->getCTime() < $time;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Include files that have been modified from a certain date.
|
||
|
|
* Example:
|
||
|
|
* $this->modified('since 13 days');.
|
||
|
|
*/
|
||
|
|
public function modified(string $date): self
|
||
|
|
{
|
||
|
|
$time = $this->formatDate($date, $operator);
|
||
|
|
|
||
|
|
if (-1 === $operator) {
|
||
|
|
$this->_filters[] = function (\SplFileInfo $current) use ($time) {
|
||
|
|
return $current->getMTime() >= $time;
|
||
|
|
};
|
||
|
|
} else {
|
||
|
|
$this->_filters[] = function (\SplFileInfo $current) use ($time) {
|
||
|
|
return $current->getMTime() < $time;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Add your own filter.
|
||
|
|
* The callback will receive 3 arguments: $current, $key and $iterator. It
|
||
|
|
* must return a boolean: true to include the file, false to exclude it.
|
||
|
|
* Example:
|
||
|
|
* // Include files that are readable
|
||
|
|
* $this->filter(function ($current) {
|
||
|
|
* return $current->isReadable();
|
||
|
|
* });.
|
||
|
|
*/
|
||
|
|
public function filter($callback): self
|
||
|
|
{
|
||
|
|
$this->_filters[] = $callback;
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sort result by name.
|
||
|
|
* If \Collator exists (from ext/intl), the $locale argument will be used
|
||
|
|
* for its constructor. Else, strcmp() will be used.
|
||
|
|
* Example:
|
||
|
|
* $this->sortByName('fr_FR');.
|
||
|
|
*/
|
||
|
|
public function sortByName(string $locale = 'root'): self
|
||
|
|
{
|
||
|
|
if (true === \class_exists('Collator', false)) {
|
||
|
|
$collator = new \Collator($locale);
|
||
|
|
|
||
|
|
$this->_sorts[] = function (\SplFileInfo $a, \SplFileInfo $b) use ($collator) {
|
||
|
|
return $collator->compare($a->getPathname(), $b->getPathname());
|
||
|
|
};
|
||
|
|
} else {
|
||
|
|
$this->_sorts[] = function (\SplFileInfo $a, \SplFileInfo $b) {
|
||
|
|
return \strcmp($a->getPathname(), $b->getPathname());
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sort result by size.
|
||
|
|
* Example:
|
||
|
|
* $this->sortBySize();.
|
||
|
|
*/
|
||
|
|
public function sortBySize(): self
|
||
|
|
{
|
||
|
|
$this->_sorts[] = function (\SplFileInfo $a, \SplFileInfo $b) {
|
||
|
|
return $a->getSize() < $b->getSize();
|
||
|
|
};
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Add your own sort.
|
||
|
|
* The callback will receive 2 arguments: $a and $b. Please see the uasort()
|
||
|
|
* function.
|
||
|
|
* Example:
|
||
|
|
* // Sort files by their modified time.
|
||
|
|
* $this->sort(function ($a, $b) {
|
||
|
|
* return $a->getMTime() < $b->getMTime();
|
||
|
|
* });.
|
||
|
|
*/
|
||
|
|
public function sort($callable): self
|
||
|
|
{
|
||
|
|
$this->_sorts[] = $callable;
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Child comes first when iterating.
|
||
|
|
*/
|
||
|
|
public function childFirst(): self
|
||
|
|
{
|
||
|
|
$this->_first = \RecursiveIteratorIterator::CHILD_FIRST;
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the iterator.
|
||
|
|
*/
|
||
|
|
public function getIterator()
|
||
|
|
{
|
||
|
|
$_iterator = new \AppendIterator();
|
||
|
|
$types = $this->getTypes();
|
||
|
|
|
||
|
|
if (!empty($types)) {
|
||
|
|
$this->_filters[] = function (\SplFileInfo $current) use ($types) {
|
||
|
|
return \in_array($current->getType(), $types);
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
$maxDepth = $this->getMaxDepth();
|
||
|
|
$splFileInfo = $this->getSplFileInfo();
|
||
|
|
|
||
|
|
foreach ($this->getPaths() as $path) {
|
||
|
|
if (1 === $maxDepth) {
|
||
|
|
$iterator = new \IteratorIterator(
|
||
|
|
new IteratorRecursiveDirectory(
|
||
|
|
$path,
|
||
|
|
$this->getFlags(),
|
||
|
|
$splFileInfo
|
||
|
|
),
|
||
|
|
$this->getFirst()
|
||
|
|
);
|
||
|
|
} else {
|
||
|
|
$iterator = new \RecursiveIteratorIterator(
|
||
|
|
new IteratorRecursiveDirectory(
|
||
|
|
$path,
|
||
|
|
$this->getFlags(),
|
||
|
|
$splFileInfo
|
||
|
|
),
|
||
|
|
$this->getFirst()
|
||
|
|
);
|
||
|
|
|
||
|
|
if (1 < $maxDepth) {
|
||
|
|
$iterator->setMaxDepth($maxDepth - 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$_iterator->append($iterator);
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach ($this->getFilters() as $filter) {
|
||
|
|
$_iterator = new \CallbackFilterIterator(
|
||
|
|
$_iterator,
|
||
|
|
$filter
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
$sorts = $this->getSorts();
|
||
|
|
|
||
|
|
if (empty($sorts)) {
|
||
|
|
return $_iterator;
|
||
|
|
}
|
||
|
|
|
||
|
|
$array = \iterator_to_array($_iterator);
|
||
|
|
|
||
|
|
foreach ($sorts as $sort) {
|
||
|
|
\uasort($array, $sort);
|
||
|
|
}
|
||
|
|
|
||
|
|
return new \ArrayIterator($array);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set SplFileInfo classname.
|
||
|
|
*/
|
||
|
|
public function setSplFileInfo(string $splFileInfo): string
|
||
|
|
{
|
||
|
|
$old = $this->_splFileInfo;
|
||
|
|
$this->_splFileInfo = $splFileInfo;
|
||
|
|
|
||
|
|
return $old;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get SplFileInfo classname.
|
||
|
|
*/
|
||
|
|
public function getSplFileInfo(): string
|
||
|
|
{
|
||
|
|
return $this->_splFileInfo;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get all paths.
|
||
|
|
*/
|
||
|
|
protected function getPaths(): array
|
||
|
|
{
|
||
|
|
return $this->_paths;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get max depth.
|
||
|
|
*/
|
||
|
|
public function getMaxDepth(): int
|
||
|
|
{
|
||
|
|
return $this->_maxDepth;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get types.
|
||
|
|
*/
|
||
|
|
public function getTypes(): array
|
||
|
|
{
|
||
|
|
return $this->_types;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get filters.
|
||
|
|
*/
|
||
|
|
protected function getFilters(): array
|
||
|
|
{
|
||
|
|
return $this->_filters;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get sorts.
|
||
|
|
*/
|
||
|
|
protected function getSorts(): array
|
||
|
|
{
|
||
|
|
return $this->_sorts;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get flags.
|
||
|
|
*/
|
||
|
|
public function getFlags(): int
|
||
|
|
{
|
||
|
|
return $this->_flags;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get first.
|
||
|
|
*/
|
||
|
|
public function getFirst(): int
|
||
|
|
{
|
||
|
|
return $this->_first;
|
||
|
|
}
|
||
|
|
}
|