yii2

Форк
1
/
UnknownCommandException.php 
139 строк · 5.0 Кб
1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7

8
namespace yii\console;
9

10
use yii\console\controllers\HelpController;
11

12
/**
13
 * UnknownCommandException represents an exception caused by incorrect usage of a console command.
14
 *
15
 * @author Carsten Brandt <mail@cebe.cc>
16
 * @since 2.0.11
17
 */
18
class UnknownCommandException extends Exception
19
{
20
    /**
21
     * @var string the name of the command that could not be recognized.
22
     */
23
    public $command;
24

25
    /**
26
     * @var Application
27
     */
28
    protected $application;
29

30

31
    /**
32
     * Construct the exception.
33
     *
34
     * @param string $route the route of the command that could not be found.
35
     * @param Application $application the console application instance involved.
36
     * @param int $code the Exception code.
37
     * @param \Throwable|null $previous the previous exception used for the exception chaining.
38
     */
39
    public function __construct($route, $application, $code = 0, $previous = null)
40
    {
41
        $this->command = $route;
42
        $this->application = $application;
43
        parent::__construct("Unknown command \"$route\".", $code, $previous);
44
    }
45

46
    /**
47
     * @return string the user-friendly name of this exception
48
     */
49
    public function getName()
50
    {
51
        return 'Unknown command';
52
    }
53

54
    /**
55
     * Suggest alternative commands for [[$command]] based on string similarity.
56
     *
57
     * Alternatives are searched using the following steps:
58
     *
59
     * - suggest alternatives that begin with `$command`
60
     * - find typos by calculating the Levenshtein distance between the unknown command and all
61
     *   available commands. The Levenshtein distance is defined as the minimal number of
62
     *   characters you have to replace, insert or delete to transform str1 into str2.
63
     *
64
     * @see https://www.php.net/manual/en/function.levenshtein.php
65
     * @return array a list of suggested alternatives sorted by similarity.
66
     */
67
    public function getSuggestedAlternatives()
68
    {
69
        $help = $this->application->createController('help');
70
        if ($help === false || $this->command === '') {
71
            return [];
72
        }
73
        /** @var $helpController HelpController */
74
        list($helpController, $actionID) = $help;
75

76
        $availableActions = [];
77
        foreach ($helpController->getCommands() as $command) {
78
            $result = $this->application->createController($command);
79
            /** @var $controller Controller */
80
            list($controller, $actionID) = $result;
81
            if ($controller->createAction($controller->defaultAction) !== null) {
82
                // add the command itself (default action)
83
                $availableActions[] = $command;
84
            }
85

86
            // add all actions of this controller
87
            $actions = $helpController->getActions($controller);
88
            $prefix = $controller->getUniqueId();
89
            foreach ($actions as $action) {
90
                $availableActions[] = $prefix . '/' . $action;
91
            }
92
        }
93

94
        return $this->filterBySimilarity($availableActions, $this->command);
95
    }
96

97
    /**
98
     * Find suggest alternative commands based on string similarity.
99
     *
100
     * Alternatives are searched using the following steps:
101
     *
102
     * - suggest alternatives that begin with `$command`
103
     * - find typos by calculating the Levenshtein distance between the unknown command and all
104
     *   available commands. The Levenshtein distance is defined as the minimal number of
105
     *   characters you have to replace, insert or delete to transform str1 into str2.
106
     *
107
     * @see https://www.php.net/manual/en/function.levenshtein.php
108
     * @param array $actions available command names.
109
     * @param string $command the command to compare to.
110
     * @return array a list of suggested alternatives sorted by similarity.
111
     */
112
    private function filterBySimilarity($actions, $command)
113
    {
114
        $alternatives = [];
115

116
        // suggest alternatives that begin with $command first
117
        foreach ($actions as $action) {
118
            if (strpos($action, $command) === 0) {
119
                $alternatives[] = $action;
120
            }
121
        }
122

123
        // calculate the Levenshtein distance between the unknown command and all available commands.
124
        $distances = array_map(function ($action) use ($command) {
125
            $action = strlen($action) > 255 ? substr($action, 0, 255) : $action;
126
            $command = strlen($command) > 255 ? substr($command, 0, 255) : $command;
127
            return levenshtein($action, $command);
128
        }, array_combine($actions, $actions));
129

130
        // we assume a typo if the levensthein distance is no more than 3, i.e. 3 replacements needed
131
        $relevantTypos = array_filter($distances, function ($distance) {
132
            return $distance <= 3;
133
        });
134
        asort($relevantTypos);
135
        $alternatives = array_merge($alternatives, array_flip($relevantTypos));
136

137
        return array_unique($alternatives);
138
    }
139
}
140

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.