/** * Includes all necessary JS code for admin editing of CmsBlocks. * * @return void */ public function includeCmsAdminAssets() { $script = 'var Cms = {AdminWidgetControllers: {}};'; $this->Html->scriptBlock($script, ['block' => true]); $this->Html->script('Cms.app/lib/AdminWidgetController.js', ['block' => true]); $availableWidgets = WidgetManager::getAvailableWidgets(); $adminControllers = []; $folder = new Folder(); foreach ($availableWidgets as $widgetIdentifier) { $widget = WidgetFactory::identifierFactory($widgetIdentifier); $webrootPath = $widget->getWebrootPath(); if (!is_dir($webrootPath)) { continue; } $folder->cd($webrootPath . 'js/'); $jsFiles = $folder->read(); if (empty($jsFiles[1])) { continue; } foreach ($jsFiles[1] as $filename) { if (strpos($filename, 'AdminWidgetController.js') !== false) { $adminControllers[] = '/cms/widget/' . $widgetIdentifier . '/js/' . $filename; } } } $this->Html->script($adminControllers, ['block' => true]); }
/** * Find the paths to all the installed shell templates in the app. * * Bake templates are directories under `Template/Bake` path. * They are listed in this order: app -> plugin -> default * * @return array Array of bake templates that are installed. */ protected function _findTemplates() { $paths = App::path('Template'); $plugins = Plugin::loaded(); foreach ($plugins as $plugin) { $paths[] = Plugin::classPath($plugin) . 'Template' . DS; } $core = current(App::core('Template')); $Folder = new Folder($core . 'Bake' . DS . 'default'); $contents = $Folder->read(); $templateFolders = $contents[0]; $paths[] = $core; foreach ($paths as $i => $path) { $paths[$i] = rtrim($path, DS) . DS; } $this->_io->verbose('Found the following bake templates:'); $templates = []; foreach ($paths as $path) { $Folder = new Folder($path . 'Bake', false); $contents = $Folder->read(); $subDirs = $contents[0]; foreach ($subDirs as $dir) { $Folder = new Folder($path . 'Bake' . DS . $dir); $contents = $Folder->read(); $subDirs = $contents[0]; if (array_intersect($contents[0], $templateFolders)) { $templateDir = $path . 'Bake' . DS . $dir . DS; $templates[$dir] = $templateDir; $this->_io->verbose(sprintf("- %s -> %s", $dir, $templateDir)); } } } return $templates; }
/** * Scan folder by path. * * @param null $path * @return void|\Cake\Network\Response */ public function scanFolder($path = null) { if (!$path) { $path = WWW_ROOT; } $Folder = new Folder(); $_path = $this->request->query('path') ? $this->request->query('path') : $path; if (!is_dir($_path)) { $Folder->create($_path); } $_path = realpath($_path) . DS; $regex = '/^' . preg_quote(realpath($path), '/') . '/'; if (preg_match($regex, $_path) == false) { $this->_controller->Flash->error(__d('file_manager', 'Path {0} is restricted', $_path)); return $this->_controller->redirect(['action' => 'browse']); } $blacklist = ['.git', '.svn', '.CVS']; $regex = '/(' . preg_quote(implode('|', $blacklist), '.') . ')/'; if (in_array(basename($_path), $blacklist) || preg_match($regex, $_path)) { $this->_controller->Flash->error(__d('file_manager', 'Path %s is restricted', $_path)); return $this->_controller->redirect(['action' => 'browse']); } $Folder->path = $_path; $content = $Folder->read(); $this->_controller->set('path', $_path); $this->_controller->set('content', $content); }
private function createFileAndDeleteTmp($identifier, $filename) { $tmpFolder = new Folder($this->tmpChunkDir($identifier)); $chunkFiles = $tmpFolder->read(true, true, true)[1]; if ($this->createFileFromChunks($chunkFiles, $this->uploadFolder . DIRECTORY_SEPARATOR . $filename) && $this->deleteTmpFolder) { $tmpFolder->delete(); } }
/** * Register all available themes in the composer classloader and load them as plugin. * * @return void */ public static function loadThemes() { $themesFolder = new Folder(ROOT . DS . 'themes'); $themes = $themesFolder->read()[0]; $loader = (require ROOT . DS . 'vendor' . DS . 'autoload.php'); foreach ($themes as $theme) { $loader->addPsr4('WasabiTheme\\' . $theme . '\\', [$themesFolder->path . DS . $theme . DS . 'src']); Plugin::load('WasabiTheme/' . $theme, ['path' => $themesFolder->path . DS . $theme . DS, 'bootstrap' => true, 'routes' => false]); } }
/** * Adds all the files in a directory to the test suite. Does not recursive through directories. * * @param string $directory The directory to add tests from. * @return void */ public function addTestDirectory($directory = '.') { $Folder = new Folder($directory); list(, $files) = $Folder->read(true, true, true); foreach ($files as $file) { if (substr($file, -4) === '.php') { $this->addTestFile($file); } } }
/** * Initialize all available modules. * * @return void */ public static function init() { foreach (self::$_modulePaths as $path) { $folder = new Folder($path); $modulePaths = $folder->read(true, false, true)[0]; foreach ($modulePaths as $modulePath) { self::_initializeModule($modulePath); } } self::$_initialized = true; }
/** * Gets a list of counties flags suitable for select boxes. * * @return array */ public static function flagsList() { $flags = []; $Folder = new Folder(Plugin::path('Locale') . 'webroot/img/flags/'); foreach ($Folder->read()[1] as $icon) { $value = $icon; $label = str_replace_last('.gif', '', $icon); $flags[$value] = $label; } asort($flags); return $flags; }
public function getFilelistFromControllerFolderAndIdFolder($controller, $id) { $filefolder = '../webroot' . DS . 'files'; $folder = new Folder($filefolder . DS . $controller . DS . $id); $files = $folder->read(); $list = []; $list[''] = ''; foreach ($files[1] as $f) { $list[$f] = $f; } return $list; }
/** * Scan a directory for .php files and return the class names that * should be within them. * * @param string $dir The directory to read. * @return array The list of shell classnames based on conventions. */ protected function _scanDir($dir) { $dir = new Folder($dir); $contents = $dir->read(true, true); if (empty($contents[1])) { return []; } $shells = []; foreach ($contents[1] as $file) { if (substr($file, -4) !== '.php') { continue; } $shells[] = substr($file, 0, -4); } return $shells; }
public static function widgets() { if (!empty(self::$_widgets)) { return self::$_widgets; } foreach (self::paths() as $path) { if (!is_dir($path)) { continue; } $folder = new Folder($path); list($widgets) = $folder->read(); foreach ($widgets as $widget) { self::$_widgets[$widget] = $path . $widget . DS; } } return self::$_widgets; }
/** * First step of the installation process. * * User must select the language they want to use for the installation process. * * @return void */ public function language() { $languages = ['en_US' => ['url' => '/installer/startup/requirements?locale=en_US', 'welcome' => 'Welcome to QuickAppsCMS', 'action' => 'Click here to install in English']]; $Folder = new Folder(Plugin::classPath('Installer') . 'Locale'); foreach ($Folder->read(false, true, true)[0] as $path) { $code = basename($path); $file = $path . '/installer.po'; if (is_readable($file)) { I18n::locale($code); // trick for __d() $languages[$code] = ['url' => "/installer/startup/requirements?locale={$code}", 'welcome' => __d('installer', 'Welcome to QuickAppsCMS'), 'action' => __d('installer', 'Click here to install in English')]; } } I18n::locale('en_US'); $this->title('Welcome to QuickAppsCMS'); $this->set('languages', $languages); $this->_step(); }
/** * Loads and registers plugin's namespace and loads its event listeners classes. * * This is used to allow plugins being installed to respond to events before * they are integrated to the system. Events such as `beforeInstall`, * `afterInstall`, etc. * * @param string $plugin Name of the plugin for which attach listeners * @param string $path Path to plugin's root directory (which contains "src") * @throws \Cake\Error\FatalErrorException On illegal usage of this method */ protected function _attachListeners($plugin, $path) { $path = normalizePath("{$path}/"); $eventsPath = normalizePath("{$path}/src/Event/"); if (is_readable($eventsPath) && is_dir($eventsPath)) { $EventManager = EventManager::instance(); $eventsFolder = new Folder($eventsPath); Plugin::load($plugin, ['autoload' => true, 'bootstrap' => false, 'routes' => false, 'path' => $path, 'classBase' => 'src', 'ignoreMissing' => true]); foreach ($eventsFolder->read(false, false, true)[1] as $classPath) { $className = preg_replace('/\\.php$/i', '', basename($classPath)); $fullClassName = implode('\\', [$plugin, 'Event', $className]); if (class_exists($fullClassName)) { $handler = new $fullClassName(); $this->_listeners[] = $handler; $EventManager->on($handler); } } } }
public function read($path) { $dir = new Folder($path); $read = $dir->read(); $result = []; foreach ($read[0] as $folder) { $info = new Folder($path . DS . $folder); $reference = Router::fullBaseUrl() . '/' . $this->toRelative($path . '/' . $folder); $data = ['name' => $folder, 'type' => 'folder', 'path' => $path . DS . $folder, 'reference' => $reference, 'extension' => 'folder', 'size' => $info->dirsize()]; $result[] = $data; } foreach ($read[1] as $file) { $info = new File($path . DS . $file, false); $reference = Router::fullBaseUrl() . '/' . $this->toRelative($path . '/' . $file); $data = ['name' => $info->info()['basename'], 'type' => 'file', 'path' => $path, 'reference' => $reference, 'extension' => $info->info()['extension'], 'size' => $info->info()['filesize']]; $result[] = $data; } return $result; }
protected function _icons() { $useCache = true; if (!empty($this->request->params['named']['reset'])) { $useCache = false; } if ($useCache && ($iconNames = Cache::read('country_icon_names')) !== false) { $this->Flash->info('Cache Used'); return $iconNames; } $handle = new Folder($this->imageFolder); $icons = $handle->read(true, true); $iconNames = []; foreach ($icons[1] as $icon) { # only use files (not folders) $iconNames[] = strtoupper(extractPathInfo('filename', $icon)); } Cache::write('country_icon_names', $iconNames); return $iconNames; }
/** * Returns an array with avilable widget identifiers * * @return array */ public static function getAvailableWidgets() { $widgets = []; $config = Configure::read('Cms.Widgets.availableWidgets'); if (is_array($config)) { return $config; } $namespace = Configure::read('App.namespace'); $widgetPaths = App::path('Widget'); foreach ($widgetPaths as $widgetPath) { $appWidgetsFolder = new Folder($widgetPath); $contents = $appWidgetsFolder->read(true); foreach ($contents[0] as $folderName) { $widgetIdentifier = "{$namespace}.{$folderName}"; if (self::widgetExists($widgetIdentifier)) { $widgets[] = $widgetIdentifier; } } } $plugins = Plugin::loaded(); foreach ($plugins as $plugin) { $widgetsPath = Plugin::classPath($plugin) . 'Widget/'; if (!is_dir($widgetsPath)) { continue; } $pluginWidgetsFolder = new Folder($widgetsPath); $contents = $pluginWidgetsFolder->read(true); foreach ($contents[0] as $folderName) { $widgetIdentifier = "{$plugin}.{$folderName}"; if (self::widgetExists($widgetIdentifier)) { $widgets[] = $widgetIdentifier; } } } $excludedWidgets = Configure::read('Cms.Widgets.excludedWidgets'); $widgets = array_filter($widgets, function ($widgetIdentifier) use($excludedWidgets) { return !in_array($widgetIdentifier, $excludedWidgets); }); return $widgets; }
public function handleChunk() { $file = $this->request->file(); $identifier = $this->_resumableParam('identifier'); $filename = $this->_resumableParam('filename'); $chunkNumber = $this->_resumableParam('chunkNumber'); $chunkSize = $this->_resumableParam('chunkSize'); $totalSize = $this->_resumableParam('totalSize'); if (!$this->isChunkUploaded($identifier, $filename, $chunkNumber)) { $chunkFile = $this->tmpChunkDir($identifier) . DIRECTORY_SEPARATOR . $this->tmpChunkFilename($filename, $chunkNumber); $this->moveUploadedFile($file['tmp_name'], $chunkFile); } if ($this->isFileUploadComplete($filename, $identifier, $chunkSize, $totalSize)) { $tmpFolder = new Folder($this->tmpChunkDir($identifier)); $chunkFiles = $tmpFolder->read(true, true, true)[1]; $this->createFileFromChunks($chunkFiles, $this->uploadFolder . DIRECTORY_SEPARATOR . $filename); if ($this->deleteTmpFolder) { $tmpFolder->delete(); } } return $this->response->header(200); }
/** * main method * * @param string $tempDir an other directory to clear of all folders and files, if desired * @return void */ public function main($tempDir = null) { if (empty($tempDir)) { $tempDir = Configure::read('Attachments.tmpUploadsPath'); } if (!Folder::isAbsolute($tempDir)) { $this->out('The path must be absolute, "' . $tempDir . '" given.'); exit; } $Folder = new Folder(); if ($Folder->cd($tempDir) === false) { $this->out('Path "' . $tempDir . '" doesn\'t seem to exist.'); exit; } $dir = new Folder($tempDir); $folders = $dir->read(); $files = $dir->findRecursive(); $deletedFiles = 0; $deletedFolders = 0; $this->out('Found ' . count($folders[0]) . ' folders and ' . count($files) . ' files'); foreach ($files as $filePath) { $file = new File($filePath); // only delete if last change is longer than 24 hours ago if ($file->lastChange() < time() - 24 * 60 * 60 && $file->delete()) { $deletedFiles++; } $file->close(); } foreach ($folders[0] as $folderName) { $folder = new Folder($dir->pwd() . $folderName); // only delete if folder is empty if ($folder->dirsize() === 0 && $folder->delete()) { $deletedFolders++; } } $this->out('Deleted ' . $deletedFolders . ' folders and ' . $deletedFiles . ' files.'); }
/** * Include necessary cms assets. This has to be called after the page has been rendered. * Best place is in the layout. * * @param array $options Options for the Html->script() calls * @return void|string */ public function includeCmsAssets(array $options = []) { if ($this->_cmsAssetsIncluded) { return; } $options = Hash::merge(['block' => true], $options); $out = ''; $out .= $this->Html->scriptBlock('var Cms = {WidgetControllers: {}};', $options); $out .= $this->Html->script('Cms.app/lib/WidgetController.js', $options); $folder = new Folder(); $controllers = []; $jsonData = []; foreach (WidgetManager::getRegistry() as $uniqueId => $widget) { $webrootPath = $widget->getWebrootPath(); if (!is_dir($webrootPath)) { continue; } $jsonData[$uniqueId] = ['identifier' => $widget->getFullIdentifier(), 'blockId' => $widget->getCmsBlock()->id, 'jsonData' => $widget->getJsonData()]; $folder->cd($webrootPath . 'js/'); $jsFiles = $folder->read(); if (empty($jsFiles[1])) { continue; } foreach ($jsFiles[1] as $filename) { if (strpos($filename, 'WidgetController.js') !== false && strpos($filename, 'AdminWidgetController.js') === false) { $controllers[] = '/cms/widget/' . $widget->getIdentifier() . '/js/' . $filename; } } } $this->FrontendBridge->setFrontendData('Cms', ['widgets' => $jsonData]); $out .= $this->Html->script($controllers, $options); $this->_cmsAssetsIncluded = true; if (!$options['block']) { return $out; } }
/** * Find and create valid modules. * * @return void */ public function create() { $folder = new Folder($this->_path); list($folders, $files) = $folder->read(); foreach ($folders as $dir) { $dir = trim($dir); $data = $this->_getData($folder, $dir); if ($data['class'] !== null && $data['config'] !== null) { $xml = Xml::build($data['config']); $attr = $this->setAttributes($xml); if ($this->isValid($attr)) { $name = $attr->get('name'); if (!isset(self::$__loaded[$name])) { $alias = Inflector::underscore($name); $class = $this->getClassName($name); /** @noinspection PhpIncludeInspection */ require_once $data['class']; if (class_exists($class)) { $module = new $class($name); if (!$module instanceof ModuleAbstract) { throw new \InvalidArgumentException(__d('union_dev', 'The class "%s" in file "%s" must extend \\Union\\Modules\\Module\\ModuleAbstract', $class)); } $module->setAttr($attr); self::$__loaded[$name] = $module; self::$__modMap[$alias] = $name; } } } } } }
/** * Get the possible classes for a given type. * * @param string $namespace The namespace fragment to look for classes in. * @return array */ protected function _getClassOptions($namespace) { $classes = []; $base = APP; if ($this->plugin) { $base = Plugin::classPath($this->plugin); } $path = $base . str_replace('\\', DS, $namespace); $folder = new Folder($path); list(, $files) = $folder->read(); foreach ($files as $file) { $classes[] = str_replace('.php', '', $file); } return $classes; }
/** * Extracts the current ZIP package. * * @param string $file Full path to the ZIP package * @return bool True on success */ protected function _unzip($file) { include_once Plugin::classPath('Installer') . 'Lib/pclzip.lib.php'; $File = new File($file); $to = normalizePath($File->folder()->pwd() . '/' . $File->name() . '_unzip/'); if (is_readable($to)) { $folder = new Folder($to); $folder->delete(); } else { $folder = new Folder($to, true); } $PclZip = new \PclZip($file); $PclZip->delete(PCLZIP_OPT_BY_EREG, '/__MACOSX/'); $PclZip->delete(PCLZIP_OPT_BY_EREG, '/\\.DS_Store$/'); if ($PclZip->extract(PCLZIP_OPT_PATH, $to)) { list($directories, $files) = $folder->read(false, false, true); if (count($directories) === 1 && empty($files)) { $container = new Folder($directories[0]); $container->move(['to' => $to]); } $this->_workingDir = $to; return true; } $this->err(__d('installer', 'Unzip error: {0}', [$PclZip->errorInfo(true)])); return false; }
/** * Look through the plugin directory and load the plugins into memory. * * This function pulls a list of all folders and files in the plugins directory and then searches for any matches to * the plugin format {system-id-name}\{system-id-name}.php and if it finds a match it will load the headers of the * plugin into a list of all available plugins. */ protected function findPlugins() { // create a Folder object to the plugins $directory = new Folder(self::$plugins_dir); // grab the plugins folder directory contents $plugins = $directory->read(); // loop through the folders in the directory and check for plugins foreach ($plugins[0] as $plugin) { $system_name = self::getSystemName($plugin); if (file_exists(self::$plugins_dir . $system_name . DS . $system_name . ".php")) { self::$plugins_list[$system_name]['system_name'] = $system_name; $this->getPluginHeaders($system_name); } } }
/** * testFolderReadWithHiddenFiles method * * @return void */ public function testFolderReadWithHiddenFiles() { $this->skipIf(!is_writable(TMP), 'Cant test Folder::read with hidden files unless the tmp folder is writable.'); $path = TMP . 'tests' . DS; $Folder = new Folder($path . 'folder_tree_hidden', true, 0777); mkdir($Folder->path . DS . '.svn'); mkdir($Folder->path . DS . 'some_folder'); touch($Folder->path . DS . 'not_hidden.txt'); touch($Folder->path . DS . '.hidden.txt'); $expected = [['some_folder'], ['not_hidden.txt']]; $result = $Folder->read(true, true); $this->assertEquals($expected, $result); $expected = [['.svn', 'some_folder'], ['.hidden.txt', 'not_hidden.txt']]; $result = $Folder->read(true); $this->assertEquals($expected, $result); }
/** * Retrieve all controller names + paths for the app src. * * @return array */ public function getControllersForApp() { $controllers = []; $ctrlFolder = new Folder(); /** @var Folder $ctrlFolder */ $ctrlFolder->cd(ROOT . DS . 'src' . DS . 'Controller'); if (!empty($ctrlFolder)) { $files = $ctrlFolder->find('.*Controller\\.php$'); $subLength = strlen('Controller.php'); foreach ($files as $f) { $filename = basename($f); if ($filename === 'AppController.php') { continue; } $ctrlName = substr($filename, 0, strlen($filename) - $subLength); $controllers[] = ['name' => $ctrlName, 'path' => $ctrlFolder->path . DS . $f]; } $subFolders = $ctrlFolder->read(true, false, true)[0]; foreach ($subFolders as $subFolder) { $ctrlFolder->cd($subFolder); $files = $ctrlFolder->find('.*Controller\\.php$'); $subLength = strlen('Controller.php'); foreach ($files as $f) { $filename = basename($f); if ($filename === 'AppController.php') { continue; } $ctrlName = substr($filename, 0, strlen($filename) - $subLength); $controllers[] = ['name' => $ctrlName, 'path' => $ctrlFolder->path . DS . $f]; } } } return $controllers; }
/** * Create the final file from chunks */ private function createFileAndDeleteTmp($identifier, $filename) { $tmpFolder = new Folder($this->tmpChunkDir($identifier)); $chunkFiles = $tmpFolder->read(true, true, true)[1]; // if the user has set a custom filename if (null !== $this->filename) { $finalFilename = $this->createSafeFilename($this->filename, $filename); } else { $finalFilename = $filename; } // replace filename reference by the final file $this->filepath = $this->uploadFolder . DIRECTORY_SEPARATOR . $finalFilename; $this->extension = $this->findExtension($this->filepath); if ($this->createFileFromChunks($chunkFiles, $this->filepath) && $this->deleteTmpFolder) { $tmpFolder->delete(); $this->uploadComplete = true; } }
/** * Checks whether connected database is empty or not. * * @param \Cake\Database\Connection $conn Database connection to use * @return bool True if database if empty and tables can be imported, false if * there are some existing tables */ public function isDbEmpty($conn) { $Folder = new Folder($this->config('schemaPath')); $existingSchemas = $conn->schemaCollection()->listTables(); $newSchemas = array_map(function ($item) { return Inflector::underscore(str_replace('Schema.php', '', $item)); }, $Folder->read()[1]); $result = !array_intersect($existingSchemas, $newSchemas); if (!$result) { $this->error(__d('installer', 'A previous installation of QuickAppsCMS already exists, please drop your database tables before continue.')); } return $result; }
protected function createFileAndDeleteTmp($identifier, $filepathname) { $tmpFolder = new Folder($this->tmpChunkDir($identifier)); $chunkFiles = $tmpFolder->read(true, true, true)[1]; if ($this->createFileFromChunks($chunkFiles, $filepathname) && $this->deleteTmpFolder) { $tmpFolder->delete(); } }
/** * Scan plugin directories and returns plugin names and their paths within file * system. We consider "plugin name" as the name of the container directory. * * Example output: * * ```php * [ * 'Users' => '/full/path/plugins/Users/', * 'ThemeManager' => '/full/path/plugins/ThemeManager/', * ... * 'MySuperPlugin' => '/full/path/plugins/MySuperPlugin/', * 'DarkGreenTheme' => '/full/path/plugins/DarkGreenTheme/', * ] * ``` * * If $ignoreThemes is set to true `DarkGreenTheme` will not be part of the * result. * * NOTE: All paths includes trailing slash. * * @param bool $ignoreThemes Whether include themes as well or not * @return array Associative array as `PluginName` => `/full/path/to/PluginName` */ public static function scan($ignoreThemes = false) { $cacheKey = "scan({$ignoreThemes})"; $cache = static::cache($cacheKey); if (!$cache) { $cache = []; $paths = App::path('Plugin'); $Folder = new Folder(); $Folder->sort = true; foreach ($paths as $path) { $Folder->cd($path); foreach ($Folder->read(true, true, true)[0] as $dir) { $name = basename($dir); $cache[$name] = normalizePath("{$dir}/"); } } // look for Cake plugins installed using Composer if (file_exists(VENDOR_INCLUDE_PATH . 'cakephp-plugins.php')) { $cakePlugins = (array) (include VENDOR_INCLUDE_PATH . 'cakephp-plugins.php'); if (!empty($cakePlugins['plugins'])) { $cache = Hash::merge($cakePlugins['plugins'], $cache); } } // filter, remove hidden folders and others foreach ($cache as $name => $path) { if (strpos($name, '.') === 0) { unset($cache[$name]); } elseif ($name == 'CMS') { unset($cache[$name]); } elseif ($ignoreThemes && str_ends_with($name, 'Theme')) { unset($cache[$name]); } } $cache = static::cache($cacheKey, $cache); } return $cache; }
/** * testDeleteOldFileOnSave * * @return void */ public function testDeleteOldFileOnSave() { $entity = $this->Image->newEntity(['foreign_key' => 'test-1', 'model' => 'Test', 'file' => ['name' => 'titus.jpg', 'size' => 332643, 'tmp_name' => Plugin::path('Burzum/FileStorage') . DS . 'tests' . DS . 'Fixture' . DS . 'File' . DS . 'titus.jpg', 'error' => 0]], ['accessibleFields' => ['*' => true]]); $this->Image->save($entity); $result = $this->Image->find()->where(['id' => $entity->id])->first(); // Get the old file path to assert late that it doesn't exist anymore $Folder = new Folder($this->testPath . $result['path']); $files = $Folder->read(); $oldFile = $result['path'] . $files[1][2]; $this->assertTrue(!empty($result) && is_a($result, '\\Cake\\ORM\\Entity')); $this->assertTrue(file_exists($this->testPath . $result['path'])); $secondEntity = $this->Image->newEntity(['foreign_key' => 'test-1', 'model' => 'Test', 'file' => ['name' => 'cake.icon.png', 'size' => 332643, 'tmp_name' => Plugin::path('Burzum/FileStorage') . DS . 'tests' . DS . 'Fixture' . DS . 'File' . DS . 'cake.icon.png', 'error' => 0], 'old_file_id' => $entity->id], ['accessibleFields' => ['*' => true]]); $this->Image->save($secondEntity); $result2 = $this->Image->find()->where(['id' => $secondEntity->id])->first(); $this->assertTrue(!empty($result) && is_a($result2, '\\Cake\\ORM\\Entity')); $this->assertFileExists($this->testPath . $result2['path']); // Assert that the old file was removed $this->assertFileNotExists($this->testPath . $oldFile); $this->assertNotEquals($result['path'], $result2['path']); $this->assertNotEquals($result['filename'], $result2['filename']); }