Completed
Push — master ( 52f6f2...1eb7a6 )
by Filippo
02:23
created

AbstractCommand::isFormatted()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 43
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 43
rs 6.7272
cc 7
eloc 20
nc 7
nop 1
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”
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
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”
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
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
   * @param[in] bool $encode (optional) JSON encodes `$arg`.
108
   * @return mixed
109
   */
110
  protected function castArg($arg, $encode = TRUE) {
111
    echo "Original argument: ".$arg.PHP_EOL;
112
    if ($this->isArray($arg))
113
      return $arg;
114
    elseif ($this->isFormatted($arg)) {
115
      if ($encode)
116
        return json_encode($arg);
117
      else
118
        return $arg;
119
    }
120
    else
121
      return $arg + 0;
122
  }
123
124
125
  /**
126
   * @brief Retrieves the connection in use.
127
   * @retval EoC::Couch The server connection.
128
   */
129
  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...
130
    $shmKey = ftok($_SERVER['PHP_SELF'], 'c');
131
132 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...
133
      // Gets shared memory block's size.
134
      $shmSize = shmop_size($shmId);
135
136
      // Now lets read the memory segment.
137
      if ($buffer = shmop_read($shmId, 0, $shmSize))
138
        $connection = unserialize($buffer);
139
      else
140
        throw new \RuntimeException("You are not connected to the server.");
141
142
      shmop_close($shmId);
143
    }
144
    else
145
      throw new \RuntimeException("You are not connected to the server.");
146
147
    return new Couch(new CurlAdapter($connection['server'], $connection['user'], $connection['password']));
148
  }
149
150
151
  /**
152
   * @brief Retrieves the database in use.
153
   * @retval string The database name.
154
   */
155
  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...
156
    $shmKey = ftok($_SERVER['PHP_SELF'], 'd');
157
158 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...
159
      // Gets shared memory block's size.
160
      $shmSize = shmop_size($shmId);
161
162
      // Now lets read the memory segment.
163
      if ($buffer = shmop_read($shmId, 0, $shmSize))
164
        $database = $buffer;
165
      else
166
        throw new \RuntimeException("No database selected.");
167
168
      shmop_close($shmId);
169
    }
170
    else
171
      throw new \RuntimeException("No database selected.");
172
173
    return $database;
174
  }
175
176
}