mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-03 22:32:40 +08:00
Fix #18676: Added method yii\helpers\BaseFileHelper::changeOwnership() and properties newFileMode/newFileOwnership in yii\console\controllers\BaseMigrateController
Co-authored-by: Bizley <pawel@positive.codes>
This commit is contained in:
@ -187,6 +187,22 @@ class m150101_185401_create_news_table extends Migration
|
|||||||
|
|
||||||
A list of all available methods for defining the column types is available in the API documentation of [[yii\db\SchemaBuilderTrait]].
|
A list of all available methods for defining the column types is available in the API documentation of [[yii\db\SchemaBuilderTrait]].
|
||||||
|
|
||||||
|
> Info: The generated file permissions and ownership will be determined by the current environment. This might lead to
|
||||||
|
inaccessible files. This could, for example, happen when the migration is created within a docker container
|
||||||
|
and the files are edited on the host. In this case the `newFileMode` and/or `newFileOwnership` of the MigrateController
|
||||||
|
can be changed. E.g. in the application config:
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'controllerMap' => [
|
||||||
|
'migrate' => [
|
||||||
|
'class' => 'yii\console\controllers\MigrateController',
|
||||||
|
'newFileOwnership' => '1000:1000', # Default WSL user id
|
||||||
|
'newFileMode' => 0660,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
## Generating Migrations <span id="generating-migrations"></span>
|
## Generating Migrations <span id="generating-migrations"></span>
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,10 @@ Yii Framework 2 Change Log
|
|||||||
- Enh #18628: Added strings "software", and "hardware" to `$specials` array in `yii\helpers\BaseInflector` (kjusupov)
|
- Enh #18628: Added strings "software", and "hardware" to `$specials` array in `yii\helpers\BaseInflector` (kjusupov)
|
||||||
- Enh #18653: Added method `yii\helpers\BaseHtml::getInputIdByName()` (WinterSilence)
|
- Enh #18653: Added method `yii\helpers\BaseHtml::getInputIdByName()` (WinterSilence)
|
||||||
- Enh #18669: Changed visibility of `yii\web\User::checkRedirectAcceptable()` to `public` (rhertogh)
|
- Enh #18669: Changed visibility of `yii\web\User::checkRedirectAcceptable()` to `public` (rhertogh)
|
||||||
|
- Enh #18676: Added method `yii\helpers\BaseFileHelper::changeOwnership()` and properties `newFileMode`/`newFileOwnership` in `yii\console\controllers\BaseMigrateController` (rhertogh)
|
||||||
- Bug #18678: Fix `yii\caching\DbCache` to use configured cache table name instead of the default one in case of MSSQL varbinary column type detection (aidanbek)
|
- Bug #18678: Fix `yii\caching\DbCache` to use configured cache table name instead of the default one in case of MSSQL varbinary column type detection (aidanbek)
|
||||||
|
|
||||||
|
|
||||||
2.0.42.1 May 06, 2021
|
2.0.42.1 May 06, 2021
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|||||||
@ -84,6 +84,20 @@ abstract class BaseMigrateController extends Controller
|
|||||||
* or a file path.
|
* or a file path.
|
||||||
*/
|
*/
|
||||||
public $templateFile;
|
public $templateFile;
|
||||||
|
/**
|
||||||
|
* @var int the permission to be set for newly generated migration files.
|
||||||
|
* This value will be used by PHP chmod() function. No umask will be applied.
|
||||||
|
* If not set, the permission will be determined by the current environment.
|
||||||
|
* @since 2.0.43
|
||||||
|
*/
|
||||||
|
public $newFileMode;
|
||||||
|
/**
|
||||||
|
* @var string|int the user and/or group ownership to be set for newly generated migration files.
|
||||||
|
* If not set, the ownership will be determined by the current environment.
|
||||||
|
* @since 2.0.43
|
||||||
|
* @see FileHelper::changeOwnership()
|
||||||
|
*/
|
||||||
|
public $newFileOwnership;
|
||||||
/**
|
/**
|
||||||
* @var bool indicates whether the console output should be compacted.
|
* @var bool indicates whether the console output should be compacted.
|
||||||
* If this is set to true, the individual commands ran within the migration will not be output to the console.
|
* If this is set to true, the individual commands ran within the migration will not be output to the console.
|
||||||
@ -663,6 +677,8 @@ abstract class BaseMigrateController extends Controller
|
|||||||
return ExitCode::IOERR;
|
return ExitCode::IOERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileHelper::changeOwnership($file, $this->newFileOwnership, $this->newFileMode);
|
||||||
|
|
||||||
$this->stdout("New migration created successfully.\n", Console::FG_GREEN);
|
$this->stdout("New migration created successfully.\n", Console::FG_GREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ namespace yii\helpers;
|
|||||||
|
|
||||||
use Yii;
|
use Yii;
|
||||||
use yii\base\ErrorException;
|
use yii\base\ErrorException;
|
||||||
|
use yii\base\Exception;
|
||||||
use yii\base\InvalidArgumentException;
|
use yii\base\InvalidArgumentException;
|
||||||
use yii\base\InvalidConfigException;
|
use yii\base\InvalidConfigException;
|
||||||
|
|
||||||
@ -874,4 +875,83 @@ class BaseFileHelper
|
|||||||
|
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the Unix user and/or group ownership of a file or directory, and optionally the mode.
|
||||||
|
* Note: This function will not work on remote files as the file to be examined must be accessible
|
||||||
|
* via the server's filesystem.
|
||||||
|
* Note: On Windows, this function fails silently when applied on a regular file.
|
||||||
|
* @param string $path the path to the file or directory.
|
||||||
|
* @param string|array|int|null $ownership the user and/or group ownership for the file or directory.
|
||||||
|
* When $ownership is a string, the format is 'user:group' where both are optional. E.g.
|
||||||
|
* 'user' or 'user:' will only change the user,
|
||||||
|
* ':group' will only change the group,
|
||||||
|
* 'user:group' will change both.
|
||||||
|
* When $owners is an index array the format is [0 => user, 1 => group], e.g. `[$myUser, $myGroup]`.
|
||||||
|
* It is also possible to pass an associative array, e.g. ['user' => $myUser, 'group' => $myGroup].
|
||||||
|
* In case $owners is an integer it will be used as user id.
|
||||||
|
* If `null`, an empty array or an empty string is passed, the ownership will not be changed.
|
||||||
|
* @param int|null $mode the permission to be set for the file or directory.
|
||||||
|
* If `null` is passed, the mode will not be changed.
|
||||||
|
*
|
||||||
|
* @since 2.0.43
|
||||||
|
*/
|
||||||
|
public static function changeOwnership($path, $ownership, $mode = null)
|
||||||
|
{
|
||||||
|
if (!file_exists($path)) {
|
||||||
|
throw new InvalidArgumentException('Unable to change ownerhip, "' . $path . '" is not a file or directory.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($ownership) && $ownership !== 0 && $mode === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $group = null;
|
||||||
|
if (!empty($ownership) || $ownership === 0 || $ownership === '0') {
|
||||||
|
if (is_int($ownership)) {
|
||||||
|
$user = $ownership;
|
||||||
|
} elseif (is_string($ownership)) {
|
||||||
|
$ownerParts = explode(':', $ownership);
|
||||||
|
$user = $ownerParts[0];
|
||||||
|
if (count($ownerParts) > 1) {
|
||||||
|
$group = $ownerParts[1];
|
||||||
|
}
|
||||||
|
} elseif (is_array($ownership)) {
|
||||||
|
$ownershipIsIndexed = ArrayHelper::isIndexed($ownership);
|
||||||
|
$user = ArrayHelper::getValue($ownership, $ownershipIsIndexed ? 0 : 'user');
|
||||||
|
$group = ArrayHelper::getValue($ownership, $ownershipIsIndexed ? 1 : 'group');
|
||||||
|
} else {
|
||||||
|
throw new InvalidArgumentException('$ownership must be an integer, string, array, or null.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($mode !== null) {
|
||||||
|
if (!is_int($mode)) {
|
||||||
|
throw new InvalidArgumentException('$mode must be an integer or null.');
|
||||||
|
}
|
||||||
|
if (!chmod($path, $mode)) {
|
||||||
|
throw new Exception('Unable to change mode of "' . $path . '" to "0' . decoct($mode) . '".');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($user !== null && $user !== '') {
|
||||||
|
if (is_numeric($user)) {
|
||||||
|
$user = (int) $user;
|
||||||
|
} elseif (!is_string($user)) {
|
||||||
|
throw new InvalidArgumentException('The user part of $ownership must be an integer, string, or null.');
|
||||||
|
}
|
||||||
|
if (!chown($path, $user)) {
|
||||||
|
throw new Exception('Unable to change user ownership of "' . $path . '" to "' . $user . '".');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($group !== null && $group !== '') {
|
||||||
|
if (is_numeric($group)) {
|
||||||
|
$group = (int) $group;
|
||||||
|
} elseif (!is_string($group)) {
|
||||||
|
throw new InvalidArgumentException('The group part of $ownership must be an integer, string or null.');
|
||||||
|
}
|
||||||
|
if (!chgrp($path, $group)) {
|
||||||
|
throw new Exception('Unable to change group ownership of "' . $path . '" to "' . $group . '".');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use yii\helpers\FileHelper;
|
use yii\helpers\FileHelper;
|
||||||
|
use yii\helpers\VarDumper;
|
||||||
use yiiunit\TestCase;
|
use yiiunit\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -937,4 +938,309 @@ class FileHelperTest extends TestCase
|
|||||||
sort($foundFiles);
|
sort($foundFiles);
|
||||||
$this->assertEquals($expectedFiles, $foundFiles);
|
$this->assertEquals($expectedFiles, $foundFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testChangeOwnership()
|
||||||
|
{
|
||||||
|
if (DIRECTORY_SEPARATOR !== '/') {
|
||||||
|
$this->markTestSkipped('FileHelper::changeOwnership() fails silently on Windows, nothing to test.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!extension_loaded('posix')) {
|
||||||
|
$this->markTestSkipped('posix extension is required.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$dirName = 'change_ownership_test_dir';
|
||||||
|
$fileName = 'file_1.txt';
|
||||||
|
$testFile = $this->testFilePath . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . $fileName;
|
||||||
|
|
||||||
|
$currentUserId = posix_getuid();
|
||||||
|
$currentUserName = posix_getpwuid($currentUserId)['name'];
|
||||||
|
$currentGroupId = posix_getgid();
|
||||||
|
$currentGroupName = posix_getgrgid($currentGroupId)['name'];
|
||||||
|
|
||||||
|
/////////////
|
||||||
|
/// Setup ///
|
||||||
|
/////////////
|
||||||
|
|
||||||
|
$this->createFileStructure([
|
||||||
|
$dirName => [
|
||||||
|
$fileName => 'test 1',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Ensure the test file is created as the current user/group and has a specific file mode
|
||||||
|
$this->assertFileExists($testFile);
|
||||||
|
$fileMode = 0770;
|
||||||
|
@chmod($testFile, $fileMode);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($currentUserId, fileowner($testFile), 'Expected created test file owner to be current user.');
|
||||||
|
$this->assertEquals($currentGroupId, filegroup($testFile), 'Expected created test file group to be current group.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be changed.');
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////
|
||||||
|
/// File Mode ///
|
||||||
|
/////////////////
|
||||||
|
|
||||||
|
// Test file mode
|
||||||
|
$fileMode = 0777;
|
||||||
|
FileHelper::changeOwnership($testFile, null, $fileMode);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($currentUserId, fileowner($testFile), 'Expected file owner to be unchanged.');
|
||||||
|
$this->assertEquals($currentGroupId, filegroup($testFile), 'Expected file group to be unchanged.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be changed.');
|
||||||
|
|
||||||
|
if ($currentUserId !== 0) {
|
||||||
|
$this->markTestInComplete(__METHOD__ . ' could only run partially, chown() can only to be tested as root user. Current user: ' . $currentUserName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
/// User Ownership ///
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
// Test user ownership as integer
|
||||||
|
$ownership = 10001;
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($ownership, fileowner($testFile), 'Expected file owner to be changed.');
|
||||||
|
$this->assertEquals($currentGroupId, filegroup($testFile), 'Expected file group to be unchanged.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user ownership as numeric string (should be treated as integer)
|
||||||
|
$ownership = '10002';
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals((int)$ownership, fileowner($testFile), 'Expected created test file owner to be changed.');
|
||||||
|
$this->assertEquals($currentGroupId, filegroup($testFile), 'Expected file group to be unchanged.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user ownership as string
|
||||||
|
$ownership = $currentUserName;
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($ownership, posix_getpwuid(fileowner($testFile))['name'], 'Expected created test file owner to be changed.');
|
||||||
|
$this->assertEquals($currentGroupId, filegroup($testFile), 'Expected file group to be unchanged.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user ownership as numeric string with trailing colon (should be treated as integer)
|
||||||
|
$ownership = '10003:';
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals((int)$ownership, fileowner($testFile), 'Expected created test file owner to be changed.');
|
||||||
|
$this->assertEquals($currentGroupId, filegroup($testFile), 'Expected file group to be unchanged.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user ownership as string with trailing colon
|
||||||
|
$ownership = $currentUserName . ':';
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals(substr($ownership, 0, -1), posix_getpwuid(fileowner($testFile))['name'], 'Expected created test file owner to be changed.');
|
||||||
|
$this->assertEquals($currentGroupId, filegroup($testFile), 'Expected file group to be unchanged.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user ownership as indexed array (integer value)
|
||||||
|
$ownership = [10004];
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($ownership[0], fileowner($testFile), 'Expected created test file owner to be changed.');
|
||||||
|
$this->assertEquals($currentGroupId, filegroup($testFile), 'Expected file group to be unchanged.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user ownership as indexed array (numeric string value)
|
||||||
|
$ownership = ['10005'];
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals((int)$ownership[0], fileowner($testFile), 'Expected created test file owner to be changed.');
|
||||||
|
$this->assertEquals($currentGroupId, filegroup($testFile), 'Expected file group to be unchanged.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user ownership as associative array (string value)
|
||||||
|
$ownership = ['user' => $currentUserName];
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($ownership['user'], posix_getpwuid(fileowner($testFile))['name'], 'Expected created test file owner to be changed.');
|
||||||
|
$this->assertEquals($currentGroupId, filegroup($testFile), 'Expected file group to be unchanged.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
/// Group Ownership ///
|
||||||
|
///////////////////////
|
||||||
|
|
||||||
|
// Test group ownership as numeric string
|
||||||
|
$ownership = ':10006';
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($currentUserId, fileowner($testFile), 'Expected file owner to be unchanged.');
|
||||||
|
$this->assertEquals((int)substr($ownership, 1), filegroup($testFile), 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test group ownership as string
|
||||||
|
$ownership = ':' . $currentGroupName;
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($currentUserId, fileowner($testFile), 'Expected file owner to be unchanged.');
|
||||||
|
$this->assertEquals(substr($ownership, 1), posix_getgrgid(filegroup($testFile))['name'], 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test group ownership as associative array (integer value)
|
||||||
|
$ownership = ['group' => 10007];
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($currentUserId, fileowner($testFile), 'Expected file owner to be unchanged.');
|
||||||
|
$this->assertEquals($ownership['group'], filegroup($testFile), 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test group ownership as associative array (numeric string value)
|
||||||
|
$ownership = ['group' => '10008'];
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($currentUserId, fileowner($testFile), 'Expected file owner to be unchanged.');
|
||||||
|
$this->assertEquals((int)$ownership['group'], filegroup($testFile), 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test group ownership as associative array (string value)
|
||||||
|
$ownership = ['group' => $currentGroupName];
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($currentUserId, fileowner($testFile), 'Expected file owner to be unchanged.');
|
||||||
|
$this->assertEquals($ownership['group'], posix_getgrgid(filegroup($testFile))['name'], 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
/// User- and Group Ownership ///
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
// Test user and group ownership as numeric string
|
||||||
|
$ownership = '10009:10010';
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals((int)explode(':', $ownership)[0], fileowner($testFile), 'Expected file owner to be changed.');
|
||||||
|
$this->assertEquals((int)explode(':', $ownership)[1], filegroup($testFile), 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user and group ownership as string
|
||||||
|
$ownership = $currentUserName . ':' . $currentGroupName;
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals(explode(':', $ownership)[0], posix_getpwuid(fileowner($testFile))['name'], 'Expected file owner to be changed.');
|
||||||
|
$this->assertEquals(explode(':', $ownership)[1], posix_getgrgid(filegroup($testFile))['name'], 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user and group ownership as indexed array (integer values)
|
||||||
|
$ownership = [10011, 10012];
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($ownership[0], fileowner($testFile), 'Expected file owner to be changed.');
|
||||||
|
$this->assertEquals($ownership[1], filegroup($testFile), 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user and group ownership as indexed array (numeric string values)
|
||||||
|
$ownership = ['10013', '10014'];
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals((int)$ownership[0], fileowner($testFile), 'Expected file owner to be changed.');
|
||||||
|
$this->assertEquals((int)$ownership[1], filegroup($testFile), 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user and group ownership as indexed array (string values)
|
||||||
|
$ownership = [$currentUserName, $currentGroupName];
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($ownership[0], posix_getpwuid(fileowner($testFile))['name'], 'Expected file owner to be changed.');
|
||||||
|
$this->assertEquals($ownership[1], posix_getgrgid(filegroup($testFile))['name'], 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user and group ownership as associative array (integer values)
|
||||||
|
$ownership = ['group' => 10015, 'user' => 10016]; // user/group reversed on purpose
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($ownership['user'], fileowner($testFile), 'Expected file owner to be changed.');
|
||||||
|
$this->assertEquals($ownership['group'], filegroup($testFile), 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user and group ownership as associative array (numeric string values)
|
||||||
|
$ownership = ['group' => '10017', 'user' => '10018']; // user/group reversed on purpose
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals((int)$ownership['user'], fileowner($testFile), 'Expected file owner to be changed.');
|
||||||
|
$this->assertEquals((int)$ownership['group'], filegroup($testFile), 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
// Test user and group ownership as associative array (string values)
|
||||||
|
$ownership = ['group' => $currentGroupName, 'user' => $currentUserName]; // user/group reversed on purpose
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals($ownership['user'], posix_getpwuid(fileowner($testFile))['name'], 'Expected file owner to be changed.');
|
||||||
|
$this->assertEquals($ownership['group'], posix_getgrgid(filegroup($testFile))['name'], 'Expected created test file group to be changed.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected file mode to be unchanged.');
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// Mode, User- and Group Ownership ///
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
// Test user ownership as integer with file mode
|
||||||
|
$ownership = '10019:10020';
|
||||||
|
$fileMode = 0774;
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership, $fileMode);
|
||||||
|
clearstatcache(true, $testFile);
|
||||||
|
$this->assertEquals(explode(':', $ownership)[0], fileowner($testFile), 'Expected created test file owner to be changed.');
|
||||||
|
$this->assertEquals(explode(':', $ownership)[1], filegroup($testFile), 'Expected file group to be unchanged.');
|
||||||
|
$this->assertEquals('0'.decoct($fileMode), substr(decoct(fileperms($testFile)), -4), 'Expected created test file mode to be changed.');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testChangeOwnershipNonExistingUser()
|
||||||
|
{
|
||||||
|
$dirName = 'change_ownership_non_existing_user';
|
||||||
|
$fileName = 'file_1.txt';
|
||||||
|
$testFile = $this->testFilePath . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . $fileName;
|
||||||
|
|
||||||
|
$this->createFileStructure([
|
||||||
|
$dirName => [
|
||||||
|
$fileName => 'test 1',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Test user ownership as integer with file mode (Due to the nature of chown we can't use PHPUnit's `expectException`)
|
||||||
|
$ownership = 'non_existing_user';
|
||||||
|
try {
|
||||||
|
FileHelper::changeOwnership($testFile, $ownership);
|
||||||
|
throw new \Exception('FileHelper::changeOwnership() should have thrown error for non existing user.');
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
$this->assertEquals('chown(): Unable to find uid for non_existing_user', $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider changeOwnershipInvalidArgumentsProvider
|
||||||
|
* @param bool $useFile
|
||||||
|
* @param mixed $ownership
|
||||||
|
* @param mixed $mode
|
||||||
|
*/
|
||||||
|
public function testChangeOwnershipInvalidArguments($useFile, $ownership, $mode)
|
||||||
|
{
|
||||||
|
$dirName = 'change_ownership_invalid_arguments';
|
||||||
|
$fileName = 'file_1.txt';
|
||||||
|
$file = $this->testFilePath . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . $fileName;
|
||||||
|
|
||||||
|
$this->createFileStructure([
|
||||||
|
$dirName => [
|
||||||
|
$fileName => 'test 1',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->expectException('yii\base\InvalidArgumentException');
|
||||||
|
FileHelper::changeOwnership($useFile ? $file : null, $ownership, $mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function changeOwnershipInvalidArgumentsProvider()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[false, '123:123', null],
|
||||||
|
[true, new stdClass(), null],
|
||||||
|
[true, ['user' => new stdClass()], null],
|
||||||
|
[true, ['group' => new stdClass()], null],
|
||||||
|
[true, null, 'test'],
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user