* @link https://TheTempusProject.com * @license https://opensource.org/licenses/MIT [MIT LICENSE] */ namespace TheTempusProject\Controllers\Admin; use TheTempusProject\Classes\Forms as TTPForms; use TheTempusProject\Houdini\Classes\Views; use TheTempusProject\Houdini\Classes\Issues; use TheTempusProject\Houdini\Classes\Navigation; use TheTempusProject\Houdini\Classes\Components; use TheTempusProject\Houdini\Classes\Forms; use TheTempusProject\Classes\AdminController; use TheTempusProject\Models\Token; use TheTempusProject\Bedrock\Functions\Input; use TheTempusProject\Bedrock\Functions\Check; use TheTempusProject\Hermes\Functions\Redirect; use TheTempusProject\Bedrock\Functions\Session; use TheTempusProject\Hermes\Functions\Route as Routes; use TheTempusProject\Bedrock\Functions\Upload; use RecursiveIteratorIterator; use RecursiveDirectoryIterator; use FilesystemIterator; class Images extends AdminController { private $directories = [ APP_ROOT_DIRECTORY . 'images', APP_ROOT_DIRECTORY . 'app/images', APP_ROOT_DIRECTORY . 'app/plugins' ]; private $excludedDirectories = [ '.', '..', 'vendor', 'docker', 'logs', 'gitlab', 'uploads', 'config', ]; public function upload() { if ( Input::exists( 'submit' ) ) { $route = ''; $destination = ''; if ( !TTPForms::check( 'addImage' ) ) { Issues::add( 'error', [ 'There was an error with your image upload.' => Check::userErrors() ] ); } else { $folder = Input::post( 'folderSelect' ) . DIRECTORY_SEPARATOR; // dv( $folder ); $upload = Upload::image( 'uploadImage', $folder ); if ( $upload ) { $route = str_replace( APP_ROOT_DIRECTORY, '', $folder ); $destination = $route . Upload::last(); Issues::add( 'success', 'Image uploaded.' ); } else { Issues::add( 'error', [ 'There was an error with your image upload.' => Check::userErrors() ] ); } } } $folders = $this->getDirectoriesRecursive( APP_ROOT_DIRECTORY ); $folderHtml = $this->generateFolderHtml( $folders ); Components::set( 'FOLDER_SELECT_ROOT', APP_ROOT_DIRECTORY ); Components::set( 'FOLDER_SELECT', Views::simpleView( 'forms.folderSelect', $folderHtml ) ); Views::view( 'admin.images.upload' ); } private function getFolderObject( $folder, $subdirs = '' ) { $names = explode( DIRECTORY_SEPARATOR, $folder ); $folderName = array_pop( $names ); $out = [ 'folderName' => $folderName, 'location' => $folder, 'subdirs' => $subdirs, ]; if ( ! empty( $subdirs ) ) { $out['folderexpand'] = ''; } else { $out['folderexpand'] = ''; } return (object) $out; } private function generateFolderHtml( $folders ) { $rows = []; foreach ( $folders as $top => $sub ) { $object = $this->getFolderObject( $top ); if ( $top == $sub ) { $html = ''; } else { $children = $this->generateFolderHtml( $sub ); Components::set( 'parentfolderName', $object->folderName ); $html = Views::simpleView( 'forms.folderSelectParent', $children ); Components::set( 'parentfolderName', '' ); } $rows[] = $this->getFolderObject( $top, $html ); } return $rows; } private function getDirectoriesRecursive( $directory ) { $dirs = []; $directory = rtrim( $directory, DIRECTORY_SEPARATOR ); $directory = $directory. DIRECTORY_SEPARATOR; $files = scandir( $directory ); $filteredFiles = array_values( array_diff( $files, $this->excludedDirectories ) ); foreach ( $filteredFiles as $key => $filename ) { $long_name = $directory . $filename; $is_dir = ( ( strpos( $filename, '.' ) === false ) && ( is_dir( $long_name ) === true ) ); if ( $is_dir ) { $recursive_dirs = $this->getDirectoriesRecursive( $long_name ); if ( empty( $recursive_dirs ) ) { $recursive_dirs = $long_name; } $dirs[$long_name] = $recursive_dirs; } } return $dirs; } public function __construct() { parent::__construct(); self::$title = 'Admin - Images'; } public function create() { if ( Input::exists( 'submit' ) ) { if ( !TTPForms::check( 'addImage' ) ) { Issues::add( 'error', [ 'There was an error with your image.' => Check::userErrors() ] ); } if ( Input::exists( 'folder' ) ) { $folder = Input::post('folder'); } else { // IMAGE_DIRECTORY $folder = UPLOAD_DIRECTORY . App::$activeUser->username . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR; } $upload = Upload::image( 'upload', $folder ); if ( $upload ) { $route = str_replace( APP_ROOT_DIRECTORY, '', $folder ); $out = $route . Upload::last(); } else { Debug::error( 'There was an error with your upload.'); Issues::add( 'error', [ 'There was an error with your upload.' => Check::userErrors() ] ); } // if ( self::$token->create( // Input::post( 'name' ), // Input::post( 'notes' ), // Input::post( 'token_type' ) // ) ) { // Session::flash( 'success', 'Token Created' ); // Redirect::to( 'admin/images' ); // } } Views::view( 'admin.images.create' ); } public function delete() { if ( self::$token->delete( [ $id ] ) ) { Session::flash( 'success', 'Token deleted.' ); } Redirect::to( 'admin/images' ); } public function rename() { if ( ! Input::exists( 'fileLocation' ) ) { Session::flash( 'warning', 'Unknown image.' ); Redirect::to( 'admin/images' ); } Components::set( 'filelocation', Input::get( 'fileLocation' ) ); if ( Input::exists( 'submit' ) ) { if ( !TTPForms::check( 'renameIImage' ) ) { Issues::add( 'error', [ 'There was an error renaming the image.' => Check::userErrors() ] ); } else { $result = $this->renameFile( Input::post( 'filelocation' ), Input::post( 'newname' ) ); if ( ! empty( $result ) ) { Session::flash( 'success', 'Image has been renamed.' ); Redirect::to( 'admin/images' ); } else { Issues::add( 'error', [ 'There was an error with the install.' => $this->installer->getErrors() ] ); } } } return Views::view( 'admin.images.rename' ); } public function index() { return Views::view( 'admin.images.list.combined', $this->getAllImageDetails() ); } public function view() { if ( Input::exists( 'fileLocation' ) ) { return Views::view( 'admin.images.view', $this->getImageByLocation( Input::get( 'fileLocation' ) ) ); } return $this->index(); } private function getAllImages() { $files = []; foreach ($this->directories as $dir) { if ($dir === 'app/plugins') { $pluginDirs = glob($dir . '/*', GLOB_ONLYDIR); foreach ($pluginDirs as $pluginDir) { $imageDir = $pluginDir . '/images'; if (is_dir($imageDir)) { $files = array_merge($files, $this->scanDirectoryRecursively($imageDir)); } } } else { $files = array_merge($files, $this->scanDirectory($dir)); } } return $files; } private function scanDirectory($path) { return glob($path . '/*.{jpg,jpeg,png,gif,webp}', GLOB_BRACE) ?: []; } private function scanDirectoryRecursively($path) { $files = []; $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)); foreach ($iterator as $file) { if (preg_match('/\.(jpg|jpeg|png|gif|webp)$/i', $file->getFilename())) { $files[] = $file->getPathname(); } } return $files; } private function getAllImageDetails() { $images = []; $files = $this->getAllImages(); foreach ( $files as $file ) { $images[] = $this->getImageByLocation( $file ); } return $images; } private function getImageByLocation( $location ) { $realPath = realpath( $location ); return (object) [ 'filename' => basename( $location ), 'extension' => pathinfo( $location , PATHINFO_EXTENSION), 'fileSize' => $this->formatFileSize(filesize( $location )), 'location' => $realPath, 'locationSafe' => urlencode( $realPath ), 'url' => Routes::getAddress() . str_replace( APP_ROOT_DIRECTORY, '', $realPath ), 'folder' => dirname( $location ) ]; } private function formatFileSize($size) { $units = ['B', 'KB', 'MB', 'GB', 'TB']; $i = 0; while ($size >= 1024 && $i < count($units) - 1) { $size /= 1024; $i++; } return round($size, 2) . ' ' . $units[$i]; } private function renameFile( $currentLocation, $newFilename ) { // Ensure the file exists if (!file_exists($currentLocation)) { throw new \Exception("File does not exist: $currentLocation"); } // Extract directory and current extension $directory = dirname($currentLocation); $currentExtension = pathinfo($currentLocation, PATHINFO_EXTENSION); $newExtension = pathinfo($newFilename, PATHINFO_EXTENSION); // Ensure the file extension has not changed if (strcasecmp($currentExtension, $newExtension) !== 0) { throw new \Exception("File extension cannot be changed."); } // Construct the new file path $newLocation = $directory . DIRECTORY_SEPARATOR . $newFilename; // Ensure the new file name does not already exist if (file_exists($newLocation)) { throw new \Exception("A file with the new name already exists: $newFilename"); } // Attempt to rename the file if (!rename($currentLocation, $newLocation)) { throw new \Exception("Failed to rename file."); } return true; } }