From 38d431b4ebf6b1f1ce9a606d0ca562143aa79131 Mon Sep 17 00:00:00 2001 From: "Edward Z. Yang" Date: Sun, 18 Mar 2007 20:12:05 +0000 Subject: [PATCH] Implement AbsolutePath and IEConditionalComments filters. Add an xc namespace (urn:xhtml-compiler) which can be used for commonly used attributes (helps cut down on xmlns declarations). DOMFilter is a little different now: instead of defining which namespaces they'd like to use, a document gets allocated a namespace based on their unique class name, so DOMFilter->ns is now that namespace, or the XC namespace if they didn't request any with DOMFilter->prefix. git-svn-id: http://htmlpurifier.org/svnroot@841 48356398-32a2-884e-a903-53898d9a118a --- XHTMLCompiler/DOMFilter.php | 35 ++++++++++++++++++++--- XHTMLCompiler/DOMFilter/AbsolutePath.php | 28 ++++++++++++++++++ XHTMLCompiler/DOMFilter/IEConditionalComments.php | 28 ++++++++++++++++++ XHTMLCompiler/DOMFilter/RSSGenerator.php | 9 +++--- XHTMLCompiler/FilterManager.php | 9 ++++++ config.default.php | 2 +- config.filters.php | 2 ++ tests/XHTMLCompiler/FilterManagerTest.php | 4 +++ 8 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 XHTMLCompiler/DOMFilter/AbsolutePath.php create mode 100644 XHTMLCompiler/DOMFilter/IEConditionalComments.php diff --git a/XHTMLCompiler/DOMFilter.php b/XHTMLCompiler/DOMFilter.php index 4beef0e..5c8777c 100644 --- a/XHTMLCompiler/DOMFilter.php +++ b/XHTMLCompiler/DOMFilter.php @@ -7,9 +7,27 @@ abstract class XHTMLCompiler_DOMFilter extends XHTMLCompiler_Filter { /** - * Lookup array of prefixes to namespace URIs for XPath. + * If set, DOMFilter will allocate a namespace for the filter + * and assign it to this prefix. + * @warning May not be 'html' or 'xc', because these are already + * allocated for the core namespaces. */ - protected $ns = array(); + protected $prefix; + + /** + * Allocated namespace for the filter, or default 'xc' one. + */ + protected $ns; + + /** + * List of attributes the extension adds to the namespace, + * helps prevent naming conflicts. + */ + protected $xcAttr = array(); + public function getXCAttributesDefined() { + return $this->xcAttr; + } + /** * Defines a filter that processes a DOMDocument. @@ -26,8 +44,17 @@ abstract class XHTMLCompiler_DOMFilter extends XHTMLCompiler_Filter public function setup($dom) { $this->dom = $dom; $this->xpath = new DOMXPath($dom); - $this->xpath->registerNamespace('html', "http://www.w3.org/1999/xhtml"); - foreach ($this->ns as $prefix => $uri) { + // defaults + $ns['html'] = "http://www.w3.org/1999/xhtml"; + $this->ns = $ns['xc'] = "urn:xhtml-compiler"; + if (isset($this->prefix)) { + if ($this->prefix == 'html' || $this->prefix == 'xc') { + throw new Exception('Prefix for ' . get_class($this) . + 'may not be the reserved ' . $this->prefix); + } + $this->ns = $ns[$this->prefix] = "urn:xhtml-compiler:" . $this->name; + } + foreach ($ns as $prefix => $uri) { $this->xpath->registerNamespace($prefix, $uri); } } diff --git a/XHTMLCompiler/DOMFilter/AbsolutePath.php b/XHTMLCompiler/DOMFilter/AbsolutePath.php new file mode 100644 index 0000000..8c8d927 --- /dev/null +++ b/XHTMLCompiler/DOMFilter/AbsolutePath.php @@ -0,0 +1,28 @@ +getConf('web_path') . '/'; + $nodes = $this->query("//*[@xc:absolute]"); + + foreach ($nodes as $node) { + // absolute + $absolute = $this->confiscateAttr($node, $this->ns, 'absolute'); + if ($absolute) { + $uri = $node->getAttribute($absolute); + $node->setAttribute($absolute, $absolute_prefix . $uri); + } + } + + } + +} + +?> \ No newline at end of file diff --git a/XHTMLCompiler/DOMFilter/IEConditionalComments.php b/XHTMLCompiler/DOMFilter/IEConditionalComments.php new file mode 100644 index 0000000..211f1fd --- /dev/null +++ b/XHTMLCompiler/DOMFilter/IEConditionalComments.php @@ -0,0 +1,28 @@ +query( "//*[@xc:ie-condition]" ); + + foreach ($nodes as $node) { + $condition = $this->confiscateAttr($node, $this->ns, 'ie-condition'); + if ($condition) { + $sxml = simplexml_import_dom($node); + $code = $sxml->asXml(); + $comment = "[if $condition]>$codeparentNode; + $parent->replaceChild($dom->createComment($comment), $node); + } + } + + } + +} + +?> \ No newline at end of file diff --git a/XHTMLCompiler/DOMFilter/RSSGenerator.php b/XHTMLCompiler/DOMFilter/RSSGenerator.php index 79224ef..3a689af 100644 --- a/XHTMLCompiler/DOMFilter/RSSGenerator.php +++ b/XHTMLCompiler/DOMFilter/RSSGenerator.php @@ -4,8 +4,7 @@ class XHTMLCompiler_DOMFilter_RSSGenerator extends XHTMLCompiler_DOMFilter { protected $name = 'RSSGenerator'; - - protected $ns = array('rss' => 'urn:xhtml-compiler:RSSGenerator'); + protected $prefix = 'rss'; // new namespace defines the following attributes: // for - IDREF to an element where we are to get the RSS info from @@ -14,7 +13,7 @@ class XHTMLCompiler_DOMFilter_RSSGenerator extends XHTMLCompiler_DOMFilter // attempt to find declarations of the namespace $nodes = $this->query( - "//attribute::*[namespace-uri() = '".$this->ns['rss']."']" + "//attribute::*[namespace-uri() = '".$this->ns."']" ); if (!$nodes->length) return; @@ -41,8 +40,8 @@ class XHTMLCompiler_DOMFilter_RSSGenerator extends XHTMLCompiler_DOMFilter $path = $page->getPath(); // remove specialized attributes - $id = $this->confiscateAttr($link, $this->ns['rss'], 'for'); - $description = $this->confiscateAttr($link, $this->ns['rss'], 'description'); + $id = $this->confiscateAttr($link, $this->ns, 'for'); + $description = $this->confiscateAttr($link, $this->ns, 'description'); $lang = $dom->documentElement->getAttribute('xml:lang'); diff --git a/XHTMLCompiler/FilterManager.php b/XHTMLCompiler/FilterManager.php index 8aa258d..59bdd57 100644 --- a/XHTMLCompiler/FilterManager.php +++ b/XHTMLCompiler/FilterManager.php @@ -9,6 +9,7 @@ class XHTMLCompiler_FilterManager protected $preTextFilters = array(); protected $postTextFilters = array(); protected $DOMFilters = array(); + protected $xcAttr = array(); protected $errors = array(); @@ -59,6 +60,14 @@ class XHTMLCompiler_FilterManager throw new Exception('Cannot overload DOM filter ' . $filter->getName()); } + $attributes = $filter->getXCAttributesDefined(); + foreach ($attributes as $attribute) { + if (isset($this->xcAttr[$attribute])) { + throw new Exception('Duplicate attribute definition for '. + 'xc:' . $attribute); + } + $this->xcAttr[$attribute] = true; + } return $this->DOMFilters[$n] = $filter; } diff --git a/config.default.php b/config.default.php index 1d5bcd4..bde8a05 100644 --- a/config.default.php +++ b/config.default.php @@ -38,7 +38,7 @@ $directory_index = 'index.html'; // ** Path to web root of the parent of XHTML Compiler's install library // If you installed XHTML Compiler at /xhtml-compiler, nothing needs to // be done. If you installed it at /subdir/xhtml-compiler, you need -// to set this variable to /subdir +// to set this variable to /subdir. MUST NOT have trailing slash $web_path = ''; ?> \ No newline at end of file diff --git a/config.filters.php b/config.filters.php index c2ed519..8fdac3f 100644 --- a/config.filters.php +++ b/config.filters.php @@ -6,5 +6,7 @@ $filters->addDOMFilter('GenerateTableOfContents'); $filters->addDOMFilter('Acronymizer'); $filters->addDOMFilter('Quoter'); $filters->addDOMFilter('RSSGenerator'); +$filters->addDOMFilter('AbsolutePath'); +$filters->addDOMFilter('IEConditionalComments'); ?> \ No newline at end of file diff --git a/tests/XHTMLCompiler/FilterManagerTest.php b/tests/XHTMLCompiler/FilterManagerTest.php index 4e58243..1990bfe 100644 --- a/tests/XHTMLCompiler/FilterManagerTest.php +++ b/tests/XHTMLCompiler/FilterManagerTest.php @@ -16,6 +16,7 @@ class XHTMLCompiler_FilterManagerTest extends UnitTestCase $filter = new XHTMLCompiler_DOMFilterMock($this); $filter->expectOnce('getName'); $filter->setReturnValue('getName', 'filter'); + $filter->setReturnValue('getXCAttributesDefined', array()); $manager->addDOMFilter($filter); $filter->tally(); } @@ -24,6 +25,7 @@ class XHTMLCompiler_FilterManagerTest extends UnitTestCase $manager = new XHTMLCompiler_FilterManager(); $filter = new XHTMLCompiler_DOMFilterMock($this); $filter->setReturnValue('getName', 'filter'); + $filter->setReturnValue('getXCAttributesDefined', array()); $filter2 = new XHTMLCompiler_DOMFilterMock($this); $filter2->setReturnValue('getName', 'filter'); $manager->addDOMFilter($filter); @@ -56,9 +58,11 @@ xmlns:proprietary="urn:foobar:foofoofoo"> // the first two DOMFilters are duds that don't do anything $dom_filter = new XHTMLCompiler_DOMFilterMock($this); $dom_filter->setReturnValue('getName', 'filter'); + $dom_filter->setReturnValue('getXCAttributesDefined', array()); $dom_filter->expectOnce('process'); $dom_filter2 = new XHTMLCompiler_DOMFilterMock($this); $dom_filter2->setReturnValue('getName', 'filter2'); + $dom_filter2->setReturnValue('getXCAttributesDefined', array()); $dom_filter2->expectOnce('process'); $dom_filter3 = new XHTMLCompiler_FilterManagerTest_DOMFilter(); -- 2.11.4.GIT