Renderer::getFormats()   B
last analyzed

Complexity

Conditions 6
Paths 7

Size

Total Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 6.6563

Importance

Changes 0
Metric Value
dl 0
loc 37
ccs 14
cts 19
cp 0.7368
rs 8.7057
c 0
b 0
f 0
cc 6
nc 7
nop 1
crap 6.6563
1
<?php
2
/**
3
 * @file
4
 * Grafizzi\Graph\Renderer: a component of the Grafizzi library.
5
 *
6
 * (c) 2012 Frédéric G. MARAND <[email protected]>
7
 *
8
 * Grafizzi is free software: you can redistribute it and/or modify it under the
9
 * terms of the GNU Lesser General Public License as published by the Free
10
 * Software Foundation, either version 3 of the License, or (at your option) any
11
 * later version.
12
 *
13
 * Grafizzi is distributed in the hope that it will be useful, but WITHOUT ANY
14
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15
 * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
16
 * details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with Grafizzi, in the COPYING.LESSER.txt file.  If not, see
20
 * <http://www.gnu.org/licenses/>
21
 */
22
23
namespace Grafizzi\Graph;
24
25
use Grafizzi\Graph\Filter\AbstractFilter;
26
use Pimple\Container;
27
28
/**
29
 * A Renderer builds a rendering pipeline by instantiating Filters and providing
30
 * a pipe to chain invokations of their filter() methods.
31
 *
32
 * @method dot()
33
 * @method string()
34
 * @method sink()
35
 */
36
class Renderer {
37
38
  /**
39
   * The dependency injection container.
40
   *
41
   * @var \Pimple\Container
42
   */
43
  public $dic;
44
45
  /**
46
   * The channel between filters.
47
   *
48
   * @var string
49
   */
50
  public $pipe = null;
51
52
  /**
53
   * Helper to enumerate GraphViz format filters on the current system.
54
   *
55
   * @throws \ErrorException
56
   *
57
   * @param \Pimple\container $dic
58
   *
59
   * @return string[]
60
   *   An array of format names or false if dot cannot be run.
61
   */
62 5
  public static function getFormats(Container $dic) {
63 5
    $dotCommand = 'dot -Tinvalid';
64 5
    $useExceptions = !empty($dic['use_exceptions']);
65
    $descriptorSpec = array(
66 5
        0 => array('pipe', 'r'),
67
        1 => array('pipe', 'w'),
68
        2 => array('pipe', 'w'),
69
    );
70
71 5
    $process = proc_open($dotCommand, $descriptorSpec, $pipes, NULL, NULL);
72 5
    if (!is_resource($process)) {
73
      if ($useExceptions) {
74
        throw new \ErrorException('GraphViz "dot" command could not be run.');
75
      }
76
      // No need to define $formats otherwise: it is always defined further down.
77
    }
78
79 5
    fclose($pipes[0]);
80 5
    fclose($pipes[1]);
81 5
    $stderr = stream_get_contents($pipes[2]);
82 5
    proc_close($process);
83
84 5
    $sts = preg_match('/(.+):( .* )*/', $stderr, $matches);
85 5
    if (!$sts || count($matches) != 3) {
86
      if ($useExceptions) {
87
        throw new \ErrorException('GraphViz did not return a usable formats list.');
88
      }
89
      else {
90
        $formats = array();
91
      }
92
    }
93
    else {
94 5
      $formats = explode(' ', trim($matches[2]));
95
    }
96
97 5
    return $formats;
98
  }
99
100
  /**
101
   * Constructor.
102
   *
103
   * @param \Pimple\Container $dic
104
   */
105 4
  public function __construct(Container $dic) {
106 4
    $this->dic = $dic;
107 4
  }
108
109
  /**
110
   * Magic method: apply filter methods by simple name.
111
   *
112
   * @see Grafizzi\Graph\Filter\AbstractFilter::create()
113
   *
114
   * @param string $name
115
   *   The simple name for a filter. Will be converted to an actual class name.
116
   * @param array $args
117
   *   An array of arguments to pass to the filter method.
118
   *
119
   * @throws \DomainException
120
   *   Throws exception if the filter name does not convert to a usable filter
121
   *   class.
122
   *
123
   * @return $this
124
   */
125 3
  public function __call($name, $args) {
126
127 3
    $filter = isset($args[0])
128 2
      ? AbstractFilter::create($name, $args[0])
129 3
      : AbstractFilter::create($name);
130
131 2
    if ($filter) {
132 2
      list($this->pipe, $err) = $filter->filter($this->pipe);
133 2
      if (!empty($err)) {
134 2
        $this->dic['logger']->debug($err);
135
      }
136
    }
137
    else {
138
      throw new \DomainException('Filter not found: ' . $name);
139
    }
140 2
    return $this;
141
  }
142
}
143