Completed
Push — master ( e81ee4...5471ad )
by Thomas
02:40
created

FluentDOM::save()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 4
nop 2
dl 0
loc 9
ccs 7
cts 7
cp 1
crap 3
rs 9.6666
c 0
b 0
f 0
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
   * @param \DOMNode|\FluentDOM\Query $node
59
   * @param string $contentType
60
   * @return string
61
   */
62 5
  public static function save($node, $contentType = 'text/xml') {
63 5
    if ($node instanceof \FluentDOM\Query) {
64 1
      $node = $node->document;
65 1
    }
66 5
    if ($serializer = self::getSerializerFactories()->createSerializer($contentType, $node)) {
67 4
      return (string)$serializer;
68
    }
69 1
    throw new \FluentDOM\Exceptions\NoSerializer($contentType);
70
  }
71
72
  /**
73
   * Create an FluentDOM::Query instance and load the source into it.
74
   *
75
   * @param mixed $source
76
   * @param string $contentType
77
   * @param array $options
78
   * @return \FluentDOM\Query
79
   */
80 5
  public static function Query($source = NULL, $contentType = 'text/xml', array $options = []) {
81 5
    $query = new FluentDOM\Query();
82 5
    if (isset($source)) {
83 4
      $query->load($source, $contentType, $options);
84 4
    }
85 5
    return $query;
86
  }
87
88
  /**
89
   * Create an FluentDOM::Query instance with a modified selector callback.
90
   * This allows to use CSS selectors instead of Xpath expression.
91
   *
92
   * @param mixed $source
93
   * @param string $contentType
94
   * @param array $options
95
   * @throws \LogicException
96
   * @return \FluentDOM\Query
97
   * @codeCoverageIgnore
98
   */
99
  public static function QueryCss($source = NULL, $contentType = 'text/xml', array $options = []) {
100
    $builder = self::getXPathTransformer();
101
    $query = self::Query($source, $contentType, $options);
102
    $isHtml = ($query->contentType === 'text/html');
103
    $query->onPrepareSelector = function($selector, $contextMode) use ($builder, $isHtml) {
104
      return $builder->toXpath($selector, $contextMode, $isHtml);
105
    };
106
    return $query;
107
  }
108
109
  /**
110
   * Set a loader used in FluentDOM::load(), NULL will reset the loader.
111
   * If no loader is provided an FluentDOM\Loader\Standard() will be created.
112
   *
113
   * @param FluentDOM\Loadable|NULL $loader
114
   */
115 3
  public static function setLoader($loader) {
116 3
    if ($loader instanceof \FluentDOM\Loadable) {
117 1
      self::$_loader = $loader;
118 3
    } elseif (NULL === $loader) {
119 1
      self::$_loader = NULL;
120 1
    } else {
121 1
      throw new \FluentDOM\Exceptions\InvalidArgument(
122 1
        'loader', ['FluentDOM\Loadable']
123 1
      );
124
    }
125 2
  }
126
127
  /**
128
   * Register an additional default loader
129
   *
130
   * @param \FluentDOM\Loadable|callable $loader
131
   * @param [string] ...$contentTypes
132
   * @return \FluentDOM\Loaders
133
   */
134 3
  public static function registerLoader($loader, ...$contentTypes) {
135 3
    $loaders = self::getDefaultLoaders();
136 3
    if (count($contentTypes) > 0) {
137 1
      $lazyLoader = new \FluentDOM\Loader\Lazy();
138 1
      foreach ($contentTypes as $contentType) {
139 1
        $lazyLoader->add($contentType, $loader);
140 1
      }
141 1
      $loaders->add($lazyLoader);
142 3
    } else if (is_callable($loader)) {
143 1
      $loaders->add($loader());
144 1
    } else {
145 1
      $loaders->add($loader);
146
    }
147 3
    self::$_loader = NULL;
148 3
    return $loaders;
149
  }
150
151
  /**
152
   * Standard loader + any registered loader.
153
   *
154
   * @return \FluentDOM\Loaders
155
   * @codeCoverageIgnore
156
   */
157
  public static function getDefaultLoaders() {
158
    if (!(self::$_defaultLoaders instanceof FluentDOM\Loaders)) {
159
      self::$_defaultLoaders = new FluentDOM\Loaders(new FluentDOM\Loader\Standard());
160
    }
161
    return self::$_defaultLoaders;
162
  }
163
164
  /**
165
   * Register a serializer factory for a specified content type(s). This can be
166
   * a callable returning the create serializer.
167
   *
168
   * @param \FluentDOM\Serializer\Factory|callable $factory
169
   * @param [string] ...$contentTypes
170
   */
171 1
  public static function registerSerializerFactory($factory, ...$contentTypes) {
172 1
    foreach ($contentTypes as $contentType) {
173 1
      self::getSerializerFactories()[$contentType] = $factory;
174 1
    }
175 1
  }
176
177
  /**
178
   * Return registered serializer factories
179
   *
180
   * @return \FluentDOM\Serializer\Factory\Group
181
   */
182 9
  public static function getSerializerFactories() {
183 9
    if (!(self::$_serializerFactories instanceof FluentDOM\Serializer\Factory)) {
184
      $xml = function($contentType, \DOMNode $node) {
185 6
        return new FluentDOM\Serializer\Xml($node);
186 1
      };
187
      $html = function($contentType, \DOMNode $node) {
188 2
        return new FluentDOM\Serializer\Html($node);
189 1
      };
190 1
      $json = function($contentType, \DOMNode $node) {
191 1
        return new FluentDOM\Serializer\Json($node);
192 1
      };
193 1
      self::$_serializerFactories = new FluentDOM\Serializer\Factory\Group(
194
        [
195 1
          'text/html' => $html,
196 1
          'html' => $html,
197 1
          'text/xml' => $xml,
198 1
          'xml' => $xml,
199 1
          'text/json' => $json,
200
          'json' => $json
201 1
        ]
202 1
      );
203 1
    }
204 9
    return self::$_serializerFactories;
205
  }
206
207
  /**
208
   * Get a xpath expression builder to convert css selectors to xpath
209
   *
210
   * @param string $errorMessage
211
   * @return \FluentDOM\Xpath\Transformer
212
   */
213 6
  public static function getXPathTransformer($errorMessage = 'No CSS selector support installed') {
214 6
    foreach (FluentDOM::$_xpathTransformers as $index => $transformer) {
215 6
      if (is_string($transformer) && class_exists($transformer)) {
216 1
        FluentDOM::$_xpathTransformers[$index] = new $transformer();
217 6
      } elseif (is_callable($transformer)) {
218 1
        FluentDOM::$_xpathTransformers[$index] = $transformer();
219 1
      }
220 6
      if (FluentDOM::$_xpathTransformers[$index] instanceof \FluentDOM\Xpath\Transformer) {
221 5
        return FluentDOM::$_xpathTransformers[$index];
222
      } else {
223 1
        unset(FluentDOM::$_xpathTransformers[$index]);
224
      }
225 1
    }
226 1
    throw new \LogicException($errorMessage);
227
  }
228
229
  /**
230
   * @param string|callable|FluentDOM\Xpath\Transformer $transformer
231
   */
232 6
  public static function registerXpathTransformer($transformer, $reset = FALSE) {
233 6
    if ($reset) {
234 6
      self::$_xpathTransformers = [];
235 6
    }
236 6
    array_unshift(self::$_xpathTransformers, $transformer);
237 6
  }
238
}
239
FluentDOM::$isHHVM = defined('HHVM_VERSION');
240
241
242
/**
243
 * FluentDOM function, is an Alias for the \FluentDOM\FluentDOM::Query()
244
 * factory class function.
245
 *
246
 * @param mixed $source
247
 * @param string $contentType
248
 * @param array $options
249
 * @return \FluentDOM\Query
250
 * @codeCoverageIgnore
251
 */
252
function FluentDOM($source = NULL, $contentType = 'text/xml', array $options = []) {
253
  return FluentDOM::Query($source, $contentType, $options);
254
}
255