<commit_before><?php

declare(strict_types=1);

/*
 * This file is part of the ************************ package.
 * _____________                           _______________
 *  ______/     \__  _____  ____  ______  / /_  _________
 *   ____/ __   / / / / _ \/ __`\/ / __ \/ __ \/ __ \___
 *    __/ / /  / /_/ /  __/ /  \  / /_/ / / / / /_/ /__
 *      \_\ \_/\____/\___/_/   / / .___/_/ /_/ .___/
 *         \_\                /_/_/         /_/
 *
 * The PHP Framework For Code Poem As Free As Wind. <Query Yet Simple>
 * (c) 2010-2019 http://queryphp.com All rights reserved.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Leevel\Option\Console;

use InvalidArgumentException;
use Leevel\Console\Command;
use Leevel\Console\Option;
use Leevel\Kernel\IProject;
use Leevel\Option\Load;

/**
 * 配置缓存.
 *
 * @author <NAME> <<EMAIL>>
 *
 * @since 2018.05.06
 *
 * @version 1.0
 */
class Cache extends Command
{
    /**
     * 命令名字.
     *
     * @var string
     */
    protected $name = 'option:cache';

    /**
     * 命令行描述.
     *
     * @var string
     */
    protected $description = 'Merge all option file to a file.';

    /**
     * 响应命令.
     *
     * @param \Leevel\Kernel\IProject $project
     */
    public function handle(IProject $project): void
    {
        $this->line('Start to cache option.');

        $load = new Load($project->optionPath());
        $data = $load->loadData($project);

        $cachePath = $project->optionCachedPath();

        $this->writeCache($cachePath, $data);

        $this->info(sprintf('Option cache file %s cache successed.', $cachePath));
    }

    /**
     * 写入缓存.
     *
     * @param string $cachePath
     * @param array  $data
     */
    protected function writeCache(string $cachePath, array $data): void
    {
        $dirname = dirname($cachePath);

        if (!is_dir($dirname)) {
            if (is_dir(dirname($dirname)) && !is_writable(dirname($dirname))) {
                throw new InvalidArgumentException(
                    sprintf('Unable to create the %s directory.', $dirname)
                );
            }

            mkdir($dirname, 0777, true);
        }

        $content = '<?'.'php /* '.date('Y-m-d H:i:s').
            ' */ ?'.'>'.
            PHP_EOL.'<?'.'php return '.
            var_export($data, true).'; ?'.'>';

        if (!is_writable($dirname) ||
            !file_put_contents($cachePath, $content)) {
            throw new InvalidArgumentException(
                sprintf('Dir %s is not writeable.', $dirname)<commit_msg>refactor(option): add relative path for option cache file<commit_after><?php

declare(strict_types=1);

/*
 * This file is part of the ************************ package.
 * _____________                           _______________
 *  ______/     \__  _____  ____  ______  / /_  _________
 *   ____/ __   / / / / _ \/ __`\/ / __ \/ __ \/ __ \___
 *    __/ / /  / /_/ /  __/ /  \  / /_/ / / / / /_/ /__
 *      \_\ \_/\____/\___/_/   / / .___/_/ /_/ .___/
 *         \_\                /_/_/         /_/
 *
 * The PHP Framework For Code Poem As Free As Wind. <Query Yet Simple>
 * (c) 2010-2019 http://queryphp.com All rights reserved.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Leevel\Option\Console;

use InvalidArgumentException;
use Leevel\Console\Command;
use Leevel\Console\Option;
use Leevel\Kernel\IProject;
use Leevel\Option\Load;

/**
 * 配置缓存.
 *
 * @author <NAME> <<EMAIL>>
 *
 * @since 2018.05.06
 *
 * @version 1.0
 */
class Cache extends Command
{
    /**
     * 命令名字.
     *
     * @var string
     */
    protected $name = 'option:cache';

    /**
     * 命令行描述.
     *
     * @var string
     */
    protected $description = 'Merge all option file to a file.';

    /**
     * 基础路径.
     *
     * @var string
     */
    protected $basePath;

    /**
     * 响应命令.
     *
     * @param \Leevel\Kernel\IProject $project
     */
    public function handle(IProject $project): void
    {
        $this->line('Start to cache option.');

        $load = new Load($project->optionPath());
        $data = $load->loadData($project);

        $cachePath = $project->optionCachedPath();
        $this->basePath = $project->path();

        $this->writeCache($cachePath, $data);

        $this->info(sprintf('Option cache file %s cache successed.', $cachePath));
    }

    /**
     * 计算相对路径
     * 忽略未包含在基础路径中的缓存相对路径.
     *
     * @param string $cachePath
     *
     * @return int
     */
    protected function computeRelativePath(string $cachePath): int
    {
        if (false === strpos($cachePath, $this->basePath)) {
            return -1;
        }

        $relativePath = str_replace($this->basePath.'/', '', $cachePath);
        $relativePath = dirname($relativePath);

        return count(explode('/', $relativePath));
    }

    /**
     * 替换相对路径.
     *
     * @param string $data
     *
     * @return string
     */
    protected function replaceRelativePath(string $data): string
    {
        return str_replace("'".$this->basePath, '$baseDir.\'', $data);
    }

    /**
     * 写入缓存.
     *
     * @param string $cachePath
     * @param array  $data
     */
    protected function writeCache(string $cachePath, array $data): void
    {
        $dirname = dirname($cachePath);

        if (!is_dir($dirname)) {
            if (is_dir(dirname($dirname)) && !is_writable(dirname($dirname))) {
                throw new InvalidArgumentException(
                    sprintf('Unable to create the %s directory.', $dirname)
                );
            }

            mkdir($dirname, 0777, true);
        }

        $relativePathLevel = $this->computeRelativePath($cachePath);
        $isRelativePath = $relativePathLevel > -1;

        $content = '<?'.'php /* '.date('Y-m-d H:i:s').
            ' */ ?'.'>';

        if ($isRelativePath) {
            $content .= PHP_EOL.'<?'.'php $baseDir = dirname(__DIR__, '.$relativePathLevel.'); ?>';
        }

        $content .= PHP_EOL.'<?'.'php return '.
            var_export($data, true).'; ?'.'>';

        if ($isRelativePath) {
            $content = $this->replaceRelativePath($content);
        }

        if (!is_writable($dirname) ||
            !file_put_contents($cachePath, $content)) {
            throw new InvalidArgumentException(
                sprintf('Dir %s is not writeable.', $dirname)
{'fraction_non_alphanumeric': 0.16240369799691834, 'fraction_numerical': 0.007395993836671803, 'mean_word_length': 1.8506807202459377, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '506159', 'n_tokens_mistral': 2107, 'n_tokens_neox': 2053, 'n_words': 417}