DbVersionInfo.php 4.46 KB
Newer Older
Ketan's avatar
Ketan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Framework\Module;

use Magento\Framework\Setup\ModuleDataSetupInterface;

/**
 * Class DbVersionInfo
 *
 */
class DbVersionInfo
{
    /**#@+
     * Constants defined for keys of version info array
     */
    const KEY_MODULE = 'module';
    const KEY_TYPE = 'type';
    const KEY_CURRENT = 'current';
    const KEY_REQUIRED = 'required';
    /**#@-*/

    /**#@-*/
    private $moduleList;

    /**
     * @var ResourceInterface
     */
    private $moduleResource;

    /**
     * @var array
     */
    private $dbVersionErrorsCache = null;

    /**
     * @param ModuleListInterface $moduleList
     * @param ResourceInterface $moduleResource
     */
    public function __construct(
        ModuleListInterface $moduleList,
        ResourceInterface $moduleResource
    ) {
        $this->moduleList = $moduleList;
        $this->moduleResource = $moduleResource;
    }

    /**
     * Check if DB schema is up to date
     *
     * @param string $moduleName
     * @return bool
     */
    public function isSchemaUpToDate($moduleName)
    {
        $dbVer = $this->moduleResource->getDbVersion($moduleName);
        return $this->isModuleVersionEqual($moduleName, $dbVer);
    }

    /**
     * @param string $moduleName
     * @return bool
     */
    public function isDataUpToDate($moduleName)
    {
        $dataVer = $this->moduleResource->getDataVersion($moduleName);
        return $this->isModuleVersionEqual($moduleName, $dataVer);
    }

    /**
     * Check if DB schema is up to date, version info if it is not.
     *
     * @param string $moduleName
     * @return string[] Contains current and needed version strings
     */
    private function getSchemaInfo($moduleName)
    {
        $dbVer = $this->moduleResource->getDbVersion($moduleName); // version saved in DB
        $module = $this->moduleList->getOne($moduleName);
        $configVer = $module['setup_version'];
        $dbVer = $dbVer ?: 'none';
        return [
            self::KEY_CURRENT => $dbVer,
            self::KEY_REQUIRED => $configVer,
            self::KEY_MODULE => $moduleName,
            self::KEY_TYPE => 'schema'
        ];
    }

    /**
     * Get array of errors if DB is out of date, return [] if DB is current.
     *
     * @return string[] Array of errors, each error contains module name, current version, required version,
     *                  and type (schema or data).  The array will be empty if all schema and data are current.
     */
    public function getDbVersionErrors()
    {
        if ($this->dbVersionErrorsCache === null) {
            $this->dbVersionErrorsCache = [];
            foreach ($this->moduleList->getNames() as $moduleName) {
                if (!$this->isSchemaUpToDate($moduleName)) {
                    $this->dbVersionErrorsCache[] = $this->getSchemaInfo($moduleName);
                }
                if (!$this->isDataUpToDate($moduleName)) {
                    $this->dbVersionErrorsCache[] = $this->getDataInfo($moduleName);
                }
            }
        }

        return $this->dbVersionErrorsCache;
    }

    /**
     * Get error data for an out-of-date schema or data.
     *
     * @param string $moduleName
     * @return string[]
     */
    private function getDataInfo($moduleName)
    {
        $dataVer = $this->moduleResource->getDataVersion($moduleName);
        $module = $this->moduleList->getOne($moduleName);
        $configVer = $module['setup_version'];
        $dataVer = $dataVer ?: 'none';
        return [
            self::KEY_CURRENT => $dataVer,
            self::KEY_REQUIRED => $configVer,
            self::KEY_MODULE => $moduleName,
            self::KEY_TYPE => 'data'
        ];
    }

    /**
     * Check if DB data is up to date
     *
     * @param string $moduleName
     * @param string|bool $version
     * @return bool
     */
    private function isModuleVersionEqual($moduleName, $version)
    {
        $module = $this->moduleList->getOne($moduleName);
        $configVer = isset($module['setup_version']) ? $module['setup_version'] : null;

        if (empty($configVer)) {
            /**
             * If setup_version was removed, this means that we want to ignore old scripts and do installation only
             * with declarative schema and data/schema patches
             */
            return true;
        }

        return version_compare($configVer, $version) === ModuleDataSetupInterface::VERSION_COMPARE_EQUAL;
    }
}