Passed
Push — master ( 6f7339...89f27a )
by P.R.
02:14
created

PropertiesCommand::appendProperties()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 36
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 18
nc 9
nop 2
dl 0
loc 36
rs 8.8333
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Plaisio\Console\Kernel\Command;
5
6
use Plaisio\Console\Command\PlaisioCommand;
7
use Plaisio\Console\Helper\PlaisioXmlPathHelper;
8
use Plaisio\Console\Helper\TwoPhaseWrite;
9
use Plaisio\Console\Kernel\Helper\ClassHelper;
10
use Plaisio\Console\Kernel\Helper\PlaisioXmlQueryHelper;
11
use Plaisio\PlaisioKernel;
12
use SetBased\Exception\RuntimeException;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Output\OutputInterface;
15
16
/**
17
 * Command for adding a property to the kernel (i.e. class \Plaisio\Kernel\Nub).
18
 */
19
class PropertiesCommand extends PlaisioCommand
20
{
21
  //--------------------------------------------------------------------------------------------------------------------
22
  /**
23
   * @inheritdoc
24
   */
25
  protected function configure()
26
  {
27
    $this->setName('plaisio:kernel-properties')
28
         ->setDescription('Adds properties to the kernel');
29
  }
30
31
  //--------------------------------------------------------------------------------------------------------------------
32
  /**
33
   * @inheritdoc
34
   */
35
  protected function execute(InputInterface $input, OutputInterface $output): int
36
  {
37
    $this->io->title('Plaisio: Kernel Properties');
38
39
    $nubPath = ClassHelper::classPath(PlaisioKernel::class);
40
    $source  = $this->addProperties($nubPath);
41
42
    $this->io->text('');
43
44
    $helper = new TwoPhaseWrite($this->io);
45
    $helper->write($nubPath, $source);
46
47
    return 0;
48
  }
49
50
  //--------------------------------------------------------------------------------------------------------------------
51
  /**
52
   * Adds a property to the source of a class.
53
   *
54
   * @param string $path The path to the source of the class.
55
   *
56
   * @return string
57
   */
58
  private function addProperties(string $path): string
59
  {
60
    $source = file_get_contents($path);
61
    $lines  = explode(PHP_EOL, $source);
62
63
    $properties = $this->collectProperties();
64
    $lines      = $this->removeProperties($lines);
65
    $lines      = $this->appendProperties($lines, $properties);
66
67
    return implode(PHP_EOL, $lines);
68
  }
69
70
  //--------------------------------------------------------------------------------------------------------------------
71
  /**
72
   * Adds properties to the kernel.
73
   *
74
   * @param string[] $lines      The source of the class.
75
   * @param array    $properties The details of the properties.
76
   *
77
   * @return string[]
78
   */
79
  private function appendProperties(array $lines, array $properties): array
80
  {
81
    $key = ClassHelper::classDeclarationLine($lines, 'PlaisioKernel');
82
83
    if ($key<=2 || ($lines[$key - 1]!==' */' && $lines[$key - 1]!=='#[\AllowDynamicProperties]'))
84
    {
85
      throw new RuntimeException('Unable to add property');
86
    }
87
88
    if ($lines[$key - 1]!=='#[AllowDynamicProperties]')
89
    {
90
      $key = $key - 1;
91
    }
92
93
    if ($lines[$key - 2]!==' *')
94
    {
95
      array_splice($lines, $key - 1, 0, [' *']);
96
      $key++;
97
    }
98
99
    $code = [];
100
    foreach ($properties as $property)
101
    {
102
      $name = '$'.ltrim($property['name'], '$');
103
104
      $this->io->text(sprintf('Adding property %s', $name));
105
106
      $code[] = rtrim(sprintf(' * @property-read %s %s %s',
107
                              $property['type'],
108
                              $name,
109
                              $property['description']));
110
    }
111
112
    array_splice($lines, $key - 1, 0, $code);
113
114
    return $lines;
115
  }
116
117
  //--------------------------------------------------------------------------------------------------------------------
118
  /**
119
   * Collects all kernel properties defined in all plaisio-kernel.xml files under current project.
120
   *
121
   * @return array
122
   */
123
  private function collectProperties(): array
124
  {
125
    $files = PlaisioXmlPathHelper::findPlaisioXmlAll('kernel');
126
127
    $properties = [];
128
129
    foreach ($files as $file)
130
    {
131
      $config = new PlaisioXmlQueryHelper($file);
132
133
      $properties = array_merge($properties, $config->queryKernelProperties());
134
    }
135
136
    usort($properties, function ($a, $b) {
137
      return $a['name']<=>$b['name'];
138
    });
139
140
    return $properties;
141
  }
142
143
  //--------------------------------------------------------------------------------------------------------------------
144
  /**
145
   * Removes a property from the source of the kernel.
146
   *
147
   * @param string[] $lines The source of the class.
148
   *
149
   * @return string[]
150
   */
151
  private function removeProperties(array $lines): array
152
  {
153
    $ret = [];
154
155
    foreach ($lines as $line)
156
    {
157
      if (preg_match('/^(.*@property(-read)?)/', $line)===0)
158
      {
159
        $ret[] = $line;
160
      }
161
    }
162
163
    return $ret;
164
  }
165
166
  //--------------------------------------------------------------------------------------------------------------------
167
}
168
169
//----------------------------------------------------------------------------------------------------------------------
170