Welcome to Kodlogs Q&A, where you can ask programming questions and receive answers from other members of the community. For programmers, by programmers Kodlogs is an open community for anyone that does coding. We help you get answers to your toughest coding questions, share knowledge with your coworkers in private, and find your next IT dream job.
0 votes
33 views
What is prevnext from MODX Revolution? Is there any documentation or tuitorial to show how to use prevnext navigator snippet from MODX Revolution to navigate to Previous and Next links in a page?

I can't find much information in the web.

http://modx.com/extras/package/prevnext
in MODX by (8.5k points)
edited by

3 Answers

0 votes

prevNext MODX Addon:

prevNext is a snippet to navigate to Previous and Next links in a page.This was released  as extra by goldsky.  prevNext was released on August 3, 2014.

Their supported version ranges from 2.2 till current. More than three thousand copies of prevNext has been downloaded. 

prevNext supports MySQL database for information storage. It seems the minimum MODX Requirement is 2.2 for successful execution.

prevNext Addon from MODX revolution:

 prevNext MODX features:

Some of properties of Basic call: [[!prevNext]] are as following:

* &sort

* &includeHidden

 * &prevPrefix

 *  &nextPrefix

*  &tvPrefix

*  &tpl

*  &css

*  &includeTVs

*  &includeTVList

*  &processTVs

*  &processTVList

*  &parents

*  &toArray

*  &toPlaceholder

Latest features in prevNext 1.0.1

Some of the new  features updates in prevNext as on Mar 1, 2016 are as following:

- getbootstrap's dependency has been removed, CSS file has been added.

- When there is duplication, there is fixed comparison when resource has the same   published data

- logic has been moved to class

userNext Usage Instructions:

Package Manger provides download link for installation of userNext addon.

Some suggested readings:

https://modx.com/extras/package/prevnext

https://github.com/goldsky/prevNext

 

 

 

by (8.5k points)
edited by
0 votes

code snippets for prevnext

* @package prevnext

* @subpackage build

*/

$mtime = microtime();

$mtime = explode(" ", $mtime);

$mtime = $mtime[1] + $mtime[0];

$tstart = $mtime;

set_time_limit(0);

/* define version */

define('PKG_NAME', 'PrevNext');

define('PKG_NAME_LOWER', 'prevnext');

/* override with your own defines here (see build.config.sample.php) */

require_once dirname(__FILE__) . '/build.config.php';

require_once realpath(MODX_CORE_PATH) . '/model/modx/modx.class.php';

/* define sources */

$root = dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR;

$sources = array(

'root' => $root,

'build' => BUILD_PATH,

'resolvers' => BUILD_PATH . 'resolvers' . DIRECTORY_SEPARATOR,

'validators' => realpath(BUILD_PATH . 'validators/') . DIRECTORY_SEPARATOR,

'data' => BUILD_PATH . 'data' . DIRECTORY_SEPARATOR,

'properties' => realpath(BUILD_PATH . 'data/properties/') . DIRECTORY_SEPARATOR,

'source_core' => realpath(MODX_CORE_PATH . 'components') . DIRECTORY_SEPARATOR . PKG_NAME_LOWER,

'source_assets' => realpath(MODX_ASSETS_PATH . 'components') . DIRECTORY_SEPARATOR . PKG_NAME_LOWER,

'docs' => realpath(MODX_CORE_PATH . 'components/' . PKG_NAME_LOWER . '/docs/') . DIRECTORY_SEPARATOR,

'lexicon' => realpath(MODX_CORE_PATH . 'components/' . PKG_NAME_LOWER . '/lexicon/') . DIRECTORY_SEPARATOR,

);

unset($root);

$modx = new modX();

$modx->initialize('mgr');

$modx->setLogLevel(modX::LOG_LEVEL_INFO);

$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');

echo '<pre>';

$prevnext = $modx->getService('prevnext', 'PrevNext', MODX_CORE_PATH . 'components/prevnext/model/prevnext/');

if (!($prevnext instanceof PrevNext))

return '';

define('PKG_VERSION', PrevNext::VERSION);

define('PKG_RELEASE', PrevNext::RELEASE);

$modx->loadClass('transport.modPackageBuilder', '', false, true);

$builder = new modPackageBuilder($modx);

$builder->createPackage(PKG_NAME_LOWER, PKG_VERSION, PKG_RELEASE);

$builder->registerNamespace(PKG_NAME_LOWER, false, true, '{core_path}components/' . PKG_NAME_LOWER . '/');

/**

* SYSTEM SETTINGS

*/

$settings = include $sources['data'] . 'transport.settings.php';

if (!is_array($settings)) {

$modx->log(modX::LOG_LEVEL_ERROR, 'Could not package in settings.');

} else {

$modx->log(modX::LOG_LEVEL_INFO, 'Packaging in System Settings...');

$settingAttributes = array(

xPDOTransport::UNIQUE_KEY => 'key',

xPDOTransport::PRESERVE_KEYS => true,

xPDOTransport::UPDATE_OBJECT => false,

);

foreach ($settings as $setting) {

$settingVehicle = $builder->createVehicle($setting, $settingAttributes);

$builder->putVehicle($settingVehicle);

}

$modx->log(modX::LOG_LEVEL_INFO, 'Packaged in ' . count($settings) . ' System Settings done.');

unset($settingVehicle, $settings, $setting, $settingAttributes);

}

/**

* CATEGORY

*/

$category = $modx->newObject('modCategory');

$category->set('id', 1);

$category->set('category', 'PrevNext');

/**

* SNIPPETS

*/

$modx->log(modX::LOG_LEVEL_INFO, 'Adding in snippets.');

$snippets = include $sources['data'] . 'transport.snippets.php';

if (is_array($snippets)) {

$category->addMany($snippets);

$modx->log(modX::LOG_LEVEL_INFO, 'Adding in ' . count($snippets) . ' snippets done.');

} else {

$modx->log(modX::LOG_LEVEL_FATAL, 'Adding snippets failed.');

}

/**

* Apply category to the elements

*/

$elementsAttribute = array(

xPDOTransport::UNIQUE_KEY => 'category',

xPDOTransport::PRESERVE_KEYS => false,

xPDOTransport::UPDATE_OBJECT => true,

xPDOTransport::RELATED_OBJECTS => true,

xPDOTransport::RELATED_OBJECT_ATTRIBUTES => array(

'Snippets' => array(

xPDOTransport::PRESERVE_KEYS => false,

xPDOTransport::UPDATE_OBJECT => true,

xPDOTransport::UNIQUE_KEY => 'name',

),

)

);

$elementsVehicle = $builder->createVehicle($category, $elementsAttribute);

/**

* FILE RESOLVERS

*/

$elementsVehicle->resolve('file', array(

'source' => $sources['source_core'],

'target' => "return MODX_CORE_PATH . 'components/';",

));

$elementsVehicle->resolve('file', array(

'source' => $sources['source_assets'],

'target' => "return MODX_ASSETS_PATH . 'components/';",

));

$modx->log(modX::LOG_LEVEL_INFO, 'Adding in files done.');

$builder->putVehicle($elementsVehicle);

unset($elementsVehicle);

$modx->log(modX::LOG_LEVEL_INFO, 'Packaged in Elements done.');

flush();

/**

* license file, readme and setup options

*/

$builder->setPackageAttributes(array(

'license' => file_get_contents($sources['docs'] . 'license.txt'),

'readme' => file_get_contents($sources['docs'] . 'readme.txt'),

'changelog' => file_get_contents($sources['docs'] . 'changelog.txt'),

));

$builder->pack();

$mtime = microtime();

$mtime = explode(" ", $mtime);

$mtime = $mtime[1] + $mtime[0];

$tend = $mtime;

$totalTime = ($tend - $tstart);

$totalTime = sprintf("%2.4f s", $totalTime);

$modx->log(modX::LOG_LEVEL_INFO, "\n<br />" . PKG_NAME . " package built.<br />\nExecution time: {$totalTime}\n");

exit();

by (8.5k points)
0 votes
* @package prevnext

 * @subpackage class

 */

class PrevNext {

    const VERSION = '1.0.1';

    const RELEASE = 'pl';

    /**

     * modX object

     * @var object

     */

    public $modx;

    /**

     * $scriptProperties

     * @var array

     */

    public $config;

    /**

     * To hold error message

     * @var string

     */

    private $_error = '';

    /**

     * To hold output message

     * @var string

     */

    private $_output = '';

    /**

     * To hold placeholder array, flatten array with prefixable

     * @var array

     */

    private $_placeholders = array();

    /**

     * store the chunk's HTML to property to save memory of loop rendering

     * @var array

     */

    private $_chunks = array();

    /**

     * constructor

     * @param   modX    $modx

     * @param   array   $config     parameters

     */

    public function __construct(modX $modx, $config = array()) {

        $this->modx = & $modx;

        $config = is_array($config) ? $config : array();

        $basePath = $this->modx->getOption('prevnext.core_path', $config, $this->modx->getOption('core_path') . 'components/prevnext/');

        $this->config = array_merge(array(

            'version' => self::VERSION . '-' . self::RELEASE,

            'basePath' => $basePath,

          

     */

    public function parseTpl($tpl, array $phs = array()) {

        $output = '';

        if (isset($this->_chunks[$tpl]) && !empty($this->_chunks[$tpl])) {

            return $this->parseTplCode($this->_chunks[$tpl], $phs);

        }

        if (preg_match('/^(@CODE|@INLINE)/i', $tpl)) {

            $tplString = preg_replace('/^(@CODE|@INLINE)/i', '', $tpl);

            // tricks @CODE: / @INLINE:

            $tplString = ltrim($tplString, ':');

            $tplString = trim($tplString);

            $this->_chunks[$tpl] = $tplString;

            $output = $this->parseTplCode($tplString, $phs);

        } elseif (preg_match('/^@FILE/i', $tpl)) {

            $tplFile = preg_replace('/^@FILE/i', '', $tpl);

            // tricks @FILE:

            $tplFile = ltrim($tplFile, ':');

            $tplFile = trim($tplFile);

            $tplFile = $this->replacePropPhs($tplFile);

            try {

                $output = $this->parseTplFile($tplFile, $phs);

            } catch (Exception $e) {

                return $e->getMessage();

            }

        }

        // ignore @CHUNK / @CHUNK: / empty @BINDING

        else {

            $tplChunk = preg_replace('/^@CHUNK/i', '', $tpl);

            // tricks @CHUNK:

            $tplChunk = ltrim($tpl, ':');

            $tplChunk = trim($tpl);

            $chunk = $this->modx->getObject('modChunk', array('name' => $tplChunk), true);

            if (empty($chunk)) {

                // try to use @splittingred's fallback

                $f = $this->config['chunksPath'] . strtolower($tplChunk) . '.chunk.tpl';

                try {

                    $output = $this->parseTplFile($f, $phs);

                } catch (Exception $e) {

                    $output = $e->getMessage();

                    return 'Chunk: ' . $tplChunk . ' is not found, neither the file ' . $output;

                }

            } else {

//                $output = $this->modx->getChunk($tplChunk, $phs);

                /**

                 * @link    http://forums.modx.com/thread/74071/help-with-getchunk-and-modx-speed-please?page=4#dis-post-464137

                 */

                $chunk = $this->modx->getParser()->getElement('modChunk', $tplChunk);

                $this->_chunks[$tpl] = $chunk->get('content');

                $chunk->setCacheable(false);

                $chunk->_processed = false;

                $output = $chunk->process($phs);

            }

        }

        return $output;

    }

    /**

     * Parsing inline template code

     * @param   string  $code   HTML with tags

     * @param   array   $phs    placeholders

     * @return  string  parsed output

     */

    public function parseTplCode($code, array $phs = array()) {

        $chunk = $this->modx->newObject('modChunk');

        $chunk->setContent($code);

        $chunk->setCacheable(false);

        $phs = $this->replacePropPhs($phs);

        $chunk->_processed = false;

        return $chunk->process($phs);

    }

    /**

     * Parsing file based template

     * @param   string  $file   file path

     * @param   array   $phs    placeholders

     * @return  string  parsed output

     * @throws  Exception if file is not found

     */

    public function parseTplFile($file, array $phs = array()) {

        if (!file_exists($file)) {

            throw new Exception('File: ' . $file . ' is not found.');

        }

        $o = file_get_contents($file);

        $this->_chunks[$file] = $o;

        $chunk = $this->modx->newObject('modChunk');

        // just to create a name for the modChunk object.

        $name = strtolower(basename($file));

        $name = rtrim($name, '.tpl');

        $name = rtrim($name, '.chunk');

        $chunk->set('name', $name);

        $chunk->setCacheable(false);

        $chunk->setContent($o);

        $chunk->_processed = false;

        $output = $chunk->process($phs);

        return $output;

    }

    /**

     * If the chunk is called by AJAX processor, it needs to be parsed for the

     * other elements to work, like snippet and output filters.

     *

     * Example:

     * <pre><code>

     * <?php

     * $content = $myObject->parseTpl('tplName', $placeholders);

     * $content = $myObject->processElementTags($content);

     * </code></pre>

     *

     * @param   string  $content    the chunk output

     * @param   array   $options    option for iteration

     * @return  string  parsed content

     */

    public function processElementTags($content, array $options = array()) {

        $maxIterations = intval($this->modx->getOption('parser_max_iterations', $options, 10));

        if (!$this->modx->parser) {

            $this->modx->getParser();

        }

        $this->modx->parser->processElementTags('', $content, true, false, '[[', ']]', array(), $maxIterations);

        $this->modx->parser->processElementTags('', $content, true, true, '[[', ']]', array(), $maxIterations);

        return $content;

    }

    /**

     * Replace the property's placeholders

     * @param   string|array    $subject    Property

     * @return  array           The replaced results

     */

    public function replacePropPhs($subject) {

        $pattern = array(

            '/\{core_path\}/',

            '/\{base_path\}/',

            '/\{assets_url\}/',

            '/\{filemanager_path\}/',

            '/\[\[\+\+core_path\]\]/',

            '/\[\[\+\+base_path\]\]/'

        );

        $replacement = array(

            $this->modx->getOption('core_path'),

            $this->modx->getOption('base_path'),

            $this->modx->getOption('assets_url'),

            $this->modx->getOption('filemanager_path'),

            $this->modx->getOption('core_path'),

            $this->modx->getOption('base_path')

        );

        if (is_array($subject)) {

            $parsedString = array();

            foreach ($subject as $k => $s) {

                if (is_array($s)) {

                    $s = $this->replacePropPhs($s);

                }

                $parsedString[$k] = preg_replace($pattern, $replacement, $s);

            }

            return $parsedString;

        } else {

            return preg_replace($pattern, $replacement, $subject);

        }

    }

    /**

     * Get sibling of current resource

     * @param   string  $direction  '<' (default) or '>'

     * @return  array   resource's data in array

     */

    public function getSibling($direction = '<') {

        $direction = ($direction === '<' ? '<' : '>');

        if ($direction === '<') {

            $prefix = $this->config['prevPrefix'];

            $sortDir = 'desc';

        } else {

            $prefix = $this->config['nextPrefix'];

            $sortDir = 'asc';

        }

        $resource = $this->modx->resource->toArray();

        $resource['createdon'] = strtotime($resource['createdon']);

        $resource['editedon'] = strtotime($resource['editedon']);

        $resource['publishedon'] = strtotime($resource['publishedon']);

        $c = $this->modx->newQuery('modResource');

        $c->select('id');

        if (!empty($this->config['select'])) {

            $c->select($this->config['select']);

        } else {

            $c->select(array(

                'id', 'pagetitle'

            ));

        }

        $where = array();

        $i = 0;

        $fields = array();

        foreach ($this->config['sort'] as $v) {

            if (empty($v)) {

                continue;

            }

            if (isset($resource[$v]) && !empty($resource[$v])) {

                $fields[] = array(

                    ($i > 0 ? 'OR:' : '') . $v . ':' . $direction => $resource[$v]

                );

                $i++;

            }

        }

        if (empty($fields)) {

            $where[] = array('id:' . $direction => $resource['id']);

        }

        $where[] = array(

            'parent:IN' => $this->config['parents'],

            'published:=' => 1,

            'deleted:!=' => 1,

            'id:!=' => $resource['id'],

        );

        if (!$this->config['includeHidden']) {

            $where[] = array(

                'hidemenu:!=' => 1,

            );

        }

        $c->where($where);

        if (empty($this->config['sort'])) {

            $c->sortby('id', $sortDir);

        } else {

            foreach ($this->config['sort'] as $v) {

                if (empty($v)) {

                    continue;

                }

                $c->sortby($v, $sortDir); // reverse the sort to get the closest sibling

            }

        }
by (8.5k points)
...