Company information
Fill up the form and we will contact you shortly.
ServoCode Sp. z o.o.
Jasionka 954E, 36-002 Jasionka, Poland
NIP: 8133719852
REGON: 364182909
KRS: 0000611643
The best plugins are the ones that are made by someone else and ready to use, right? Unfortunately, not all functionalities have dedicated MODX plugins. You must make them. If you do it well, you can reuse these plugins later. All hail to the MODX plugin development!
Now the question is how to make it right?
First, I'll introduce you to MODX plugin development with a simple example of an xPDO object with its schema and a certain output:
Controllers - a folder that contains controllers of the plugin.
Docs - readme, changelogs, docs for the plugin.
Elements - Snippets, Chunks, code.
Lexicon - translations for plugin.
Model - folder that contains object representations and XML schema of costume tables structure.
Processors - Costume processors of our plugin.
It will store main routes to the plugin.
testplugin.core_path - /www/page/core/components/testplugin/
testplugin.assets_url - /page/assets/components/testplugin/
Routes can be different due to the system setup.
Snippet file will be used to render the content of the custom object. Create a file with the snippet to output example content of our plugin in:
/www/page/core/components/testplugin/elements/snippets/snippet.doodles.php
It should look like:
<?php
$testPlug = $modx->getService('testplugin','TestPlugin',$modx->getOption('testplugin.core_path',null,$modx->getOption('core_path')).'model/testplugin/',$scriptProperties);
if (!($testPlug instanceof TestPlugin)) return '';
$tpl = $modx->getOption('tpl',$scriptProperties,'rowTpl');
$sort = $modx->getOption('sort',$scriptProperties,'name');
$dir = $modx->getOption('dir',$scriptProperties,'ASC');
/* build query */
$c = $modx->newQuery('TestPlugin');
$c->sortby($sort,$dir);
$tests = $modx->getCollection('TestPlugin',$c);
print_r($tests);
/* iterate */
$output = '';
foreach ($tests as $test) {
$doodleArray = $test->toArray();
$output .= $testPlug->getChunk($tpl,$doodleArray);
}
return $output;
This snippet will get the xPDO object and show it with tpl which must be created under:
/www/page/core/components/testplugin/elements/chunks/
with the name rowtpl.chunk.tpl. It should contain simple output template:
<li><strong>[[+name]]</strong> - [[+description]]</li>
It will handle the main behavior of plugin and some main methods:
<?php
class TestPlugin
{
public $modx;
public $config = array();
public function __construct(modX &$modx, array $config = array())
{
$this->modx =& $modx;
$basePath = $this->modx->getOption('testplugin.core_path', $config, $this->modx->getOption('core_path') . 'components/testplugin/');
$assetsUrl = $this->modx->getOption('testplugin.assets_url', $config, $this->modx->getOption('assets_url') . 'components/testplugin/');
$this->config = array_merge(array(
'basePath' => $basePath,
'corePath' => $basePath,
'modelPath' => $basePath . 'model/',
'processorsPath' => $basePath . 'processors/',
'templatesPath' => $basePath . 'templates/',
'chunksPath' => $basePath . 'elements/chunks/',
'jsUrl' => $assetsUrl . 'js/',
'cssUrl' => $assetsUrl . 'css/',
'assetsUrl' => $assetsUrl,
'connectorUrl' => $assetsUrl . 'connector.php',
), $config);
// add this below
$this->modx->addPackage('testplugin',$this->config['modelPath']);
}
public function getChunk($name, $properties = array())
{
$chunk = null;
if (!isset($this->chunks[$name])) {
$chunk = $this->modx->getObject('modChunk', array('name' => $name));
if (empty($chunk) || !is_object($chunk)) {
$chunk = $this->_getTplChunk($name);
if ($chunk == false) return false;
}
$this->chunks[$name] = $chunk->getContent();
} else {
$o = $this->chunks[$name];
$chunk = $this->modx->newObject('modChunk');
$chunk->setContent($o);
}
$chunk->setCacheable(false);
return $chunk->process($properties);
}
private function _getTplChunk($name, $postfix = '.chunk.tpl')
{
$chunk = false;
$f = $this->config['chunksPath'] . strtolower($name) . $postfix;
if (file_exists($f)) {
$o = file_get_contents($f);
$chunk = $this->modx->newObject('modChunk');
$chunk->set('name', $name);
$chunk->setContent($o);
}
return $chunk;
}
}
It contains the xPDO schema with fields and object name and defines it.
Under /www/site/core/components/testplugin/model/schema/ create file testplugin.mysql.schema.xml whitch will contain object schema:
<?xml version="1.0" encoding="UTF-8"?>
<model package="testplugin" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.0">
<object class="TestPlugin" table="testplugin" extends="xPDOSimpleObject">
<field key="name" dbtype="varchar" precision="255" phptype="string" null="false" default=""/>
<field key="description" dbtype="text" phptype="string" null="false" default=""/>
<field key="createdon" dbtype="datetime" phptype="datetime" null="true"/>
<field key="createdby" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" />
<field key="editedon" dbtype="datetime" phptype="datetime" null="true"/>
<field key="editedby" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" />
<aggregate alias="CreatedBy" class="modUser" local="createdby" foreign="id" cardinality="one" owner="foreign"/>
<aggregate alias="EditedBy" class="modUser" local="editedby" foreign="id" cardinality="one" owner="foreign"/>
</object>
</model>
Build script under the folder /www/site/core/components/testplugin/_build and create two files. One of them will contain config and another build script whitch will create tables in the base and generate a part of the plugin:
The firsts file is build.config.php whitch contains the constants and conf of the build:
<?php
include_once dirname(dirname(dirname(dirname(__FILE__)))).'/config/config.inc.php';
You also can create or owerride settings with define('MODX_EXAPLE_VAR', 'some value for our variable');
Now create the build script whitch will hadle plugin setup build.schema.php:
<?php
require_once dirname(__FILE__).'/build.config.php';
include_once MODX_CORE_PATH . 'model/modx/modx.class.php';
$modx= new modX();
$modx->initialize('mgr');
$modx->loadClass('transport.modPackageBuilder','',false, true);
$modx->setLogLevel(modX::LOG_LEVEL_INFO);
$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
$sources = array(
'model' => $modx->getOption('testplugin.core_path').'model/',
'schema_file' => $modx->getOption('testplugin.core_path').'model/schema/testplugin.mysql.schema.xml'
);
$manager= $modx->getManager();
$generator= $manager->getGenerator();
if (!is_dir($sources['model'])) { $modx->log(modX::LOG_LEVEL_ERROR,'Model directory not found!'); die(); }
if (!file_exists($sources['schema_file'])) { $modx->log(modX::LOG_LEVEL_ERROR,'Schema file not found!'); die(); }
$generator->parseSchema($sources['schema_file'],$sources['model']);
$modx->addPackage('testplugin', $sources['model']); // add package to make all models available
$manager->createObjectContainer('TestPlugin'); // created the database table
$modx->log(modX::LOG_LEVEL_INFO, 'Done!');
For displaying the chunk, you may use a static snippet in manager in file field add a file of the snippet, for its better modifying process:
That's enough for today's post. If you have any questions, feel free to ask them below!
MODx multi-language web app using native modx contexts and Babel
Have an idea ? Let’s talk
Fill up the form and we will contact you shortly.
ServoCode Sp. z o.o.
Jasionka 954E, 36-002 Jasionka, Poland
NIP: 8133719852
REGON: 364182909
KRS: 0000611643
Your message has been sent!
Your message has been sent!