Notes on MODX Revo from beginner


Disclaimer: of Course, most likely a lot of the presented in this article seem captaincy summarized for people. However, perhaps someone it will help...

Introduction


So, what is MODX (by the way, is spelled just so — MODX, and not as the name of the hub — MODx)? If you read the official website's CMS. However, this is only part of the truth. Actually, MODX is approximately in the middle between CMS and CMF. However, anyone who would be interested in MODX it would have quickly learned from other articles, so I will not dwell on this point in detail.

Because MODX is in the middle between CMS and CMF, its not so easy to master, as a simple CMS like Wordpress or Joomla. Perhaps this article was written in an effort to uncover some of the subtleties that seem obvious at a first glance.



Installation


Personally, I installed MODX Revo 2.2.4 on a server with nginx and PHP-FPM.
As MODX imprisoned under Apache + PHP extension for nginx configuration required. My configuration looks like this:
nginx configuration
server {
listen 80;
server_name example.com *.example.com; #with this setting, MODX will process including the subdomains of the site.
index index.php index.html;
root /srv/http/example.com/public;
access_log /srv/http/example.com/logs/http_access.log main buffer=50k;
error_log /srv/http/example.com/logs/http_error.log;

# Disable logging for robots.txt. Why do we need information who watched file?
location = /robots.txt {
access_log off;
log_subrequest off;
log_not_found off;
}

# Disable logging for favicon.ico
location = /favicon.ico {
access_log off;
log_subrequest off;
log_not_found off;
}

# Disable logging for sitemap.xml
location = /sitemap.xml {
access_log off;
log_subrequest off;
log_not_found off;
}

# Disable logging for *.css And *.js files
location ~* ^.+\.(css|js)$ {
access_log off;
log_subrequest off;
log_not_found off;
}

# Also, disable log for images, files
location ~* ^.+\.(bmp|gif|jpg|jpeg|ico|png|swf)$ {
access_log off;
log_subrequest off;
log_not_found off;
}

# Block access to all hidden files, don't want to see .htaccess .git .svn, etc.
location ~ /\. {
deny all;
}

# This code directly to MODX. If the file system does not have the requested file (or folder), use a rewrite (just below himself to. htaccess). We don't want images processed MODX?
location / {
try_files $uri $uri/ @rewrite;
}

# Rewrite itself. It's very simple - MODX handles all with index.php?q= - so just we way there and toss.
location @rewrite {
rewrite ^/(.*)$ /index.php?q=$1;
}

# Plug-in the php-fpm handler
location ~ \.php$ {
# php-fpm. A socket connection.
location unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param DOCUMENT_ROOT /srv/http/example.com/public; # same as in root
fastcgi_param SCRIPT_FILENAME /srv/http/example.com/public$fastcgi_script_name; # same thing in root + $fastcgi_script_name
include fastcgi_params;
fastcgi_param REMOTE_ADDR $remote_addr; # needed to requestor's IP in PHP was not localhost.
}
}

Actually this config, I'm sure that is not ideal, but the initial configuration might be helpful. You can stay there only two things that actually connect MODX (in order to properly CNC):
the
 server_name example.com *.example.com; #with this setting, MODX will process including the subdomains of the site.

# This code directly to MODX. If the file system does not have the requested file (or folder), use a rewrite (just below himself to. htaccess). We don't want images processed MODX?
location / {
try_files $uri $uri/ @rewrite;
}

# Rewrite itself. It's very simple - MODX handles all with index.php?q= - so just we way there and toss.
location @rewrite {
rewrite ^/(.*)$ /index.php?q=$1;
}

Actually this seems to be enough for correct operation as MODX, and for everything else (loading nginx-th CSS, JS, images and other things without the participation of PHP).
The installation itself is very simple, just extract the files to the correct folder, Yes to hammer in the address bar example.com/setup/, and then uploaded a simple installer.

to human readable (friendly) URLS


Default MODX is disabled CNC. Included it is very simple: the System -> system Settings -> into the filter to drive "friendly_urls" and press Enter (you can of course and handles to find, but it's faster) -> Toggle the value to Yes and click "Save" at the top.
Do not forget that in MODX the save button located in the UPPER RIGHT CORNER. Sometimes about it it is possible to forget, and then the settings can be lost because the MODX-e AutoSave sometimes works and sometimes not.
Do the same for the function "automatic_alias" for automatic generation of the CNC.
We happily turned on the CNC, and now links will be formed in the following way:
the
example.com/resourcename.html

Please note that at the end of the expansion .html! It depends on the Content-Type and each individual resource (changes in the properties of the resource itself). The settings Content-Type-ov can be found in System -> content Types.
However, all additional GET parameters still remain the same, and it works around this:
the
example.com/news.html?date=05092012&nid=1

Me personally such a system is not liked, and I began to look for ways of how these parameters make part of the CNC. And we found it!
To begin with, should tell you a bit about the various elements to expand MODX. There are several:
the
    the
  • Template Variables — additional properties field resources. They will be back in a bit
  • the
  • Chunks — blocks of HTML code (with a possible MODX markup) that can be inserted in any drugoy chunk, online or even anywhere. Attention! PHP to insert here is impossible!
  • the
  • Snippets — blocks of PHP code which displays some data where they are inserted (with the help of MODX markup). Original PHP-equivalent chunks.
  • the
  • Plugins — blocks of PHP code that is executed in accordance with the defined events occurring within MODX. Something like Drupal-native-hooks, perhaps.

In this case, we will need snippets and plugins.
So, how to integrate into MODX with my URL format? in fact, very simple — allow MODX to try to find the page at the given URL, and when he can't find her — to take control and parse, pointing after that MODX wherever necessary. It is necessary to use a plug-in event OnPageNotFound.
plugin's Code for "improved" CNC
<?php
if($modx->request->getResourceMethod()!="alias")
return;
$uri = $modx- > resourceIdentifier;
$uriChunks = explode("/", $uri);
$paramNum=0;
$uriChunksCount = count($uriChunks);
$paramDelimiter="-"; //DO NOT use "/"! Set the desired delimiter here.
for($i=$uriChunksCount-1;$i > 0;$i--)
{
$parameter=explode($paramDelimiter, $uriChunks[$i], 2);
if(count($parameter)!=2)
return;
$modx->request->parameters['GET'][$parameter[0]]=$parameter[1];
if(empty($modx->request->parameters['POST'][$parameter[0]]))
$modx->request->parameters['REQUEST'][$parameter[0]]=$parameter[1];
$paramNum++;
unset($uriChunks[$i]);
$uri = implode("/", $uriChunks);
if (array_key_exists($uri, $modx- > aliasMap))
{
$modx- > sendForward($modx- > aliasMap[$uri]);
}
}
if($paramNum==($uriChunksCount-1))
{
$parameter=explode($paramDelimiter, $uriChunks[0], 2);
if(count($parameter)!=2)
return;
$modx->request->parameters['GET'][$parameter[0]]=$parameter[1];
if(empty($modx->request->parameters['POST'][$parameter[0]]))
$modx->request->parameters['REQUEST'][$parameter[0]]=$parameter[1];
$modx- > sendForward($modx- > getOption('site_start', null, 1));
}

In fact, it is perhaps worth looking at the following things:
the
$modx->request->getResourceMethod()

Check, whether any of the CNC.
the
$modx- > resourceIdentifier

This is not so obvious variable is stored in the requested URL.
the
$paramDelimiter="-";

This variable specifies the separator between a name of a GET parameter and its value. Unable to change to anything but "/".
the
$modx->request->parameters['GET'][$parameter[0]]=$parameter[1];
if(empty($modx->request->parameters['POST'][$parameter[0]]))
$modx->request->parameters['REQUEST'][$parameter[0]]=$parameter[1];

The fact is that with each request MODX saves all information about GET and POST parameters into their own arrays, and then generates a shared array approximately in this way:
the
$modx->request->parameters['REQUEST'] = array_merge($modx->request->parameters['GET'], ($modx->request->parameters['POST']);

To preserve this structure we have to check every time, not stored in a REQUEST-array data from the POST array, and only in their absence, to replace the data in the REQUEST array.
{ $modx- > sendForward($modx- > aliasMap[$uri]); }
And this is actually a redirect to the desired resource. $Modx- > aliasMap kept just the whole table CNC, and with it we are reconciled, figuring out, isn't it time for us to have to navigate to the desired resource or content from our neoprene uri still consists of parameters. $modx- > sendForward and it performs the redirection.

However, might want to give references to, for example, the current page using the given mechanism of the formation of the URL! For this I wrote a simple snippet, generating the URL of the current page. Of course, it can be extended to generate other links, but it will be a personal homework someone need it — nothing complicated about this present :)
the
<?php
$currentURL="";
foreach($modx->request->getParameters() as $key => $value)
{
$currentURL.=$key."=".$value."&";
}
$currentURL = $modx- > makeUrl($modx->resource->get("id"), $modx->context->get("key"), $currentURL);
return $currentURL;

In fact, too much and explain nothing. $modx- > makeUrl creates the URL. For the record — it generates it relative to the context — second parameter just sets the context.

Multisymbol in MODX


Handling multiple domains, different contexts, one MODX-om

Actually, this topic has been raised, for example, this topic and on the Internet. I would like to present your solution, I think, is quite simple. But first, list the main methods of solving this problem:
    the
  1. edit index.php. In index.php explicitly stated what the context is loaded at the start. It can be completely corrected, and to substitute in there the conditions with the choice of your context. Why is this method I don'T like: edit original files modx. Why I don't like this fact? The difficulty with updates. What I love about modx (and equally don't like forum engine SMF), it's because there's NO NEED to change any files of the original MODX that's just so much easier to update the engine as possible.
  2. the
  3. creating a plug-in event OnHandleRequest (a common drawback: uses a little more resources — always loads the web context, and only after that is loaded by the context):
      the
    1. Similarly edit index.php but without his edits. Everything is almost the same — rigidly specifies the list of domains that are handled in a strictly specified list of contexts. Alternatively, the context name contains the name of the domain (the context for the forum subdomain forum.example.com for example), on what basis and searches for the desired context For the sites will work, but flexibility is not enough.
    2. the
    3. Scan settings contexts to search. Maximum flexibility, auto-generation of contexts, there is no need to edit the plugin after it is created.



I'm going to describe here is just the last option. My text of the plugin (remember, the event is OnHandleRequest):
Plugin-gateway
<?php
if($modx->context->key!="mgr")
{
$object = $modx- > getObject('modContextSetting', array('key' => 'multisite_http_host', 'value' => $modx- > getOption('http_host')));
if($object)
$modx- > switchContext($object->get('context_key'));
}

You need to use the context properties to set the parameter "multisite_http_host" with a value of the domain it handles. If the plugin found no appropriate context, it uses the default web context.
Here I want to focus on two things.
First, in order to successfully use MODX, you need to understand the principle of xPDO. xPDO is a mechanism for communication between the database and PHP objects. Working with an object in PHP we have access to the database. Virtually everything in MODX xPDO uses to communicate with the database.
the
$object = $modx- > getObject('modContextSetting', array('key' => 'multisite_http_host', 'value' => $modx- > getOption('http_host')));

This code just refers to the database for the search object context settings, containing certain conditions (namely, the "configuration key multisite_http_host" with the value of our http host-a). Then we get the key of the context that we need to load, already from the resulting object ($object->get("context_key")).
It's very simple, it follows from the mechanism of combination of settings of system, context and user. The fact that the system settings are overwritten with the settings of the context, and those, in turn, the user settings.
In this case, http_host is the configuration of the system. If I were to use the http_host context settings is multisite_http_host, it would be overwritten by setting the context. Of course, in this particular example, it is not so bad. But need only slightly to rewrite this plugin to handle all subdomains of this domain in one context! Or, do the treatment in one context of several different domains (e.g., driving in the parameter approximately in such format: sub1.example.com;sub2.example.com;sub3.example.com" etc.). In this case, http_host was located would not http_host used in the request, namely this is the set up. But you never know, we may need the original http_host anywhere else...

Authentication in multiple contexts

Sometimes you want to authenticate the user in multiple contexts. By default, the user logging into the system (for example, by using fashion Login), logs only on a single context. The following plagini authorization automatically sets in multiple contexts (events OnWebLogin and OnWebLogout):
Multicentricity
<?php
$currentSiteGroup = $modx- > getOption("multisite_site_group");
if(empty($currentSiteGroup)) return;
$currentContext = $modx->context->get("key");
$currentContextSettings = $modx- > getCollection('modContextSetting', array('key' => "multisite_site_group", "value" => $currentSiteGroup));
foreach($currentContextSettings as $currentContextSetting)
{
$contextKey = $currentContextSetting->get('context_key');
if($contextKey!="mgr" && $contextKey!=$currentContext)
{
if($user)
{
if($modx->event->name=="OnWebLogout")
{
$modx->user->removeSessionContext($contextKey);
}
else if($modx->event->name=="OnWebLogin")
{
$modx->user->addSessionContext($contextKey);
$_SESSION['modx.'.$contextKey.'.session.cookie.lifetime']=$attributes ['lifetime'];
}
}
}
}


To use, you must put down all contexts that you want to at the same time the user has visited, the parameter "multisite_site_group" with value is the same for all required contexts.
Just a few comments:
Here searching for the right contexts is very similar to how we have implemented them in previous plugin, the only difference is the use getCollection instead of getObject. In doing so, we get an array of objects that follow the specified conditions.
the
$modx->user->addSessionContext($contextKey);

and
the
$modx->user->removeSessionContext($contextKey);

just implement authorization on a particular context.
the
$_SESSION['modx.'.$contextKey.'.session.cookie.lifetime']=$attributes ['lifetime'];

put "lifetime" authorization for all other contexts the same as for the current.

At the moment it is like everything that I wanted to tell. Developments with switching languages will be perhaps later when I have them a few drawbacks. Thank you for your attention!
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

The release of the new version of the module modLivestreet 0.3.0-rc

mSearch: search + filter for MODX Revolution

Emulator data from GNSS receiver NMEA