HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/inzigd.komma.pro/app/Komma/Shop/TranslationInstallationController.php
<?php
namespace App\Komma\Shop;
use Illuminate\Console\Command;

/**
 * Class InstallationController
 * @package App\Komma\Shop
 */
class TranslationInstallationController
{
    /**
     * @var $translationsFolder string A folder where locale folders (ex: en, nl as iso2) are located wherein translations files can be found
     */
    private $translationsFolder;

    /**
     * @var $laravelsTranslationsFolder string The folder to the lang resource folder. Usually this is resources/lang
     */
    private $laravelsTranslationsFolder;

    public function __construct()
    {
        $this->translationsFolder = __DIR__.DIRECTORY_SEPARATOR.'Translations'.DIRECTORY_SEPARATOR;
        $this->laravelsTranslationsFolder = resource_path('lang');
        $this->laravelsTranslationsFolder = $this->laravelsTranslationsFolder.DIRECTORY_SEPARATOR;
    }

    /**
     * Installs the shop translations to resources\lang folders depending on the folders in the shops Translations folder
     * @param Command $command
     * @param bool $installViaCopy
     */
    public function translations(Command $command, $installViaCopy = false)
    {
        $folders = $this->getShopTranslationFolders();
        $command->info("Detected the following shop translation folders: ".implode(", ", $folders));

        //Create the folder in Laravel's lang resource folder if it does not exists
        $this->createLanguageFoldersForLaravel($folders, $command);

        //Get the files from the iso2 folders and create files that include them in Laravel's language resource directory (Pretty much like symbolic linking)
        $installation = $this->getInstallation($folders, $command);

        $command->info("Installing the shop translation files...");
        //Install the translations
        foreach($installation as $relativeFile)
        {
            $dirnameToCheck = dirname($this->laravelsTranslationsFolder.$relativeFile);
            if(file_exists($dirnameToCheck) === false) {
                mkdir($dirnameToCheck, 0777, true);
            }

            if($installViaCopy) {
                //Install by copy
                if (!copy($this->translationsFolder . $relativeFile,
                    $this->laravelsTranslationsFolder . $relativeFile)) {
                    throw new \RuntimeException("Could not install language file '" . $relativeFile . "' to '" . $this->laravelsTranslationsFolder . $relativeFile . "'. Check directory permissions first");
                }
            } else {
                //Install by requiring
                file_put_contents($this->laravelsTranslationsFolder . $relativeFile, [
                    '<?php' . PHP_EOL,
                    'return require("' . $this->translationsFolder . $relativeFile . '");' . PHP_EOL . PHP_EOL
                ]);
            }
        }
        $command->info("Installed the shop translation files!");
    }

    /**
     * Builds and returns an array that represents the installation that needs to be done or undone.
     * For example if you give it the folder Translations (next to this file) it will return for example an array like this:
     * ["en/shop/shop.sidebar.php", "nl/shop/shop.sidebar.php"]
     *
     * @param array $shopTranslationFolders An array containing folder names from the shop Translations folder.
     * @param Command $command The artisan command. Used for logging
     * @return array
     */
    public function getInstallation(array $shopTranslationFolders, Command $command): array
    {
        $translationFilesCount = 0;
        $isoFolderCount = 0;
        $destinationsAndSourceFiles = []; //The keys are the destination folders. Values are numeric arrays that contain absolute paths to files that will be put in the destination folders
        foreach($shopTranslationFolders as $iso2Folder)
        {
//            $destinationsAndSourceFiles[$this->laravelsTranslationsFolder.DIRECTORY_SEPARATOR.$iso2Folder] = [];

            $translationFoldersAndFiles = $this->scanDirRecursivelyAndReturnPhpFiles(__DIR__.DIRECTORY_SEPARATOR.'Translations'.DIRECTORY_SEPARATOR.$iso2Folder);

            foreach($translationFoldersAndFiles as $translationFoldersAndFile)
            {
                //Skip if folder is the current folder (.) or the parent folder (..)
                if($translationFoldersAndFile == '.' || $translationFoldersAndFile == '..') continue;

                if(!is_dir($this->translationsFolder.DIRECTORY_SEPARATOR.$translationFoldersAndFile)) {
//                    $destinationsAndSourceFiles[$this->laravelsTranslationsFolder.DIRECTORY_SEPARATOR.$iso2Folder][] = $translationFoldersAndFile;
                    $destinationsAndSourceFiles[] = $iso2Folder.DIRECTORY_SEPARATOR.$translationFoldersAndFile;
                    $translationFilesCount++;
                }
            }

            $isoFolderCount++;
        }
        if($command) $command->info("Detected ".$translationFilesCount." shop translation file(s) in ".$isoFolderCount." shop translation language (iso2) folder(s)");

        return $destinationsAndSourceFiles;
    }

    /**
     * Returns all file paths that are below a certain directory. Relative to the root directory
     *
     * @param $root string The directory in which we start to search recursively for files
     * @param $startRoot string The root directory that the search was started in. Internally used. Must not be used by humans
     * @param array $files internal carrier variable. Humans must not use this variable
     * @return array
     */
    private function scanDirRecursivelyAndReturnPhpFiles($root, $startRoot = null, &$files = []):array
    {
        if($startRoot == null) $startRoot = $root;

        if (is_file($root) || !is_dir($root)) {
            if(is_file($root) && pathinfo($root, PATHINFO_EXTENSION) == 'php')
                $files[] = str_replace($startRoot.DIRECTORY_SEPARATOR, '', $root);
            return $files;
        }

        // starts the scan
        $dirsAndFiles = scandir($root);
        foreach ($dirsAndFiles as $dirOrFile) {
            if ($dirOrFile == '.' || $dirOrFile == '..') {
                continue; // skip . and ..
            }

            $path = $root . '/' . $dirOrFile;
            $this->scanDirRecursivelyAndReturnPhpFiles($path, $startRoot, $files);
        }

        return $files;
    }

    /**
     * Returns an array of strings containing the names of the folders in the shop's translations folder
     *
     * @return string[]
     */
    private function getShopTranslationFolders(): array
    {
        $translationFoldersAndFiles = scandir(__DIR__.DIRECTORY_SEPARATOR.'Translations'.DIRECTORY_SEPARATOR, SCANDIR_SORT_ASCENDING);
        $folders = [];
        foreach($translationFoldersAndFiles as $translationFoldersAndFile)
        {
            //Skip if folder is the current folder (.) or the parent folder (..)
            if($translationFoldersAndFile == '.' || $translationFoldersAndFile == '..') continue;

            //Add
            if(is_dir($this->translationsFolder.DIRECTORY_SEPARATOR.$translationFoldersAndFile)) {
                $folders[] = $translationFoldersAndFile;
            }
        }

        return $folders;
    }

    /**
     * Receives an array containing names of folders that should exist in laravels lang resource folder.
     *
     * @param array $languageFolderNames
     * @param Command $command The artisan command. Used to log progress
     */
    private function createLanguageFoldersForLaravel(array $languageFolderNames, Command $command = null): void
    {
        foreach($languageFolderNames as $iso2Folder)
        {
            $currentIso2ResourceFolder = $this->laravelsTranslationsFolder.DIRECTORY_SEPARATOR.$iso2Folder;
            if(!file_exists($currentIso2ResourceFolder))
                if(!mkdir($currentIso2ResourceFolder, 0777, true)) {
                    throw new \RuntimeException("The iso2 language resource folder '".$currentIso2ResourceFolder."' could not be created and therefore the '".$iso2Folder."' shop translation could not be installed");
                } else {
                    if($command) $command->info("Shop language folder '".$currentIso2ResourceFolder."' created in laravels lang resource folder because it did not exist: '".$this->laravelsTranslationsFolder."'");
                };
        }
    }

    /**
     * Uninstalls shop translations
     * @param Command $command
     */
    public function translationsUninstall(Command $command)
    {
        $folders = $this->getShopTranslationFolders();
        $command->info("Detected the following shop translation folders: ".implode(", ", $folders));

        //Create the folder in Laravel's lang resource folder if it does not exists
        $this->createLanguageFoldersForLaravel($folders, $command);

        //Get the files from the iso2 folders and delete files that include them in Laravel's language resource directory (Pretty much like symbolic linking)
        $installation = $this->getInstallation($folders, $command);

        $command->info("Deleting the shop translation files...");
        //delete the translations

        foreach($installation as $relativeFile)
        {
            if(file_exists($this->laravelsTranslationsFolder.$relativeFile) && !unlink($this->laravelsTranslationsFolder.$relativeFile))
                throw new \RuntimeException("Installation (partially) aborted. Could not uninstall translation file: ".$this->laravelsTranslationsFolder.$relativeFile);
        }

        foreach ($installation as $relativeFile)
        {
            $dir = dirname($this->laravelsTranslationsFolder.$relativeFile);
            $this->forceRmDir($dir);
            if(file_exists($dir))
                throw new \RuntimeException("Installation (partially) aborted. Could not delete directory: ".$dir.'. Try to delete it yourself and uninstall again.');
        }
        $command->info("Deleted the shop translation files!");
    }

    /**
     * Removes the specifies directory after deleting all items in it
     *
     * @param $dir
     */
    function forceRmDir($dir) {
        if (is_dir($dir)) {
            $objects = scandir($dir);
            foreach ($objects as $object) {
                if ($object != "." && $object != "..") {
                    if (filetype($dir."/".$object) == "dir") $this->forceRmDir($dir."/".$object); else unlink($dir."/".$object);
                }
            }
            reset($objects);
            rmdir($dir);
        }
    }
}