mirror of
https://github.com/danog/tgseclib.git
synced 2024-11-27 04:34:45 +01:00
Merge pull request #364 from terrafrost/sftp-sort2
SFTP: add the ability for nlist() and rawlist() to be sorted * terrafrost/sftp-sort2: SFTP: update one last comment SFTP: update unit test comments SFTP: add new line to end of unit test SFTP: assertEquals -> assertSame SFTP: reset sort options every time and update unit test SFTP: rm whitespace SFTP: define $sortOptions SFTP: add the ability for nlist() and rawlist() to be sorted
This commit is contained in:
commit
6e796d091a
@ -262,6 +262,16 @@ class Net_SFTP extends Net_SSH2
|
||||
*/
|
||||
var $use_stat_cache = true;
|
||||
|
||||
/**
|
||||
* Sort Options
|
||||
*
|
||||
* @see Net_SFTP::_comparator()
|
||||
* @see Net_SFTP::setListOrder()
|
||||
* @var Array
|
||||
* @access private
|
||||
*/
|
||||
var $sortOptions = array();
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
@ -809,16 +819,12 @@ class Net_SFTP extends Net_SSH2
|
||||
/**
|
||||
* Reads a list, be it detailed or not, of files in the given directory
|
||||
*
|
||||
* $realpath exists because, in the case of the recursive deletes and recursive chmod's $realpath has already
|
||||
* been calculated.
|
||||
*
|
||||
* @param String $dir
|
||||
* @param optional Boolean $raw
|
||||
* @param optional Boolean $realpath
|
||||
* @return Mixed
|
||||
* @access private
|
||||
*/
|
||||
function _list($dir, $raw = true, $realpath = true)
|
||||
function _list($dir, $raw = true)
|
||||
{
|
||||
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
|
||||
return false;
|
||||
@ -878,11 +884,7 @@ class Net_SFTP extends Net_SSH2
|
||||
$attributes['type'] = $fileType;
|
||||
}
|
||||
}
|
||||
if (!$raw) {
|
||||
$contents[] = $shortname;
|
||||
} else {
|
||||
$contents[$shortname] = $attributes;
|
||||
}
|
||||
$contents[$shortname] = $attributes + array('filename' => $shortname);
|
||||
|
||||
if (isset($attributes['type']) && $attributes['type'] == NET_SFTP_TYPE_DIRECTORY && ($shortname != '.' && $shortname != '..')) {
|
||||
$this->_update_stat_cache($dir . '/' . $shortname, array());
|
||||
@ -915,7 +917,111 @@ class Net_SFTP extends Net_SSH2
|
||||
return false;
|
||||
}
|
||||
|
||||
return $contents;
|
||||
if (count($this->sortOptions)) {
|
||||
uasort($contents, array(&$this, '_comparator'));
|
||||
}
|
||||
|
||||
return $raw ? $contents : array_keys($contents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two rawlist entries using parameters set by setListOrder()
|
||||
*
|
||||
* Intended for use with uasort()
|
||||
*
|
||||
* @param Array $a
|
||||
* @param Array $b
|
||||
* @return Integer
|
||||
* @access private
|
||||
*/
|
||||
function _comparator($a, $b)
|
||||
{
|
||||
switch (true) {
|
||||
case $a['filename'] === '.' || $b['filename'] === '.':
|
||||
if ($a['filename'] === $b['filename']) {
|
||||
return 0;
|
||||
}
|
||||
return $a['filename'] === '.' ? -1 : 1;
|
||||
case $a['filename'] === '..' || $b['filename'] === '..':
|
||||
if ($a['filename'] === $b['filename']) {
|
||||
return 0;
|
||||
}
|
||||
return $a['filename'] === '..' ? -1 : 1;
|
||||
case isset($a['type']) && $a['type'] === NET_SFTP_TYPE_DIRECTORY:
|
||||
if (!isset($b['type'])) {
|
||||
return 1;
|
||||
}
|
||||
if ($b['type'] !== $a['type']) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case isset($b['type']) && $b['type'] === NET_SFTP_TYPE_DIRECTORY:
|
||||
return 1;
|
||||
}
|
||||
foreach ($this->sortOptions as $sort => $order) {
|
||||
if (!isset($a[$sort]) || !isset($b[$sort])) {
|
||||
if (isset($a[$sort])) {
|
||||
return -1;
|
||||
}
|
||||
if (isset($b[$sort])) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
switch ($sort) {
|
||||
case 'filename':
|
||||
$result = strcasecmp($a['filename'], $b['filename']);
|
||||
if ($result) {
|
||||
return $order === SORT_DESC ? -$result : $result;
|
||||
}
|
||||
break;
|
||||
case 'permissions':
|
||||
case 'mode':
|
||||
$a[$sort]&= 07777;
|
||||
$b[$sort]&= 07777;
|
||||
default:
|
||||
if ($a[$sort] === $b[$sort]) {
|
||||
break;
|
||||
}
|
||||
return $order === SORT_ASC ? $a[$sort] - $b[$sort] : $b[$sort] - $a[$sort];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines how nlist() and rawlist() will be sorted - if at all.
|
||||
*
|
||||
* If sorting is enabled directories and files will be sorted independently with
|
||||
* directories appearing before files in the resultant array that is returned.
|
||||
*
|
||||
* Any parameter returned by stat is a valid sort parameter for this function.
|
||||
* Filename comparisons are case insensitive.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* $sftp->setListOrder('filename', SORT_ASC);
|
||||
* $sftp->setListOrder('size', SORT_DESC, 'filename', SORT_ASC);
|
||||
* $sftp->setListOrder(true);
|
||||
* Separates directories from files but doesn't do any sorting beyond that
|
||||
* $sftp->setListOrder();
|
||||
* Don't do any sort of sorting
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function setListOrder()
|
||||
{
|
||||
$this->sortOptions = array();
|
||||
$args = func_get_args();
|
||||
if (empty($args)) {
|
||||
return;
|
||||
}
|
||||
$len = count($args) & 0x7FFFFFFE;
|
||||
for ($i = 0; $i < $len; $i+=2) {
|
||||
$this->sortOptions[$args[$i]] = $args[$i + 1];
|
||||
}
|
||||
if (!count($this->sortOptions)) {
|
||||
$this->sortOptions = array('bogus' => true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -166,6 +166,48 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
|
||||
/**
|
||||
* @depends testPutSizeGetFile
|
||||
*/
|
||||
public function testTouch($sftp)
|
||||
{
|
||||
$this->assertTrue(
|
||||
$sftp->touch('file2.txt'),
|
||||
'Failed asserting that touch() successfully ran.'
|
||||
);
|
||||
|
||||
$this->assertTrue(
|
||||
$sftp->file_exists('file2.txt'),
|
||||
'Failed asserting that touch()\'d file exists'
|
||||
);
|
||||
|
||||
return $sftp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testTouch
|
||||
*/
|
||||
public function testTruncate($sftp)
|
||||
{
|
||||
$this->assertTrue(
|
||||
$sftp->touch('file3.txt'),
|
||||
'Failed asserting that touch() successfully ran.'
|
||||
);
|
||||
|
||||
$this->assertTrue(
|
||||
$sftp->truncate('file3.txt', 1024 * 1024),
|
||||
'Failed asserting that touch() successfully ran.'
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
1024 * 1024,
|
||||
$sftp->size('file3.txt'),
|
||||
'Failed asserting that truncate()\'d file has the expected length'
|
||||
);
|
||||
|
||||
return $sftp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testTruncate
|
||||
*/
|
||||
public function testChDirOnFile($sftp)
|
||||
{
|
||||
$this->assertFalse(
|
||||
@ -205,17 +247,17 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
|
||||
public function testFileExistsIsFileIsDirFileNonexistent($sftp)
|
||||
{
|
||||
$this->assertFalse(
|
||||
$sftp->file_exists('file2.txt'),
|
||||
$sftp->file_exists('file4.txt'),
|
||||
'Failed asserting that a nonexistent file does not exist.'
|
||||
);
|
||||
|
||||
$this->assertFalse(
|
||||
$sftp->is_file('file2.txt'),
|
||||
$sftp->is_file('file4.txt'),
|
||||
'Failed asserting that is_file() on nonexistent file returns false.'
|
||||
);
|
||||
|
||||
$this->assertFalse(
|
||||
$sftp->is_dir('file2.txt'),
|
||||
$sftp->is_dir('file4.txt'),
|
||||
'Failed asserting that is_dir() on nonexistent file returns false.'
|
||||
);
|
||||
|
||||
@ -225,6 +267,58 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
|
||||
/**
|
||||
* @depends testFileExistsIsFileIsDirFileNonexistent
|
||||
*/
|
||||
public function testSortOrder($sftp)
|
||||
{
|
||||
$this->assertTrue(
|
||||
$sftp->mkdir('temp'),
|
||||
"Failed asserting that a new scratch directory temp could " .
|
||||
'be created.'
|
||||
);
|
||||
|
||||
$sftp->setListOrder('filename', SORT_DESC);
|
||||
|
||||
$list = $sftp->nlist();
|
||||
$expected = array('.', '..', 'temp', 'file3.txt', 'file2.txt', 'file1.txt');
|
||||
|
||||
$this->assertSame(
|
||||
$list,
|
||||
$expected,
|
||||
'Failed asserting that list sorted correctly.'
|
||||
);
|
||||
|
||||
$sftp->setListOrder('filename', SORT_ASC);
|
||||
|
||||
$list = $sftp->nlist();
|
||||
$expected = array('.', '..', 'temp', 'file1.txt', 'file2.txt', 'file3.txt');
|
||||
|
||||
$this->assertSame(
|
||||
$list,
|
||||
$expected,
|
||||
'Failed asserting that list sorted correctly.'
|
||||
);
|
||||
|
||||
$sftp->setListOrder('size', SORT_DESC);
|
||||
|
||||
$files = $sftp->nlist();
|
||||
|
||||
$last_size = 0x7FFFFFFF;
|
||||
foreach ($files as $file) {
|
||||
if ($sftp->is_file($file)) {
|
||||
$cur_size = $sftp->size($file);
|
||||
$this->assertLessThanOrEqual(
|
||||
$last_size, $cur_size,
|
||||
'Failed asserting that nlist() is in descending order'
|
||||
);
|
||||
$last_size = $cur_size;
|
||||
}
|
||||
}
|
||||
|
||||
return $sftp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testSortOrder
|
||||
*/
|
||||
public function testChDirUpHome($sftp)
|
||||
{
|
||||
$this->assertTrue(
|
||||
|
Loading…
Reference in New Issue
Block a user