AbstractCommand::getDatabase()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 12

Duplication

Lines 14
Ratio 70 %

Importance

Changes 0
Metric Value
dl 14
loc 20
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 12
nc 3
nop 0
1
<?php
2
3
/**
4
 * @file AbstractCommand.php
5
 * @brief This file contains the AbstractCommand class.
6
 * @details
7
 * @author Filippo F. Fadda
8
 */
9
10
11
//! This is the Commands namespace.
12
namespace EoC\CLI\Command;
13
14
15
use EoC\Adapter\CurlAdapter;
16
use EoC\Couch;
17
18
use Symfony\Component\Console\Command\Command;
19
20
21
/**
22
 * @brief This class represents an abstract command that implements the InjectionAwareInterface to automatic set the
23
 * Phalcon Dependency Injector and make it available to every subclasses.
24
 * @nosubgrouping
25
 */
26
abstract class AbstractCommand extends Command {
27
28
  /**
29
   * @brief Creates an instance of the command.
30
   */
31
  public function __construct() {
32
    parent::__construct();
33
  }
34
35
36
  /**
37
   * @brief Returns `true` in case `$arg` seems to be the string representation of an array, `false` otherwise.
38
   * @param[in] mixed $arg The command line argument.
39
   * @return bool
40
   */
41
  protected function isArray($arg) {
42
    if (preg_match('/\A[\[]([^\[\]]+)[\]]\z/i', $arg, $matches))
43
      return TRUE;
44
    else
45
      return FALSE;
46
  }
47
48
49
  /**
50
   * @brief Returns `true` in case `$arg` is a formatted argument, `false` otherwise.
51
   * @details The argument type can be specified using the syntax \%s/. The final slash is followed by the value.\n
52
   *     \%s - the argument is treated as a string.\n
53
   *     \%b - the argument is treated as a boolean.\n
54
   *     \%i - the argument is treated as an integer.\n
55
   *     \%f - the argument is treated as a float.
56
   * @param[in,out] mixed $arg The command line argument.
57
   * @return bool
58
   */
59
  protected function isFormatted(&$arg) {
60
    //  \A            # Assert position at the beginning of the string
61
    //  (?P<type>     # Match the regular expression below and capture its match into backreference with name “type”
62
    //                  # Match either the regular expression below (attempting the next alternative only if this one fails)
63
    //        %s          # Match the characters “%s” literally
64
    //     |            # Or match regular expression number 2 below (attempting the next alternative only if this one fails)
65
    //        %b          # Match the characters “%b” literally
66
    //     |            # Or match regular expression number 3 below (attempting the next alternative only if this one fails)
67
    //        %i          # Match the characters “%i” literally
68
    //     |            # Or match regular expression number 4 below (the entire group fails if this one fails to match)
69
    //        %f          # Match the characters “%f” literally
70
    //  )
71
    //  /             # Match the character “/” literally
72
    //  (?P<value>    # Match the regular expression below and capture its match into backreference with name “value”
73
    //        .         # Match any single character that is not a line break character
74
    //          +         # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
75
    //  )
76
    //  \z            # Assert position at the very end of the string
77
    if (preg_match('#\A(?P<type>%s|%b|%i|%f)/(?P<value>.+)\z#i', $arg, $matches)) {
78
      $type = $matches['type'];
79
      $value = $matches['value'];
80
81
      switch ($type) {
82
        case '%s':
83
          $arg = (string)$value;
84
          break;
85
        case '%b':
86
          $arg = (strtolower($value) === 'false') ? FALSE : (bool)$value;
87
          break;
88
        case '%i':
89
          $arg = (integer)$value;
90
          break;
91
        case '%f':
92
          $arg = (float)$value;
93
          break;
94
      }
95
96
      return TRUE;
97
    }
98
    else {
99
      return FALSE;
100
    }
101
  }
102
103
104
  /**
105
   * @brief Casts the argument to the right format and jsonify it when necessary.
106
   * @param[in] mixed $arg The command line argument.
107
   * @return mixed
108
   */
109
  protected function castArg($arg) {
110
    //echo "Original argument: ".$arg.PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
111
112
    if ($this->isArray($arg)) {
113
      // Removes `[` and `]` from the argument.
114
      $str = substr($arg, 1, -1);
115
116
      // Splits a string using the delimiter `,` and returns the result as an array of strings.
117
      $values = explode(',', $str);
118
119
      $argument = [];
120
      foreach ($values as $value) {
121
        if ($this->isFormatted($value))
122
          $argument[] = $value;
123
        else
124
          $argument[] = (string)$value;
125
      }
126
127
      return $argument;
128
    }
129
    elseif ($this->isFormatted($arg))
130
      return $arg;
131
    else
132
      return (string)$arg ;
133
  }
134
135
136
  /**
137
   * @brief Retrieves the connection in use.
138
   * @retval EoC::Couch The server connection.
139
   */
140
  protected function getConnection() {
0 ignored issues
show
Coding Style introduced by
getConnection uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
141
    $shmKey = ftok($_SERVER['PHP_SELF'], 'c');
142
143 View Code Duplication
    if (@$shmId = shmop_open($shmKey, "a", 0, 0)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
      // Gets shared memory block's size.
145
      $shmSize = shmop_size($shmId);
146
147
      // Now lets read the memory segment.
148
      if ($buffer = shmop_read($shmId, 0, $shmSize))
149
        $connection = unserialize($buffer);
150
      else
151
        throw new \RuntimeException("You are not connected to the server.");
152
153
      shmop_close($shmId);
154
    }
155
    else
156
      throw new \RuntimeException("You are not connected to the server.");
157
158
    return new Couch(new CurlAdapter($connection['server'], $connection['user'], $connection['password']));
159
  }
160
161
162
  /**
163
   * @brief Retrieves the database in use.
164
   * @retval string The database name.
165
   */
166
  protected function getDatabase() {
0 ignored issues
show
Coding Style introduced by
getDatabase uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
167
    $shmKey = ftok($_SERVER['PHP_SELF'], 'd');
168
169 View Code Duplication
    if (@$shmId = shmop_open($shmKey, "a", 0, 0)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
170
      // Gets shared memory block's size.
171
      $shmSize = shmop_size($shmId);
172
173
      // Now lets read the memory segment.
174
      if ($buffer = shmop_read($shmId, 0, $shmSize))
175
        $database = $buffer;
176
      else
177
        throw new \RuntimeException("No database selected.");
178
179
      shmop_close($shmId);
180
    }
181
    else
182
      throw new \RuntimeException("No database selected.");
183
184
    return $database;
185
  }
186
187
}