⬆️ ⬇️

Easyweb: New Year Update

In my previous post , which introduced Easyweb web engine to a respected public, it was said:

It is planned that the first version, which can be called stable and completely usable, will appear before the end of the year.


Since there is less than a day left before the end of the year, let me tell you what else we have been able to do this year.





XML facilities



Among other tasks assigned to Easyweb, there was a need to make working with XML on the PHP side as clean, elegant, compact and easy to understand. At the moment, all the basic methods of XML-Facilitation are added. Description of public methods and small examples of use:



As always, any additional functionality can be requested via the feature request on GitHub.



I will give an example of solving the same problem on the standard PHP DOM API, and on Easyweb XML facilities. The bottom line is this. You need to download a file with a description of the books, and do the following with each book: reset the price, replace the currency code with its lower case writing, and set the specified identifiers for the author and the category of the book (including error checking).

')

It was:

<?php function replace($author_id, $category_id) { $xml = new DOMDocument(); if(!$xml->load('/var/www/html/mywebsite/xml/library.xml')) { throw new Exception('Error loading XML file'); } $xpath = new DOMXPath($xml); foreach($xpath->query('/books/book') as $book) { $price = $xpath->query('price', $book); if($price->length != 1) { throw new Exception('Node "price" should be unique for the book'); } $price->item[0]->nodeValue = 0; $currency = $price->getAttribute('currency'); if($currency) { $book->setAttribute('currency', strtolower($currency)); } else { throw new Exception('Attribute "currency" not found'); } $book->setAttribute('author_id', $author_id); $book->setAttribute('category_id', $category_id); } } ?> 


It became:

 <?php function replace($author_id, $category_id) { $xml = xml::load('/xml/library.xml'); foreach($xml->query('/books/book') as $book) { $book['price'] = 0; $book['price/@currency'] = strtolower($book['price/@currency']); $book['@author_id'] = $author_id; $book['@category_id'] = $category_id; } } ?> 


Easyweb XML facilitations can be constructed from native PHP DOM resource handle, and also given to the user through the member function ::get() , so you can easily integrate with third-party libraries working through native PHP DOM objects.





XPath extension www: paginate



www:paginate($page, $count, $size)



The function is intended to simplify the rendering of a static paginator.

$page is the current page.

$count - the total number of pages.

$size - paginator size.

The current page is marked with the current attribute. On the first page there will be no <previous /> node, on the last page there will be <next /> nodes.



Calling the function www:paginate(15, 85, 10) will return the following XML:

 <pages> <previous>14</previous> <page>10</page> <page>11</page> <page>12</page> <page>13</page> <page>14</page> <page current="current">15</page> <page>16</page> <page>17</page> <page>18</page> <page>19</page> <next>16</next> </pages> 


Layout example:

 <xsl:template match="/"> <xsl:apply-templates select="www:paginate(15, 85, 10)/pages/*" /> </xsl:template> <xsl:template match="previous"> <a href="/page/{.}/" class="page">← Previous</a> </xsl:template> <xsl:template match="next"> <a href="/page/{.}/" class="page">Next →</a> </xsl:template> <xsl:template match="page[@current]"> <span class="page current"><xsl:value-of select="." /></span> </xsl:template> <xsl:template match="page"> <a href="/page/{.}/" class="page"><xsl:value-of select="." /></a> </xsl:template> 


Possible result:

image





Block caching



Now the result of the www:xslt XSL extension can be cached into files. To do this, add the attribute cache="true" . There are also two optional attributes cache-args and cache-lifetime , the first of which allows you to transfer a list of simple parameters to the cached block, and the second to limit the lifetime of the cached data. Usage example:

 <www:xslt xsl="/books.xsl" xml="book:list(author_id -> {$author_id})" args="page -> {$page}, count -> 10" cache="true" cache-args="domain -> '{$domain}'" cache-lifetime="600" /> 




Xquery



The first version of XQuery support in Easyweb. At the moment, its capabilities are severely limited: you cannot pass parameters, you cannot use Easyweb XSL and XPath extensions. The main problem now is that a good XQuery library for PHP could not be found in principle. If you can help with wise advice, I will be glad to hear it here: habrahabr.ru/qa/31087



At the moment, XQuery is made through XQuery Lite ( http://phpxmlclasses.sourceforge.net/xquery_lite.html ), which was made and abandoned by its author back in 2002. XQuery Lite is laid out in the Easyweb repository due to the fact that it had to be finished with a file in order for it to work in PHP5.



XQuery support now is to introduce the www:xquery XSL extension:

 <div> <h1>External Resources</h1> <www:xquery src="/tpl/links.xq" /> </div> 




Custom XSL Extensions



Now the user can register his own XSL extensions in the engine. For your own extension, you must specify the namespace, as well as its URI. The same thing needs to be done in the XSL page templates. An example of registering an XSL extension that implements some text processing (for example, some custom markup):

 $www = www::create('en', 'us'); $www->register_xsl('http://supermarkup.com/about', 'sm', 'block', function($node) { $xml = new xml(); foreach($node->children() as $child) { $xml->append($xml->import($child)); } foreach($xml->query('//text()') as $text) { $parent = $text->parent(); $parent->append(supermarkup($text->value())); $parent->remove($text); } return $xml; }); 


Use in pattern:

 <?xml version="1.0" encoding="utf-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" xmlns:www="https://github.com/nyan-cat/easyweb" xmlns:sm="http://supermarkup.com/about" exclude-result-prefixes="php www sm"> <xsl:template match="/"> <sm:block> <xsl:copy-of select="message" /> </sm:block> </xsl:template> </xsl:stylesheet> 


The extension handler function works through Easyweb XML Facility. It takes as input an XML node, which is an extension, and returns either an XML node or an XML document to replace the extension node.



Why is it better to write custom extensions than poking around in the engine code? Because Easyweb guarantees (or almost guarantees) that the registration interface and extension handler will not change, but the undocumented entrails may well be sawed through.





Geoip



Support for GeoIP appeared in the engine. For his work you will need to install PHP PECL GeoIP. GeoIP support is made through the Easyweb abstract procedure interface. An example of a description of a GeoIP procedure in the site config:

 <procedure name="geoip:record" datasource="geoip" method="record" root="record"> <param name="host" type="string" /> </procedure> 


Now this procedure can be used in any place where Easyweb abstract procedures are used: when rendering a page, when rendering a block, when calculating access rights groups, when calling the www:query XPath extension, or from PHP via an Easyweb instance. Call example:

 $record = $www->query('geoip:record', array ( 'host' => $www->variable('user:ip') )); 


Possible result:

 <?xml version="1.0"?> <record> <country> <alpha2>US</alpha2> <alpha3>USA</alpha3> <name>United States</name> </country> <region>NC</region> <city>Charlotte</city> <latitude>35.206001281738</latitude> <longitude>-80.829002380371</longitude> </record> 


Do not forget that you need to download the GeoIP base separately:





Full-text and faceted search



The first trial version of full-text and faceted search appeared. Search is performed via Apache Solr ( http://lucene.apache.org/solr/ ). To use the search, you will need to install Java, Servlet container (for example, Tomcat or Jetty), Solr itself, as well as PHP PECL SolrClient. Simple and accessible article on installing Solr on CentOS: http://blog.nexcess.net/2011/12/30/installing-apache-solr-on-centos/ .



As in the case of GeoIP, Solr-search is implemented through Easyweb abstract procedures that can be used in different engine subsystems. Config example:

 <datasource name="metadata" type="solr" server="localhost" port="8080" url="/solr/" username="admin" password="samplepassword" /> <!-- ... --> <procedure name="guestbook:add" datasource="guestbook" core="guestbook" method="add"> <param name="author_id" type="natural" /> <param name="message" type="author" /> <param name="host" type="ipv4" /> </procedure> <!-- ... --> <procedure name="guestbook:list" datasource="guestbook" core="guestbook" method="query" root="messages" item="message"> *:* </procedure> 


So far, you need to configure Solr yourself. In the future, it is planned to make a Solr circuit generator on the fly.





Conclusion



So, the engine implements all the core core-level functions that were previously planned. LL (1) parsers, the ORM system and the framework for full-duplex communication between the client and the server remain in the longer-term plans.



Plans for the beginning of the next year are to move one Large Commercial Website © using all Easyweb functions to a new version of the engine, in parallel with which the detected errors will be fixed.



With great joy, I will accept your features, bug reports, and simple questions on installing and using Easyweb.



Happy New Year!

Source: https://habr.com/ru/post/164397/



All Articles