<?php
namespace Croogo\Nodes\View\Helper;
use Cake\Collection\Collection;
use Cake\Core\Configure;
use Cake\Core\Plugin;
use Cake\Event\Event;
use Cake\Utility\Hash;
use Cake\View\Helper;
use Cake\View\View;
use Croogo\Core\Croogo;
use Croogo\Core\Utility\StringConverter;
use Croogo\Nodes\Model\Entity\Node;
/**
* Nodes Helper
*
* @category Helper
* @package Croogo.Nodes
* @version 1.0
* @author Fahad Ibnay Heylaal <contact@fahad19.com>
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
* @link http://www.croogo.org
*/
class NodesHelper extends Helper
{
/**
* Other helpers used by this helper
*
* @var array
* @access public
*/
public $helpers = [
'Croogo/Core.Url',
'Croogo/Core.Layout',
'Croogo/Core.Html',
'Time',
];
/**
* Current Node
*
* @var \Croogo\Nodes\Model\Entity\Node
* @access public
*/
public $node = null;
/**
* StringConverter instance
*
* @var StringConverter
*/
protected $_converter = null;
/**
* constructor
*/
public function __construct(View $view, $settings = [])
{
parent::__construct($view);
$this->_converter = new StringConverter();
$this->_setupEvents();
}
/**
* setup events
*/
protected function _setupEvents()
{
$events = [
'Helper.Layout.beforeFilter' => [
'callable' => 'filter', 'passParams' => true,
],
];
$eventManager = $this->_View->getEventManager();
foreach ($events as $name => $config) {
$eventManager->on($name, $config, [$this, 'filter']);
}
}
/**
* Show nodes list
*
* @param string $alias Node query alias
* @param array $options (optional)
* @return string
*/
public function nodeList($alias, $options = [])
{
$_options = [
'link' => true,
'plugin' => 'Croogo/Nodes',
'controller' => 'Nodes',
'action' => 'view',
'element' => 'Croogo/Nodes.node_list',
];
$options = array_merge($_options, $options);
$output = '';
if (isset($this->_View->viewVars['nodesForLayout'][$alias])) {
$nodes = $this->_View->viewVars['nodesForLayout'][$alias];
$output = $this->_View->element($options['element'], [
'alias' => $alias,
'nodesList' => $this->_View->viewVars['nodesForLayout'][$alias],
'options' => $options,
]);
}
return $output;
}
/**
* Filter content for Nodes
*
* Replaces [node:unique_name_for_query] or [n:unique_name_for_query] with Nodes list
*
* @param Event $event
* @return string
*/
public function filter(Event $event, $options = [])
{
$data = $event->getData();
preg_match_all('/\[(node|n):([A-Za-z0-9_\-]*)(.*?)\]/i', $data['content'], $tagMatches);
for ($i = 0, $ii = count($tagMatches[1]); $i < $ii; $i++) {
$regex = '/(\S+)=[\'"]?((?:.(?![\'"]?\s+(?:\S+)=|[>\'"]))+.)[\'"]?/i';
preg_match_all($regex, $tagMatches[3][$i], $attributes);
$alias = $tagMatches[2][$i];
$options = [];
for ($j = 0, $jj = count($attributes[0]); $j < $jj; $j++) {
$options[$attributes[1][$j]] = $attributes[2][$j];
}
$data['content'] = str_replace($tagMatches[0][$i], $this->nodeList($alias, $options), $data['content']);
}
return $event->getData();
}
/**
* Set current Node
*
* @param array $node
* @return void
*/
public function set($node)
{
$event = Croogo::dispatchEvent('Helper.Nodes.beforeSetNode', $this->_View, [
'node' => $node,
]);
$this->node = $event->getData('node');
$this->Layout->hook('afterSetNode');
Croogo::dispatchEvent('Helper.Nodes.afterSetNode', $this->_View, [
'node' => $this->node
]);
}
/**
* Get value of a Node field
*
* @param string $field
* @return string
*/
public function field($field = 'id', $value = null)
{
if ($value) {
return $this->node->set($field, $value);
}
return Hash::get($this->node, $field);
}
/**
* Node info
*
* @param array $options
* @return string
*/
public function info($options = [])
{
$_options = [
'element' => 'Croogo/Nodes.node_info',
];
$options = array_merge($_options, $options);
$output = $this->Layout->hook('beforeNodeInfo');
$output .= $this->_View->element($options['element']);
$output .= $this->Layout->hook('afterNodeInfo');
return $output;
}
/**
* Node excerpt (summary)
*
* Options:
* - `element`: Element to use when rendering excerpt
* - `body`: Extract first paragraph from body as excerpt. Default is `false`
*
* @param array $options
* @return string
*/
public function excerpt($options = [])
{
$_options = [
'element' => 'Croogo/Nodes.node_excerpt',
'body' => false,
];
$options = array_merge($_options, $options);
$excerpt = $this->node->excerpt;
$node = $this->node;
if ($options['body'] && empty($excerpt)) {
$excerpt = $this->_converter->firstPara(
$this->node->body,
['tag' => true]
);
}
$output = $this->Layout->hook('beforeNodeExcerpt');
$output .= $this->_View->element($options['element'], compact('excerpt', 'node'));
$output .= $this->Layout->hook('afterNodeExcerpt');
return $output;
}
/**
* Node body
*
* @param array $options
* @return string
*/
public function body($options = [])
{
$_options = [
'element' => 'Croogo/Nodes.node_body',
];
$options = array_merge($_options, $options);
$output = $this->Layout->hook('beforeNodeBody');
$output .= $this->_View->element($options['element']);
$output .= $this->Layout->hook('afterNodeBody');
return $output;
}
/**
* Node more info
*
* @param array $options
* @return string
*/
public function moreInfo($options = [])
{
$_options = [
'element' => 'Croogo/Nodes.node_more_info',
];
$options = array_merge($_options, $options);
$output = $this->Layout->hook('beforeNodeMoreInfo');
$output .= $this->_View->element($options['element']);
$output .= $this->Layout->hook('afterNodeMoreInfo');
return $output;
}
/**
* Convenience method to generate url to a node or current node
*
* @param \Croogo\Nodes\Model\Entity\Node $node Node data
* @param bool $full
* @return string
*/
public function url(Node $node = null, $full = false)
{
if ($node === null) {
$node = $this->node;
}
return $this->Url->build($node->url, $full);
}
/**
* Return formatted date
*
* @param \Cake\I18n\FrozenTime $date date to format
* @return string
*/
public function date($date)
{
$tz = $this->getView()->getRequest()->getSession()->read('Auth.User.timezone') ?: Configure::read('Site.timezone');
return $this->Time->format($date, Configure::read('Reading.date_time_format'), null, $tz);
}
/**
* Return all term links
*
* @return array
*/
public function nodeTermLinks()
{
return (new Collection($this->node->taxonomies))->map(function ($taxonomy) {
return $this->Html->link($taxonomy->term->title, [
'plugin' => 'Croogo/Nodes',
'controller' => 'Nodes',
'action' => 'term',
'type' => $this->field('type'),
'term' => $taxonomy->term->slug,
]);
})->toArray();
}
/**
* Check if comments plugin is enable
*
* @return bool
*/
public function commentsEnabled()
{
return Plugin::isLoaded('Croogo/Comments');
}
}