Passed
Push — master ( e0c5e8...7926db )
by P.R.
04:00
created

writeClassHeader()   B

Complexity

Conditions 7
Paths 32

Size

Total Lines 57
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 7.0178

Importance

Changes 0
Metric Value
cc 7
eloc 28
nc 32
nop 0
dl 0
loc 57
ccs 26
cts 28
cp 0.9286
crap 7.0178
rs 8.5386
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
namespace SetBased\Stratum\MySql\Backend;
5
6
use SetBased\Exception\RuntimeException;
7
use SetBased\Helper\CodeStore\PhpCodeStore;
8
use SetBased\Stratum\Backend\RoutineWrapperGeneratorWorker;
9
use SetBased\Stratum\Middle\NameMangler\NameMangler;
10
use SetBased\Stratum\MySql\Wrapper\Wrapper;
11
12
/**
13
 * Command for generating a class with wrapper methods for calling stored routines in a MySQL database.
14
 */
15
class MySqlRoutineWrapperGeneratorWorker extends MySqlWorker implements RoutineWrapperGeneratorWorker
16
{
17
  //--------------------------------------------------------------------------------------------------------------------
18
  /**
19
   * Store php code with indention.
20
   *
21
   * @var PhpCodeStore
22
   */
23
  private $codeStore;
24
25
  /**
26
   * Array with fully qualified names that must be imported.
27
   *
28
   * @var array
29
   */
30
  private $imports = [];
31
32
  /**
33
   * The filename of the file with the metadata of all stored procedures.
34
   *
35
   * @var string
36
   */
37
  private $metadataFilename;
38
39
  /**
40
   * Class name for mangling routine and parameter names.
41
   *
42
   * @var string
43
   */
44
  private $nameMangler;
45
46
  /**
47
   * The class name (including namespace) of the parent class of the routine wrapper.
48
   *
49
   * @var string
50
   */
51
  private $parentClassName;
52
53
  /**
54
   * If true wrapper must declare strict types.
55
   *
56
   * @var bool
57
   */
58
  private $strictTypes;
59
60
  /**
61
   * The class name (including namespace) of the routine wrapper.
62
   *
63
   * @var string
64
   */
65
  private $wrapperClassName;
66
67
  /**
68
   * The filename where the generated wrapper class must be stored
69
   *
70
   * @var string
71
   */
72
  private $wrapperFilename;
73
74
  //--------------------------------------------------------------------------------------------------------------------
75
  /**
76
   * @inheritdoc
77
   *
78
   * @throws RuntimeException
79
   */
80 1
  public function execute(): int
81
  {
82 1
    $this->readConfigurationFile();
83
84 1
    if ($this->wrapperClassName!==null)
85
    {
86 1
      $this->generateWrapperClass();
87
    }
88
89 1
    return 0;
90
  }
91
92
  //--------------------------------------------------------------------------------------------------------------------
93
  /**
94
   * Generates the wrapper class.
95
   *
96
   * @throws RuntimeException
97
   */
98 1
  private function generateWrapperClass(): void
99
  {
100 1
    $this->io->title('PhpStratum: MySql Wrapper');
101
102 1
    $this->codeStore = new PhpCodeStore();
103
104
    /** @var NameMangler $mangler */
105 1
    $mangler  = new $this->nameMangler();
106 1
    $routines = $this->readRoutineMetadata();
107
108 1
    if (!empty($routines))
109
    {
110
      // Sort routines by their wrapper method name.
111 1
      $sorted_routines = [];
112 1
      foreach ($routines as $routine)
113
      {
114 1
        $method_name                   = $mangler->getMethodName($routine['routine_name']);
115 1
        $sorted_routines[$method_name] = $routine;
116
      }
117 1
      ksort($sorted_routines);
118
119
      // Write methods for each stored routine.
120 1
      foreach ($sorted_routines as $method_name => $routine)
121
      {
122
        // If routine type is hidden don't create routine wrapper.
123 1
        if ($routine['designation']!='hidden')
124
        {
125 1
          $this->writeRoutineFunction($routine, $mangler);
126
        }
127
      }
128
    }
129
    else
130
    {
131
      echo "No files with stored routines found.\n";
132
    }
133
134 1
    $wrappers        = $this->codeStore->getRawCode();
135 1
    $this->codeStore = new PhpCodeStore();
136
137
    // Write the header of the wrapper class.
138 1
    $this->writeClassHeader();
139
140
    // Write methods of the wrapper calls.
141 1
    $this->codeStore->append($wrappers, false);
142
143
    // Write the trailer of the wrapper class.
144 1
    $this->writeClassTrailer();
145
146
    // Write the wrapper class to the filesystem.
147 1
    $this->storeWrapperClass();
148 1
  }
149
150
  //--------------------------------------------------------------------------------------------------------------------
151
  /**
152
   * Reads parameters from the configuration file.
153
   */
154 1
  private function readConfigurationFile(): void
155
  {
156 1
    $this->wrapperClassName = $this->settings->optString('wrapper.wrapper_class');
157 1
    if ($this->wrapperClassName!==null)
158
    {
159 1
      $this->parentClassName  = $this->settings->manString('wrapper.parent_class');
160 1
      $this->nameMangler      = $this->settings->manString('wrapper.mangler_class');
161 1
      $this->wrapperFilename  = $this->settings->manString('wrapper.wrapper_file');
162 1
      $this->metadataFilename = $this->settings->manString('loader.metadata');
163 1
      $this->strictTypes      = $this->settings->manBool('wrapper.strict_types', true);
164
    }
165 1
  }
166
167
  //--------------------------------------------------------------------------------------------------------------------
168
  /**
169
   * Returns the metadata of stored routines.
170
   *
171
   * @return array
172
   *
173
   * @throws RuntimeException
174
   */
175 1
  private function readRoutineMetadata(): array
176
  {
177 1
    $data = file_get_contents($this->metadataFilename);
178
179 1
    $routines = (array)json_decode($data, true);
180 1
    if (json_last_error()!=JSON_ERROR_NONE)
181
    {
182
      throw new RuntimeException("Error decoding JSON: '%s'.", json_last_error_msg());
183
    }
184
185 1
    return $routines;
186
  }
187
188
  //--------------------------------------------------------------------------------------------------------------------
189
  /**
190
   * Writes the wrapper class to the filesystem.
191
   */
192 1
  private function storeWrapperClass(): void
193
  {
194 1
    $code = $this->codeStore->getCode();
195 1
    $this->writeTwoPhases($this->wrapperFilename, $code);
196 1
  }
197
198
  //--------------------------------------------------------------------------------------------------------------------
199
  /**
200
   * Generate a class header for stored routine wrapper.
201
   */
202 1
  private function writeClassHeader(): void
203
  {
204 1
    $p = strrpos($this->wrapperClassName, '\\');
205 1
    if ($p!==false)
206
    {
207 1
      $namespace  = ltrim(substr($this->wrapperClassName, 0, $p), '\\');
208 1
      $class_name = substr($this->wrapperClassName, $p + 1);
209
    }
210
    else
211
    {
212
      $namespace  = null;
213
      $class_name = $this->wrapperClassName;
214
    }
215
216
    // Write PHP tag.
217 1
    $this->codeStore->append('<?php');
218
219
    // Write strict types.
220 1
    if ($this->strictTypes)
221
    {
222 1
      $this->codeStore->append('declare(strict_types=1);');
223
    }
224
225
    // Write name space of the wrapper class.
226 1
    if ($namespace!==null)
227
    {
228 1
      $this->codeStore->append('');
229 1
      $this->codeStore->append(sprintf('namespace %s;', $namespace));
230 1
      $this->codeStore->append('');
231
    }
232
233
    // If the child class and parent class have different names import the parent class. Otherwise use the fully
234
    // qualified parent class name.
235 1
    $parent_class_name = substr($this->parentClassName, strrpos($this->parentClassName, '\\') + 1);
236 1
    if ($class_name!=$parent_class_name)
237
    {
238 1
      $this->imports[]       = $this->parentClassName;
239 1
      $this->parentClassName = $parent_class_name;
240
    }
241
242
    // Write use statements.
243 1
    if (!empty($this->imports))
244
    {
245 1
      $this->imports = array_unique($this->imports, SORT_REGULAR);
246 1
      foreach ($this->imports as $import)
247
      {
248 1
        $this->codeStore->append(sprintf('use %s;', $import));
249
      }
250 1
      $this->codeStore->append('');
251
    }
252
253
    // Write class name.
254 1
    $this->codeStore->append('/**');
255 1
    $this->codeStore->append(' * The data layer.', false);
256 1
    $this->codeStore->append(' */', false);
257 1
    $this->codeStore->append(sprintf('class %s extends %s', $class_name, $this->parentClassName));
258 1
    $this->codeStore->append('{');
259 1
  }
260
261
  //--------------------------------------------------------------------------------------------------------------------
262
  /**
263
   * Generate a class trailer for stored routine wrapper.
264
   */
265 1
  private function writeClassTrailer(): void
266
  {
267 1
    $this->codeStore->appendSeparator();
268 1
    $this->codeStore->append('}');
269 1
    $this->codeStore->append('');
270 1
    $this->codeStore->appendSeparator();
271 1
  }
272
273
  //--------------------------------------------------------------------------------------------------------------------
274
  /**
275
   * Generates a complete wrapper method for a stored routine.
276
   *
277
   * @param array       $routine     The metadata of the stored routine.
278
   * @param NameMangler $nameMangler The mangler for wrapper and parameter names.
279
   */
280 1
  private function writeRoutineFunction(array $routine, NameMangler $nameMangler): void
281
  {
282 1
    $wrapper = Wrapper::createRoutineWrapper($routine, $this->codeStore, $nameMangler);
283 1
    $wrapper->writeRoutineFunction();
284
285 1
    $this->imports = array_merge($this->imports, $wrapper->getImports());
286 1
  }
287
288
  //--------------------------------------------------------------------------------------------------------------------
289
}
290
291
//----------------------------------------------------------------------------------------------------------------------
292