AbstractStep::getPhpExecutable()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * AppserverIo\Provisioning\Steps\AbstractStep
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2018 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/provisioning
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Provisioning\Steps;
22
23
use AppserverIo\Provisioning\Utils\ParamKeys;
24
use AppserverIo\Provisioning\Api\Node\StepNode;
25
use AppserverIo\Psr\Application\ApplicationInterface;
26
use AppserverIo\Psr\ApplicationServer\ServiceInterface;
27
use AppserverIo\Psr\ApplicationServer\ContextInterface;
28
use AppserverIo\Psr\ApplicationServer\Configuration\DatasourceConfigurationInterface;
29
30
/**
31
 * Abstract base class for a step implementation.
32
 *
33
 * @author    Tim Wagner <[email protected]>
34
 * @copyright 2018 TechDivision GmbH <[email protected]>
35
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
36
 * @link      https://github.com/appserver-io/provisioning
37
 * @link      http://www.appserver.io
38
 */
39
abstract class AbstractStep extends \Thread implements StepInterface
40
{
41
42
    /**
43
     * The maximum number of retries.
44
     *
45
     * @var integer
46
     */
47
    const MAX_RETRIES = 0;
48
49
    /**
50
     * The provisioning service.
51
     *
52
     * @var \AppserverIo\Provisioning\Api\ProvisioningServiceInterface
53
     */
54
    protected $service;
55
56
    /**
57
     * The step node with the configuration data for this step.
58
     *
59
     * @var \AppserverIo\Provisioning\Api\Node\StepNode
60
     */
61
    protected $stepNode;
62
63
    /**
64
     * The datasource node found in the provisioning configuration.
65
     *
66
     * @var \AppserverIo\Psr\ApplicationServer\Configuration\DatasourceConfigurationInterface
67
     */
68
    protected $datasourceNode;
69
70
    /**
71
     * The initial context.
72
     *
73
     * @var \AppserverIo\Psr\ApplicationServer\ContextInterface
74
     */
75
    protected $initialContext;
76
77
    /**
78
     * The absolute path to the appserver PHP executable.
79
     *
80
     * @var string
81
     */
82
    protected $phpExecutable;
83
84
    /**
85
     * The absolute path to the applications folder.
86
     *
87
     * @var string
88
     */
89
    protected $webappPath;
90
91
    /**
92
     * The application instance.
93
     *
94
     * @var \AppserverIo\Psr\Application\ApplicationInterface
95
     */
96
    protected $application;
97
98
    /**
99
     * Injects the provisioning service.
100
     *
101
     * @param \AppserverIo\Psr\ApplicationServer\ServiceInterface $service The provisioning service
102
     *
103
     * @return void
104
     */
105
    public function injectService(ServiceInterface $service)
106
    {
107
        $this->service = $service;
0 ignored issues
show
Documentation Bug introduced by
$service is of type AppserverIo\Psr\ApplicationServer\ServiceInterface, but the property $service was declared to be of type AppserverIo\Provisioning...sioningServiceInterface. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
108
    }
109
110
    /**
111
     * Injects the step node with the configuration data for this step.
112
     *
113
     * @param \AppserverIo\Provisioning\Api\Node\StepNode $stepNode The step node data
114
     *
115
     * @return void
116
     */
117
    public function injectStepNode(StepNode $stepNode)
118
    {
119
        $this->stepNode = $stepNode;
120
    }
121
122
    /**
123
     * Injects the datasource node found in the provisioning configuration.
124
     *
125
     * @param \AppserverIo\Psr\ApplicationServer\Configuration\DatasourceConfigurationInterface $datasourceNode The datasource node data
126
     *
127
     * @return void
128
     */
129
    public function injectDatasourceNode(DatasourceConfigurationInterface $datasourceNode)
130
    {
131
        $this->datasourceNode = $datasourceNode;
132
    }
133
134
    /**
135
     * Injects the absolute path to the appservers PHP executable.
136
     *
137
     * @param string $phpExecutable The absolute path to the appservers PHP executable
138
     *
139
     * @return void
140
     */
141
    public function injectPhpExecutable($phpExecutable)
142
    {
143
        $this->phpExecutable = $phpExecutable;
144
    }
145
146
    /**
147
     * Injects the absolute path to the applications folder.
148
     *
149
     * @param string $webappPath The absolute path to applications folder
150
     *
151
     * @return void
152
     */
153
    public function injectWebappPath($webappPath)
154
    {
155
        $this->webappPath = $webappPath;
156
    }
157
158
    /**
159
     * Injects the initial context.
160
     *
161
     * @param \AppserverIo\Psr\ApplicationServer\ContextInterface $initialContext The initial context instance
162
     *
163
     * @return void
164
     */
165
    public function injectInitialContext(ContextInterface $initialContext)
166
    {
167
        $this->initialContext = $initialContext;
168
    }
169
170
    /**
171
     * Injects the application instance.
172
     *
173
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
174
     *
175
     * @return void
176
     */
177
    public function injectApplication(ApplicationInterface $application)
178
    {
179
        $this->application = $application;
180
    }
181
182
    /**
183
     * Returns the provisioning service.
184
     *
185
     * @return \AppserverIo\Provisioning\Api\ProvisioningServiceInterface The provisioning service
186
     */
187
    protected function getService()
188
    {
189
        return $this->service;
190
    }
191
192
    /**
193
     * Returns the step node data.
194
     *
195
     * @return \AppserverIo\Provisioning\Api\Node\StepNode The step node data
196
     */
197
    protected function getStepNode()
198
    {
199
        return $this->stepNode;
200
    }
201
202
    /**
203
     * Returns the datasource node found in the provisioning configuration.
204
     *
205
     * @return \AppserverIo\Psr\ApplicationServer\Configuration\DatasourceConfigurationInterface The datasource node data
206
     */
207
    protected function getDatasourceNode()
208
    {
209
        return $this->datasourceNode;
210
    }
211
212
    /**
213
     * Returns the initial context instance.
214
     *
215
     * @return \AppserverIo\Psr\ApplicationServer\ContextInterface The initial context
216
     */
217
    protected function getInitialContext()
218
    {
219
        return $this->initialContext;
220
    }
221
222
    /**
223
     * Returns the absolute path to the appservers PHP executable.
224
     *
225
     * @return string The absolute path to the appservers PHP executable
226
     */
227
    protected function getPhpExecutable()
228
    {
229
        return $this->phpExecutable;
230
    }
231
232
    /**
233
     * Returns the absolute path to the applications folder.
234
     *
235
     * @return string The applications folder
236
     */
237
    protected function getWebappPath()
238
    {
239
        return $this->webappPath;
240
    }
241
242
    /**
243
     * Returns the application instance.
244
     *
245
     * @return \AppserverIo\Psr\Application\ApplicationInterface The application instance
246
     */
247
    protected function getApplication()
248
    {
249
        return $this->application;
250
    }
251
252
    /**
253
     * Will return the name of the application
254
     *
255
     * @return string
256
     */
257
    protected function getAppName()
258
    {
259
        return $this->getApplication()->getName();
260
    }
261
262
    /**
263
     * Will return the name of the application environment
264
     *
265
     * @return string
266
     */
267
    protected function getAppEnvironment()
268
    {
269
        return $this->getApplication()->getEnvironmentName();
0 ignored issues
show
Bug introduced by
The method getEnvironmentName() does not exist on AppserverIo\Psr\Application\ApplicationInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

269
        return $this->getApplication()->/** @scrutinizer ignore-call */ getEnvironmentName();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
270
    }
271
272
    /**
273
     * Return's the container instance the application is bound to.
274
     *
275
     * @return \AppserverIo\Psr\ApplicationServer\ContainerInterface The container instance
276
     */
277
    protected function getContainer()
278
    {
279
        return $this->getApplication()->getContainer();
0 ignored issues
show
Bug introduced by
The method getContainer() does not exist on AppserverIo\Psr\Application\ApplicationInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

279
        return $this->getApplication()->/** @scrutinizer ignore-call */ getContainer();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
280
    }
281
282
    /**
283
     * Return's the container configuration instance.
284
     *
285
     * @return \AppserverIo\Psr\ApplicationServer\Configuration\ContainerConfigurationInterface The container configuration
286
     */
287
    protected function getContainerNode()
288
    {
289
        return $this->getContainer()->getContainerNode();
290
    }
291
292
    /**
293
     * Return's the system properties.
294
     *
295
     * @return \AppserverIo\Properties\PropertiesInterface The system properties
296
     */
297
    protected function getSystemProperties()
298
    {
299
        return $this->getApplication()->getSystemProperties();
0 ignored issues
show
Bug introduced by
The method getSystemProperties() does not exist on AppserverIo\Psr\Application\ApplicationInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

299
        return $this->getApplication()->/** @scrutinizer ignore-call */ getSystemProperties();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
300
    }
301
302
    /**
303
     * Return's the maximum number of retries.
304
     *
305
     * @return integer The maximum number
306
     */
307
    protected function getMaxRetries()
308
    {
309
310
        // try to load the number of maximum retries from the step configuration
311
        $maxRetries = $this->getStepNode()->getParam(ParamKeys::MAX_RETRIES);
312
313
        // return the number of maximum retries
314
        return $maxRetries ? $maxRetries : AbstractStep::MAX_RETRIES;
315
    }
316
317
    /**
318
     * Logs the start of the provisioning.
319
     *
320
     * @return void
321
     */
322
    protected function logStart()
323
    {
324
        \info(
0 ignored issues
show
Bug introduced by
The function info was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

324
        /** @scrutinizer ignore-call */ 
325
        \info(
Loading history...
325
            sprintf(
326
                'Now start to execute provisioning step %s for application %s (env %s)',
327
                $this->getStepNode()->getType(),
328
                $this->getAppName(),
329
                $this->getAppEnvironment()
330
            )
331
        );
332
    }
333
334
    /**
335
     * Logs the retry of the provisioning.
336
     *
337
     * @param integer $retry         The retry number
338
     * @param string  $failureReason The reason the last try failed
339
     *
340
     * @return void
341
     */
342
    protected function logRetry($retry, $failureReason)
343
    {
344
        \info(
0 ignored issues
show
Bug introduced by
The function info was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

344
        /** @scrutinizer ignore-call */ 
345
        \info(
Loading history...
345
            sprintf(
346
                'Provisioning step %s of application %s (env %s) failed %d (of %d) times with message "%s"',
347
                $this->getStepNode()->getType(),
348
                $this->getAppName(),
349
                $this->getAppEnvironment(),
350
                $retry,
351
                AbstractStep::MAX_RETRIES,
352
                $failureReason
353
            )
354
        );
355
    }
356
357
    /**
358
     * Logs the success of the provisioning.
359
     *
360
     * @return void
361
     */
362
    protected function logSuccess()
363
    {
364
        \info(
0 ignored issues
show
Bug introduced by
The function info was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

364
        /** @scrutinizer ignore-call */ 
365
        \info(
Loading history...
365
            sprintf(
366
                'Successfully executed provisioning step %s of application %s (env %s)',
367
                $this->getStepNode()->getType(),
368
                $this->getAppName(),
369
                $this->getAppEnvironment()
370
            )
371
        );
372
    }
373
374
    /**
375
     * Return's the param with the passed name.
376
     *
377
     * @param string $name The name of the param to return
378
     *
379
     * @return mixed The param value
380
     */
381
    protected function getParam($name)
382
    {
383
        return $this->getStepNode()->getParam($name);
384
    }
385
386
    /**
387
     * Executes the steps functionality in a separate context.
388
     *
389
     * @return void
390
     */
391
    public function run()
392
    {
393
394
        // register the default autoloader
395
        require SERVER_AUTOLOADER;
0 ignored issues
show
Bug introduced by
The constant AppserverIo\Provisioning\Steps\SERVER_AUTOLOADER was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
396
397
        // register shutdown handler
398
        register_shutdown_function(array(&$this, "shutdown"));
399
400
        // synchronize the application instance and register the class loaders
401
        $application = $this->getApplication();
402
        $application->registerClassLoaders();
0 ignored issues
show
Bug introduced by
The method registerClassLoaders() does not exist on AppserverIo\Psr\Application\ApplicationInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

402
        $application->/** @scrutinizer ignore-call */ 
403
                      registerClassLoaders();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
403
404
        // register the applications annotation registries
405
        $application->registerAnnotationRegistries();
0 ignored issues
show
Bug introduced by
The method registerAnnotationRegistries() does not exist on AppserverIo\Psr\Application\ApplicationInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

405
        $application->/** @scrutinizer ignore-call */ 
406
                      registerAnnotationRegistries();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
406
407
        // add the application instance to the environment
408
        $application->registerEnvironment();
0 ignored issues
show
Bug introduced by
The method registerEnvironment() does not exist on AppserverIo\Psr\Application\ApplicationInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

408
        $application->/** @scrutinizer ignore-call */ 
409
                      registerEnvironment();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
409
410
        // initialize retry flag and counter
411
        $retry = true;
412
        $retryCount = 0;
413
414
        // log a message that provisioning starts
415
        $this->logStart();
416
417
        do {
418
            try {
419
                // run the actual provisioning
420
                $this->execute();
421
422
                // log a message that provisioning has been successfull
423
                $this->logSuccess();
424
425
                // don't retry, because step has been successful
426
                $retry = false;
427
            } catch (\Exception $e) {
428
                // raise the retry count
429
                $retryCount++;
430
                // query whether or not we've reached the maximum retry count
431
                if ($retryCount < $this->getMaxRetries()) {
432
                    // sleep for an increasing number of seconds
433
                    sleep($retryCount + 1);
434
                    // debug log the exception
435
                    $this->logRetry($retryCount, $e->getMessage());
436
                } else {
437
                    // log a message and stop retrying
438
                    \error($e);
0 ignored issues
show
Bug introduced by
The function error was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

438
                    /** @scrutinizer ignore-call */ 
439
                    \error($e);
Loading history...
439
                    $retry = false;
440
                }
441
            }
442
        } while ($retry);
443
    }
444
445
    /**
446
     * Shutdown function to log unexpected errors.
447
     *
448
     * @return void
449
     * @see http://php.net/register_shutdown_function
450
     */
451
    public function shutdown()
452
    {
453
        // check if there was a fatal error caused shutdown
454
        if ($lastError = error_get_last()) {
455
            // initialize error type and message
456
            $type = 0;
457
            $message = '';
458
            // extract the last error values
459
            extract($lastError);
460
            // query whether we've a fatal/user error
461
            if ($type === E_ERROR || $type === E_USER_ERROR) {
462
                $this->getInitialContext()->getSystemLogger()->critical($message);
463
            }
464
        }
465
    }
466
}
467