Completed
Push — master ( 39b072...2fa9c0 )
by Thomas
02:12
created

src/FluentDOM.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
abstract class FluentDOM {
4
5
  /**
6
   * @var bool
7
   */
8
  public static $isHHVM = FALSE;
9
10
  /**
11
   * @var FluentDOM\Loadable
12
   */
13
  private static $_loader = NULL;
14
15
  /**
16
   * @var array
17
   */
18
  private static $_xpathTransformers = [];
19
20
  /**
21
   * @var FluentDOM\Loadable
22
   */
23
  private static $_defaultLoaders = [];
24
25
  /**
26
   * @var FluentDOM\Serializer\Factory\Group
27
   */
28
  private static $_serializerFactories = NULL;
29
30
  /**
31
   * Load a data source into a FluentDOM\Document
32
   *
33
   * @param mixed $source
34
   * @param string $contentType
35
   * @param array $options
36
   * @return \FluentDOM\Document
37
   */
38 5
  public static function load($source, $contentType = 'text/xml', array $options = []) {
39 5
    if (!isset(self::$_loader)) {
40 4
      self::$_loader = self::getDefaultLoaders();
41 4
    }
42 5
    $result = self::$_loader->load($source, $contentType, $options);
43 5
    return $result instanceof \DOMDocument ? $result : $result->getDocument();
44
  }
45
46
  /**
47
   * Return a FluentDOM Creator instance, allow to create a DOM using nested function calls
48
   *
49
   * @param string $version
50
   * @param string $encoding
51
   * @return \FluentDOM\Nodes\Creator
52
   */
53 2
  public static function create($version = '1.0', $encoding = 'UTF-8') {
54 2
    return new \FluentDOM\Nodes\Creator($version, $encoding);
55
  }
56
57
  /**
58
   * Create an FluentDOM::Query instance and load the source into it.
59
   *
60
   * @param mixed $source
61
   * @param string $contentType
62
   * @param array $options
63
   * @return \FluentDOM\Query
64
   */
65 4
  public static function Query($source = NULL, $contentType = 'text/xml', array $options = []) {
66 4
    $query = new FluentDOM\Query();
67 4
    if (isset($source)) {
68 3
      $query->load($source, $contentType, $options);
69 3
    }
70 4
    return $query;
71
  }
72
73
  /**
74
   * Create an FluentDOM::Query instance with a modified selector callback.
75
   * This allows to use CSS selectors instead of Xpath expression.
76
   *
77
   * @param mixed $source
78
   * @param string $contentType
79
   * @param array $options
80
   * @throws \LogicException
81
   * @return \FluentDOM\Query
82
   * @codeCoverageIgnore
83
   */
84
  public static function QueryCss($source = NULL, $contentType = 'text/xml', array $options = []) {
85
    $builder = self::getXPathTransformer();
86
    $query = self::Query($source, $contentType, $options);
87
    $isHtml = ($query->contentType === 'text/html');
88
    $query->onPrepareSelector = function($selector, $contextMode) use ($builder, $isHtml) {
89
      return $builder->toXpath($selector, $contextMode, $isHtml);
90
    };
91
    return $query;
92
  }
93
94
  /**
95
   * Set a loader used in FluentDOM::load(), NULL will reset the loader.
96
   * If no loader is provided an FluentDOM\Loader\Standard() will be created.
97
   *
98
   * @param FluentDOM\Loadable|NULL $loader
99
   */
100 3
  public static function setLoader($loader) {
101 3
    if ($loader instanceof \FluentDOM\Loadable) {
102 1
      self::$_loader = $loader;
103 3
    } elseif (NULL === $loader) {
104 1
      self::$_loader = NULL;
105 1
    } else {
106 1
      throw new \FluentDOM\Exceptions\InvalidArgument(
107 1
        'loader', ['FluentDOM\Loadable']
108 1
      );
109
    }
110 2
  }
111
112
  /**
113
   * Register an additional default loader
114
   *
115
   * @param \FluentDOM\Loadable|callable $loader
116
   * @param [string] ...$contentTypes
117
   * @return \FluentDOM\Loaders
118
   */
119 3
  public static function registerLoader($loader, ...$contentTypes) {
120 3
    $loaders = self::getDefaultLoaders();
121 3
    if (count($contentTypes) > 0) {
122 1
      $lazyLoader = new \FluentDOM\Loader\Lazy();
123 1
      foreach ($contentTypes as $contentType) {
124 1
        $lazyLoader->add($contentType, $loader);
0 ignored issues
show
It seems like $loader defined by parameter $loader on line 119 can also be of type callable; however, FluentDOM\Loader\Lazy::add() does only seem to accept object<FluentDOM\Loadable>|object<callable>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
125 1
      }
126 1
      $loaders->add($lazyLoader);
127 3
    } else if (is_callable($loader)) {
128 1
      $loaders->add($loader());
129 1
    } else {
130 1
      $loaders->add($loader);
131
    }
132 3
    self::$_loader = NULL;
133 3
    return $loaders;
134
  }
135
136
  /**
137
   * Standard loader + any registered loader.
138
   *
139
   * @return \FluentDOM\Loaders
140
   * @codeCoverageIgnore
141
   */
142
  public static function getDefaultLoaders() {
143
    if (!(self::$_defaultLoaders instanceof FluentDOM\Loaders)) {
144
      self::$_defaultLoaders = new FluentDOM\Loaders(new FluentDOM\Loader\Standard());
145
    }
146
    return self::$_defaultLoaders;
147
  }
148
149
  /**
150
   * Register a serializer factory for a specified content type(s). This can be
151
   * a callable returning the create serializer.
152
   *
153
   * @param \FluentDOM\Serializer\Factory|callable $factory
154
   * @param [string] ...$contentTypes
155
   */
156 1
  public static function registerSerializerFactory($factory, ...$contentTypes) {
157 1
    foreach ($contentTypes as $contentType) {
158 1
      self::getSerializerFactories()[$contentType] = $factory;
159 1
    }
160 1
  }
161
162
  /**
163
   * Return registered serializer factories
164
   *
165
   * @return \FluentDOM\Serializer\Factory\Group
166
   */
167 4
  public static function getSerializerFactories() {
168 4
    if (!(self::$_serializerFactories instanceof FluentDOM\Serializer\Factory)) {
169
      $xml = function($contentType, \DOMNode $node) {
170 3
        return new FluentDOM\Serializer\Xml($node);
171 1
      };
172
      $html = function($contentType, \DOMNode $node) {
173 1
        return new FluentDOM\Serializer\Html($node);
174 1
      };
175 1
      $json = function($contentType, \DOMNode $node) {
176 1
        return new FluentDOM\Serializer\Json($node);
177 1
      };
178 1
      self::$_serializerFactories = new FluentDOM\Serializer\Factory\Group(
179
        [
180 1
          'text/html' => $html,
181 1
          'html' => $html,
182 1
          'text/xml' => $xml,
183 1
          'xml' => $xml,
184 1
          'text/json' => $json,
185
          'json' => $json
186 1
        ]
187 1
      );
188 1
    }
189 4
    return self::$_serializerFactories;
190
  }
191
192
  /**
193
   * Get a xpath expression builder to convert css selectors to xpath
194
   *
195
   * @param string $errorMessage
196
   * @return \FluentDOM\Xpath\Transformer
197
   */
198 6
  public static function getXPathTransformer($errorMessage = 'No CSS selector support installed') {
199 6
    foreach (FluentDOM::$_xpathTransformers as $index => $transformer) {
200 6
      if (is_string($transformer) && class_exists($transformer)) {
201 1
        FluentDOM::$_xpathTransformers[$index] = new $transformer();
202 6
      } elseif (is_callable($transformer)) {
203 1
        FluentDOM::$_xpathTransformers[$index] = $transformer();
204 1
      }
205 6
      if (FluentDOM::$_xpathTransformers[$index] instanceof \FluentDOM\Xpath\Transformer) {
206 5
        return FluentDOM::$_xpathTransformers[$index];
207
      } else {
208 1
        unset(FluentDOM::$_xpathTransformers[$index]);
209
      }
210 1
    }
211 1
    throw new \LogicException($errorMessage);
212
  }
213
214
  /**
215
   * @param string|callable|FluentDOM\Xpath\Transformer $transformer
216
   */
217 6
  public static function registerXpathTransformer($transformer, $reset = FALSE) {
218 6
    if ($reset) {
219 6
      self::$_xpathTransformers = [];
220 6
    }
221 6
    array_unshift(self::$_xpathTransformers, $transformer);
222 6
  }
223
}
224
FluentDOM::$isHHVM = defined('HHVM_VERSION');
225
226
227
/**
228
 * FluentDOM function, is an Alias for the \FluentDOM\FluentDOM::Query()
229
 * factory class function.
230
 *
231
 * @param mixed $source
232
 * @param string $contentType
233
 * @param array $options
234
 * @return \FluentDOM\Query
235
 * @codeCoverageIgnore
236
 */
237
function FluentDOM($source = NULL, $contentType = 'text/xml', array $options = []) {
238
  return FluentDOM::Query($source, $contentType, $options);
239
}
240