e107inc/e107

View on GitHub
.github/workflows/build-release/CoreImage.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
/**
 * e107 website system
 *
 * Copyright (C) 2008-2020 e107 Inc (e107.org)
 * Released under the terms and conditions of the
 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
 */

abstract class CoreImage
{
    const EXCLUDED_PATHS = [
        'install.php',
        'robots.txt'
    ];

    const EXCLUDED_PATHS_REMOVED = [
        ...self::EXCLUDED_PATHS,
        'e107_plugins/tagwords/',
        'e107_plugins/alt_auth/',
        'e107_plugins/alt_news/',
        'e107_plugins/calendar_menu/',
        'e107_plugins/content/',
        'e107_plugins/integrity_check/',
        'e107_plugins/linkspage/',
        'e107_plugins/newsletter/',
        'e107_plugins/online_extended_menu/',
        'e107_plugins/pdf/',
        'e107_plugins/tree_menu/',
        'e107_plugins/articles_menu/',
        'e107_plugins/backend_menu/',
        'e107_plugins/custom/',
        'e107_plugins/custom_pages/',
        'e107_plugins/fader_menu/',
        'e107_plugins/headlines_menu/',
        'e107_plugins/newforumposts_main/',
        'e107_plugins/newforumposts_menu/',
        'e107_plugins/review_menu/',
        'e107_plugins/ypslide_menu/',
        'e107_plugins/theme_layout/',
        'e107_themes/bootstrap4/',
        'e107_themes/landingzero/',
        'e107_themes/bootstrap/',
        'e107_themes/core/',
        'e107_themes/crahan/',
        'e107_themes/e107v4a/',
        'e107_themes/human_condition/',
        'e107_themes/interfectus/',
        'e107_themes/jayya/',
        'e107_themes/khatru/',
        'e107_themes/kubrick/',
        'e107_themes/lamb/',
        'e107_themes/leaf/',
        'e107_themes/newsroom/',
        'e107_themes/sebes/',
        'e107_themes/templates/',
        'e107_themes/vekna_blue/',
        'e107_themes/reline/',
        'e107_themes/clan/',
        'e107_themes/comfort/',
        'e107_themes/e107/',
        'e107_themes/fiblack3d/',
        'e107_themes/nordranious/',
        'e107_themes/phpbb/',
        'e107_themes/ranyart/',
        'e107_themes/smacks/',
        'e107_themes/soar/',
        'e107_themes/wan/',
        'e107_themes/xog/',
        'e107_themes/blue_patriot/',
        'e107_themes/comfortless/',
        'e107_themes/example/',
        'e107_themes/leap of faith/',
        'e107_themes/nagrunium/',
    ];

    protected function create_image($exportFolder, $tempFolder, $currentVersion)
    {
        echo("[Core-Image] Scanning Dir: " . $exportFolder . "\n");
        $this->generateCurrentChecksums($exportFolder, $currentVersion);

        echo("[Core-Image] Scanning Removed Files from Git" . "\n");
        $this->generateRemovedChecksums($tempFolder);
    }

    protected function generateCurrentChecksums($exportFolder, $currentVersion)
    {
        $absoluteBase = realpath($exportFolder);
        $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($exportFolder));

        /**
         * @var $file DirectoryIterator
         */
        foreach ($iterator as $file)
        {
            if ($file->isDir()) continue;

            $absolutePath = $file->getRealPath();
            $relativePath = preg_replace("/^" . preg_quote($absoluteBase . "/", "/") . "/", "", $absolutePath);

            if (empty($relativePath) || $relativePath == $absolutePath) continue;
            if ($this->isExcluded($relativePath, self::EXCLUDED_PATHS)) continue;

            $checksum = $this->checksumPath($absolutePath);
            $this->insertChecksumIntoDatabase($relativePath, $checksum, $currentVersion);
        }
    }

    protected function checksumPath($filename)
    {
        return $this->checksum(file_get_contents($filename));
    }

    protected function checksum($body)
    {
        return md5(str_replace(array(chr(13), chr(10)), '', $body));
    }

    abstract protected function insertChecksumIntoDatabase(&$relativePath, &$checksum, &$releaseVersion);

    protected function generateRemovedChecksums($tempFolder)
    {
        $tags = $this->getGitTags();
        $timeMachineFolder = $this->prepTimeMachine($tempFolder);
        $this->generateRemovedChecksumsFromTags($tags, $timeMachineFolder);
    }

    /**
     * @return array
     */
    protected function getGitTags()
    {
        $stdout = '';
        OsHelper::runValidated('git tag --list ' . escapeshellarg("v*"), $stdout);
        $tags = explode("\n", trim($stdout));
        $versions = [];
        foreach ($tags as $tag)
        {
            $versions[] = preg_replace("/^v/", "", $tag);
        }
        $tags = array_combine($tags, $versions);
        unset($versions);
        uasort($tags, function ($a, $b)
        {
            return -version_compare($a, $b);
        });
        $tags = array_filter($tags, function ($version)
        {
            return !preg_match("/[a-z]/i", $version);
        });
        return $tags;
    }

    /**
     * @param $tempFolder
     * @param $repoFolder
     * @return string
     */
    protected function prepTimeMachine($tempFolder)
    {
        $timeMachineFolder = $tempFolder . "/git_time_machine/";
        OsHelper::runValidated('mkdir -p ' . escapeshellarg($timeMachineFolder));
        OsHelper::runValidated('git rev-parse --show-toplevel', $repoFolder);
        $repoFolder = realpath(trim($repoFolder) . "/.git");
        OsHelper::runValidated(
            'cp -a ' .
            escapeshellarg($repoFolder) .
            ' ' .
            escapeshellarg($timeMachineFolder)
        );
        return $timeMachineFolder;
    }

    /**
     * @param array $tags
     * @param $timeMachineFolder
     */
    protected function generateRemovedChecksumsFromTags($tags, $timeMachineFolder)
    {
        foreach ($tags as $tag => $version)
        {
            $stdout = '';
            OsHelper::runValidated(
                'git --no-pager diff --no-renames --name-only --diff-filter D ' . escapeshellarg($tag),
                $stdout
            );
            $removedFiles = explode("\n", trim($stdout));
            OsHelper::runValidated(
                'git -C ' . escapeshellarg($timeMachineFolder) . ' ' .
                'checkout ' . escapeshellarg($tag)
            );
            foreach ($removedFiles as $removedFilePath)
            {
                if ($this->isExcluded($removedFilePath, self::EXCLUDED_PATHS_REMOVED)) continue;

                $checksum = $this->checksumPath($timeMachineFolder . '/' . $removedFilePath);
                $this->insertChecksumIntoDatabase($removedFilePath, $checksum, $version);
            }
        }

        OsHelper::runValidated('rm -rf ' . escapeshellarg($timeMachineFolder));
    }


    protected function generateStub()
    {
        $data = "<?php\n";
        $data .= "/*\n";
        $data .= "+ ----------------------------------------------------------------------------+\n";
        $data .= "|     e107 website system\n";
        $data .= "|\n";
        $data .= "|     Copyright (C) 2008-" . date("Y") . " e107 Inc. \n";
        $data .= "|     http://e107.org\n";
        //    $data .= "|     jalist@e107.org\n";
        $data .= "|\n";
        $data .= "|     Released under the terms and conditions of the\n";
        $data .= "|     GNU General Public License (http://gnu.org).\n";
        $data .= "|\n";
        $data .= "|     \$URL$\n";
        $data .= "|     \$Id$\n";
        $data .= "+----------------------------------------------------------------------------+\n";
        $data .= "*/\n\n";
        $data .= "if (!defined('e107_INIT')) { exit; }\n\n";

        return $data;
    }

    /**
     * Determines whether the provided relative path should make it into the generated integrity database
     * @param string $relativePath Relative path candidate
     * @param string[] $excludedPaths The list of paths to exclude
     * @return bool TRUE if the relative path should not be added to the integrity database; FALSE otherwise
     */
    protected function isExcluded($relativePath, $excludedPaths = self::EXCLUDED_PATHS)
    {
        $excludedFolders = array_filter($excludedPaths, function ($excludedPath)
        {
            $needle = '/';
            return substr($excludedPath, -strlen($needle)) === $needle;
        });
        foreach ($excludedFolders as $excludedFolder)
        {
            if (substr($relativePath, 0, strlen($excludedFolder)) === $excludedFolder) return true;
        }

        $excludedFiles = array_diff($excludedPaths, $excludedFolders);
        return in_array($relativePath, $excludedFiles);
    }
}