Completed
Pull Request — master (#41)
by Dima
05:18
created

BaseCommand::rewriteConfig()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
ccs 0
cts 4
cp 0
rs 9.4285
cc 2
eloc 3
nc 2
nop 0
crap 6
1
<?php
2
//----------------------------------------------------------------------------------------------------------------------
3
namespace SetBased\Audit\Command;
4
5
use SetBased\Exception\RuntimeException;
6
use SetBased\Stratum\Style\StratumStyle;
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Formatter\OutputFormatter;
9
10
//----------------------------------------------------------------------------------------------------------------------
11
/**
12
 * Base command for other commands of AuditApplication.
13
 */
14
class BaseCommand extends Command
15
{
16
  //--------------------------------------------------------------------------------------------------------------------
17
  /**
18
   * All config file as array.
19
   *
20
   * @var array
21
   */
22
  protected $config;
23
24
  /**
25
   * The name of the configuration file.
26
   *
27
   * @var string
28
   */
29
  protected $configFileName;
30
31
  /**
32
   * The Output decorator.
33
   *
34
   * @var StratumStyle
35
   */
36
  protected $io;
37
38
  /**
39
   * If set (the default) the config file must be rewritten. Set to false for testing only.
40
   *
41
   * @var bool
42
   */
43
  protected $rewriteConfigFile = true;
44
45
  //--------------------------------------------------------------------------------------------------------------------
46
  /**
47
   * Returns the value of a setting.
48
   *
49
   * @param array  $settings    The settings as returned by parse_ini_file.
50
   * @param bool   $mandatory   If set and setting $settingName is not found in section $sectionName an exception
51
   *                            will be thrown.
52
   * @param string $sectionName The name of the section of the requested setting.
53
   * @param string $settingName The name of the setting of the requested setting.
54
   *
55
   * @return null|string
56
   *
57
   * @throws RuntimeException
58
   */
59 13
  protected static function getSetting($settings, $mandatory, $sectionName, $settingName)
60
  {
61
    // Test if the section exists.
62 13 View Code Duplication
    if (!array_key_exists($sectionName, $settings))
63 13
    {
64
      if ($mandatory)
65
      {
66
        throw new RuntimeException("Section '%s' not found in configuration file.", $sectionName);
67
      }
68
      else
69
      {
70
        return null;
71
      }
72
    }
73
74
    // Test if the setting in the section exists.
75 13 View Code Duplication
    if (!array_key_exists($settingName, $settings[$sectionName]))
76 13
    {
77
      if ($mandatory)
78
      {
79
        throw new RuntimeException("Setting '%s' not found in section '%s' configuration file.",
80
                                   $settingName,
81
                                   $sectionName);
82
      }
83
      else
84
      {
85
        return null;
86
      }
87
    }
88
89 13
    return $settings[$sectionName][$settingName];
90
  }
91
92
  //--------------------------------------------------------------------------------------------------------------------
93
  /**
94
   * Reads configuration parameters from the configuration file.
95
   */
96 13
  public function readConfigFile()
97
  {
98 13
    $content = file_get_contents($this->configFileName);
99
100 13
    $this->config = (array)json_decode($content, true);
101 13
    if (json_last_error()!=JSON_ERROR_NONE)
102 13
    {
103
      throw new RuntimeException("Error decoding JSON: '%s'.", json_last_error_msg());
104
    }
105
106 13
    if (!isset($this->config['audit_columns']))
107 13
    {
108 1
      $this->config['audit_columns'] = [];
109 1
    }
110
111 13
    if (!isset($this->config['additional_sql']))
112 13
    {
113 2
      $this->config['additional_sql'] = [];
114 2
    }
115
116 13
    if (!isset($this->config['tables']))
117 13
    {
118 13
      $this->config['tables'] = [];
119 13
    }
120
121 13
    foreach ($this->config['tables'] as $table_name => $params)
122
    {
123
      $this->config['tables'][$table_name]['audit'] = filter_var($params['audit'], FILTER_VALIDATE_BOOLEAN);
124 13
    }
125 13
  }
126
127
  //--------------------------------------------------------------------------------------------------------------------
128
  /**
129
   * Use for testing only.
130
   *
131
   * @param bool $rewriteConfigFile If true the config file must be rewritten. Otherwise the config must not be
132
   *                                rewritten.
133
   */
134 13
  public function setRewriteConfigFile($rewriteConfigFile)
135
  {
136 13
    $this->rewriteConfigFile = $rewriteConfigFile;
137 13
  }
138
139
  //--------------------------------------------------------------------------------------------------------------------
140
  /**
141
   * Rewrites the config file with updated data.
142
   */
143
  protected function rewriteConfig()
144
  {
145
    // Return immediately when the config file must not be rewritten. 
146
    if (!$this->rewriteConfigFile) return;
147
148
    $this->writeTwoPhases($this->configFileName, json_encode($this->config, JSON_PRETTY_PRINT));
149
  }
150
151
  //--------------------------------------------------------------------------------------------------------------------
152
  /**
153
   * Writes a file in two phase to the filesystem.
154
   *
155
   * First write the data to a temporary file (in the same directory) and than renames the temporary file. If the file
156
   * already exists and its content is equal to the data that must be written no action  is taken. This has the
157
   * following advantages:
158
   * * In case of some write error (e.g. disk full) the original file is kept in tact and no file with partially data
159
   * is written.
160
   * * Renaming a file is atomic. So, running processes will never read a partially written data.
161
   *
162
   * @param string $filename The name of the file were the data must be stored.
163
   * @param string $data     The data that must be written.
164
   */
165
  protected function writeTwoPhases($filename, $data)
166
  {
167
    $write_flag = true;
168
    if (file_exists($filename))
169
    {
170
      $old_data = file_get_contents($filename);
171
      if ($data==$old_data) $write_flag = false;
172
    }
173
174
    if ($write_flag)
175
    {
176
      $tmp_filename = $filename.'.tmp';
177
      file_put_contents($tmp_filename, $data);
178
      rename($tmp_filename, $filename);
179
180
      $this->io->text(sprintf('Wrote <fso>%s</fso>', OutputFormatter::escape($filename)));
181
    }
182
    else
183
    {
184
      $this->io->text(sprintf('File <fso>%s</fso> is up to date', OutputFormatter::escape($filename)));
185
    }
186
  }
187
188
  //--------------------------------------------------------------------------------------------------------------------
189
}
190
191
//----------------------------------------------------------------------------------------------------------------------
192