mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-01-08 11:11:39 +09:00
Add admin screen to delete unnecessary core files from older versions
This commit is contained in:
parent
e97f44826d
commit
ba107a6abf
7 changed files with 488 additions and 3 deletions
120
modules/admin/controllers/maintenance/CacheReset.php
Normal file
120
modules/admin/controllers/maintenance/CacheReset.php
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
namespace Rhymix\Modules\Admin\Controllers\Maintenance;
|
||||
|
||||
use FileHandler;
|
||||
use ModuleModel;
|
||||
use ModuleObject;
|
||||
use Rhymix\Framework\Cache;
|
||||
use Rhymix\Framework\Config;
|
||||
use Rhymix\Framework\Storage;
|
||||
use Rhymix\Modules\Admin\Controllers\Base;
|
||||
|
||||
class CacheReset extends Base
|
||||
{
|
||||
/**
|
||||
* Regenerate all cache files
|
||||
*/
|
||||
public function procAdminRecompileCacheFile()
|
||||
{
|
||||
// rename cache dir
|
||||
$truncate_method = Config::get('cache.truncate_method');
|
||||
if ($truncate_method === 'empty')
|
||||
{
|
||||
$tmp_basedir = \RX_BASEDIR . 'files/cache/truncate_' . time();
|
||||
Storage::createDirectory($tmp_basedir);
|
||||
$dirs = Storage::readDirectory(\RX_BASEDIR . 'files/cache', true, false, false);
|
||||
if ($dirs)
|
||||
{
|
||||
foreach ($dirs as $dir)
|
||||
{
|
||||
Storage::moveDirectory($dir, $tmp_basedir . '/' . basename($dir));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Storage::move(\RX_BASEDIR . 'files/cache', \RX_BASEDIR . 'files/cache_' . time());
|
||||
Storage::createDirectory(\RX_BASEDIR . 'files/cache');
|
||||
}
|
||||
|
||||
// remove module extend cache
|
||||
Storage::delete(RX_BASEDIR . 'files/config/module_extend.php');
|
||||
|
||||
// remove debug files
|
||||
Storage::delete(RX_BASEDIR . 'files/_debug_message.php');
|
||||
Storage::delete(RX_BASEDIR . 'files/_debug_db_query.php');
|
||||
Storage::delete(RX_BASEDIR . 'files/_db_slow_query.php');
|
||||
|
||||
$module_list = ModuleModel::getModuleList();
|
||||
|
||||
// call recompileCache for each module
|
||||
foreach($module_list as $module)
|
||||
{
|
||||
$oModule = getClass($module->module);
|
||||
if (!$oModule)
|
||||
{
|
||||
$oModule = ModuleModel::getModuleInstallClass($module->module);
|
||||
}
|
||||
if ($oModule instanceof ModuleObject && method_exists($oModule, 'recompileCache'))
|
||||
{
|
||||
call_user_func([$oModule, 'recompileCache']);
|
||||
}
|
||||
}
|
||||
|
||||
// remove object cache
|
||||
if (!in_array(Cache::getDriverName(), array('file', 'sqlite', 'dummy')))
|
||||
{
|
||||
Cache::clearAll();
|
||||
}
|
||||
|
||||
// remove old cache dir
|
||||
if ($truncate_method === 'empty')
|
||||
{
|
||||
$tmp_cache_list = FileHandler::readDir(\RX_BASEDIR . 'files/cache', '/^(truncate_[0-9]+)/');
|
||||
$tmp_cache_prefix = \RX_BASEDIR . 'files/cache/';
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmp_cache_list = FileHandler::readDir(\RX_BASEDIR . 'files', '/^(cache_[0-9]+)/');
|
||||
$tmp_cache_prefix = \RX_BASEDIR . 'files/';
|
||||
}
|
||||
|
||||
if($tmp_cache_list)
|
||||
{
|
||||
foreach($tmp_cache_list as $tmp_dir)
|
||||
{
|
||||
if(strval($tmp_dir) !== '')
|
||||
{
|
||||
$tmp_dir = $tmp_cache_prefix . $tmp_dir;
|
||||
if (!Storage::isDirectory($tmp_dir))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If possible, use system command to speed up recursive deletion
|
||||
if (function_exists('exec') && !preg_match('/(?<!_)exec/', ini_get('disable_functions')))
|
||||
{
|
||||
if (strncasecmp(\PHP_OS, 'win', 3) == 0)
|
||||
{
|
||||
@exec('rmdir /S /Q ' . escapeshellarg($tmp_dir));
|
||||
}
|
||||
else
|
||||
{
|
||||
@exec('rm -rf ' . escapeshellarg($tmp_dir));
|
||||
}
|
||||
}
|
||||
|
||||
// If the directory still exists, delete using PHP.
|
||||
Storage::deleteDirectory($tmp_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check autoinstall packages
|
||||
$oAutoinstallAdminController = getAdminController('autoinstall');
|
||||
$oAutoinstallAdminController->checkInstalled();
|
||||
|
||||
$this->setMessage('success_updated');
|
||||
}
|
||||
}
|
||||
375
modules/admin/controllers/maintenance/Cleanup.php
Normal file
375
modules/admin/controllers/maintenance/Cleanup.php
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
<?php
|
||||
|
||||
namespace Rhymix\Modules\Admin\Controllers\Maintenance;
|
||||
|
||||
use Context;
|
||||
use Rhymix\Framework\Security;
|
||||
use Rhymix\Framework\Storage;
|
||||
use Rhymix\Modules\Admin\Controllers\Base;
|
||||
|
||||
class Cleanup extends Base
|
||||
{
|
||||
/**
|
||||
* Cleanup list screen.
|
||||
*/
|
||||
public function dispAdminCleanupList()
|
||||
{
|
||||
// Get the list of files to clean up.
|
||||
$cleanup_list = $this->checkFiles();
|
||||
Context::set('cleanup_list', $cleanup_list);
|
||||
|
||||
// Check previous errors.
|
||||
Context::set('cleanup_errors', $_SESSION['admin_cleanup_errors'] ?? []);
|
||||
unset($_SESSION['admin_cleanup_errors']);
|
||||
|
||||
// Set the template file.
|
||||
$this->setTemplateFile('cleanup');
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup action.
|
||||
*/
|
||||
public function procAdminCleanupFiles()
|
||||
{
|
||||
// Cleanup!
|
||||
$result = self::deleteFiles();
|
||||
if (!count($result))
|
||||
{
|
||||
$this->setMessage('success_deleted');
|
||||
}
|
||||
|
||||
// If there were errors, set information in session.
|
||||
else
|
||||
{
|
||||
$this->setMessage('msg_cleanup_manually');
|
||||
$_SESSION['admin_cleanup_errors'] = $result;
|
||||
}
|
||||
|
||||
// Redirect to the list screen.
|
||||
$this->setRedirectUrl(Context::get('success_return_url') ?: getNotEncodedUrl('', 'module', 'admin', 'act', 'dispAdminCleanupList'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for files to clean up.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function checkFiles(): array
|
||||
{
|
||||
$result = [];
|
||||
foreach (self::CLEANUP_LIST as $name => $reason)
|
||||
{
|
||||
// Skip if file/directory distinction doesn't match.
|
||||
if (str_ends_with($name, '/') && !Storage::isDirectory(\RX_BASEDIR . rtrim($name, '/')))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!str_ends_with($name, '/') && !Storage::isFile(\RX_BASEDIR . $name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for case difference and moved target.
|
||||
if ($reason === 'case')
|
||||
{
|
||||
if ($this->checkCaseSensitiveFilesystem())
|
||||
{
|
||||
$result[$name] = $reason;
|
||||
}
|
||||
}
|
||||
elseif (preg_match('/^moved:(.+)$/', $reason, $matches))
|
||||
{
|
||||
if (Storage::exists(\RX_BASEDIR . $matches[1]))
|
||||
{
|
||||
$result[$name] = $reason;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$result[$name] = $reason;
|
||||
}
|
||||
}
|
||||
|
||||
ksort($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filesystem is case-sensitive.
|
||||
*
|
||||
* This method generally returns true on Linux, and false on Windows and Mac OS,
|
||||
* but the result may differ if tested on an unusual filesystem.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function checkCaseSensitiveFilesystem(): bool
|
||||
{
|
||||
// Don't check more than once on the same platform.
|
||||
static $cache = null;
|
||||
if ($cache !== null)
|
||||
{
|
||||
return $cache;
|
||||
}
|
||||
|
||||
// Create two files that differ only in case, and check if they overwrite each other.
|
||||
$file1 = \RX_BASEDIR . 'files/cache/caseTest.php';
|
||||
$file2 = \RX_BASEDIR . 'files/cache/caseTEST.php';
|
||||
Storage::write($file1, '#1:' . Security::getRandom(36) . \PHP_EOL);
|
||||
Storage::write($file2, '#2:' . Security::getRandom(36) . \PHP_EOL);
|
||||
$result = (Storage::read($file1) !== Storage::read($file2));
|
||||
|
||||
// Clean up test files and return the result.
|
||||
Storage::delete($file1);
|
||||
Storage::delete($file2);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete files.
|
||||
*
|
||||
* If a name is given, only that file or directory will be deleted.
|
||||
* Otherwise, all files in the cleanup list will be deleted.
|
||||
*
|
||||
* This method returns the list of files that could not be deleted,
|
||||
* with reasons for each file.
|
||||
*
|
||||
* @param ?string $name
|
||||
* @return array
|
||||
*/
|
||||
public function deleteFiles($name = null): array
|
||||
{
|
||||
// Compile the list of files to delete.
|
||||
$list = [];
|
||||
if ($name !== null)
|
||||
{
|
||||
if (array_key_exists($name, self::CLEANUP_LIST))
|
||||
{
|
||||
$list[$name] = 'deleted';
|
||||
}
|
||||
else
|
||||
{
|
||||
return [$name => 'INVALID'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$list = $this->checkFiles();
|
||||
}
|
||||
|
||||
// Delete each file or directory.
|
||||
$result = [];
|
||||
foreach ($list as $name => $reason)
|
||||
{
|
||||
$normalized_path = \RX_BASEDIR . rtrim($name, '/');
|
||||
if (str_ends_with($name, '/'))
|
||||
{
|
||||
$success = Storage::deleteDirectory($normalized_path, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
$success = Storage::delete($normalized_path);
|
||||
}
|
||||
|
||||
if (!$success && Storage::exists($normalized_path))
|
||||
{
|
||||
if (!Storage::isWritable($normalized_path) || !Storage::isWritable(dirname($normalized_path)))
|
||||
{
|
||||
$result[$name] = 'PERMISSION';
|
||||
}
|
||||
elseif (Storage::isSymlink($normalized_path))
|
||||
{
|
||||
$result[$name] = 'SYMLINK';
|
||||
}
|
||||
else
|
||||
{
|
||||
$result[$name] = 'UNKNOWN';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of files and directories to clean up.
|
||||
*/
|
||||
public const CLEANUP_LIST = [
|
||||
|
||||
// Unnecessary files in the root directory
|
||||
'composer.json' => 'moved:common/composer.json',
|
||||
'composer.lock' => 'moved:common/composer.lock',
|
||||
'Gruntfile.js' => 'deleted:xe',
|
||||
'gulpfile.babel.js' => 'deleted:xe',
|
||||
'package.json' => 'deleted:xe',
|
||||
'.babelrc' => 'deleted:xe',
|
||||
'.jshintignore' => 'deleted:xe',
|
||||
'.jshintrc' => 'deleted:xe',
|
||||
'.travis.yml' => 'deleted:xe',
|
||||
|
||||
// Deleted files and directories
|
||||
'classes/cache/CacheApc.class.php' => 'deleted:xe',
|
||||
'classes/cache/CacheFile.class.php' => 'deleted:xe',
|
||||
'classes/cache/CacheMemcache.class.php' => 'deleted:xe',
|
||||
'classes/cache/CacheWincache.class.php' => 'deleted:xe',
|
||||
'classes/db/DBCubrid.class.php' => 'deleted:xe',
|
||||
'classes/db/DBMssql.class.php' => 'deleted:xe',
|
||||
'classes/db/DBMysql.class.php' => 'deleted:xe',
|
||||
'classes/db/DBMysql_innodb.class.php' => 'deleted:xe',
|
||||
'classes/db/DBMysqli.class.php' => 'deleted:xe',
|
||||
'classes/db/DBMysqli_innodb.class.php' => 'deleted:xe',
|
||||
'classes/db/queryparts/' => 'deleted:xe',
|
||||
'classes/object/BaseObject.class.php' => 'deleted:xe',
|
||||
'classes/xml/XmlQueryParser.class.php' => 'deleted:xe',
|
||||
'classes/xml/xmlquery/' => 'deleted:xe',
|
||||
'common/img/flvplayer.swf' => 'deleted:xe',
|
||||
'common/js/jquery-1.12.4.min.js' => 'deleted',
|
||||
'common/js/jquery-1.12.4.js' => 'deleted',
|
||||
'common/js/plugins/jquery.migrate/jquery-migrate-1.4.1.js' => 'deleted',
|
||||
'common/js/plugins/spectrum/bower.json' => 'deleted',
|
||||
'common/js/plugins/spectrum/Gruntfile.js' => 'deleted',
|
||||
'common/js/plugins/spectrum/index.html' => 'deleted',
|
||||
'common/js/plugins/spectrum/package.json' => 'deleted',
|
||||
'common/js/plugins/spectrum/build/' => 'deleted',
|
||||
'common/js/plugins/spectrum/docs/' => 'deleted',
|
||||
'common/js/plugins/spectrum/example/' => 'deleted',
|
||||
'common/js/plugins/spectrum/test/' => 'deleted',
|
||||
'common/libraries/bmp.php' => 'deleted',
|
||||
'common/manual/server_config/rhymix-nginx-help.md' => 'deleted',
|
||||
'config/func.inc.php' => 'deleted:xe',
|
||||
'config/package.inc.php' => 'deleted:xe',
|
||||
'doxygen/' => 'deleted:xe',
|
||||
'libs/' => 'deleted:xe',
|
||||
'modules/admin/ruleset/toggleFavorite.xml' => 'deleted',
|
||||
'modules/admin/tpl/config_ftp.html' => 'deleted',
|
||||
'modules/admin/tpl/img/faviconSample.png' => 'deleted',
|
||||
'modules/admin/tpl/img/mobiconSample.png' => 'deleted',
|
||||
'modules/counter/queries/deleteSiteCounter.xml' => 'deleted:xe',
|
||||
'modules/counter/queries/deleteSiteCounterLog.xml' => 'deleted:xe',
|
||||
'modules/counter/queries/getSiteCounterStatus.xml' => 'deleted:xe',
|
||||
'modules/counter/queries/getSiteCounterStatusDays.xml' => 'deleted:xe',
|
||||
'modules/counter/queries/getSiteStartLogDate.xml' => 'deleted:xe',
|
||||
'modules/counter/queries/getSiteTodayStatus.xml' => 'deleted:xe',
|
||||
'modules/counter/queries/insertSiteTodayStatus.xml' => 'deleted:xe',
|
||||
'modules/counter/queries/updateSiteCounterPageview.xml' => 'deleted:xe',
|
||||
'modules/counter/queries/updateSiteCounterUnique.xml' => 'deleted:xe',
|
||||
'modules/counter/queries/updateSiteTotalCounterUnique.xml' => 'deleted:xe',
|
||||
'modules/editor/skins/xpresseditor/' => 'deleted:xe',
|
||||
'modules/editor/styles/' => 'deleted:xe',
|
||||
'modules/spamfilter/ruleset/' => 'deleted',
|
||||
'phpDoc/' => 'deleted:xe',
|
||||
'tools/' => 'deleted:xe',
|
||||
|
||||
// Deleted lang.xml
|
||||
'common/lang/lang.xml' => 'deleted:xmllang',
|
||||
'layouts/xedition/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/addon/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/admin/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/advanced_mailer/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/autoinstall/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/board/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/comment/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/communication/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/counter/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/document/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/editor/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/editor/skins/ckeditor/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/file/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/importer/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/install/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/integration_search/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/krzip/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/layout/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/member/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/menu/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/message/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/module/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/ncenterlite/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/page/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/point/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/poll/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/rss/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/session/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/spamfilter/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/syndication/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/trash/lang/lang.xml' => 'deleted:xmllang',
|
||||
'modules/widget/lang/lang.xml' => 'deleted:xmllang',
|
||||
|
||||
// Lowercase version of case-sensitive filenames
|
||||
'common/framework/cache.php' => 'case',
|
||||
'common/framework/calendar.php' => 'case',
|
||||
'common/framework/config.php' => 'case',
|
||||
'common/framework/db.php' => 'case',
|
||||
'common/framework/datetime.php' => 'case',
|
||||
'common/framework/debug.php' => 'case',
|
||||
'common/framework/exception.php' => 'case',
|
||||
'common/framework/formatter.php' => 'case',
|
||||
'common/framework/image.php' => 'case',
|
||||
'common/framework/korea.php' => 'case',
|
||||
'common/framework/lang.php' => 'case',
|
||||
'common/framework/mime.php' => 'case',
|
||||
'common/framework/mail.php' => 'case',
|
||||
'common/framework/pagination.php' => 'case',
|
||||
'common/framework/password.php' => 'case',
|
||||
'common/framework/push.php' => 'case',
|
||||
'common/framework/router.php' => 'case',
|
||||
'common/framework/sms.php' => 'case',
|
||||
'common/framework/security.php' => 'case',
|
||||
'common/framework/session.php' => 'case',
|
||||
'common/framework/storage.php' => 'case',
|
||||
'common/framework/timer.php' => 'case',
|
||||
'common/framework/ua.php' => 'case',
|
||||
'common/framework/url.php' => 'case',
|
||||
'common/framework/drivers/cacheinterface.php' => 'case',
|
||||
'common/framework/drivers/mailinterface.php' => 'case',
|
||||
'common/framework/drivers/pushinterface.php' => 'case',
|
||||
'common/framework/drivers/smsinterface.php' => 'case',
|
||||
'common/framework/exceptions/dberror.php' => 'case',
|
||||
'common/framework/exceptions/featuredisabled.php' => 'case',
|
||||
'common/framework/exceptions/invalidrequest.php' => 'case',
|
||||
'common/framework/exceptions/mustlogin.php' => 'case',
|
||||
'common/framework/exceptions/notpermitted.php' => 'case',
|
||||
'common/framework/exceptions/queryerror.php' => 'case',
|
||||
'common/framework/exceptions/securityviolation.php' => 'case',
|
||||
'common/framework/exceptions/targetnotfound.php' => 'case',
|
||||
'common/framework/filters/filecontentfilter.php' => 'case',
|
||||
'common/framework/filters/filenamefilter.php' => 'case',
|
||||
'common/framework/filters/htmlfilter.php' => 'case',
|
||||
'common/framework/filters/ipfilter.php' => 'case',
|
||||
'common/framework/filters/mediafilter.php' => 'case',
|
||||
'common/framework/helpers/confighelper.php' => 'case',
|
||||
'common/framework/helpers/dbhelper.php' => 'case',
|
||||
'common/framework/helpers/dbresulthelper.php' => 'case',
|
||||
'common/framework/helpers/dbstmthelper.php' => 'case',
|
||||
'common/framework/helpers/sessionhelper.php' => 'case',
|
||||
'common/framework/parsers/baseparser.php' => 'case',
|
||||
'common/framework/parsers/configparser.php' => 'case',
|
||||
'common/framework/parsers/dbqueryparser.php' => 'case',
|
||||
'common/framework/parsers/dbtableparser.php' => 'case',
|
||||
'common/framework/parsers/editorcomponentparser.php' => 'case',
|
||||
'common/framework/parsers/langparser.php' => 'case',
|
||||
'common/framework/parsers/moduleactionparser.php' => 'case',
|
||||
'common/framework/parsers/moduleinfoparser.php' => 'case',
|
||||
'common/framework/parsers/xmlrpcparser.php' => 'case',
|
||||
'common/framework/parsers/dbquery/columnread.php' => 'case',
|
||||
'common/framework/parsers/dbquery/columnwrite.php' => 'case',
|
||||
'common/framework/parsers/dbquery/condition.php' => 'case',
|
||||
'common/framework/parsers/dbquery/conditiongroup.php' => 'case',
|
||||
'common/framework/parsers/dbquery/emptystring.php' => 'case',
|
||||
'common/framework/parsers/dbquery/groupby.php' => 'case',
|
||||
'common/framework/parsers/dbquery/indexhint.php' => 'case',
|
||||
'common/framework/parsers/dbquery/navigation.php' => 'case',
|
||||
'common/framework/parsers/dbquery/nullvalue.php' => 'case',
|
||||
'common/framework/parsers/dbquery/orderby.php' => 'case',
|
||||
'common/framework/parsers/dbquery/query.php' => 'case',
|
||||
'common/framework/parsers/dbquery/table.php' => 'case',
|
||||
'common/framework/parsers/dbquery/variablebase.php' => 'case',
|
||||
'common/framework/parsers/dbtable/column.php' => 'case',
|
||||
'common/framework/parsers/dbtable/constraint.php' => 'case',
|
||||
'common/framework/parsers/dbtable/index.php' => 'case',
|
||||
'common/framework/parsers/dbtable/table.php' => 'case',
|
||||
'modules/member/controllers/device.php' => 'case',
|
||||
|
||||
// Vendor directory
|
||||
'vendor/' => 'moved:common/vendor/',
|
||||
];
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue