📜 ⬆️ ⬇️

QuadBraces III

Good health to all!

It has been almost exactly two years since my first publication on the QuadBraces parser , an MODX Evolution alternative for the simplest projects that require standardization. These can be single pages with typical publications, portfolios, business cards, consisting of almost static pages, and so on. Since then, I updated my development and unnoticed by the community crawled to the third version. The current version of the QuadBraces parser contains so many changes that I just have to publish a detailed tutorial. So…

Tags


Let's start with tag handlers. In QuadBraces, 3 tag handlers are rendered into separate classes. Now the developer is free to define his tag types without changing the code of the parser itself. To do this, create a descendant of the QuadBracesTagPrototype class, where you need to define the following:


On the example of a constant tag handler:
')
class QuadBracesTagConstant extends QuadBracesTagPrototype { protected $_name = 'constant'; protected $_start = '\{\*'; protected $_rstart = '\/'; protected $_finish = '\*\}'; protected $_order = 5; public function main(array $m,$key='') { $v = ''; if (empty($key) || !defined($key)) { $this->_error = 'not found'; } else { $v = constant($key); } return $v; } } 

Yeah, right - everything is just that simple. Although I, as a programmer of the old school, are terribly enraged by the need to store files of microscopic size. But this is a personal matter, as they say.

For those who have not read the previous publication. The syntax of QuadBraces tags is the same for all tag types:

  1. The initial sequence of characters. For example, "{{".
  2. Entity ID. It should consist of Latin, numerals, "logs", a dash and / or a dot. For example, "my-chunk". Note! The point in the identifier plays the role of a nesting level separator. That is, looking ahead, for example, the variable "my.var" will be located in fact here - $ parser-> data ['my'] ['var']. About chunks, snippets and templates - below.
  3. A number of handler extensions (optional). Each is a construction of the form ": some_id" or ": some_id =` some_data` "(without a space between the colon and the identifier). Handler extensions work with the end result of tag processing. That is, for example, we received a variable containing a phone number, and then formatted it for human comprehension.
  4. For compatibility with the MODX syntax, a question mark may follow.
  5. A certain number of arguments (optional). Each argument is a construction of the form "& some_name =` certain_value` ". Yes, variables can even have arguments. Yes, they work. In most cases, the arguments passed are used in local placeholders.
  6. The final sequence of characters. For example, "}}".

In the third version of the parser, as you probably already understood, there is a MODX Revolution syntax mode. In this mode, tags start with two opening square brackets, followed by some symbol that defines the type of tag. And the tag is always closed with two closing square brackets.

An example of a certain chunk tag:

 {{news-item? &title=`   ` &date=`15-09-17` &url=`/news/150917.html`}} 

If the chunk is:
 <article> <h3>[+title+]</h3> <span class="date">[+date+]</span> <a href="[+url+]"> </a> </article> 

Then, as a result, on the site of the chunk will be displayed:
 <article> <h3>   </h3> <span class="date">15-09-17</span> <a href="/news/150917.html"> </a> </article> 

Speaking of flies. Didn’t they eat the HTML item from the “source code” menu of the editor in our Cozy?

Out of the box, QuadBraces supports the following types of tags (the starting and ending sequences for two modes are indicated):


In the current version of the parser, it is possible to cram a so-called set into the parser object. resources. In essence, this is about the same as the resources in MODX. Roughly speaking, a table is stored in the database of the final project, in which the entries with posts for the blog are stored. The main thing is to remember that each entry must contain a numeric ID, a parent ID or NULL and an alias for creating a URL. Setting the resources property of the parser object sets the idx property of the parser object. It is an index of the branches of the resource tree. This allows you to work with the structure of the final set of resources. Actually, the link tag works with all this garbage functionality.

Custom variable handlers are such micro-parsers that arbitrarily process parser variables. For example, if a certain variable of the parser (let's call it, say, top-menu) contains an array with URLs of the form:

 array( array('url' => '/','title' => ''), array('url' => '/about.html','title' => ' '), array( 'url' => '/news/','title' => '','children' => array( array('url' => '/news/10-09-17.html','title' => '   '), array('url' => '/news/15-09-17.html','title' => '   ') ) ), array('url' => '/contacts.html','title' => ''), ); 

From it you can make a menu. To do this, it is enough to place the structure in the right place:

 [:menu@top-menu:] 

In its place will be displayed menu with the help of bulleted lists. In the best traditions of Wayfinder, so to speak.

In general, on custom handlers, I think, you will need to write a separate article.

Separately, about one important piece of templates, namely about the metafield. Almost from the first version, it is possible to set meta fields in the template code. They are essentially variables defined in the template itself by this construction:

<!-- FIELD:_? [] -->

Arguments are about the same as in parser tags. Regardless of which arguments will be specified in the field, the final field will contain three attributes:


All metafields will be available through the parser's fields property.

Meta values ​​are no less important. Imagine that in our parser the variable somevar is defined. The meta value in the set pattern can override the current value of the variable. Meta values ​​are determined by the construction:

<!-- DATA:_ ` ` -->

When a template is installed, both are removed from the final template code.

Class API


Class properties (most important)

:

Methods

:

Where to look?


One of the most important properties of the QuadBraces parser is the paths property. It determines where the parser will look for chunks, snippets, extensions, templates. The language system works a bit isolated. In the process of searching for an element, the parser iterates through all the registered paths. Each time, the search function adds a folder to the selected path, depending on the type of item. Chunks - chunks, templates - snippets - snippets. And already there is searched for the desired item. I recall that the dot in the keys of the chunks, snippets and templates in fact replaces the directory separator.

Example:

 $parser->paths = 'D:/projects/mysite/content,D:/repo/templates/default'; $fn = $parser->search('snippet','basis.snipcon'); 

In fact, the parser in this case will check for the existence of the following files:

D:/projects/mysite/content/snippets/basis/snipcon.php
D:/repo/templates/default/snippets/basis/snipcon.php


The last found file will be returned. When the language system is enabled, paths with language signatures are actually added to the search. Suppose the installed language is Russian, that is, the signature is “ru”. Thus the file list is as follows:

D:/projects/mysite/content/snippets/basis/snipcon.php
D:/projects/mysite/content/snippets/basis/ru/snipcon.php
D:/repo/templates/default/snippets/basis/snipcon.php
D:/repo/templates/default/snippets/basis/ru/snipcon.php


Everything else is obtained through properties and methods.

Language system


First, at once I will make a reservation that the language system should be included explicitly. This is done by connecting the QuadBracesLang class. This is done with the simplest code before the main class includes:

 define("QUADBRACES_LOCALIZED",true); 

It is best to enable the loadLanguage flag. Then the dictionaries will be loaded automatically. In principle, by default, when installing parser paths, the paths of the language system are set. In fact, the language system is looking for its files on the same principle as the search engine of elements. Only the language system folder is lang.

Example:

 $parser->paths = 'D:/projects/mysite/content,D:/repo/templates/default'; $parser->language = 'ru'; 

Folders will be scanned:

D:/projects/mysite/content/lang/ru/
D:/repo/templates/default/lang/ru/


In this, all files with the extension “lng” will be searched. Each file is read line by line. Each line contains four elements - a language key, title, description, placeholder. The language key is what is later used in the language tag. Caption - replaces the default language tag. Description (description) - usually used for hints or descriptions of fields. Placeholder (placeholder) - most often used for the corresponding attribute of input elements.

Developments


The parser object supports events. Handlers, as I wrote above, are installed by the registerEvent method.

Supported events (everywhere $ p is a parser object):




I repent, unknowingly ran into one feature of PHP. If, say, you assign a function to the event handler for templateNotFound, and in it try to set the template property, nothing happens. This is due to the limitations of recursion when calling accessors on properties of a PHP object. In short, you cannot set a property through an accessor and the accessor of the same property. No From the word "absolutely." So if you want to make the 404th through the templateNotFound event handler, call the setTemplate method inside it.

Handler Extensions


All tags support final value handlers. For example, we received a variable, and it is empty. The notempty handler allows you to set the output text for this case. Some extensions have additional "extensions". For example, the base logic has the extensions “then” and “else”.

Supported Handlers



The ul / ol extension has two internal placeholders: [+ classes +] - element classes (first, last), [+ item +] - the actual string. An internal placeholder [+ iterator +] is available for the for extension, containing the current iteration number. For the foreach extension, internal placeholders are available: [+ iterator.index +] - the position number of the current iteration, [+ iterator +] - the current index.

Practical work


Actually, working with the parser class is very easy. Basic example:

 <?php require 'quadbraces/parser.php'; $parser = new QuadBracesParser('//__'); $parser->template = 'my-template'; echo $parser->parse(); ?> 

In it, we connect the class of the parser, initialize the object with passing the path to the template data, set the template and parsim. Of course, prior to processing, you can pass in the "settings" parser, variables. And before turning on the class of the parser, turn on the language system, as described above. A more practical example:

 <?php define("QUADBRACES_LOCALIZED",true); require 'quadbraces/parser.php'; $parser = new QuadBracesParser('D:/projects/foo/content/template'); $parser->language = 'ru'; $parser->data = array( 'pagetitle' => '  ', 'date' => '20-09-17', 'image' => 'content/images/flies.jpg' ); $parser->template = 'news.single'; echo $parser->parse(); ?> 

The template will be searched in the following files:

D:/projects/foo/content/template/templates/news/single.html
D:/projects/foo/content/template/templates/news/ru/single.html


Outcome-disclaimer


Immediately I apologize for my inability to write tutorials and documentation! If the community is really interesting, the most interesting moments will be revealed in subsequent publications. Ask questions - I will answer with pleasure. If you notice an error, write issues on the github here .

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


All Articles