123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework\Setup;
- use Magento\Framework\App\Filesystem\DirectoryList;
- use Magento\Framework\Backup\Filesystem\Iterator\Filter;
- use Magento\Framework\Filesystem;
- use Magento\Framework\Filesystem\Filter\ExcludeFilter;
- use Magento\Framework\App\State;
- use Magento\Framework\App\ObjectManager;
- /**
- * Checks permissions to files and folders.
- */
- class FilePermissions
- {
- /**
- * @var Filesystem
- */
- protected $filesystem;
- /**
- * @var DirectoryList
- */
- protected $directoryList;
- /**
- * @var State
- */
- private $state;
- /**
- * List of required writable directories for installation
- *
- * @var array
- */
- protected $installationWritableDirectories = [];
- /**
- * List of recommended non-writable directories for application
- *
- * @var array
- */
- protected $applicationNonWritableDirectories = [];
- /**
- * List of current writable directories for installation
- *
- * @var array
- */
- protected $installationCurrentWritableDirectories = [];
- /**
- * List of current non-writable directories for application
- *
- * @var array
- */
- protected $applicationCurrentNonWritableDirectories = [];
- /**
- * List of non-writable paths in a specified directory
- *
- * @var array
- */
- protected $nonWritablePathsInDirectories = [];
- /**
- * @param Filesystem $filesystem
- * @param DirectoryList $directoryList
- * @param State $state
- */
- public function __construct(
- Filesystem $filesystem,
- DirectoryList $directoryList,
- State $state = null
- ) {
- $this->filesystem = $filesystem;
- $this->directoryList = $directoryList;
- $this->state = $state ?: ObjectManager::getInstance()->get(State::class);
- }
- /**
- * Retrieve list of required writable directories for installation
- *
- * @return array
- */
- public function getInstallationWritableDirectories()
- {
- if (!$this->installationWritableDirectories) {
- $data = [
- DirectoryList::CONFIG,
- DirectoryList::VAR_DIR,
- DirectoryList::MEDIA,
- DirectoryList::STATIC_VIEW,
- ];
- if ($this->state->getMode() !== State::MODE_PRODUCTION) {
- $data[] = DirectoryList::GENERATED;
- }
- foreach ($data as $code) {
- $this->installationWritableDirectories[$code] = $this->directoryList->getPath($code);
- }
- }
- return array_values($this->installationWritableDirectories);
- }
- /**
- * Retrieve list of recommended non-writable directories for application
- *
- * @return array
- */
- public function getApplicationNonWritableDirectories()
- {
- if (!$this->applicationNonWritableDirectories) {
- $data = [
- DirectoryList::CONFIG,
- ];
- foreach ($data as $code) {
- $this->applicationNonWritableDirectories[$code] = $this->directoryList->getPath($code);
- }
- }
- return array_values($this->applicationNonWritableDirectories);
- }
- /**
- * Retrieve list of currently writable directories for installation
- *
- * @return array
- */
- public function getInstallationCurrentWritableDirectories()
- {
- if (!$this->installationCurrentWritableDirectories) {
- foreach ($this->installationWritableDirectories as $code => $path) {
- if ($this->isWritable($code)) {
- if ($this->checkRecursiveDirectories($path)) {
- $this->installationCurrentWritableDirectories[] = $path;
- }
- } else {
- $this->nonWritablePathsInDirectories[$path] = [$path];
- }
- }
- }
- return $this->installationCurrentWritableDirectories;
- }
- /**
- * Check all sub-directories and files except for generated/code and generated/metadata
- *
- * @param string $directory
- * @return bool
- */
- private function checkRecursiveDirectories($directory)
- {
- /** @var $directoryIterator \RecursiveIteratorIterator */
- $directoryIterator = new \RecursiveIteratorIterator(
- new \RecursiveDirectoryIterator($directory, \RecursiveDirectoryIterator::SKIP_DOTS),
- \RecursiveIteratorIterator::CHILD_FIRST
- );
- $noWritableFilesFolders = [
- $this->directoryList->getPath(DirectoryList::GENERATED_CODE) . '/',
- $this->directoryList->getPath(DirectoryList::GENERATED_METADATA) . '/',
- ];
- $directoryIterator = new Filter($directoryIterator, $noWritableFilesFolders);
- $directoryIterator = new ExcludeFilter(
- $directoryIterator,
- [
- $this->directoryList->getPath(DirectoryList::SESSION) . '/',
- ]
- );
- $directoryIterator->setMaxDepth(1);
- $foundNonWritable = false;
- try {
- foreach ($directoryIterator as $subDirectory) {
- if (!$subDirectory->isWritable() && !$subDirectory->isLink()) {
- $this->nonWritablePathsInDirectories[$directory][] = $subDirectory->getPathname();
- $foundNonWritable = true;
- }
- }
- } catch (\UnexpectedValueException $e) {
- return false;
- }
- return !$foundNonWritable;
- }
- /**
- * Retrieve list of currently non-writable directories for application
- *
- * @return array
- */
- public function getApplicationCurrentNonWritableDirectories()
- {
- if (!$this->applicationCurrentNonWritableDirectories) {
- foreach ($this->applicationNonWritableDirectories as $code => $path) {
- if ($this->isNonWritable($code)) {
- $this->applicationCurrentNonWritableDirectories[] = $path;
- }
- }
- }
- return $this->applicationCurrentNonWritableDirectories;
- }
- /**
- * Checks if directory is writable by given directory code
- *
- * @param string $code
- * @return bool
- */
- protected function isWritable($code)
- {
- $directory = $this->filesystem->getDirectoryWrite($code);
- return $this->isReadableDirectory($directory) && $directory->isWritable();
- }
- /**
- * Checks if directory is non-writable by given directory code
- *
- * @param string $code
- * @return bool
- */
- protected function isNonWritable($code)
- {
- $directory = $this->filesystem->getDirectoryWrite($code);
- return $this->isReadableDirectory($directory) && !$directory->isWritable();
- }
- /**
- * Checks if directory exists and is readable
- *
- * @param \Magento\Framework\Filesystem\Directory\WriteInterface $directory
- * @return bool
- */
- protected function isReadableDirectory($directory)
- {
- if (!$directory->isExist() || !$directory->isDirectory() || !$directory->isReadable()) {
- return false;
- }
- return true;
- }
- /**
- * Checks writable paths for installation, returns associative array if input is true, else returns simple array
- *
- * @param bool $associative
- * @return array
- */
- public function getMissingWritablePathsForInstallation($associative = false)
- {
- $required = $this->getInstallationWritableDirectories();
- $current = $this->getInstallationCurrentWritableDirectories();
- $missingPaths = [];
- foreach (array_diff($required, $current) as $missingPath) {
- if (isset($this->nonWritablePathsInDirectories[$missingPath])) {
- if ($associative) {
- $missingPaths[$missingPath] = $this->nonWritablePathsInDirectories[$missingPath];
- } else {
- $missingPaths = array_merge(
- $missingPaths,
- $this->nonWritablePathsInDirectories[$missingPath]
- );
- }
- }
- }
- if ($associative) {
- $required = array_flip($required);
- $missingPaths = array_merge($required, $missingPaths);
- }
- return $missingPaths;
- }
- /**
- * Checks writable paths for database upgrade, returns array of directory paths that requires write permission
- *
- * @return array List of directories that requires write permission for database upgrade
- */
- public function getMissingWritableDirectoriesForDbUpgrade()
- {
- $writableDirectories = [
- DirectoryList::CONFIG,
- DirectoryList::VAR_DIR
- ];
- $requireWritePermission = [];
- foreach ($writableDirectories as $code) {
- if (!$this->isWritable($code)) {
- $path = $this->directoryList->getPath($code);
- if (!$this->checkRecursiveDirectories($path)) {
- $requireWritePermission[] = $path;
- }
- }
- }
- return $requireWritePermission;
- }
- /**
- * Checks writable directories for installation
- *
- * @deprecated 100.1.0 Use getMissingWritablePathsForInstallation()
- * to get all missing writable paths required for install.
- * @return array
- */
- public function getMissingWritableDirectoriesForInstallation()
- {
- $required = $this->getInstallationWritableDirectories();
- $current = $this->getInstallationCurrentWritableDirectories();
- return array_diff($required, $current);
- }
- /**
- * Checks non-writable directories for application
- *
- * @return array
- */
- public function getUnnecessaryWritableDirectoriesForApplication()
- {
- $required = $this->getApplicationNonWritableDirectories();
- $current = $this->getApplicationCurrentNonWritableDirectories();
- return array_diff($required, $current);
- }
- }
|