Continued:
[core.git] / framework / main / classes / resolver / command / class_BaseCommandResolver.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Resolver\Command;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
7 use Org\Mxchange\CoreFramework\Command\Commandable;
8 use Org\Mxchange\CoreFramework\Command\InvalidCommandException;
9 use Org\Mxchange\CoreFramework\Factory\Object\ObjectFactory;
10 use Org\Mxchange\CoreFramework\Generic\FrameworkInterface;
11 use Org\Mxchange\CoreFramework\Request\Requestable;
12 use Org\Mxchange\CoreFramework\Resolver\BaseResolver;
13 use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils;
14
15 // Import SPL stuff
16 use \InvalidArgumentException;
17 use \UnexpectedValueException;
18
19 /**
20  * A generic command resolver class
21  *
22  * @author              Roland Haeder <webmaster@shipsimu.org>
23  * @version             0.0.0
24  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2023 Core Developer Team
25  * @license             GNU GPL 3.0 or any newer version
26  * @link                http://www.shipsimu.org
27  *
28  * This program is free software: you can redistribute it and/or modify
29  * it under the terms of the GNU General Public License as published by
30  * the Free Software Foundation, either version 3 of the License, or
31  * (at your option) any later version.
32  *
33  * This program is distributed in the hope that it will be useful,
34  * but WITHOUT ANY WARRANTY; without even the implied warranty of
35  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36  * GNU General Public License for more details.
37  *
38  * You should have received a copy of the GNU General Public License
39  * along with this program. If not, see <http://www.gnu.org/licenses/>.
40  */
41 abstract class BaseCommandResolver extends BaseResolver {
42         /**
43          * Command name
44          */
45         private $commandName = '';
46
47         /**
48          * Protected constructor
49          *
50          * @param       $className      Name of the class
51          * @return      void
52          */
53         protected function __construct (string $className) {
54                 // Call parent constructor
55                 parent::__construct($className);
56         }
57
58         /**
59          * Setter for command name
60          *
61          * @param       $commandName    Last validated command name
62          * @return      void
63          */
64         protected final function setCommandName (string $commandName) {
65                 $this->commandName = $commandName;
66         }
67
68         /**
69          * Getter for command name
70          *
71          * @return      $commandName    Last validated command name
72          */
73         public final function getCommandName () {
74                 return $this->commandName;
75         }
76
77         /**
78          * "Loads" a given command and instances it if not yet cached
79          *
80          * @param       $commandName                            A command name we shall look for
81          * @return      $commandInstance                        A loaded command instance
82          * @throws      InvalidCommandException         Thrown if even the default
83          *                                                                              command class is missing (bad!)
84          */
85         protected function loadCommand (string $commandName) {
86                 // Init command instance
87                 $commandInstance = NULL;
88
89                 // Create class name
90                 $className = sprintf(
91                         '%s\%s%sCommand',
92                         $this->getNamespace(),
93                         $this->getCapitalizedClassPrefix(),
94                         StringUtils::convertToClassName($commandName)
95                 );
96
97                 // Create command class name
98                 $this->setClassName($className);
99
100                 // Is this class loaded?
101                 if (!class_exists($this->getClassName())) {
102                         // Class not found, so throw an exception
103                         throw new InvalidCommandException(array($this, $commandName), self::EXCEPTION_INVALID_COMMAND);
104                 }
105
106                 // Initiate the command
107                 $commandInstance = ObjectFactory::createObjectByName($this->getClassName(), [$this]);
108
109                 // Return the result
110                 return $commandInstance;
111         }
112
113         /**
114          * Returns an command instance for a given request class or null if
115          * it was not found
116          *
117          * @param       $requestInstance        An instance of a Requestable class
118          * @return      $commandInstance        An instance of the resolved command
119          * @throws      InvalidCommandException         Thrown if $commandName is invalid
120          * @throws      UnexpectedValueException        Thrown if $commandInstance is an invalid instance
121          */
122         public function resolveCommandByRequest (Requestable $requestInstance) {
123                 // Init variables
124                 $commandName = $requestInstance->getRequestElement('command');
125                 $commandType = FrameworkBootstrap::getRequestTypeFromSystem();
126                 $commandInstance = NULL;
127
128                 // Is the command empty? Then fall back to default command
129                 if (empty($commandName)) {
130                         // Fall back to default command
131                         $commandName = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry(sprintf('default_%s_command', $commandType));
132                 }
133
134                 // Check if command is valid
135                 if ($this->isCommandValid($this->getNamespace(), $commandName) === false) {
136                         // This command is invalid!
137                         throw new InvalidCommandException(array($this, $commandName), self::EXCEPTION_INVALID_COMMAND);
138                 }
139
140                 // Get the command
141                 $commandInstance = $this->loadCommand($commandName);
142
143                 // And validate it
144                 if ((!is_object($commandInstance)) || (!$commandInstance instanceof Commandable)) {
145                         // This command has an invalid instance!
146                         throw new UnexpectedValueException(sprintf('commandInstance for commandName=%s is not object (%s) or does not implement Commandable.', $commandName, gettype($commandInstance)), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE);
147                 }
148
149                 // Set last command
150                 $this->setResolvedInstance($commandInstance);
151
152                 // Init template engine
153                 $commandInstance->initTemplateEngine($commandType);
154
155                 // Return the resolved command instance
156                 return $commandInstance;
157         }
158
159         /**
160          * Resolves the command by its direct name and returns an instance of its class
161          *
162          * @param       $namespace                      Namespace to look in
163          * @param       $commandName            The direct command name we shall resolve
164          * @return      $commandInstance        An instance of the command class
165          * @throws      InvalidCommandException         Thrown if $commandName is invalid
166          */
167         public function resolveCommand (string $namespace, string $commandName) {
168                 // Is a action set?
169                 if (empty($namespace)) {
170                         // Then thrown an exception here
171                         throw new InvalidArgumentException('Parameter "namespace" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
172                 } elseif (empty($commandName)) {
173                         // Then thrown an exception here
174                         throw new InvalidArgumentException('Parameter "commandName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
175                 }
176
177                 // Initiate the instance variable
178                 $commandInstance = NULL;
179                 $commandType = FrameworkBootstrap::getRequestTypeFromSystem();
180
181                 // Is the command empty? Then fall back to default command
182                 if (empty($commandName)) {
183                         // Init default command
184                         $commandName = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry(sprintf('default_%s_command', $commandType));
185                 }
186
187                 // Check if command is valid
188                 if ($this->isCommandValid($namespace, $commandName) === false) {
189                         // This command is invalid!
190                         throw new InvalidCommandException(array($this, $commandName), self::EXCEPTION_INVALID_COMMAND);
191                 }
192
193                 // Get the command
194                 $commandInstance = $this->loadCommand($commandName);
195
196                 // Init template engine
197                 $commandInstance->initTemplateEngine($commandType);
198
199                 // Return the instance
200                 return $commandInstance;
201         }
202
203         /**
204          * Checks whether the given command is valid
205          *
206          * @param       $namespace              Namespace to look in
207          * @param       $commandName    The default command we shall execute
208          * @return      $isValid                Whether the given command is valid
209          * @throws      InvalidArgumentException        Thrown if given command is not set
210          */
211         protected function isCommandValid (string $namespace, string $commandName) {
212                 // Is namespace and command name set?
213                 if (empty($namespace)) {
214                         // Then thrown an exception here
215                         throw new InvalidArgumentException('Parameter "namespace" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
216                 } elseif (empty($commandName)) {
217                         // Then thrown an exception here
218                         throw new InvalidArgumentException('Parameter "commandName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
219                 }
220
221                 // By default nothing shall be valid
222                 $isValid = false;
223
224                 // Create the full class name
225                 $className = sprintf(
226                         '%s\%s%sCommand',
227                         $namespace,
228                         $this->getCapitalizedClassPrefix(),
229                         StringUtils::convertToClassName($commandName)
230                 );
231
232                 // Now, let us create the full name of the command class
233                 $this->setClassName($className);
234
235                 // Is this class already loaded?
236                 if (class_exists($this->getClassName())) {
237                         // This class does exist. :-)
238                         $isValid = true;
239                 }
240
241                 // Set command name
242                 $this->setCommandName($commandName);
243
244                 // Return the result
245                 return $isValid;
246         }
247
248 }