mirror of
https://github.com/espocrm/espocrm.git
synced 2026-06-30 07:56:05 +00:00
908 lines
26 KiB
PHP
908 lines
26 KiB
PHP
<?php
|
|
/************************************************************************
|
|
* This file is part of EspoCRM.
|
|
*
|
|
* EspoCRM - Open Source CRM application.
|
|
* Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
|
* Website: http://www.espocrm.com
|
|
*
|
|
* EspoCRM is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* EspoCRM is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
|
*
|
|
* The interactive user interfaces in modified source and object code versions
|
|
* of this program must display Appropriate Legal Notices, as required under
|
|
* Section 5 of the GNU General Public License version 3.
|
|
*
|
|
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
|
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
|
************************************************************************/
|
|
|
|
namespace Espo\Core\Utils\File;
|
|
use Espo\Core\Utils,
|
|
Espo\Core\Exceptions\Error;
|
|
|
|
class Manager
|
|
{
|
|
private $permission;
|
|
|
|
private $permissionDeniedList = array();
|
|
|
|
public function __construct(\Espo\Core\Utils\Config $config = null)
|
|
{
|
|
$params = null;
|
|
if (isset($config)) {
|
|
$params = array(
|
|
'defaultPermissions' => $config->get('defaultPermissions'),
|
|
'permissionMap' => $config->get('permissionMap'),
|
|
);
|
|
}
|
|
|
|
$this->permission = new Permission($this, $params);
|
|
}
|
|
|
|
public function getPermissionUtils()
|
|
{
|
|
return $this->permission;
|
|
}
|
|
|
|
/**
|
|
* Get a list of files in specified directory
|
|
*
|
|
* @param string $path string - Folder path, Ex. myfolder
|
|
* @param bool | int $recursively - Find files in subfolders
|
|
* @param string $filter - Filter for files. Use regular expression, Ex. \.json$
|
|
* @param bool $onlyFileType [null, true, false] - Filter for type of files/directories. If TRUE - returns only file list, if FALSE - only directory list
|
|
* @param bool $isReturnSingleArray - if need to return a single array of file list
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getFileList($path, $recursively = false, $filter = '', $onlyFileType = null, $isReturnSingleArray = false)
|
|
{
|
|
$path = $this->concatPaths($path);
|
|
|
|
$result = array();
|
|
|
|
if (!file_exists($path) || !is_dir($path)) {
|
|
return $result;
|
|
}
|
|
|
|
$cdir = scandir($path);
|
|
foreach ($cdir as $key => $value)
|
|
{
|
|
if (!in_array($value,array(".", "..")))
|
|
{
|
|
$add = false;
|
|
if (is_dir($path . Utils\Util::getSeparator() . $value)) {
|
|
if ($recursively || (is_int($recursively) && $recursively!=0) ) {
|
|
$nextRecursively = is_int($recursively) ? ($recursively-1) : $recursively;
|
|
$result[$value] = $this->getFileList($path . Utils\Util::getSeparator() . $value, $nextRecursively, $filter, $onlyFileType);
|
|
}
|
|
else if (!isset($onlyFileType) || !$onlyFileType){ /*save only directories*/
|
|
$add = true;
|
|
}
|
|
}
|
|
else if (!isset($onlyFileType) || $onlyFileType) { /*save only files*/
|
|
$add = true;
|
|
}
|
|
|
|
if ($add) {
|
|
if (!empty($filter)) {
|
|
if (preg_match('/'.$filter.'/i', $value)) {
|
|
$result[] = $value;
|
|
}
|
|
}
|
|
else {
|
|
$result[] = $value;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if ($isReturnSingleArray) {
|
|
return $this->getSingeFileList($result, $onlyFileType);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Convert file list to a single array
|
|
*
|
|
* @param aray $fileList
|
|
* @param bool $onlyFileType [null, true, false] - Filter for type of files/directories.
|
|
* @param string $parentDirName
|
|
*
|
|
* @return aray
|
|
*/
|
|
protected function getSingeFileList(array $fileList, $onlyFileType = null, $parentDirName = '')
|
|
{
|
|
$singleFileList = array();
|
|
foreach($fileList as $dirName => $fileName) {
|
|
|
|
if (is_array($fileName)) {
|
|
$currentDir = Utils\Util::concatPath($parentDirName, $dirName);
|
|
|
|
if (!isset($onlyFileType) || $onlyFileType == $this->isFile($currentDir)) {
|
|
$singleFileList[] = $currentDir;
|
|
}
|
|
|
|
$singleFileList = array_merge($singleFileList, $this->getSingeFileList($fileName, $onlyFileType, $currentDir));
|
|
|
|
} else {
|
|
$currentFileName = Utils\Util::concatPath($parentDirName, $fileName);
|
|
|
|
if (!isset($onlyFileType) || $onlyFileType == $this->isFile($currentFileName)) {
|
|
$singleFileList[] = $currentFileName;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $singleFileList;
|
|
}
|
|
|
|
/**
|
|
* Reads entire file into a string
|
|
*
|
|
* @param string | array $path Ex. 'path.php' OR array('dir', 'path.php')
|
|
* @param boolean $useIncludePath
|
|
* @param resource $context
|
|
* @param integer $offset
|
|
* @param integer $maxlen
|
|
* @return mixed
|
|
*/
|
|
public function getContents($path, $useIncludePath = false, $context = null, $offset = -1, $maxlen = null)
|
|
{
|
|
$fullPath = $this->concatPaths($path);
|
|
|
|
if (file_exists($fullPath)) {
|
|
if (isset($maxlen)) {
|
|
return file_get_contents($fullPath, $useIncludePath, $context, $offset, $maxlen);
|
|
} else {
|
|
return file_get_contents($fullPath, $useIncludePath, $context, $offset);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get PHP array from PHP file
|
|
*
|
|
* @param string | array $path
|
|
* @return array | bool
|
|
*/
|
|
public function getPhpContents($path)
|
|
{
|
|
$fullPath = $this->concatPaths($path);
|
|
|
|
if (file_exists($fullPath) && strtolower(substr($fullPath, -4)) == '.php') {
|
|
$phpContents = include($fullPath);
|
|
if (is_array($phpContents)) {
|
|
return $phpContents;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Write data to a file
|
|
*
|
|
* @param string | array $path
|
|
* @param mixed $data
|
|
* @param integer $flags
|
|
* @param resource $context
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function putContents($path, $data, $flags = 0, $context = null)
|
|
{
|
|
$fullPath = $this->concatPaths($path); //todo remove after changing the params
|
|
|
|
if ($this->checkCreateFile($fullPath) === false) {
|
|
throw new Error('Permission denied for '. $fullPath);
|
|
}
|
|
|
|
$res = (file_put_contents($fullPath, $data, $flags, $context) !== FALSE);
|
|
if ($res && function_exists('opcache_invalidate')) {
|
|
opcache_invalidate($fullPath);
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* Save PHP content to file
|
|
*
|
|
* @param string | array $path
|
|
* @param string $data
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function putPhpContents($path, $data, $withObjects = false)
|
|
{
|
|
|
|
return $this->putContents($path, $this->wrapForDataExport($data, $withObjects), LOCK_EX);
|
|
}
|
|
|
|
/**
|
|
* Save JSON content to file
|
|
*
|
|
* @param string | array $path
|
|
* @param string $data
|
|
* @param integer $flags
|
|
* @param resource $context
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function putContentsJson($path, $data)
|
|
{
|
|
if (!Utils\Json::isJSON($data)) {
|
|
$data = Utils\Json::encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
}
|
|
|
|
return $this->putContents($path, $data, LOCK_EX);
|
|
}
|
|
|
|
/**
|
|
* Merge file content and save it to a file
|
|
*
|
|
* @param string | array $path
|
|
* @param string $content JSON string
|
|
* @param bool $isReturnJson
|
|
* @param string | array $removeOptions - List of unset keys from content
|
|
* @param bool $isPhp - Is merge php files
|
|
*
|
|
* @return bool | array
|
|
*/
|
|
public function mergeContents($path, $content, $isReturnJson = false, $removeOptions = null, $isPhp = false)
|
|
{
|
|
if ($isPhp) {
|
|
$fileContent = $this->getPhpContents($path);
|
|
} else {
|
|
$fileContent = $this->getContents($path);
|
|
}
|
|
|
|
$fullPath = $this->concatPaths($path);
|
|
if (file_exists($fullPath) && ($fileContent === false || empty($fileContent))) {
|
|
throw new Error('FileManager: Failed to read file [' . $fullPath .'].');
|
|
}
|
|
|
|
$savedDataArray = Utils\Json::getArrayData($fileContent);
|
|
$newDataArray = Utils\Json::getArrayData($content);
|
|
|
|
if (isset($removeOptions)) {
|
|
$savedDataArray = Utils\Util::unsetInArray($savedDataArray, $removeOptions);
|
|
$newDataArray = Utils\Util::unsetInArray($newDataArray, $removeOptions);
|
|
}
|
|
|
|
$data = Utils\Util::merge($savedDataArray, $newDataArray);
|
|
|
|
if ($isReturnJson) {
|
|
$data = Utils\Json::encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
}
|
|
|
|
if ($isPhp) {
|
|
return $this->putPhpContents($path, $data);
|
|
}
|
|
|
|
return $this->putContents($path, $data);
|
|
}
|
|
|
|
/**
|
|
* Merge PHP content and save it to a file
|
|
*
|
|
* @param string | array $path
|
|
* @param string $content JSON string
|
|
* @param string | array $removeOptions - List of unset keys from content
|
|
* @return bool
|
|
*/
|
|
public function mergePhpContents($path, $content, $removeOptions = null)
|
|
{
|
|
return $this->mergeContents($path, $content, false, $removeOptions, true);
|
|
}
|
|
|
|
/**
|
|
* Append the content to the end of the file
|
|
*
|
|
* @param string | array $path
|
|
* @param mixed $data
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function appendContents($path, $data)
|
|
{
|
|
return $this->putContents($path, $data, FILE_APPEND | LOCK_EX);
|
|
}
|
|
|
|
/**
|
|
* Unset some element of content data
|
|
*
|
|
* @param string | array $path
|
|
* @param array | string $unsets
|
|
* @return bool
|
|
*/
|
|
public function unsetContents($path, $unsets, $isJSON = true)
|
|
{
|
|
$currentData = $this->getContents($path);
|
|
if (!isset($currentData) || !$currentData) {
|
|
$GLOBALS['log']->notice('FileManager::unsetContents: File ['.$this->concatPaths($path).'] does not exist.');
|
|
return false;
|
|
}
|
|
|
|
$currentDataArray = Utils\Json::getArrayData($currentData);
|
|
|
|
$unsettedData = Utils\Util::unsetInArray($currentDataArray, $unsets, true);
|
|
|
|
if (is_null($unsettedData) || (is_array($unsettedData) && empty($unsettedData))) {
|
|
$fullPath = $this->concatPaths($path);
|
|
return $this->unlink($fullPath);
|
|
}
|
|
|
|
if ($isJSON) {
|
|
return $this->putContentsJson($path, $unsettedData);
|
|
}
|
|
|
|
return $this->putContents($path, $unsettedData);
|
|
}
|
|
|
|
|
|
/**
|
|
* Concat paths
|
|
* @param string | array $paths Ex. array('pathPart1', 'pathPart2', 'pathPart3')
|
|
* @return string
|
|
*/
|
|
protected function concatPaths($paths)
|
|
{
|
|
if (is_string($paths)) {
|
|
return $paths;
|
|
}
|
|
|
|
$fullPath = '';
|
|
foreach ($paths as $path) {
|
|
$fullPath = Utils\Util::concatPath($fullPath, $path);
|
|
}
|
|
|
|
return $fullPath;
|
|
}
|
|
|
|
/**
|
|
* Create a new dir
|
|
*
|
|
* @param string | array $path
|
|
* @param int $permission - ex. 0755
|
|
* @param bool $recursive
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function mkdir($path, $permission = null, $recursive = false)
|
|
{
|
|
$fullPath = $this->concatPaths($path);
|
|
|
|
if (file_exists($fullPath) && is_dir($path)) {
|
|
return true;
|
|
}
|
|
|
|
$defaultPermissions = $this->getPermissionUtils()->getDefaultPermissions();
|
|
|
|
if (!isset($permission)) {
|
|
$permission = (string) $defaultPermissions['dir'];
|
|
$permission = base_convert($permission, 8, 10);
|
|
}
|
|
|
|
try {
|
|
$result = mkdir($fullPath, $permission, true);
|
|
|
|
if (!empty($defaultPermissions['user'])) {
|
|
$this->getPermissionUtils()->chown($fullPath);
|
|
}
|
|
|
|
if (!empty($defaultPermissions['group'])) {
|
|
$this->getPermissionUtils()->chgrp($fullPath);
|
|
}
|
|
} catch (\Exception $e) {
|
|
$GLOBALS['log']->critical('Permission denied: unable to create the folder on the server - '.$fullPath);
|
|
}
|
|
|
|
return isset($result) ? $result : false;
|
|
}
|
|
|
|
/**
|
|
* Copy files from one direcoty to another
|
|
* Ex. $sourcePath = 'data/uploads/extensions/file.json', $destPath = 'data/uploads/backup', result will be data/uploads/backup/data/uploads/backup/file.json.
|
|
*
|
|
* @param string $sourcePath
|
|
* @param string $destPath
|
|
* @param boolean $recursively
|
|
* @param array $fileList - list of files that should be copied
|
|
* @param boolean $copyOnlyFiles - copy only files, instead of full path with directories, Ex. $sourcePath = 'data/uploads/extensions/file.json', $destPath = 'data/uploads/backup', result will be 'data/uploads/backup/file.json'
|
|
* @return boolen
|
|
*/
|
|
public function copy($sourcePath, $destPath, $recursively = false, array $fileList = null, $copyOnlyFiles = false)
|
|
{
|
|
$sourcePath = $this->concatPaths($sourcePath);
|
|
$destPath = $this->concatPaths($destPath);
|
|
|
|
if (isset($fileList)) {
|
|
if (!empty($sourcePath)) {
|
|
foreach ($fileList as &$fileName) {
|
|
$fileName = $this->concatPaths(array($sourcePath, $fileName));
|
|
}
|
|
}
|
|
} else {
|
|
$fileList = is_file($sourcePath) ? (array) $sourcePath : $this->getFileList($sourcePath, $recursively, '', true, true);
|
|
}
|
|
|
|
/** Check permission before copying */
|
|
$permissionDeniedList = array();
|
|
foreach ($fileList as $file) {
|
|
|
|
if ($copyOnlyFiles) {
|
|
$file = pathinfo($file, PATHINFO_BASENAME);
|
|
}
|
|
|
|
$destFile = $this->concatPaths(array($destPath, $file));
|
|
|
|
$isFileExists = file_exists($destFile);
|
|
|
|
if ($this->checkCreateFile($destFile) === false) {
|
|
$permissionDeniedList[] = $destFile;
|
|
} else if (!$isFileExists) {
|
|
$this->removeFile($destFile);
|
|
}
|
|
}
|
|
/** END */
|
|
|
|
if (!empty($permissionDeniedList)) {
|
|
$betterPermissionList = $this->getPermissionUtils()->arrangePermissionList($permissionDeniedList);
|
|
throw new Error("Permission denied for <br>". implode(", <br>", $betterPermissionList));
|
|
}
|
|
|
|
$res = true;
|
|
foreach ($fileList as $file) {
|
|
|
|
if ($copyOnlyFiles) {
|
|
$file = pathinfo($file, PATHINFO_BASENAME);
|
|
}
|
|
|
|
$sourceFile = is_file($sourcePath) ? $sourcePath : $this->concatPaths(array($sourcePath, $file));
|
|
$destFile = $this->concatPaths(array($destPath, $file));
|
|
|
|
if (file_exists($sourceFile) && is_file($sourceFile)) {
|
|
$res &= copy($sourceFile, $destFile);
|
|
}
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* Create a new file if not exists with all folders in the path.
|
|
*
|
|
* @param string $filePath
|
|
* @return string
|
|
*/
|
|
public function checkCreateFile($filePath)
|
|
{
|
|
$defaultPermissions = $this->getPermissionUtils()->getDefaultPermissions();
|
|
|
|
if (file_exists($filePath)) {
|
|
|
|
if (!in_array($this->getPermissionUtils()->getCurrentPermission($filePath), array($defaultPermissions['file'], $defaultPermissions['dir']))) {
|
|
return $this->getPermissionUtils()->setDefaultPermissions($filePath, true);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
$pathParts = pathinfo($filePath);
|
|
if (!file_exists($pathParts['dirname'])) {
|
|
$dirPermission = $defaultPermissions['dir'];
|
|
$dirPermission = is_string($dirPermission) ? base_convert($dirPermission,8,10) : $dirPermission;
|
|
|
|
if (!$this->mkdir($pathParts['dirname'], $dirPermission, true)) {
|
|
throw new Error('Permission denied: unable to create a folder on the server - ' . $pathParts['dirname']);
|
|
}
|
|
}
|
|
|
|
if (touch($filePath)) {
|
|
return $this->getPermissionUtils()->setDefaultPermissions($filePath, true);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Remove file/files by given path
|
|
*
|
|
* @param array $filePaths - File paths list
|
|
* @return bool
|
|
*/
|
|
public function unlink($filePaths)
|
|
{
|
|
return $this->removeFile($filePaths);
|
|
}
|
|
|
|
public function rmdir($dirPaths)
|
|
{
|
|
if (!is_array($dirPaths)) {
|
|
$dirPaths = (array) $dirPaths;
|
|
}
|
|
|
|
$result = true;
|
|
foreach ($dirPaths as $dirPath) {
|
|
if (is_dir($dirPath) && is_writable($dirPath)) {
|
|
$result &= rmdir($dirPath);
|
|
}
|
|
}
|
|
|
|
return (bool) $result;
|
|
}
|
|
|
|
/**
|
|
* Remove file/files by given path
|
|
*
|
|
* @param array $filePaths - File paths list
|
|
* @param string $dirPath - directory path
|
|
* @return bool
|
|
*/
|
|
public function removeFile($filePaths, $dirPath = null)
|
|
{
|
|
if (!is_array($filePaths)) {
|
|
$filePaths = (array) $filePaths;
|
|
}
|
|
|
|
$result = true;
|
|
foreach ($filePaths as $filePath) {
|
|
if (isset($dirPath)) {
|
|
$filePath = Utils\Util::concatPath($dirPath, $filePath);
|
|
}
|
|
|
|
if (file_exists($filePath) && is_file($filePath)) {
|
|
$result &= unlink($filePath);
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Remove all files inside given path
|
|
*
|
|
* @param string $dirPath - directory path
|
|
* @param bool $removeWithDir - if remove with directory
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function removeInDir($dirPath, $removeWithDir = false)
|
|
{
|
|
$fileList = $this->getFileList($dirPath, false);
|
|
|
|
$result = true;
|
|
if (is_array($fileList)) {
|
|
foreach ($fileList as $file) {
|
|
$fullPath = Utils\Util::concatPath($dirPath, $file);
|
|
if (is_dir($fullPath)) {
|
|
$result &= $this->removeInDir($fullPath, true);
|
|
} else if (file_exists($fullPath)) {
|
|
$result &= unlink($fullPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($removeWithDir) {
|
|
$result &= $this->rmdir($dirPath);
|
|
}
|
|
|
|
return (bool) $result;
|
|
}
|
|
|
|
/**
|
|
* Remove items (files or directories)
|
|
*
|
|
* @param string | array $items
|
|
* @param string $dirPath
|
|
* @return boolean
|
|
*/
|
|
public function remove($items, $dirPath = null, $removeEmptyDirs = false)
|
|
{
|
|
if (!is_array($items)) {
|
|
$items = (array) $items;
|
|
}
|
|
|
|
$permissionDeniedList = array();
|
|
foreach ($items as $item) {
|
|
if (isset($dirPath)) {
|
|
$item = Utils\Util::concatPath($dirPath, $item);
|
|
}
|
|
|
|
if (!is_writable($item)) {
|
|
$permissionDeniedList[] = $item;
|
|
} else if (!is_writable(dirname($item))) {
|
|
$permissionDeniedList[] = dirname($item);
|
|
}
|
|
}
|
|
|
|
if (!empty($permissionDeniedList)) {
|
|
$betterPermissionList = $this->getPermissionUtils()->arrangePermissionList($permissionDeniedList);
|
|
throw new Error("Permission denied for <br>". implode(", <br>", $betterPermissionList));
|
|
}
|
|
|
|
$result = true;
|
|
foreach ($items as $item) {
|
|
if (isset($dirPath)) {
|
|
$item = Utils\Util::concatPath($dirPath, $item);
|
|
}
|
|
|
|
if (is_dir($item)) {
|
|
$result &= $this->removeInDir($item, true);
|
|
} else {
|
|
$result &= $this->removeFile($item);
|
|
}
|
|
|
|
if ($removeEmptyDirs) {
|
|
$result &= $this->removeEmptyDirs($item);
|
|
}
|
|
}
|
|
|
|
return (bool) $result;
|
|
}
|
|
|
|
/**
|
|
* Remove empty parent directories if they are empty
|
|
* @param string $path
|
|
* @return bool
|
|
*/
|
|
protected function removeEmptyDirs($path)
|
|
{
|
|
$parentDirName = $this->getParentDirName($path);
|
|
|
|
$res = true;
|
|
if ($this->isDirEmpty($parentDirName)) {
|
|
$res &= $this->rmdir($parentDirName);
|
|
$res &= $this->removeEmptyDirs($parentDirName);
|
|
}
|
|
|
|
return (bool) $res;
|
|
}
|
|
|
|
/**
|
|
* Check if $dirname is directory.
|
|
*
|
|
* @param string $dirname
|
|
* @return boolean
|
|
*/
|
|
public function isDir($dirname)
|
|
{
|
|
return is_dir($dirname);
|
|
}
|
|
|
|
/**
|
|
* Check if $filename is file. If $filename doesn'ot exist, check by pathinfo
|
|
*
|
|
* @param string $filename
|
|
* @return boolean
|
|
*/
|
|
public function isFile($filename)
|
|
{
|
|
if (file_exists($filename)) {
|
|
return is_file($filename);
|
|
}
|
|
|
|
$fileExtension = pathinfo($filename, PATHINFO_EXTENSION);
|
|
if (!empty($fileExtension)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Check if directory is empty
|
|
* @param string $path
|
|
* @return boolean
|
|
*/
|
|
public function isDirEmpty($path)
|
|
{
|
|
if (is_dir($path)) {
|
|
$fileList = $this->getFileList($path, true);
|
|
|
|
if (is_array($fileList) && empty($fileList)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get a filename without the file extension
|
|
*
|
|
* @param string $filename
|
|
* @param string $ext - extension, ex. '.json'
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getFileName($fileName, $ext='')
|
|
{
|
|
if (empty($ext)) {
|
|
$fileName= substr($fileName, 0, strrpos($fileName, '.', -1));
|
|
}
|
|
else {
|
|
if (substr($ext, 0, 1)!='.') {
|
|
$ext= '.'.$ext;
|
|
}
|
|
|
|
if (substr($fileName, -(strlen($ext)))==$ext) {
|
|
$fileName= substr($fileName, 0, -(strlen($ext)));
|
|
}
|
|
}
|
|
|
|
$exFileName = explode('/', Utils\Util::toFormat($fileName, '/'));
|
|
|
|
return end($exFileName);
|
|
}
|
|
|
|
/**
|
|
* Get a directory name from the path
|
|
*
|
|
* @param string $path
|
|
* @param bool $isFullPath
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getDirName($path, $isFullPath = true, $useIsDir = true)
|
|
{
|
|
$dirName = preg_replace('/\/$/i', '', $path);
|
|
$dirName = ($useIsDir && is_dir($dirName)) ? $dirName : pathinfo($dirName, PATHINFO_DIRNAME);
|
|
|
|
if (!$isFullPath) {
|
|
$pieces = explode('/', $dirName);
|
|
$dirName = $pieces[count($pieces)-1];
|
|
}
|
|
|
|
return $dirName;
|
|
}
|
|
|
|
/**
|
|
* Get parent dir name/path
|
|
*
|
|
* @param string $path
|
|
* @param boolean $isFullPath
|
|
* @return string
|
|
*/
|
|
public function getParentDirName($path, $isFullPath = true)
|
|
{
|
|
return $this->getDirName($path, $isFullPath, false);
|
|
}
|
|
|
|
/**
|
|
* Return content of PHP file
|
|
*
|
|
* @param string $varName - name of variable which contains the content
|
|
* @param array $content
|
|
*
|
|
* @return string | false
|
|
*/
|
|
public function wrapForDataExport($content, $withObjects = false)
|
|
{
|
|
if (!isset($content)) {
|
|
return false;
|
|
}
|
|
|
|
if (!$withObjects) {
|
|
return "<?php\n".
|
|
"return " . var_export($content, true) . ";\n".
|
|
"?>";
|
|
} else {
|
|
return "<?php\n".
|
|
"return " . $this->varExport($content) . ";\n".
|
|
"?>";
|
|
}
|
|
}
|
|
|
|
public function varExport($variable, $level = 0)
|
|
{
|
|
$tab = '';
|
|
$tabElement = ' ';
|
|
for ($i = 0; $i <= $level; $i++) {
|
|
$tab .= $tabElement;
|
|
}
|
|
$prevTab = substr($tab, 0, strlen($tab) - strlen($tabElement));
|
|
|
|
if ($variable instanceof \StdClass) {
|
|
$result = "(object) " . $this->varExport(get_object_vars($variable), $level);
|
|
} else if (is_array($variable)) {
|
|
$array = array();
|
|
foreach ($variable as $key => $value) {
|
|
$array[] = var_export($key, true) . " => " . $this->varExport($value, $level + 1);
|
|
}
|
|
$result = "[\n" . $tab . implode(",\n" . $tab, $array) . "\n" . $prevTab . "]";
|
|
} else {
|
|
$result = var_export($variable, true);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Check if $paths are writable. Permission denied list are defined in getLastPermissionDeniedList()
|
|
*
|
|
* @param array $paths
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function isWritableList(array $paths)
|
|
{
|
|
$permissionDeniedList = array();
|
|
|
|
$result = true;
|
|
foreach ($paths as $path) {
|
|
$rowResult = $this->isWritable($path);
|
|
if (!$rowResult) {
|
|
$permissionDeniedList[] = $path;
|
|
}
|
|
$result &= $rowResult;
|
|
}
|
|
|
|
if (!empty($permissionDeniedList)) {
|
|
$this->permissionDeniedList = $this->getPermissionUtils()->arrangePermissionList($permissionDeniedList);
|
|
}
|
|
|
|
return (bool) $result;
|
|
}
|
|
|
|
/**
|
|
* Get last permission denied list
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getLastPermissionDeniedList()
|
|
{
|
|
return $this->permissionDeniedList;
|
|
}
|
|
|
|
/**
|
|
* Check if $path is writable
|
|
*
|
|
* @param string | array $path
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function isWritable($path)
|
|
{
|
|
$existFile = $this->getExistsPath($path);
|
|
|
|
return is_writable($existFile);
|
|
}
|
|
|
|
/**
|
|
* Get exists path. Ex. if check /var/www/espocrm/custom/someFile.php and this file doesn't extist, result will be /var/www/espocrm/custom
|
|
*
|
|
* @param string | array $path
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function getExistsPath($path)
|
|
{
|
|
$fullPath = $this->concatPaths($path);
|
|
|
|
if (!file_exists($fullPath)) {
|
|
$fullPath = $this->getExistsPath(pathinfo($fullPath, PATHINFO_DIRNAME));
|
|
}
|
|
|
|
return $fullPath;
|
|
}
|
|
}
|
|
|