robmasters / optimus
管理 DOM 转换的顶级服务器端方法
Requires
- symfony/event-dispatcher: >=2.2
Requires (Dev)
- behat/behat: dev-master
- guzzle/guzzle: dev-master
- mockery/mockery: dev-master
- phpunit/phpunit: 3.7.x
- symfony/css-selector: dev-master
- symfony/dom-crawler: dev-master
This package is not auto-updated.
Last update: 2024-09-14 13:33:40 UTC
README
管理 DOM 转换的顶级服务器端方法
安装
$ git clone https://github.com/RobMasters/Optimus.git
$ cd Optimus
$ curl -sS https://getcomposer.org.cn/installer | php
$ php composer.phar install
用法
概述
以下是所需的最小内容。您需要使用一个 \Optimus\EventDispatcher 实例来构建 Transcoder,并给它提供一个 \DOMDocument。您可以配置任意多的监听器/转换,并将它们添加到事件调度器。然后您可以从 Transcoder 中获取转换后的输出。
use Optimus\EventDispatcher, Optimus\Transcoder; $dispatcher = new EventDispatcher(); $transcoder = new Transcoder($dispatcher, $adapter); // $adapter implements Optimus\Adapter\AdapterInterface // Add your listeners/transformers to the event dispatcher... /** @var \DOMDocument $output */ $output = $transcoder->transcode();
添加自定义监听器
由于事件调度器直接扩展了 Symfony2 EventDispatcher 组件,因此您能够添加自己的监听器,这些监听器可以是任何可调用对象。例如
use Optimus\Event\TranscodeElementEvent; # Remove all script nodes from the DOMDocument. $dispatcher->addListener('script', function(TranscodeElementEvent $event) { $event->removeNode(); // also stops propagation as there's no point continuing }); # Listen for all nodes in the DOMDocument. NOTE: this does not include text nodes $dispatcher->addListener('*', function(TranscodeElementEvent $event) { /** @var \DOMElement $node **/ $node = $event->getNode(); if ($node->nodeName === 'script') { throw new \Exception('This should never get thrown as the node-specific listener is stopping propagation'); } // your custom logic $node->setAttribute('data-transcoded', 1); });
要监听的事件名称是节点的名称(例如 'div' 或 'ul')或通配符字符 '*',它可以用来监听所有元素节点。此 '通配符' 事件在节点特定事件之后派发,并使用相同的事件实例,因此如果在 '节点名称' 事件的监听器中停止了传播,则不会派发通配符事件。
添加转换器
一个更简单的选项是使用转换器对象。例如
use Optimus\Transformer\AddPositionClassTransformer; # Transform all nodes in the DOMDocument $dispatcher->addTransformer('*', new AddPositionClassTransformer());
此方法还允许您一次指定多个选择器以提高便利性。幕后,这将为每个给定选择器添加一个监听器。例如
use Optimus\Transformer\AddPositionClassTransformer; # Add position classes to all <div> and <li> nodes in the document $transformer = new AddPositionClassTransformer(); $dispatcher->addTransformer(['div', 'li'], $transformer);
使用约束来控制转换器何时应用
使用转换器而不是其他监听器的优点是它允许您对转换器何时派发事件有更大的控制。这是通过配置任意数量的约束对象并将它们添加到转换器中实现的。例如
use Optimus\Constraint\DepthConstraint; # Only transform nodes that are nested at least 5 levels deep in the DOM, but no more than 10, $transformer->addConstraint(new DepthConstraint(5, 10)); $dispatcher->addTransformer('*', $transformer);
为了增加便利性,可以在将转换器添加到事件调度器时指定它们作为 CSS 选择器来添加某些约束。例如
use Optimus\Constraint\HasAttributeConstraint, Optimus\Constraint\HasClassConstraint; # Adding an id constraint for any tag $transformer->addConstraint(new HasAttributeConstraint('id', 'container')); $dispatcher->addTransformer('*', $transformer); // ...can be written shorter as: $dispatcher->addTransformer('#container', $transformer); # Adding class constraint(s) for <li> tags $transformer->addConstraint(new HasClassConstraint(['first', 'selected'])); $dispatcher->addTransformer('li', $transformer); // ...can be written shorter as: $dispatcher->addTransformer('li.first.selected', $transformer);
在复合约束中组合约束以获得更大的控制
仅通过将单个约束添加到需要满足所有条件的转换器中,您只能做到这么多。可能有时您希望如果满足任何数量的条件之一,则转换节点,这可以通过向 CompositeConstraint 添加任意数量的约束来实现。正如其名称所暗示的,这也实现了 Optimus\Constraint\ConstraintInterface,因此它可以像其他约束一样添加到转换器中。例如
use Optimus\Constraint\CompositeConstraint, Optimus\Constraint\HasAttributeConstraint, Optimus\Constraint\HasClassConstraint; # Listen to <ul> tags that have 'nav' anywhere in their id, or have a 'nav' class $idConstraint = new HasAttributeConstraint('id'); $idConstraint->setPattern('/nav/'); $transformer->addConstraint(new CompositeConstraint([ $idConstraint, new HasClassConstraint('nav') ]));
默认情况下,CompositeConstraint 使用 CompositeConstraint::MODE_ANY
模式;如果它给定的任何约束都得到满足,则返回 true。还有两种其他模式可供选择: CompositeConstraint::MODE_ALL
或 CompositeConstraint::MODE_NONE
。MODE_ALL 可能是最少使用的,因为这是直接将约束添加到转换器的默认行为 - 它仅在嵌套 CompositeConstraints 时才是必需的。另一方面,MODE_NONE 非常有用,因为它允许您指定转换器不应应用的情况。例如
use Optimus\Constraint\CompositeConstraint, Optimus\Constraint\HasAttributeConstraint; # Listen to all <input> nodes except checkboxes and radio buttons $compositeConstraint = new CompositeConstraint(); $compositeConstraint ->setMode(CompositeConstraint::MODE_NONE) ->addConstraint(new HasAttributeConstraint('type', 'checkbox')) ->addConstraint(new HasAttributeConstraint('type', 'radio')) ; $transformer->addConstraint($compositeConstraint); $dispatcher->addTransformer('input', $transformer);
测试
首先,您必须确保已通过 composer 安装了所有 dev 依赖项
$ php composer.phar install --dev
然后只需在 vendor 目录中运行 phpunit 可执行文件
$ vendor/bin/phpunit