Spade
Mini Shell
fabrik/fabrik/Controllers/Controller.php000064400000002746151165341560014422
0ustar00<?php
/**
* Created by PhpStorm.
* User: rob
* Date: 24/05/2016
* Time: 09:56
*/
namespace Fabrik\Controllers;
defined('_JEXEC') or die;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\Document\Document;
use Joomla\CMS\Session\Session;
use Joomla\CMS\User\User;
use Joomla\CMS\Factory;
use Joomla\Utilities\ArrayHelper;
class Controller extends BaseController
{
/**
* @var JApplicationCMS
*/
protected $app;
/**
* @var User
*/
protected $user;
/**
* @var string
*/
protected $package;
/**
* @var Session
*/
protected $session;
/**
* @var Document
*/
protected $doc;
/**
* @var JDatabaseDriver
*/
protected $db;
/**
* @var Registry
*/
protected $config;
/**
* Constructor
*
* @param array $config A named configuration array for object
construction.
*
*/
public function __construct($config = array())
{
$this->app = ArrayHelper::getValue($config, 'app',
Factory::getApplication());
$this->user = ArrayHelper::getValue($config, 'user',
Factory::getUser());
$this->package =
$this->app->getUserState('com_fabrik.package',
'fabrik');
$this->session = ArrayHelper::getValue($config, 'session',
Factory::getSession());
$this->doc = ArrayHelper::getValue($config, 'doc',
Factory::getDocument());
$this->db = ArrayHelper::getValue($config, 'db',
Factory::getDbo());
$this->config = ArrayHelper::getValue($config, 'config',
Factory::getApplication()->getConfig());
parent::__construct($config);
}
}fabrik/fabrik/Document/PartialDocument.php000064400000055721151165341570014644
0ustar00<?php
/**
* Partial Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Utility\Utility;
use Joomla\CMS\Cache\Cache;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Uri\Uri;
use Joomla\Registry\Registry;
use Joomla\CMS\Factory;
use Joomla\CMS\Document\Document;
use Fabrik\Helpers\Php;
jimport('joomla.utilities.utility');
/**
* HtmlDocument class, provides an easy interface to parse and display a
HTML document
*
* @since 11.1
*/
class PartialDocument extends Document
{
/**
* Array of Header `<link>` tags
*
* @var array
* @since 11.1
*/
public $_links = array();
/**
* Array of custom tags
*
* @var array
* @since 11.1
*/
public $_custom = array();
/**
* Name of the template
*
* @var string
* @since 11.1
*/
public $template = null;
/**
* Base url
*
* @var string
* @since 11.1
*/
public $baseurl = null;
/**
* Array of template parameters
*
* @var array
* @since 11.1
*/
public $params = null;
/**
* File name
*
* @var array
* @since 11.1
*/
public $_file = null;
/**
* String holding parsed template
*
* @var string
* @since 11.1
*/
protected $_template = '';
/**
* Array of parsed template JDoc tags
*
* @var array
* @since 11.1
*/
protected $_template_tags = array();
/**
* Integer with caching setting
*
* @var integer
* @since 11.1
*/
protected $_caching = null;
/**
* Set to true when the document should be output as HTML5
*
* @var boolean
* @since 12.1
*
* @note 4.0 Will be replaced by $html5 and the default value will be
true.
*/
private $_html5 = null;
/**
* Class constructor
*
* @param array $options Associative array of options
*
* @since 11.1
*/
public function __construct($options = array())
{
parent::__construct($options);
// Set document type
$this->_type = 'partial';
// Set default mime type and document metadata (meta data syncs
with mime type by default)
$this->setMimeEncoding('text/html');
}
/**
* Get the HTML document head data
*
* @return array The document head data in array form
*
* @since 11.1
*/
public function getHeadData()
{
$data = array();
$data['title'] = $this->title;
$data['description'] = $this->description;
$data['link'] = $this->link;
$data['metaTags'] = $this->_metaTags;
$data['links'] = $this->_links;
$data['styleSheets'] = $this->_styleSheets;
$data['style'] = $this->_style;
$data['scripts'] = $this->_scripts;
$data['script'] = $this->_script;
$data['custom'] = $this->_custom;
$data['scriptText'] = Text::script();
return $data;
}
/**
* Reset the HTML document head data
*
* @param mixed $types type or types of the heads elements to reset
*
* @return PartialDocument instance of $this to allow chaining
*
* @since 3.7.0
*/
public function resetHeadData($types = null)
{
if (is_null($types))
{
$this->title = '';
$this->description = '';
$this->link = '';
$this->_metaTags = array();
$this->_links = array();
$this->_styleSheets = array();
$this->_style = array();
$this->_scripts = array();
$this->_script = array();
$this->_custom = array();
}
if (is_array($types))
{
foreach ($types as $type)
{
$this->resetHeadDatum($type);
}
}
if (is_string($types))
{
$this->resetHeadDatum($types);
}
return $this;
}
/**
* Reset a part the HTML document head data
*
* @param string $type type of the heads elements to reset
*
* @return void
*
* @since 3.7.0
*/
private function resetHeadDatum($type)
{
switch ($type)
{
case 'title':
case 'description':
case 'link':
$this->{$type} = '';
break;
case 'metaTags':
case 'links':
case 'styleSheets':
case 'style':
case 'scripts':
case 'script':
case 'custom':
$realType = '_' . $type;
$this->{$realType} = array();
break;
}
}
/**
* Set the HTML document head data
*
* @param array $data The document head data in array form
*
* @return HtmlDocument|null instance of $this to allow chaining or
null for empty input data
*
* @since 11.1
*/
public function setHeadData($data)
{
if (empty($data) || !is_array($data))
{
return;
}
$this->title = (isset($data['title'])
&& !empty($data['title'])) ? $data['title'] :
$this->title;
$this->description = (isset($data['description'])
&& !empty($data['description'])) ?
$data['description'] : $this->description;
$this->link = (isset($data['link']) &&
!empty($data['link'])) ? $data['link'] :
$this->link;
$this->_metaTags = (isset($data['metaTags'])
&& !empty($data['metaTags'])) ?
$data['metaTags'] : $this->_metaTags;
$this->_links = (isset($data['links'])
&& !empty($data['links'])) ? $data['links'] :
$this->_links;
$this->_styleSheets = (isset($data['styleSheets'])
&& !empty($data['styleSheets'])) ?
$data['styleSheets'] : $this->_styleSheets;
$this->_style = (isset($data['style'])
&& !empty($data['style'])) ? $data['style'] :
$this->_style;
$this->_scripts = (isset($data['scripts'])
&& !empty($data['scripts'])) ? $data['scripts']
: $this->_scripts;
$this->_script = (isset($data['script'])
&& !empty($data['script'])) ? $data['script'] :
$this->_script;
$this->_custom = (isset($data['custom'])
&& !empty($data['custom'])) ? $data['custom'] :
$this->_custom;
if (isset($data['scriptText']) &&
!empty($data['scriptText']))
{
foreach ($data['scriptText'] as $key => $string)
{
Text::script($key, $string);
}
}
return $this;
}
/**
* Merge the HTML document head data
*
* @param array $data The document head data in array form
*
* @return PartialDocument|null instance of $this to allow chaining or
null for empty input data
*
* @since 11.1
*/
public function mergeHeadData($data)
{
if (empty($data) || !is_array($data))
{
return;
}
$this->title = (isset($data['title']) &&
!empty($data['title']) && !stristr($this->title,
$data['title']))
? $this->title . $data['title']
: $this->title;
$this->description = (isset($data['description'])
&& !empty($data['description']) &&
!stristr($this->description, $data['description']))
? $this->description . $data['description']
: $this->description;
$this->link = (isset($data['link'])) ?
$data['link'] : $this->link;
if (isset($data['metaTags']))
{
foreach ($data['metaTags'] as $type1 => $data1)
{
$booldog = $type1 == 'http-equiv' ? true : false;
foreach ($data1 as $name2 => $data2)
{
$this->setMetaData($name2, $data2, $booldog);
}
}
}
$this->_links = (isset($data['links']) &&
!empty($data['links']) &&
is_array($data['links']))
? array_unique(array_merge($this->_links,
$data['links']), SORT_REGULAR)
: $this->_links;
$this->_styleSheets = (isset($data['styleSheets'])
&& !empty($data['styleSheets']) &&
is_array($data['styleSheets']))
? array_merge($this->_styleSheets,
$data['styleSheets'])
: $this->_styleSheets;
if (isset($data['style']))
{
foreach ($data['style'] as $type => $stdata)
{
if (!isset($this->_style[strtolower($type)]) ||
!stristr($this->_style[strtolower($type)], $stdata))
{
$this->addStyleDeclaration($stdata, $type);
}
}
}
$this->_scripts = (isset($data['scripts']) &&
!empty($data['scripts']) &&
is_array($data['scripts']))
? array_merge($this->_scripts, $data['scripts'])
: $this->_scripts;
if (isset($data['script']))
{
foreach ($data['script'] as $type => $sdata)
{
if (!isset($this->_script[strtolower($type)]) ||
!stristr($this->_script[strtolower($type)], $sdata))
{
$this->addScriptDeclaration($sdata, $type);
}
}
}
$this->_custom = (isset($data['custom']) &&
!empty($data['custom']) &&
is_array($data['custom']))
? array_unique(array_merge($this->_custom,
$data['custom']))
: $this->_custom;
return $this;
}
/**
* Adds `<link>` tags to the head of the document
*
* $relType defaults to 'rel' as it is the most common
relation type used.
* ('rev' refers to reverse relation, 'rel'
indicates normal, forward relation.)
* Typical tag: `<link href="index.php"
rel="Start">`
*
* @param string $href The link that is being related.
* @param string $relation Relation of link.
* @param string $relType Relation type attribute. Either rel or
rev (default: 'rel').
* @param array $attribs Associative array of remaining
attributes.
*
* @return PartialDocument instance of $this to allow chaining
*
* @since 11.1
*/
public function addHeadLink($href, $relation, $relType =
'rel', $attribs = array())
{
$this->_links[$href]['relation'] = $relation;
$this->_links[$href]['relType'] = $relType;
$this->_links[$href]['attribs'] = $attribs;
return $this;
}
/**
* Adds a shortcut icon (favicon)
*
* This adds a link to the icon shown in the favorites list or on
* the left of the url in the address bar. Some browsers display
* it on the tab, as well.
*
* @param string $href The link that is being related.
* @param string $type File type
* @param string $relation Relation of link
*
* @return PartialDocument instance of $this to allow chaining
*
* @since 11.1
*/
public function addFavicon($href, $type =
'image/vnd.microsoft.icon', $relation = 'shortcut
icon')
{
$href = str_replace('\\', '/', $href);
$this->addHeadLink($href, $relation, 'rel',
array('type' => $type));
return $this;
}
/**
* Adds a custom HTML string to the head block
*
* @param string $html The HTML to add to the head
*
* @return PartialDocument instance of $this to allow chaining
*
* @since 11.1
*/
public function addCustomTag($html)
{
$this->_custom[] = trim($html);
return $this;
}
/**
* Returns whether the document is set up to be output as HTML5
*
* @return boolean true when HTML5 is used
*
* @since 12.1
*/
public function isHtml5()
{
return $this->_html5;
}
/**
* Sets whether the document should be output as HTML5
*
* @param bool $state True when HTML5 should be output
*
* @return void
*
* @since 12.1
*/
public function setHtml5($state)
{
if (is_bool($state))
{
$this->_html5 = $state;
}
}
/**
* Get the contents of a document include
*
* @param string $type The type of renderer
* @param string $name The name of the element to render
* @param array $attribs Associative array of remaining
attributes.
*
* @return mixed|string The output of the renderer
*
* @since 11.1
*/
public function getBuffer($type = null, $name = null, $attribs =
array())
{
// If no type is specified, return the whole buffer
if ($type === null)
{
return parent::$_buffer;
}
$title = (isset($attribs['title'])) ?
$attribs['title'] : null;
if (isset(parent::$_buffer[$type][$name][$title]))
{
return parent::$_buffer[$type][$name][$title];
}
$renderer = $this->loadRenderer($type);
if ($this->_caching == true && $type ==
'modules')
{
$cache = Factory::getCache('com_modules',
'');
$hash = md5(serialize(array($name, $attribs, null,
$renderer)));
$cbuffer = $cache->get('cbuffer_' . $type);
if (isset($cbuffer[$hash]))
{
return Cache::getWorkarounds($cbuffer[$hash],
array('mergehead' => 1));
}
else
{
$options = array();
$options['nopathway'] = 1;
$options['nomodules'] = 1;
$options['modulemode'] = 1;
$this->setBuffer($renderer->render($name, $attribs,
null), $type, $name);
$data = parent::$_buffer[$type][$name][$title];
$tmpdata = Cache::setWorkarounds($data, $options);
$cbuffer[$hash] = $tmpdata;
$cache->store($cbuffer, 'cbuffer_' . $type);
}
}
else
{
$this->setBuffer($renderer->render($name, $attribs,
null), $type, $name, $title);
}
return parent::$_buffer[$type][$name][$title];
}
/**
* Set the contents a document includes
*
* @param string $content The content to be set in the buffer.
* @param array $options Array of optional elements.
*
* @return PartialDocument instance of $this to allow chaining
*
* @since 11.1
*/
public function setBuffer($content, $options = array())
{
// The following code is just for backward compatibility.
if (\func_num_args() > 1 && !\is_array($options)) {
$args = \func_get_args();
$options = [];
$options['type'] = $args[1];
$options['name'] = $args[2] ?? null;
$options['title'] = $args[3] ?? null;
}
$type = $options['type'] ?? '';
$name = $options['name'] ?? '';
$title = $options['title'] ?? '';
parent::$_buffer[$type][$name][$title] = $content;
return $this;
}
/**
* Parses the template and populates the buffer
*
* @param array $params Parameters for fetching the template
*
* @return PartialDocument instance of $this to allow chaining
*
* @since 11.1
*/
public function parse($params = array())
{
return $this->_fetchTemplate($params)->_parseTemplate();
}
/**
* Outputs the template to the browser.
*
* @param boolean $caching If true, cache the output
* @param array $params Associative array of attributes
*
* @return string The rendered data
*
* @since 11.1
*/
public function render($caching = false, $params = array())
{
$this->_caching = $caching;
if (empty($this->_template))
{
$this->parse($params);
}
$data = $this->_renderTemplate();
parent::render();
return $data;
}
/**
* Count the modules based on the given condition
*
* @param string $condition The condition to use
*
* @return integer Number of modules found
*
* @since 11.1
*/
public function countModules($condition)
{
$operators =
'(\+|\-|\*|\/|==|\!=|\<\>|\<|\>|\<=|\>=|and|or|xor)';
$words = preg_split('# ' . $operators . ' #',
$condition, null, PREG_SPLIT_DELIM_CAPTURE);
if (count($words) === 1)
{
$name = strtolower($words[0]);
$result =
((isset(parent::$_buffer['modules'][$name])) &&
(parent::$_buffer['modules'][$name] === false))
? 0 : count(ModuleHelper::getModules($name));
return $result;
}
Log::add('Using an expression in
PartialDocument::countModules() is deprecated.', Log::WARNING,
'deprecated');
for ($i = 0, $n = count($words); $i < $n; $i += 2)
{
// Odd parts (modules)
$name = strtolower($words[$i]);
$words[$i] =
((isset(parent::$_buffer['modules'][$name])) &&
(parent::$_buffer['modules'][$name] === false))
? 0
: count(ModuleHelper::getModules($name));
}
$str = 'return ' . implode(' ', $words) .
';';
return Php::Eval(['code' => $str]);
}
/**
* Count the number of child menu items of the current active menu item
*
* @return integer Number of child menu items
*
* @since 11.1
*/
public function countMenuChildren()
{
static $children;
if (!isset($children))
{
$db = Factory::getDbo();
$app = Factory::getApplication();
$menu = $app->getMenu();
$active = $menu->getActive();
$children = 0;
if ($active)
{
$query = $db->getQuery(true)
->select('COUNT(*)')
->from('#__menu')
->where('parent_id = ' . $active->id)
->where('published = 1');
$db->setQuery($query);
$children = $db->loadResult();
}
}
return $children;
}
/**
* Load a template file
*
* @param string $directory The name of the template
* @param string $filename The actual filename
*
* @return string The contents of the template
*
* @since 11.1
*/
protected function _loadTemplate($directory, $filename)
{
$contents = '';
// Check to see if we have a valid template file
if (file_exists($directory . '/' . $filename))
{
// Store the file path
$this->_file = $directory . '/' . $filename;
// Get the file content
ob_start();
require $directory . '/' . $filename;
$contents = ob_get_contents();
ob_end_clean();
}
// Try to find a favicon by checking the template and root folder
$icon = '/favicon.ico';
foreach (array($directory, JPATH_BASE) as $dir)
{
if (file_exists($dir . $icon))
{
$path = str_replace(JPATH_BASE, '', $dir);
$path = str_replace('\\', '/', $path);
$this->addFavicon(Uri::base(true) . $path . $icon);
break;
}
}
return $contents;
}
/**
* Fetch the template, and initialise the params
*
* @param array $params Parameters to determine the template
*
* @return PartialDocument instance of $this to allow chaining
*
* @since 11.1
*/
protected function _fetchTemplate($params = array())
{
// Check
$directory = isset($params['directory']) ?
$params['directory'] : 'templates';
$filter = InputFilter::getInstance();
$template = $filter->clean($params['template'],
'cmd');
$file = $filter->clean($params['file'],
'cmd');
if (!file_exists($directory . '/' . $template .
'/' . $file))
{
$template = 'system';
}
if (!file_exists($directory . '/' . $template .
'/' . $file))
{
$file = 'index.php';
}
// Load the language file for the template
$lang = Factory::getApplication()->getLanguage();
// 1.5 or core then 1.6
$lang->load('tpl_' . $template, JPATH_BASE, null,
false, true)
|| $lang->load('tpl_' . $template, $directory .
'/' . $template, null, false, true);
// Assign the variables
$this->template = $template;
$this->baseurl = Uri::base(true);
$this->params = isset($params['params']) ?
$params['params'] : new Registry;
// Load
$this->_template = $this->_loadTemplate($directory .
'/' . $template, $file);
return $this;
}
/**
* Parse a document template
*
* @return PartialDocument instance of $this to allow chaining
*
* @since 11.1
*/
protected function _parseTemplate()
{
$matches = array();
if (preg_match_all('#<jdoc:include\
type="([^"]+)"(.*)\/>#iU', $this->_template,
$matches))
{
$template_tags_first = array();
$template_tags_last = array();
// Step through the jdocs in reverse order.
for ($i = count($matches[0]) - 1; $i >= 0; $i--)
{
$type = $matches[1][$i];
$attribs = empty($matches[2][$i]) ? array() :
Utility::parseAttributes($matches[2][$i]);
$name = isset($attribs['name']) ?
$attribs['name'] : null;
// Separate buffers to be executed first and last
if ($type == 'module' || $type ==
'modules')
{
$template_tags_first[$matches[0][$i]] =
array('type' => $type, 'name' => $name,
'attribs' => $attribs);
}
else
{
$template_tags_last[$matches[0][$i]] =
array('type' => $type, 'name' => $name,
'attribs' => $attribs);
}
}
// Reverse the last array so the jdocs are in forward order.
$template_tags_last = array_reverse($template_tags_last);
$this->_template_tags = $template_tags_first +
$template_tags_last;
}
return $this;
}
/**
* Render pre-parsed template
*
* @return string rendered template
*
* @since 11.1
*/
protected function _renderTemplate()
{
$replace = array();
$with = array();
foreach ($this->_template_tags as $jdoc => $args)
{
$replace[] = $jdoc;
$with[] = $this->getBuffer($args['type'],
$args['name'], $args['attribs']);
}
return str_replace($replace, $with, $this->_template);
}
}
fabrik/fabrik/Document/PdfDocument.php000064400000015034151165341570013752
0ustar00<?php
/**
* PDF Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document;
defined('JPATH_PLATFORM') or die;
//require_once JPATH_SITE .
'/components/com_fabrik/helpers/pdf.php';
use Joomla\CMS\Language\Text;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Fabrik\Helpers\Pdf;
use Joomla\CMS\Document\HtmlDocument;
jimport('joomla.utilities.utility');
/**
* PdfDocument class, provides an easy interface to parse and display a PDF
document
*
* @since 11.1
*/
class PdfDocument extends HtmlDocument
{
/**
* Array of Header `<link>` tags
*
* @var array
* @since 11.1
*/
public $_links = array();
/**
* Array of custom tags
*
* @var array
* @since 11.1
*/
public $_custom = array();
/**
* Name of the template
*
* @var string
* @since 11.1
*/
public $template = null;
/**
* Base url
*
* @var string
* @since 11.1
*/
public $baseurl = null;
/**
* Array of template parameters
*
* @var array
* @since 11.1
*/
public $params = null;
/**
* File name
*
* @var array
* @since 11.1
*/
public $_file = null;
/**
* String holding parsed template
*
* @var string
* @since 11.1
*/
protected $_template = '';
/**
* Array of parsed template JDoc tags
*
* @var array
* @since 11.1
*/
protected $_template_tags = array();
/**
* Integer with caching setting
*
* @var integer
* @since 11.1
*/
protected $_caching = null;
/**
* Set to true when the document should be output as HTML5
*
* @var boolean
* @since 12.1
*
* @note 4.0 Will be replaced by $html5 and the default value will be
true.
*/
private $_html5 = null;
/**
* Fabrik config
*
* @var null
*/
protected $config = null;
/**
* Orientation
*
* @var string
*/
private $orientation = 'P';
/**
* Paper size
*
* @var string
*/
private $size = 'A4';
/**
* Class constructor
*
* @param array $options Associative array of options
*
* @since 11.1
*/
public function __construct($options = array())
{
parent::__construct($options);
$this->config = ComponentHelper::getParams('com_fabrik');
if ($this->config->get('pdf_debug', false))
{
$this->setMimeEncoding('text/html');
$this->_type = 'pdf';
}
else
{
// Set mime type
$this->_mime = 'application/pdf';
// Set document type
$this->_type = 'pdf';
}
$this->iniPdf();
}
/**
* Init selected PDF
*/
protected function iniPdf()
{
if ($this->config->get('fabrik_pdf_lib',
'dompdf') === 'dompdf')
{
if (!$this->iniDomPdf())
{
throw new
RuntimeException(Text::_('COM_FABRIK_NOTICE_DOMPDF_NOT_FOUND'));
}
}
}
/**
* Set up DomPDF engine
*
* @return bool
*/
protected function iniDomPdf()
{
$this->engine = Pdf::iniDomPdf(true);
return $this->engine;
}
/**
* Set the paper size and orientation
* Note if too small for content then the pdf renderer will bomb out in an
infinite loop
* Legal seems to be more lenient than a4 for example
* If doing landscape set large paper size
*
* @param string $size Paper size E.g A4,legal
* @param string $orientation Paper orientation landscape|portrait
*
* @since 3.0.7
*
* @return void
*/
public function setPaper($size = 'A4', $orientation =
'landscape')
{
if ($this->config->get('fabrik_pdf_lib',
'dompdf') === 'dompdf')
{
$size = strtoupper($size);
$this->engine->set_paper($size, $orientation);
}
else
{
$this->size = ucfirst($size);
switch ($orientation)
{
case 'landscape':
$this->orientation = 'L';
$this->size .= '-' . $this->orientation;
break;
case 'portrait':
default:
$this->orientation = 'P';
break;
}
}
}
/**
* Sets the document name
*
* @param string $name Document name
*
* @return void
*/
public function setName($name = 'joomla')
{
$this->name = $name;
}
/**
* Returns the document name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Render the document.
*
* @param boolean $cache If true, cache the output
* @param array $params Associative array of attributes
*
* @return string
*/
public function render($cache = false, $params = array())
{
// mb_encoding foo when content-type had been set to text/html; uft-8;
$this->_metaTags['http-equiv'] = array();
$this->_metaTags['http-equiv']['content-type'] =
'text/html';
// Testing using futural font.
// $this->addStyleDeclaration('body: { font-family: futural
!important; }');
$data = parent::render();
Pdf::fullPaths($data);
/**
* I think we need this to handle some HTML entities when rendering
otherlanguages (like Polish),
* but haven't tested it much
*/
$data =
mb_convert_encoding($data,'HTML-ENTITIES','UTF-8');
$config = ComponentHelper::getParams('com_fabrik');
if ($this->config->get('fabrik_pdf_lib',
'dompdf') === 'dompdf')
{
$this->engine->load_html($data);
if ($config->get('pdf_debug', false))
{
return $this->engine->output_html();
}
else
{
$this->engine->render();
$this->engine->stream($this->getName() . '.pdf');
}
}
else
{
if ($config->get('pdf_debug', false))
{
return $data;
}
else
{
try
{
$mpdf = new \Mpdf\Mpdf(
[
'tempDir' =>
Factory::getApplication()->getConfig()->get('tmp_path',
JPATH_ROOT . '/tmp'),
'mode' => 'utf-8',
'format' => $this->size,
'orientation' => $this->orientation
]
);
//$mpdf->shrink_tables_to_fit = 1;
$mpdf->use_kwt = true;
$mpdf->WriteHTML($data);
$mpdf->Output($this->getName() . '.pdf',
\Mpdf\Output\Destination::INLINE);
}
catch (\Mpdf\MpdfException $e)
{
// mmmphh
echo 'Error creating PDF: ' . ($e->getMessage());
}
}
}
return '';
}
/**
* Get the contents of a document include
*
* @param string $type The type of renderer
* @param string $name The name of the element to render
* @param array $attribs Associative array of remaining attributes.
*
* @return The output of the renderer
*/
public function getBuffer($type = null, $name = null, $attribs = array())
{
if ($type == 'head' || $type == 'component')
{
return parent::getBuffer($type, $name, $attribs);
}
else
{
return '';
}
}
}
fabrik/fabrik/Document/Renderer/Partial/ComponentRenderer.php000064400000001643151165341570020336
0ustar00<?php
/**
* Partial Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document\Renderer\Partial;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Document\DocumentRenderer;
/**
* HTML document renderer for the component output
*
* @since 3.5
*/
class ComponentRenderer extends DocumentRenderer
{
/**
* Renders a component script and returns the results as a string
*
* @param string $component The name of the component to render
* @param array $params Associative array of values
* @param string $content Content script
*
* @return string The output of the script
*
* @since 3.5
*/
public function render($component = null, $params = array(), $content =
null)
{
return $content;
}
}
fabrik/fabrik/Document/Renderer/Partial/HeadRenderer.php000064400000030523151165341570017234
0ustar00<?php
/**
* Partial Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document\Renderer\Partial;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Document\HtmlDocument;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Helper\TagsHelper;
use Joomla\CMS\Uri\Uri;
use Joomla\Utilities\ArrayHelper;
use Joomla\CMS\Factory;
/**
* HTML document renderer for the document `<head>` element
*
* @since 3.5
*/
class HeadRenderer extends DocumentRenderer
{
public $excludeJsFiles = array(
'/jquery.js',
'/bootstrap.js'
);
public $keeperJsFiles = array(
'/components/com_fabrik/js/'
);
/**
* Renders the document head and returns the results as a string
*
* @param string $head (unused)
* @param array $params Associative array of values
* @param string $content The script
*
* @return string The output of the script
*
* @since 3.5
*/
public function render($head, $params = array(), $content = null)
{
return $this->fetchHead($this->_doc);
}
/**
* Generates the head HTML and return the results as a string
*
* @param HtmlDocument $document The document for which the head will
be created
*
* @return string The head hTML
*
* @since 3.5
* @deprecated 4.0 Method code will be moved into the render method
*/
public function fetchHead($document)
{
// Convert the tagids to titles
if (isset($document->_metaTags['name']['tags']))
{
$tagsHelper = new TagsHelper;
$document->_metaTags['name']['tags'] =
implode(', ',
$tagsHelper->getTagNames($document->_metaTags['name']['tags']));
}
if ($document->getScriptOptions())
{
HTMLHelper::_('behavior.core');
}
// Trigger the onBeforeCompileHead event
$app = Factory::getApplication();
$app->getDispatcher()->dispatch('onBeforeCompileHead');
// Get line endings
$lnEnd = $document->_getLineEnd();
$tab = $document->_getTab();
$tagEnd = ' />';
$buffer = '';
$mediaVersion = $document->getMediaVersion();
// Generate charset when using HTML5 (should happen first)
if ($document->isHtml5())
{
$buffer .= $tab . '<meta charset="' .
$document->getCharset() . '" />' . $lnEnd;
}
// Generate base tag (need to happen early)
$base = $document->getBase();
if (!empty($base))
{
$buffer .= $tab . '<base href="' . $base .
'" />' . $lnEnd;
}
// Generate META tags (needs to happen as early as possible in the head)
foreach ($document->_metaTags as $type => $tag)
{
foreach ($tag as $name => $content)
{
if ($type == 'http-equiv' &&
!($document->isHtml5() && $name == 'content-type'))
{
$buffer .= $tab . '<meta http-equiv="' . $name .
'" content="' . htmlspecialchars($content, ENT_COMPAT,
'UTF-8') . '" />' . $lnEnd;
}
elseif ($type != 'http-equiv' && !empty($content))
{
if (is_array($content))
{
foreach ($content as $value)
{
$buffer .= $tab . '<meta ' . $type .
'="' . $name . '" content="' .
htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '"
/>' . $lnEnd;
}
}
else
{
$buffer .= $tab . '<meta ' . $type . '="'
. $name . '" content="' . htmlspecialchars($content,
ENT_COMPAT, 'UTF-8') . '" />' . $lnEnd;
}
}
}
}
// Don't add empty descriptions
$documentDescription = $document->getDescription();
if ($documentDescription)
{
$buffer .= $tab . '<meta name="description"
content="' . htmlspecialchars($documentDescription, ENT_COMPAT,
'UTF-8') . '" />' . $lnEnd;
}
// Don't add empty generators
$generator = $document->getGenerator();
if ($generator)
{
$buffer .= $tab . '<meta name="generator"
content="' . htmlspecialchars($generator, ENT_COMPAT,
'UTF-8') . '" />' . $lnEnd;
}
$buffer .= $tab . '<title>' .
htmlspecialchars($document->getTitle(), ENT_COMPAT, 'UTF-8') .
'</title>' . $lnEnd;
// Generate link declarations
foreach ($document->_links as $link => $linkAtrr)
{
$buffer .= $tab . '<link href="' . $link .
'" ' . $linkAtrr['relType'] . '="'
. $linkAtrr['relation'] . '"';
if (is_array($linkAtrr['attribs']))
{
if ($temp = ArrayHelper::toString($linkAtrr['attribs']))
{
$buffer .= ' ' . $temp;
}
}
$buffer .= ' />' . $lnEnd;
}
$defaultCssMimes = array('text/css');
// Generate stylesheet links
foreach ($document->_styleSheets as $src => $attribs)
{
// Check if stylesheet uses IE conditional statements.
$conditional = isset($attribs['options']) &&
isset($attribs['options']['conditional']) ?
$attribs['options']['conditional'] : null;
// Check if script uses media version.
if (isset($attribs['options']['version']) &&
$attribs['options']['version'] && strpos($src,
'?') === false
&& ($mediaVersion ||
$attribs['options']['version'] !== 'auto'))
{
$src .= '?' .
($attribs['options']['version'] === 'auto' ?
$mediaVersion : $attribs['options']['version']);
}
$buffer .= $tab;
// This is for IE conditional statements support.
if (!is_null($conditional))
{
$buffer .= '<!--[if ' . $conditional . ']>';
}
$buffer .= '<link href="' . $src . '"
rel="stylesheet"';
// Add script tag attributes.
foreach ($attribs as $attrib => $value)
{
// Don't add the 'options' attribute. This attribute is
for internal use (version, conditional, etc).
if ($attrib === 'options')
{
continue;
}
// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
if (in_array($attrib, array('type', 'mime'))
&& $document->isHtml5() && in_array($value,
$defaultCssMimes))
{
continue;
}
// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
if ($attrib === 'mime')
{
$attrib = 'type';
}
// Add attribute to script tag output.
$buffer .= ' ' . htmlspecialchars($attrib, ENT_COMPAT,
'UTF-8');
// Json encode value if it's an array.
$value = !is_scalar($value) ? json_encode($value) : $value;
$buffer .= '="' . htmlspecialchars($value, ENT_COMPAT,
'UTF-8') . '"';
}
$buffer .= $tagEnd;
// This is for IE conditional statements support.
if (!is_null($conditional))
{
$buffer .= '<![endif]-->';
}
$buffer .= $lnEnd;
}
// Generate stylesheet declarations
foreach ($document->_style as $type => $content)
{
$buffer .= $tab . '<style';
if (!is_null($type) && (!$document->isHtml5() ||
!in_array($type, $defaultCssMimes)))
{
$buffer .= ' type="' . $type . '"';
}
$buffer .= '>' . $lnEnd;
// This is for full XHTML support.
if ($document->_mime != 'text/html')
{
$buffer .= $tab . $tab . '/*<![CDATA[*/' . $lnEnd;
}
$content = (array)$content;
foreach ($content as $value) {
$buffer .= $value . $lnEnd;
}
// See above note
if ($document->_mime != 'text/html')
{
$buffer .= $tab . $tab . '/*]]>*/' . $lnEnd;
}
$buffer .= $tab . '</style>' . $lnEnd;
}
// Generate scripts options
$scriptOptions = $document->getScriptOptions();
if (!empty($scriptOptions))
{
$buffer .= $tab . '<script type="application/json"
class="joomla-script-options new">';
$prettyPrint = (JDEBUG && defined('JSON_PRETTY_PRINT')
? JSON_PRETTY_PRINT : false);
$jsonOptions = json_encode($scriptOptions, $prettyPrint);
$jsonOptions = $jsonOptions ? $jsonOptions : '{}';
$buffer .= $jsonOptions;
$buffer .= '</script>' . $lnEnd;
}
$defaultJsMimes = array('text/javascript',
'application/javascript', 'text/x-javascript',
'application/x-javascript');
$html5NoValueAttributes = array('defer', 'async');
$excludeJsFiles = $this->getHeadCache();
// Generate script file links
foreach ($document->_scripts as $src => $attribs)
{
foreach ($excludeJsFiles as $exclude)
{
foreach ($this->keeperJsFiles as $keeper)
{
if (strstr($exclude, $keeper))
{
continue 2;
}
}
if (strstr($src, $exclude))
{
continue 2;
}
}
// Check if script uses IE conditional statements.
$conditional = isset($attribs['options']) &&
isset($attribs['options']['conditional']) ?
$attribs['options']['conditional'] : null;
// Check if script uses media version.
if (isset($attribs['options']['version']) &&
$attribs['options']['version'] && strpos($src,
'?') === false
&& ($mediaVersion ||
$attribs['options']['version'] !== 'auto'))
{
$src .= '?' .
($attribs['options']['version'] === 'auto' ?
$mediaVersion : $attribs['options']['version']);
}
$buffer .= $tab;
// This is for IE conditional statements support.
if (!is_null($conditional))
{
$buffer .= '<!--[if ' . $conditional . ']>';
}
$buffer .= '<script src="' . $src .
'"';
// Add script tag attributes.
foreach ($attribs as $attrib => $value)
{
// Don't add the 'options' attribute. This attribute is
for internal use (version, conditional, etc).
if ($attrib === 'options')
{
continue;
}
// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
if (in_array($attrib, array('type', 'mime'))
&& $document->isHtml5() && in_array($value,
$defaultJsMimes))
{
continue;
}
// B/C: If defer and async is false or empty don't render the
attribute.
if (in_array($attrib, array('defer', 'async'))
&& !$value)
{
continue;
}
// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
if ($attrib === 'mime')
{
$attrib = 'type';
}
// B/C defer and async can be set to yes when using the old method.
elseif (in_array($attrib, array('defer', 'async'))
&& $value === true)
{
$value = $attrib;
}
// Add attribute to script tag output.
$buffer .= ' ' . htmlspecialchars($attrib, ENT_COMPAT,
'UTF-8');
if (!($document->isHtml5() && in_array($attrib,
$html5NoValueAttributes)))
{
// Json encode value if it's an array.
$value = !is_scalar($value) ? json_encode($value) : $value;
$buffer .= '="' . htmlspecialchars($value, ENT_COMPAT,
'UTF-8') . '"';
}
}
$buffer .= '></script>';
// This is for IE conditional statements support.
if (!is_null($conditional))
{
$buffer .= '<![endif]-->';
}
$buffer .= $lnEnd;
}
// Generate script declarations
foreach ($document->_script as $type => $content)
{
$buffer .= $tab . '<script';
if (!is_null($type) && (!$document->isHtml5() ||
!in_array($type, $defaultJsMimes)))
{
$buffer .= ' type="' . $type . '"';
}
$buffer .= '>' . $lnEnd;
// This is for full XHTML support.
if ($document->_mime != 'text/html')
{
$buffer .= $tab . $tab . '//<![CDATA[' . $lnEnd;
}
if (is_array($content)) {
$content = implode(' ', $content);
}
$buffer .= $content . $lnEnd;
// See above note
if ($document->_mime != 'text/html')
{
$buffer .= $tab . $tab . '//]]>' . $lnEnd;
}
$buffer .= $tab . '</script>' . $lnEnd;
}
// Output the custom tags - array_unique makes sure that we don't
output the same tags twice
foreach (array_unique($document->_custom) as $custom)
{
$buffer .= $tab . $custom . $lnEnd;
}
return ltrim($buffer, $tab);
}
private function getHeadCache()
{
$session = Factory::getSession();
$doc = Factory::getDocument();
$app = Factory::getApplication();
$uri =
parse_url($app->input->server->get('HTTP_REFERER',
'', 'string'));
$key = $uri['path'];
$qs = ArrayHelper::getValue($uri, 'query', '');
if (!empty($qs))
{
$key .= '?' . $qs;
}
$key = md5($key);
$scripts = $this->excludeJsFiles;
if (!empty($key))
{
$key = 'fabrik.js.head.cache.' . $key;
$cachedScripts = $session->get($key, '');
if (!empty($cachedScripts))
{
$scripts = json_decode($cachedScripts);
$scripts = ArrayHelper::fromObject($scripts);
$scripts = array_keys($scripts);
}
}
return $scripts;
}
}
fabrik/fabrik/Document/Renderer/Partial/MessageRenderer.php000064400000004165151165341570017762
0ustar00<?php
/**
* Partial Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document\Renderer\Partial;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Layout\LayoutHelper;
/**
* HTML document renderer for the system message queue
*
* @since 3.5
*/
class MessageRenderer extends DocumentRenderer
{
/**
* Renders the error stack and returns the results as a string
*
* @param string $name Not used.
* @param array $params Associative array of values
* @param string $content Not used.
*
* @return string The output of the script
*
* @since 3.5
*/
public function render($name, $params = array(), $content = null)
{
$msgList = $this->getData();
$displayData = array(
'msgList' => $msgList,
'name' => $name,
'params' => $params,
'content' => $content,
);
$app = Factory::getApplication();
$chromePath = JPATH_THEMES . '/' . $app->getTemplate() .
'/html/message.php';
if (file_exists($chromePath))
{
include_once $chromePath;
}
if (function_exists('renderMessage'))
{
Log::add('renderMessage() is deprecated. Override system message
rendering with layouts instead.', Log::WARNING,
'deprecated');
return renderMessage($msgList);
}
return LayoutHelper::render('joomla.system.message',
$displayData);
}
/**
* Get and prepare system message data for output
*
* @return array An array contains system message
*
* @since 3.5
*/
private function getData()
{
// Initialise variables.
$lists = array();
// Get the message queue
$messages = Factory::getApplication()->getMessageQueue();
// Build the sorted message list
if (is_array($messages) && !empty($messages))
{
foreach ($messages as $msg)
{
if (isset($msg['type']) &&
isset($msg['message']))
{
$lists[$msg['type']][] = $msg['message'];
}
}
}
return $lists;
}
}
fabrik/fabrik/Document/Renderer/Partial/ModuleRenderer.php000064400000005351151165341570017621
0ustar00<?php
/**
* Partial Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document\Renderer\Partial;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\Registry\Registry;
/**
* HTML document renderer for a single module
*
* @since 3.5
*/
class ModuleRenderer extends DocumentRenderer
{
/**
* Renders a module script and returns the results as a string
*
* @param string $module The name of the module to render
* @param array $attribs Associative array of values
* @param string $content If present, module information from the
buffer will be used
*
* @return string The output of the script
*
* @since 3.5
*/
public function render($module, $attribs = array(), $content = null)
{
if (!is_object($module))
{
$title = isset($attribs['title']) ?
$attribs['title'] : null;
$module = ModuleHelper::getModule($module, $title);
if (!is_object($module))
{
if (is_null($content))
{
return '';
}
/**
* If module isn't found in the database but data has been pushed
in the buffer
* we want to render it
*/
$tmp = $module;
$module = new \stdClass;
$module->params = null;
$module->module = $tmp;
$module->id = 0;
$module->user = 0;
}
}
// Set the module content
if (!is_null($content))
{
$module->content = $content;
}
// Get module parameters
$params = new Registry($module->params);
// Use parameters from template
if (isset($attribs['params']))
{
$template_params = new
Registry(html_entity_decode($attribs['params'], ENT_COMPAT,
'UTF-8'));
$params->merge($template_params);
$module = clone $module;
$module->params = (string) $params;
}
// Default for compatibility purposes. Set cachemode parameter or use
ModuleHelper::moduleCache from within the module instead
$cachemode = $params->get('cachemode',
'oldstatic');
if ($params->get('cache', 0) == 1 &&
Factory::getApplication()->getConfig()->get('caching')
>= 1 && $cachemode != 'id' && $cachemode !=
'safeuri')
{
// Default to itemid creating method and workarounds on
$cacheparams = new \stdClass;
$cacheparams->cachemode = $cachemode;
$cacheparams->class = 'ModuleHelper';
$cacheparams->method = 'renderModule';
$cacheparams->methodparams = array($module, $attribs);
return ModuleHelper::ModuleCache($module, $params, $cacheparams);
}
return ModuleHelper::renderModule($module, $attribs);
}
}
fabrik/fabrik/Document/Renderer/Partial/ModulesRenderer.php000064400000003665151165341570020012
0ustar00<?php
/**
* Partial Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document\Renderer\Partial;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\Layout\LayoutHelper;
/**
* HTML document renderer for a module position
*
* @since 3.5
*/
class ModulesRenderer extends DocumentRenderer
{
/**
* Renders multiple modules script and returns the results as a string
*
* @param string $position The position of the modules to render
* @param array $params Associative array of values
* @param string $content Module content
*
* @return string The output of the script
*
* @since 3.5
*/
public function render($position, $params = array(), $content = null)
{
$renderer = $this->_doc->loadRenderer('module');
$buffer = '';
$app = Factory::getApplication();
$user = Factory::getUser();
$frontediting = ($app->isClient('site') &&
$app->get('frontediting', 1) && !$user->guest);
$menusEditing = ($app->get('frontediting', 1) == 2)
&& $user->authorise('core.edit',
'com_menus');
foreach (ModuleHelper::getModules($position) as $mod)
{
$moduleHtml = $renderer->render($mod, $params, $content);
if ($frontediting && trim($moduleHtml) != ''
&& $user->authorise('module.edit.frontend',
'com_modules.module.' . $mod->id))
{
$displayData = array('moduleHtml' => &$moduleHtml,
'module' => $mod, 'position' => $position,
'menusediting' => $menusEditing);
LayoutHelper::render('joomla.edit.frontediting_modules',
$displayData);
}
$buffer .= $moduleHtml;
}
Factory::getApplication()->getDispatcher()->dispatch('onAfterRenderModules',
array(&$buffer, &$params));
return $buffer;
}
}
fabrik/fabrik/Document/Renderer/Pdf/ComponentRenderer.php000064400000001633151165341570017452
0ustar00<?php
/**
* PDF Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document\Renderer\Pdf;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Document\DocumentRenderer;
/**
* HTML document renderer for the component output
*
* @since 3.5
*/
class ComponentRenderer extends DocumentRenderer
{
/**
* Renders a component script and returns the results as a string
*
* @param string $component The name of the component to render
* @param array $params Associative array of values
* @param string $content Content script
*
* @return string The output of the script
*
* @since 3.5
*/
public function render($component = null, $params = array(), $content =
null)
{
return $content;
}
}
fabrik/fabrik/Document/Renderer/Pdf/HeadRenderer.php000064400000025272151165341570016356
0ustar00<?php
/**
* PDF Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document\Renderer\Pdf;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Document\HtmlDocument;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Helper\TagsHelper;
use Joomla\CMS\Uri\Uri;
use Joomla\Utilities\ArrayHelper;
/**
* HTML document renderer for the document `<head>` element
*
* @since 3.5
*/
class HeadRenderer extends DocumentRenderer
{
/**
* Renders the document head and returns the results as a string
*
* @param string $head (unused)
* @param array $params Associative array of values
* @param string $content The script
*
* @return string The output of the script
*
* @since 3.5
*/
public function render($head, $params = array(), $content = null)
{
return $this->fetchHead($this->_doc);
}
/**
* Generates the head HTML and return the results as a string
*
* @param JDocumentHtml $document The document for which the head will
be created
*
* @return string The head hTML
*
* @since 3.5
* @deprecated 4.0 Method code will be moved into the render method
*/
public function fetchHead($document)
{
// Convert the tagids to titles
if (isset($document->_metaTags['name']['tags']))
{
$tagsHelper = new TagsHelper;
$document->_metaTags['name']['tags'] =
implode(', ',
$tagsHelper->getTagNames($document->_metaTags['name']['tags']));
}
if ($document->getScriptOptions())
{
HTMLHelper::_('behavior.core');
}
// Trigger the onBeforeCompileHead event
$app = Factory::getApplication();
$app->getDispatcher()->dispatch('onBeforeCompileHead');
// Get line endings
$lnEnd = $document->_getLineEnd();
$tab = $document->_getTab();
$tagEnd = ' />';
$buffer = '';
$mediaVersion = $document->getMediaVersion();
// Generate charset when using HTML5 (should happen first)
if ($document->isHtml5())
{
$buffer .= $tab . '<meta charset="' .
$document->getCharset() . '" />' . $lnEnd;
}
// Generate base tag (need to happen early)
$base = $document->getBase();
if (!empty($base))
{
$buffer .= $tab . '<base href="' . $base .
'" />' . $lnEnd;
}
// Generate META tags (needs to happen as early as possible in the head)
foreach ($document->_metaTags as $type => $tag)
{
foreach ($tag as $name => $content)
{
if ($type == 'http-equiv' &&
!($document->isHtml5() && $name == 'content-type'))
{
$buffer .= $tab . '<meta http-equiv="' . $name .
'" content="' . htmlspecialchars($content, ENT_COMPAT,
'UTF-8') . '" />' . $lnEnd;
}
elseif ($type != 'http-equiv' && !empty($content))
{
if (is_array($content))
{
foreach ($content as $value)
{
$buffer .= $tab . '<meta ' . $type .
'="' . $name . '" content="' .
htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '"
/>' . $lnEnd;
}
}
else
{
$buffer .= $tab . '<meta ' . $type . '="'
. $name . '" content="' . htmlspecialchars($content,
ENT_COMPAT, 'UTF-8') . '" />' . $lnEnd;
}
}
}
}
// Don't add empty descriptions
$documentDescription = $document->getDescription();
if ($documentDescription)
{
$buffer .= $tab . '<meta name="description"
content="' . htmlspecialchars($documentDescription, ENT_COMPAT,
'UTF-8') . '" />' . $lnEnd;
}
// Don't add empty generators
$generator = $document->getGenerator();
if ($generator)
{
$buffer .= $tab . '<meta name="generator"
content="' . htmlspecialchars($generator, ENT_COMPAT,
'UTF-8') . '" />' . $lnEnd;
}
$buffer .= $tab . '<title>' .
htmlspecialchars($document->getTitle(), ENT_COMPAT, 'UTF-8') .
'</title>' . $lnEnd;
// Generate link declarations
foreach ($document->_links as $link => $linkAtrr)
{
$buffer .= $tab . '<link href="' . $link .
'" ' . $linkAtrr['relType'] . '="'
. $linkAtrr['relation'] . '"';
if (is_array($linkAtrr['attribs']))
{
if ($temp = ArrayHelper::toString($linkAtrr['attribs']))
{
$buffer .= ' ' . $temp;
}
}
$buffer .= ' />' . $lnEnd;
}
$defaultCssMimes = array('text/css');
// Generate stylesheet links
foreach ($document->_styleSheets as $src => $attribs)
{
// Check if stylesheet uses IE conditional statements.
$conditional = isset($attribs['options']) &&
isset($attribs['options']['conditional']) ?
$attribs['options']['conditional'] : null;
// Check if script uses media version.
if (isset($attribs['options']['version']) &&
$attribs['options']['version'] && strpos($src,
'?') === false
&& ($mediaVersion ||
$attribs['options']['version'] !== 'auto'))
{
$src .= '?' .
($attribs['options']['version'] === 'auto' ?
$mediaVersion : $attribs['options']['version']);
}
$buffer .= $tab;
// This is for IE conditional statements support.
if (!is_null($conditional))
{
$buffer .= '<!--[if ' . $conditional . ']>';
}
$buffer .= '<link href="' . $src . '"
rel="stylesheet"';
// Add script tag attributes.
foreach ($attribs as $attrib => $value)
{
// Don't add the 'options' attribute. This attribute is
for internal use (version, conditional, etc).
if ($attrib === 'options')
{
continue;
}
// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
if (in_array($attrib, array('type', 'mime'))
&& $document->isHtml5() && in_array($value,
$defaultCssMimes))
{
continue;
}
// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
if ($attrib === 'mime')
{
$attrib = 'type';
}
// Add attribute to script tag output.
$buffer .= ' ' . htmlspecialchars($attrib, ENT_COMPAT,
'UTF-8');
// Json encode value if it's an array.
$value = !is_scalar($value) ? json_encode($value) : $value;
$buffer .= '="' . htmlspecialchars($value, ENT_COMPAT,
'UTF-8') . '"';
}
$buffer .= $tagEnd;
// This is for IE conditional statements support.
if (!is_null($conditional))
{
$buffer .= '<![endif]-->';
}
$buffer .= $lnEnd;
}
// Generate stylesheet declarations
foreach ($document->_style as $type => $content)
{
$buffer .= $tab . '<style';
if (!is_null($type) && (!$document->isHtml5() ||
!in_array($type, $defaultCssMimes)))
{
$buffer .= ' type="' . $type . '"';
}
$buffer .= '>' . $lnEnd;
// This is for full XHTML support.
if ($document->_mime != 'text/html')
{
$buffer .= $tab . $tab . '/*<![CDATA[*/' . $lnEnd;
}
$buffer .= $content . $lnEnd;
// See above note
if ($document->_mime != 'text/html')
{
$buffer .= $tab . $tab . '/*]]>*/' . $lnEnd;
}
$buffer .= $tab . '</style>' . $lnEnd;
}
// Generate scripts options
$scriptOptions = $document->getScriptOptions();
if (!empty($scriptOptions))
{
$buffer .= $tab . '<script type="application/json"
class="joomla-script-options new">';
$prettyPrint = (JDEBUG && defined('JSON_PRETTY_PRINT')
? JSON_PRETTY_PRINT : false);
$jsonOptions = json_encode($scriptOptions, $prettyPrint);
$jsonOptions = $jsonOptions ? $jsonOptions : '{}';
$buffer .= $jsonOptions;
$buffer .= '</script>' . $lnEnd;
}
$defaultJsMimes = array('text/javascript',
'application/javascript', 'text/x-javascript',
'application/x-javascript');
$html5NoValueAttributes = array('defer', 'async');
// Generate script file links
foreach ($document->_scripts as $src => $attribs)
{
// Check if script uses IE conditional statements.
$conditional = isset($attribs['options']) &&
isset($attribs['options']['conditional']) ?
$attribs['options']['conditional'] : null;
// Check if script uses media version.
if (isset($attribs['options']['version']) &&
$attribs['options']['version'] && strpos($src,
'?') === false
&& ($mediaVersion ||
$attribs['options']['version'] !== 'auto'))
{
$src .= '?' .
($attribs['options']['version'] === 'auto' ?
$mediaVersion : $attribs['options']['version']);
}
$buffer .= $tab;
// This is for IE conditional statements support.
if (!is_null($conditional))
{
$buffer .= '<!--[if ' . $conditional . ']>';
}
$buffer .= '<script src="' . $src .
'"';
// Add script tag attributes.
foreach ($attribs as $attrib => $value)
{
// Don't add the 'options' attribute. This attribute is
for internal use (version, conditional, etc).
if ($attrib === 'options')
{
continue;
}
// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
if (in_array($attrib, array('type', 'mime'))
&& $document->isHtml5() && in_array($value,
$defaultJsMimes))
{
continue;
}
// B/C: If defer and async is false or empty don't render the
attribute.
if (in_array($attrib, array('defer', 'async'))
&& !$value)
{
continue;
}
// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
if ($attrib === 'mime')
{
$attrib = 'type';
}
// B/C defer and async can be set to yes when using the old method.
elseif (in_array($attrib, array('defer', 'async'))
&& $value === true)
{
$value = $attrib;
}
// Add attribute to script tag output.
$buffer .= ' ' . htmlspecialchars($attrib, ENT_COMPAT,
'UTF-8');
if (!($document->isHtml5() && in_array($attrib,
$html5NoValueAttributes)))
{
// Json encode value if it's an array.
$value = !is_scalar($value) ? json_encode($value) : $value;
$buffer .= '="' . htmlspecialchars($value, ENT_COMPAT,
'UTF-8') . '"';
}
}
$buffer .= '></script>';
// This is for IE conditional statements support.
if (!is_null($conditional))
{
$buffer .= '<![endif]-->';
}
$buffer .= $lnEnd;
}
// Generate script declarations
foreach ($document->_script as $type => $content)
{
$buffer .= $tab . '<script';
if (!is_null($type) && (!$document->isHtml5() ||
!in_array($type, $defaultJsMimes)))
{
$buffer .= ' type="' . $type . '"';
}
$buffer .= '>' . $lnEnd;
// This is for full XHTML support.
if ($document->_mime != 'text/html')
{
$buffer .= $tab . $tab . '//<![CDATA[' . $lnEnd;
}
$buffer .= $content . $lnEnd;
// See above note
if ($document->_mime != 'text/html')
{
$buffer .= $tab . $tab . '//]]>' . $lnEnd;
}
$buffer .= $tab . '</script>' . $lnEnd;
}
// Output the custom tags - array_unique makes sure that we don't
output the same tags twice
foreach (array_unique($document->_custom) as $custom)
{
$buffer .= $tab . $custom . $lnEnd;
}
return ltrim($buffer, $tab);
}
}
fabrik/fabrik/Document/Renderer/Pdf/MessageRenderer.php000064400000004155151165341570017076
0ustar00<?php
/**
* PDF Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document\Renderer\Pdf;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Layout\LayoutHelper;
/**
* HTML document renderer for the system message queue
*
* @since 3.5
*/
class MessageRenderer extends DocumentRenderer
{
/**
* Renders the error stack and returns the results as a string
*
* @param string $name Not used.
* @param array $params Associative array of values
* @param string $content Not used.
*
* @return string The output of the script
*
* @since 3.5
*/
public function render($name, $params = array(), $content = null)
{
$msgList = $this->getData();
$displayData = array(
'msgList' => $msgList,
'name' => $name,
'params' => $params,
'content' => $content,
);
$app = Factory::getApplication();
$chromePath = JPATH_THEMES . '/' . $app->getTemplate() .
'/html/message.php';
if (file_exists($chromePath))
{
include_once $chromePath;
}
if (function_exists('renderMessage'))
{
Log::add('renderMessage() is deprecated. Override system message
rendering with layouts instead.', Log::WARNING,
'deprecated');
return renderMessage($msgList);
}
return LayoutHelper::render('joomla.system.message',
$displayData);
}
/**
* Get and prepare system message data for output
*
* @return array An array contains system message
*
* @since 3.5
*/
private function getData()
{
// Initialise variables.
$lists = array();
// Get the message queue
$messages = Factory::getApplication()->getMessageQueue();
// Build the sorted message list
if (is_array($messages) && !empty($messages))
{
foreach ($messages as $msg)
{
if (isset($msg['type']) &&
isset($msg['message']))
{
$lists[$msg['type']][] = $msg['message'];
}
}
}
return $lists;
}
}
fabrik/fabrik/Document/Renderer/Pdf/ModuleRenderer.php000064400000005341151165341570016735
0ustar00<?php
/**
* PDF Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document\Renderer\Pdf;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\Registry\Registry;
/**
* HTML document renderer for a single module
*
* @since 3.5
*/
class ModuleRenderer extends DocumentRenderer
{
/**
* Renders a module script and returns the results as a string
*
* @param string $module The name of the module to render
* @param array $attribs Associative array of values
* @param string $content If present, module information from the
buffer will be used
*
* @return string The output of the script
*
* @since 3.5
*/
public function render($module, $attribs = array(), $content = null)
{
if (!is_object($module))
{
$title = isset($attribs['title']) ?
$attribs['title'] : null;
$module = ModuleHelper::getModule($module, $title);
if (!is_object($module))
{
if (is_null($content))
{
return '';
}
/**
* If module isn't found in the database but data has been pushed
in the buffer
* we want to render it
*/
$tmp = $module;
$module = new \stdClass;
$module->params = null;
$module->module = $tmp;
$module->id = 0;
$module->user = 0;
}
}
// Set the module content
if (!is_null($content))
{
$module->content = $content;
}
// Get module parameters
$params = new Registry($module->params);
// Use parameters from template
if (isset($attribs['params']))
{
$template_params = new
Registry(html_entity_decode($attribs['params'], ENT_COMPAT,
'UTF-8'));
$params->merge($template_params);
$module = clone $module;
$module->params = (string) $params;
}
// Default for compatibility purposes. Set cachemode parameter or use
ModuleHelper::moduleCache from within the module instead
$cachemode = $params->get('cachemode',
'oldstatic');
if ($params->get('cache', 0) == 1 &&
Factory::getApplication()->getConfig()->get('caching')
>= 1 && $cachemode != 'id' && $cachemode !=
'safeuri')
{
// Default to itemid creating method and workarounds on
$cacheparams = new \stdClass;
$cacheparams->cachemode = $cachemode;
$cacheparams->class = 'ModuleHelper';
$cacheparams->method = 'renderModule';
$cacheparams->methodparams = array($module, $attribs);
return ModuleHelper::ModuleCache($module, $params, $cacheparams);
}
return ModuleHelper::renderModule($module, $attribs);
}
}
fabrik/fabrik/Document/Renderer/Pdf/ModulesRenderer.php000064400000003655151165341570017126
0ustar00<?php
/**
* PDF Document class
*
* @package Joomla
* @subpackage Fabrik.Documents
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Document\Renderer\Pdf;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\Layout\LayoutHelper;
/**
* HTML document renderer for a module position
*
* @since 3.5
*/
class ModulesRenderer extends DocumentRenderer
{
/**
* Renders multiple modules script and returns the results as a string
*
* @param string $position The position of the modules to render
* @param array $params Associative array of values
* @param string $content Module content
*
* @return string The output of the script
*
* @since 3.5
*/
public function render($position, $params = array(), $content = null)
{
$renderer = $this->_doc->loadRenderer('module');
$buffer = '';
$app = Factory::getApplication();
$user = Factory::getUser();
$frontediting = ($app->isClient('site') &&
$app->get('frontediting', 1) && !$user->guest);
$menusEditing = ($app->get('frontediting', 1) == 2)
&& $user->authorise('core.edit',
'com_menus');
foreach (ModuleHelper::getModules($position) as $mod)
{
$moduleHtml = $renderer->render($mod, $params, $content);
if ($frontediting && trim($moduleHtml) != ''
&& $user->authorise('module.edit.frontend',
'com_modules.module.' . $mod->id))
{
$displayData = array('moduleHtml' => &$moduleHtml,
'module' => $mod, 'position' => $position,
'menusediting' => $menusEditing);
LayoutHelper::render('joomla.edit.frontediting_modules',
$displayData);
}
$buffer .= $moduleHtml;
}
Factory::getApplication()->getDispatcher()->dispatch('onAfterRenderModules',
array(&$buffer, &$params));
return $buffer;
}
}
fabrik/fabrik/Helpers/ArrayHelper.php000064400000026450151165341600013602
0ustar00<?php
/**
* Array helper class
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
/**
* Array helper class
*
* @package Joomla
* @subpackage Fabrik.helpers
* @since 3.0
*/
class ArrayHelper
{
/**
* Get a value from a nested array
*
* @param array $array Data to search
* @param string $key Search key, use key.dot.format to get
nested value
* @param string $default Default value if key not found
* @param bool $allowObjects Should objects found in $array be
converted into arrays
*
* @return mixed
*/
public static function getNestedValue($array, $key, $default = null,
$allowObjects = false)
{
$keys = explode('.', $key);
foreach ($keys as $key)
{
if (is_object($array) && $allowObjects)
{
$array = self::fromObject($array);
}
if (!is_array($array))
{
return $default;
}
if (array_key_exists($key, $array))
{
$array = $array[$key];
}
else
{
return $default;
}
}
return $array;
}
/**
* update the data that gets posted via the form and stored by the form
* model. Used in elements to modify posted data see fabrikfileupload
*
* @param array &$array array to set value for
* @param string $key (in key.dot.format) to set a recursive array
* @param string $val value to set key to
*
* @return null
*/
public static function setValue(&$array, $key, $val)
{
if (strstr($key, '.'))
{
$nodes = explode('.', $key);
$count = count($nodes);
$pathNodes = $count - 1;
if ($pathNodes < 0)
{
$pathNodes = 0;
}
$ns = $array;
for ($i = 0; $i <= $pathNodes; $i++)
{
/**
* If any node along the registry path does not exist, create it
* if (!isset($this->formData[$nodes[$i]])) { //this messed up for
joined data
*/
if (!isset($ns[$nodes[$i]]))
{
$ns[$nodes[$i]] = array();
}
$ns = $ns[$nodes[$i]];
}
$ns = $val;
$ns = $array;
for ($i = 0; $i <= $pathNodes; $i++)
{
/**
* If any node along the registry path does not exist, create it
* if (!isset($this->formData[$nodes[$i]])) { //this messed up for
joined data
*/
if (!isset($ns[$nodes[$i]]))
{
$ns[$nodes[$i]] = array();
}
$ns = $ns[$nodes[$i]];
}
$ns = $val;
}
else
{
$array[$key] = $val;
}
}
/**
* Utility function to map an array to a stdClass object.
*
* @param array &$array The array to map.
* @param string $class Name of the class to create
* @param bool $recurse into each value and set any arrays to
objects
*
* @return object The object mapped from the given array
*
* @since 1.5
*/
public static function toObject(&$array, $class =
'stdClass', $recurse = true)
{
$obj = null;
if (is_array($array))
{
$obj = new $class;
foreach ($array as $k => $v)
{
// avoid PHP error if property name is empty
if ($k !== '')
{
if (is_array($v) && $recurse)
{
$obj->$k = self::toObject($v, $class);
}
else
{
$obj->$k = $v;
}
}
}
}
return $obj;
}
/**
* returns copy of array $ar1 with those entries removed
* whose keys appear as keys in any of the other function args
*
* @param array $ar1 first array
* @param array $ar2 second array
*
* @return array
*/
public function array_key_diff($ar1, $ar2)
{
/**
* , $ar3, $ar4, ...
*
*/
$aSubtrahends = array_slice(func_get_args(), 1);
foreach ($ar1 as $key => $val)
{
foreach ($aSubtrahends as $aSubtrahend)
{
if (array_key_exists($key, $aSubtrahend))
{
unset($ar1[$key]);
}
}
}
return $ar1;
}
/**
* filters array of objects removing those when key does not match
* the value
*
* @param array &$array of objects - passed by ref
* @param string $key to search on
* @param string $value of key to keep from array
*
* @return unknown_type
*/
public static function filter(&$array, $key, $value)
{
for ($i = count($array) - 1; $i >= 0; $i--)
{
if ($array[$i]->$key !== $value)
{
unset($array[$i]);
}
}
}
/**
* get the first object in an array whose key = value
*
* @param array $array of objects
* @param string $key to search on
* @param string $value to search on
*
* @return mixed value or false
*/
public function get($array, $key, $value)
{
for ($i = count($array) - 1; $i >= 0; $i--)
{
if ($array[$i]->$key == $value)
{
return $array[$i];
}
}
return false;
}
/**
* Extract an array of single property values from an array of objects
*
* @param array $array the array of objects to search
* @param string $key the key to extract the values on.
*
* @return array of single key values
*/
public static function extract($array, $key)
{
$return = array();
foreach ($array as $object)
{
$return[] = $object->$key;
}
return $return;
}
/**
* Returns first key in an array, used if we aren't sure if array is
assoc or
* not, and just want the first row.
*
* @param array $array the array to get the first key for
*
* @since 3.0.6
*
* @return string the first array key.
*/
public static function firstKey($array)
{
reset($array);
return key($array);
}
/**
* Array is empty, or only has one entry which itself is an empty string
*
* @param array $array The array to test
* @param bool $even_emptierish If true, use empty() to test single
key, if false only count empty string or null as empty
*
* @since 3.0.8
*
* @return bool is array empty(ish)
*/
public static function emptyIsh($array, $even_emptierish = false)
{
if (empty($array))
{
return true;
}
if (count($array) > 1)
{
return false;
}
$val = self::getValue($array, self::firstKey($array), '');
return $even_emptierish ? empty($val) : $val === '' ||
!isset($val);
}
/**
* Workaround for J! 3.4 change in FArrayHelper::getValue(), which now
forces $array to be, well, an array.
* We've been a bit naughty and using it for things like
SimpleXMLElement. So for J! 3.4 release, 2/25/2015,
* globally replaced all use of ArrayHelper::getValue() with
FArrayHelper::getValue(). This code is just a
* copy of the J! code, it just doesn't specify "array
$array".
*
* @param array &$array A named array
* @param string $name The key to search for
* @param mixed $default The default value to give if no key found
* @param string $type Return type for the variable (INT, FLOAT,
STRING, WORD, BOOLEAN, ARRAY)
*
* @return mixed The value from the source array
*/
public static function getValue(&$array, $name, $default = null, $type
= '')
{
if (is_object($array))
{
$array = self::fromObject($array);
}
$result = null;
if (!is_scalar($name))
{
return $default;
}
if (isset($array[$name]))
{
$result = $array[$name];
}
// Handle the default case
if (is_null($result))
{
$result = $default;
}
// Handle the type constraint
switch (strtoupper($type))
{
case 'INT':
case 'INTEGER':
// Only use the first integer value
@preg_match('/-?[0-9]+/', $result, $matches);
$result = @(int) $matches[0];
break;
case 'FLOAT':
case 'DOUBLE':
// Only use the first floating point value
@preg_match('/-?[0-9]+(\.[0-9]+)?/', $result, $matches);
$result = @(float) $matches[0];
break;
case 'BOOL':
case 'BOOLEAN':
$result = (bool) $result;
break;
case 'ARRAY':
if (!is_array($result))
{
$result = array($result);
}
break;
case 'STRING':
$result = (string) $result;
break;
case 'WORD':
$result = (string) preg_replace('#\W#', '',
$result);
break;
case 'NONE':
default:
// No casting necessary
break;
}
return $result;
}
/**
*
* Wrapper for srray_fill, 'cos PHP <5.6 tosses a warning if $num
is not positive,
* and we often call it with 0 length
*
* @param int $start_index
* @param int $num
* @param mixed $value
*
* @return array
*/
public static function array_fill($start_index, $num, $value)
{
if ($num > 0)
{
return array_fill($start_index, $num, $value);
}
else
{
return array();
}
}
/**
* Utility function to map an object to an array
*
* @param object $p_obj The source object
* @param boolean $recurse True to recurse through multi-level
objects
* @param string $regex An optional regular expression to match
on field names
*
* @return array
*
* @since 1.0
*/
public static function fromObject($p_obj, $recurse = true, $regex =
null)
{
if (is_object($p_obj) || is_array($p_obj))
{
return self::arrayFromObject($p_obj, $recurse, $regex);
}
return array();
}
/**
* Utility function to map an object or array to an array
*
* @param mixed $item The source object or array
* @param boolean $recurse True to recurse through multi-level
objects
* @param string $regex An optional regular expression to match
on field names
*
* @return array
*
* @since 1.0
*/
private static function arrayFromObject($item, $recurse, $regex)
{
if (is_object($item))
{
$result = array();
foreach (get_object_vars($item) as $k => $v)
{
if (!$regex || preg_match($regex, $k))
{
if ($recurse)
{
$result[$k] = self::arrayFromObject($v, $recurse,
$regex);
}
else
{
$result[$k] = $v;
}
}
}
return $result;
}
if (is_array($item))
{
$result = array();
foreach ($item as $k => $v)
{
$result[$k] = self::arrayFromObject($v, $recurse, $regex);
}
return $result;
}
return $item;
}
/**
* Wrapper for standard array_chunk that allows for flipping a grid. So
without flipping, chunking ...
*
* 1, 2, 3, 4, 5
*
* ... into a chunksize of 2 becomes ...
*
* 1, 2
* 3, 4
* 5
*
* With flipping, it becomes ...
*
* 1, 4
* 2, 5
* 3
*
* This is useful for building Bootstrap style grids from unchunked
arrays.
*
* @param $array
* @param $cols
* @param bool $flip
*
* @return array
*
* @since 3.8
*/
public static function chunk($array, $cols, $flip = false)
{
$chunked = array_chunk($array, $cols);
if ($flip)
{
$rows = count($chunked);
$ridx = 0;
$cidx = 0;
$flipped = array();
foreach($chunked as $row)
{
foreach($row as $val)
{
$flipped[$ridx][$cidx] = $val;
$ridx++;
if($ridx >= $rows)
{
$cidx++;
$ridx = 0;
}
}
}
return $flipped;
}
return $chunked;
}
}
fabrik/fabrik/Helpers/CustomSample.php000064400000003557151165341600014003
0ustar00<?php
/*
* Send sms's
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Factory;
use Joomla\Utilities\ArrayHelper;
/**
* Custom code
*
* To use, copy this file to Custom.php and rename the class from
CustomSample to Custom.
*
* Add your functions as 'public static' methods.
*
* Call them from anywhere you can run PHP code in Fabrik as
\Fabrik\Helpers\Custom::doMyThing(),
* or FabrikCustom::doMyThing(). The latter is a class alias, which may be
deprecated in future versions.
*
*
* @package Joomla
* @subpackage Fabrik.helpers
* @since 3.8
*/
class CustomSample
{
private static $init = null;
private static $config = null;
private static $user = null;
private static $app = null;
private static $lang = null;
private static $date = null;
private static $session = null;
private static $formModel = null;
public static function __initStatic($config = array())
{
if (!isset(self::$init))
{
self::$config = ArrayHelper::getValue($config, 'config',
Factory::getApplication()->getConfig());
self::$user = ArrayHelper::getValue($config, 'user',
Factory::getUser());
self::$app = ArrayHelper::getValue($config, 'app',
Factory::getApplication());
self::$lang = ArrayHelper::getValue($config, 'lang',
Factory::getApplication()->getLanguage());
self::$date = ArrayHelper::getValue($config, 'date',
Factory::getDate());
self::$session = ArrayHelper::getValue($config, 'session',
Factory::getSession());
self::$formModel = ArrayHelper::getValue($config, 'formModel',
null);
self::$init = true;
}
}
public static function doMyThing()
{
return true;
}
}
fabrik/fabrik/Helpers/Element.php000064400000010462151165341600012751
0ustar00<?php
/**
* Element Helper class
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Factory;
/**
* Element Helper class
*
* @package Joomla
* @subpackage Fabrik.helpers
* @since 3.0.6
*/
class Element
{
/**
* For processing repeat elements we need to make its
* ID element during the form process
*
* @param plgFabrik_Element $baseElement repeat element (e.g. db join
rendered as checkbox)
*
* @return plgFabrik_ElementInternalid
*/
public static function makeIdElement($baseElement)
{
$pluginManager = Worker::getPluginManager();
$groupModel = $baseElement->getGroupModel();
$elementModel = $pluginManager->getPlugIn('internalid',
'element');
$elementModel->getElement()->name = 'id';
$elementModel->getParams()->set('repeat',
$baseElement->isJoin());
$elementModel->getElement()->group_id = $groupModel->getId();
$elementModel->setGroupModel($baseElement->getGroupModel());
$elementModel->_joinModel = $groupModel->getJoinModel();
return $elementModel;
}
/**
* For processing repeat elements we need to make its
* parent id element during the form process
*
* @param plgFabrik_Element $baseElement repeat element (e.g. db join
rendered as checkbox)
*
* @return plgFabrik_ElementField
*/
public static function makeParentElement($baseElement)
{
$pluginManager = Worker::getPluginManager();
$groupModel = $baseElement->getGroupModel();
$elementModel = $pluginManager->getPlugIn('field',
'element');
$elementModel->getElement()->name = 'parent_id';
$elementModel->getParams()->set('repeat',
$baseElement->isJoin());
$elementModel->getElement()->group_id = $groupModel->getId();
$elementModel->setGroupModel($baseElement->getGroupModel());
$elementModel->_joinModel = $groupModel->getJoinModel();
return $elementModel;
}
/**
* Short cut for getting the element's filter value, or false if no
value
*
* @param int $elementId Element id
* @param string $identifier Option listref (like 12_com_content_12)
if you need to override default X_com_fabrik_X
*
* @since 3.0.7
*
* @return mixed
*/
public static function filterValue($elementId, $identifier = '')
{
$app = Factory::getApplication();
$pluginManager = Worker::getPluginManager();
$model = $pluginManager->getElementPlugin($elementId);
$listModel = $model->getListModel();
$identifier = empty($identifier) ?
$listModel->getRenderContext() : $identifier;
$key = 'com_fabrik.list' . $identifier .
'.filter';
$filters = ArrayHelper::fromObject($app->getUserState($key));
$elementIds = (array) ArrayHelper::getValue($filters,
'elementid', array());
$index = array_search($elementId, $elementIds);
$value = $index === false ? false :
ArrayHelper::getValue($filters['value'], $index, false);
return $value;
}
/**
* Is the key part of an element join's data. Used in csv
import/export
*
* @param FabrikFEModelForm $model Form model
* @param string $key Key - full element name or full
element name with _id / ___params appended
*
* @return boolean
*/
public static function keyIsElementJoinInfo($model, $key)
{
$elementModel = self::findElementFromJoinKeys($model, $key);
if ($elementModel && $elementModel->isJoin())
{
return true;
}
return false;
}
/**
* Find the element associated with a key.
* Loose lookup to find join element from any key related to the join
(e.g. _id & __params).
* Used in csv import/export
*
* @param FabrikFEModelForm $model Form model
* @param string $key Key - full element name or full
element name with _id / ___params appended
*
* @return PlgFabrik_Element|boolean
*/
public static function findElementFromJoinKeys($model, $key)
{
// Search on fullname fullname_id and fullname___params
$lookUps = array($key, substr($key, 0, StringHelper::strlen($key) - 3),
substr($key, 0, StringHelper::strlen($key) - 9));
foreach ($lookUps as $lookup)
{
$elementModel = $model->getElement($lookup);
if ($elementModel)
{
return $elementModel;
}
}
return false;
}
}
fabrik/fabrik/Helpers/FCipher.php000064400000020753151165341600012704
0ustar00<?php
/**
* @package ${NAMESPACE}
* @subpackage
*
* @copyright A copyright
* @license A "Slug" license name e.g. GPL2
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Table\Table;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Crypt\Cipher;
use Joomla\CMS\Crypt\Key;
use Joomla\CMS\Crypt\Cipher\SodiumCipher;
use Joomla\CMS\Encrypt\Aes;
class FCipher
{
private $key;
private $cipher;
private $type;
public function __construct($type = 'aes')
{
$this->type = $type;
if ($type === 'crypt')
{
$this->cipher = new Cipher\CryptoCipher();
$this->key = $this->getKey();
}
else if ($type === 'simple')
{
$this->key = $this->oldKey();
}
else if ($type === 'sodium')
{
$this->cipher = new SodiumCipher();
$this->key = $this->getKey();
}
else
{
$config = Factory::getApplication()->getConfig();
$secret = $config->get('secret', '');
if (trim($secret) == '')
{
throw new RuntimeException('You must supply a secret code in your
Joomla configuration.php file');
}
// $this->cipher = new \FOFEncryptAes($secret, 256);
$this->cipher = new Aes($secret, 256);
}
}
public function encrypt($data)
{
try
{
if ($this->type === 'crypt')
{
return bin2hex($this->cipher->encrypt($data, $this->key));
}
else if ($this->type === 'sodium')
{
$this->cipher->setNonce(\Sodium\randombytes_buf(\Sodium\CRYPTO_BOX_NONCEBYTES));
return bin2hex($this->cipher->encrypt($data, $this->key));
}
else if ($this->type === 'simple')
{
return $this->oldEncrypt($data, $this->key);
}
else
{
return $this->cipher->encryptString($data);
}
}
catch (\Exception $e)
{
return false;
}
}
public function decrypt($data)
{
try
{
if ($this->type === 'crypt')
{
return $this->cipher->decrypt(hex2bin($data), $this->key);
}
else if ($this->type === 'sodium')
{
$this->cipher->setNonce(\Sodium\randombytes_buf(\Sodium\CRYPTO_BOX_NONCEBYTES));
return bin2hex($this->cipher->decrypt($data, $this->key));
}
else if ($this->type === 'simple')
{
return $this->oldDecrypt($data, $this->key);
}
else
{
//return rtrim($this->cipher->decryptString($data),
"\0");
return $this->cipher->decryptString($data);
}
}
catch (\Exception $e)
{
return false;
}
}
private function getKey()
{
$fbConfig = ComponentHelper::getParams('com_fabrik');
$privateKey = $fbConfig->get('fabrik_private_key',
'');
$publicKey = $fbConfig->get('fabrik_public_key',
'');
if (empty($privateKey))
{
$key = $this->generateKey();
}
else
{
$key = new Key('crypto', hex2bin($privateKey),
hex2bin($publicKey));
}
return $key;
}
private function generateKey()
{
$fbConfig = ComponentHelper::getParams('com_fabrik');
$key = $this->cipher->generateKey();
//$privateKey = $key->getPrivate();
//$publicKey = $key->getPublic();
$privateKey = $key->private;
$publicKey = $key->public;
$fbConfig->set('fabrik_private_key', bin2hex($privateKey));
$fbConfig->set('fabrik_public_key', bin2hex($publicKey));
$componentid =
ComponentHelper::getComponent('com_fabrik')->id;
$table = Table::getInstance('extension');
$table->load($componentid);
$table->bind(array('params' =>
$fbConfig->toString()));
// check for error
if (!$table->check()) {
echo $table->getError();
return false;
}
// Save to database
if (!$table->store()) {
echo $table->getError();
return false;
}
return $key;
}
/**
* Method to decrypt a data string.
*
* NOTE - this is the old deprecated J! simple crypt, only here for legacy
(converting old to new)
*
* @param string $data The encrypted string to decrypt.
* @param object $key The key[/pair] object to use for decryption.
*
* @return string The decrypted data string.
*
* @since 12.1
* @throws \InvalidArgumentException
*/
public function oldDecrypt($data, $key)
{
// Validate key.
if ($key->type != 'simple')
{
throw new \InvalidArgumentException('Invalid key of type: ' .
$key->type . '. Expected simple.');
}
$decrypted = '';
$tmp = $key->public;
// Convert the HEX input into an array of integers and get the number of
characters.
$chars = $this->_hexToIntArray($data);
$charCount = count($chars);
// Repeat the key as many times as necessary to ensure that the key is at
least as long as the input.
for ($i = 0; $i < $charCount; $i = strlen($tmp))
{
$tmp = $tmp . $tmp;
}
// Get the XOR values between the ASCII values of the input and key
characters for all input offsets.
for ($i = 0; $i < $charCount; $i++)
{
$decrypted .= chr($chars[$i] ^ ord($tmp[$i]));
}
return $decrypted;
}
/**
* Method to encrypt a data string.
*
* NOTE - this is the old deprecated J! simple crypt, only here for legacy
(converting old to new)
*
* @param string $data The data string to encrypt.
* @param object $key The key[/pair] object to use for encryption.
*
* @return string The encrypted data string.
*
* @since 12.1
* @throws \InvalidArgumentException
*/
public function oldEncrypt($data, $key)
{
// Validate key.
if ($key->type != 'simple')
{
throw new \InvalidArgumentException('Invalid key of type: ' .
$key->type . '. Expected simple.');
}
$encrypted = '';
$tmp = $key->private;
// Split up the input into a character array and get the number of
characters.
$chars = preg_split('//', $data, -1, PREG_SPLIT_NO_EMPTY);
$charCount = count($chars);
// Repeat the key as many times as necessary to ensure that the key is at
least as long as the input.
for ($i = 0; $i < $charCount; $i = strlen($tmp))
{
$tmp = $tmp . $tmp;
}
// Get the XOR values between the ASCII values of the input and key
characters for all input offsets.
for ($i = 0; $i < $charCount; $i++)
{
$encrypted .= $this->_intToHex(ord($tmp[$i]) ^ ord($chars[$i]));
}
return $encrypted;
}
/**
* Method to generate a new encryption key[/pair] object.
*
* @param array $options Key generation options.
*
* @return Key
*
* @since 12.1
*/
public function oldKey(array $options = array())
{
// Create the new encryption key[/pair] object.
$key = new \stdClass();
// Just a random key of a given length.
$key->type = 'simple';
$key->private =
Factory::getApplication()->getConfig()->get('secret');
$key->public = $key->private;
return $key;
}
/**
* Convert hex to an integer
*
* @param string $s The hex string to convert.
* @param integer $i The offset?
*
* @return integer
*
* @since 11.1
*/
private function _hexToInt($s, $i)
{
$j = (int) $i * 2;
$k = 0;
$s1 = (string) $s;
// Get the character at position $j.
$c = substr($s1, $j, 1);
// Get the character at position $j + 1.
$c1 = substr($s1, $j + 1, 1);
switch ($c)
{
case 'A':
$k += 160;
break;
case 'B':
$k += 176;
break;
case 'C':
$k += 192;
break;
case 'D':
$k += 208;
break;
case 'E':
$k += 224;
break;
case 'F':
$k += 240;
break;
case ' ':
$k += 0;
break;
default:
(int) $k = $k + (16 * (int) $c);
break;
}
switch ($c1)
{
case 'A':
$k += 10;
break;
case 'B':
$k += 11;
break;
case 'C':
$k += 12;
break;
case 'D':
$k += 13;
break;
case 'E':
$k += 14;
break;
case 'F':
$k += 15;
break;
case ' ':
$k += 0;
break;
default:
$k += (int) $c1;
break;
}
return $k;
}
/**
* Convert hex to an array of integers
*
* @param string $hex The hex string to convert to an integer array.
*
* @return array An array of integers.
*
* @since 11.1
*/
private function _hexToIntArray($hex)
{
$array = array();
$j = (int) strlen($hex) / 2;
for ($i = 0; $i < $j; $i++)
{
$array[$i] = (int) $this->_hexToInt($hex, $i);
}
return $array;
}
/**
* Convert an integer to a hexadecimal string.
*
* @param integer $i An integer value to convert to a hex string.
*
* @return string
*
* @since 11.1
*/
private function _intToHex($i)
{
// Sanitize the input.
$i = (int) $i;
// Get the first character of the hexadecimal string if there is one.
$j = (int) ($i / 16);
if ($j === 0)
{
$s = ' ';
}
else
{
$s = strtoupper(dechex($j));
}
// Get the second character of the hexadecimal string.
$k = $i - $j * 16;
$s = $s . strtoupper(dechex($k));
return $s;
}
}fabrik/fabrik/Helpers/Googlemap.php000064400000004002151165341600013263
0ustar00<?php
/**
* Google Map helper class
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
use \stdClass;
/**
* Google Map class
*
* @package Joomla
* @subpackage Fabrik.helpers
* @since 3.0
*/
class Googlemap
{
/**
* Set the google map style
*
* @param object $params Element/vis parameters (contains gmap_styles
property as json string)
*
* @since 3.0.7
*
* @return array Styles
*/
public static function styleJs($params)
{
$styles = $params->get('gmap_styles');
$styles = is_string($styles) ? json_decode($styles) : $styles;
if (!$styles)
{
return array();
}
// Map Feature type to style
$features = $styles->style_feature;
// What exactly to style in the feature type (road, fill, border etc)
$elements = $styles->style_element;
$styleKeys = $styles->style_styler_key;
$styleValues = $styles->style_styler_value;
// First merge any identical feature styles
$stylers = array();
for ($i = 0; $i < count($features); $i ++)
{
$feature = ArrayHelper::getValue($features, $i);
$element = ArrayHelper::getValue($elements, $i);
$key = $feature . '|' . $element;
if (!array_key_exists($key, $stylers))
{
$stylers[$key] = array();
}
$aStyle = new \stdClass;
$styleKey = ArrayHelper::getValue($styleKeys, $i);
$styleValue = ArrayHelper::getValue($styleValues, $i);
if ($styleKey && $styleValue)
{
$aStyle->$styleKey = $styleValue;
$stylers[$key][] = $aStyle;
}
}
$return = array();
foreach ($stylers as $styleKey => $styler)
{
$o = new \stdClass;
$bits = explode('|', $styleKey);
if ( $bits[0] !== 'all')
{
$o->featureType = $bits[0];
}
$o->elementType = $bits[1];
$o->stylers = $styler;
$return[] = $o;
}
return $return;
}
}
fabrik/fabrik/Helpers/Html.php000064400000261001151165341600012261
0ustar00<?php
/**
* Fabrik Component HTML Helper
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Layout\LayoutInterface;
use Joomla\CMS\Version;
use Joomla\CMS\Environment\Browser;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\HTML\Helpers\Bootstrap;
use Joomla\CMS\Filesystem\File;
use \stdClass;
jimport('joomla.filesystem.file');
if (!defined('COM_FABRIK_FRONTEND'))
{
throw new
RuntimeException(Text::_('COM_FABRIK_SYSTEM_PLUGIN_NOT_ACTIVE'),
400);
}
/**
* Fabrik Component HTML Helper
*
* @static
* @package Joomla
* @subpackage Fabrik.helpers
* @since 1.5
*/
class Html
{
/**
* Is the Fabrik JavaScript framework loaded
*
* @var bool
*/
protected static $framework = null;
/**
* Is the MCL JavaScript library loaded
*
* @var bool
*/
protected static $mcl = null;
/**
* Array of loaded modal window states
*
* @var array
*/
protected static $modals = array();
/**
* Array of loaded tip states
*
* @var array
*/
protected static $tips = array();
/**
* Previously loaded js scripts
*
* @var array
*/
protected static $scripts = array();
/**
* Array of rendered jLayouts for use in JS code.
*
* @var array
*/
protected static $jLayoutsJs = array();
/**
* Array of paths for requirejs
*
* @var object
*/
protected static $allRequirePaths = null;
/**
* CSS files loaded via AJAX
*
* @var array
*/
protected static $ajaxCssFiles = array();
/**
* Has the debug JavaScript been loaded
*
* @var bool
*/
protected static $debug = null;
/**
* Has the Facebook API JavaScript file been loaded
*
* @var bool
*/
protected static $facebookgraphapi = null;
/**
* Has the at who js file been loaded
*
* @var array
*/
protected static $atWho = array();
/**
* Folders to search for media
*
* @var array
*/
protected static $helperpaths = array();
/**
* Load the modal JavaScript files once
*
* @var bool
*/
protected static $modal = null;
/**
* Form email link URL
*
* @var string
*/
protected static $emailURL = null;
/**
* Form print link URL
*
* @var string
*/
protected static $printURL = null;
protected static $requireJS = array();
/**
* Array containing information for loaded files
*
* @var array
* @since 2.5
*/
protected static $loaded = array();
/**
* Array of browser request headers. Starts as null.
*
* @var array
*/
protected static $requestHeaders = null;
/**
* Usually gets set to COM_FABRIK_LIVESITE, but can be overridden by a
global option
*
* @var string
*/
protected static $baseJSAssetURI = null;
/**
* Load up window code - should be run in ajax loaded pages as well
(10/07/2012 but not json views)
* might be an issue in that we may be re-observing some links when
loading in - need to check
*
* @param string $selector Element select to auto create windows for -
was default = a.modal
* @param array $params Window parameters
*
* @deprecated use windows() instead
*
* @return void
*/
public static function mocha($selector = '', $params = array())
{
self::windows($selector, $params);
}
/**
* Build a data-toggling dropdown
*
* @param array $lis Array of links to create dropdown from
* @param string $align Should the drop down be left or right aligned -
If right then the dropdown content's end
* is right aligned to the button
*
* @return string
*/
public static function bootStrapDropDown($lis, $align = 'left')
{
$layout =
self::getLayout('listactions.dropdown');
$displayData = array();
$displayData['align'] = $align;
$displayData['items'] = $lis;
return $layout->render($displayData);
}
/**
* Wrap buttons in bootstrap btn-group div
*
* @param array $items Items
*
* @return string
*/
public static function bootStrapButtonGroup($items)
{
return '<div class="btn-group">' .
implode(' ', $items) . '</div>';
}
/**
* Build an array of the request headers by hand. Replacement for using
* apache_request_headers(), which only works in certain configurations.
* This solution gets them from the $_SERVER array, and re-munges them
back
* from HTTP_FOO_BAR format to Foo-Bar format. Stolen from:
*
http://stackoverflow.com/questions/541430/how-do-i-read-any-request-header-in-php
*
* @return array request headers assoc
*/
public static function parseRequestHeaders()
{
if (isset(self::$requestHeaders))
{
return self::$requestHeaders;
}
self::$requestHeaders = array();
foreach ($_SERVER as $key => $value)
{
if (substr($key, 0, 5) <> 'HTTP_')
{
continue;
}
$header = str_replace(' ',
'-', ucwords(str_replace('_', ' ',
strtolower(substr($key, 5)))));
self::$requestHeaders[$header] = $value;
}
return self::$requestHeaders;
}
/**
* Load up window code - should be run in ajax loaded pages as well
(10/07/2012 but not json views)
* might be an issue in that we may be re-observing some links when
loading in - need to check
*
* @param string $selector Element select to auto create windows for -
was default = a.modal
* @param array $params Window parameters
*
* @return void
*/
public static function windows($selector = '', $params =
array())
{
$app = Factory::getApplication();
$input = $app->input;
$script = '';
// Don't include in an Request.JSON call - for auto-fill form plugin
$headers = self::parseRequestHeaders();
if (ArrayHelper::getValue($headers, 'X-Request') ===
'JSON')
{
return;
}
if ($input->get('format') == 'json')
{
return;
}
$sig = md5(serialize(array($selector, $params)));
if (isset(self::$modals[$sig]) && (self::$modals[$sig]))
{
return;
}
$script .= "window.addEvent('fabrik.loaded', function()
{";
if ($selector == '')
{
return;
}
// Setup options object
$opt['ajaxOptions'] = (isset($params['ajaxOptions'])
&& (is_array($params['ajaxOptions']))) ?
$params['ajaxOptions'] : null;
$opt['size'] = (isset($params['size'])
&& (is_array($params['size']))) ?
$params['size'] : null;
$opt['onOpen'] = (isset($params['onOpen'])) ?
$params['onOpen'] : null;
$opt['onClose'] = (isset($params['onClose'])) ?
$params['onClose'] : null;
$opt['onUpdate'] = (isset($params['onUpdate'])) ?
$params['onUpdate'] : null;
$opt['onResize'] = (isset($params['onResize'])) ?
$params['onResize'] : null;
$opt['onMove'] = (isset($params['onMove'])) ?
$params['onMove'] : null;
$opt['onShow'] = (isset($params['onShow'])) ?
$params['onShow'] : null;
$opt['onHide'] = (isset($params['onHide'])) ?
$params['onHide'] : null;
// Attach modal behavior to document
// Set default values which can be overwritten in <a>'s rel
attribute
$opts = new stdClass;
$opts->id = 'fabwin';
$opts->title = Text::_('COM_FABRIK_ADVANCED_SEARCH');
$opts->loadMethod = 'xhr';
$opts->minimizable = false;
$opts->collapsible = true;
$opts->width = 500;
$opts->height = 150;
$opts = json_encode($opts);
$script .= <<<EOD
$$('$selector').each(function(el, i) {
el.addEvent('click', function(e) {
var opts = $opts;
e.stop();
opts2 = JSON.decode(el.get('rel'));
opts = Object.merge(opts, opts2 || {});
opts.contentURL = el.href;
if (opts.id === 'fabwin') {
opts.id += i;
}
Fabrik.getWindow(opts);
});
});
});
EOD;
self::addScriptDeclaration($script);
self::$modals[$sig] = true;
return;
}
/**
* Show form to allow users to email form to a friend.
* Echo's out form HTML.
*
* @param object $formModel Form model
* @param string $template Template
*
* @return void
*/
public static function emailForm($formModel, $template = '')
{
$app = Factory::getApplication();
$input = $app->input;
$layout =
self::getLayout('form.fabrik-email-form');
$displayData = new stdClass;
// $displayData->j3 = Worker::j3();
$displayData->j3 = true;
$displayData->package =
$app->getUserState('com_fabrik.package', 'fabrik');
$displayData->referrer = $input->get('referrer',
'', 'string');
$document = Factory::getDocument();
$form = $formModel->getForm();
$document->setTitle($form->label);
$document->addStyleSheet('templates/' . $template .
'/css/template_css.css');
echo $layout->render($displayData);
}
/**
* Once email has been sent to a friend show this message
*
* @return void
*/
public static function emailSent()
{
$config = Factory::getApplication()->getConfig();
$document = Factory::getDocument();
$document->setTitle($config->get('sitename'));
}
/**
* Writes a print icon
*
* @param object $formModel form model
* @param object $params parameters
*
* @return string print html icon/link
*/
public static function printIcon($formModel, $params)
{
$layout = self::getLayout('form.fabrik-print-icon');
$displayData = new stdClass;
$displayData->status =
"status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=400,height=350,directories=no,location=no";
$displayData->link = self::printURL($formModel);
$displayData->popup = $params->get('popup', 1);
if ($params->get('icons', true))
{
$displayData->image = self::image('print.png');
}
else
{
$displayData->image = ' ' .
Text::_('COM_FABRIK_PRINT');
}
return $layout->render($displayData);
}
/**
* Create print URL
*
* @param object $formModel form model
*
* @since 3.0.6
*
* @return string
*/
public static function printURL($formModel)
{
$app = Factory::getApplication();
$input = $app->input;
$form = $formModel->getForm();
$package = $app->getUserState('com_fabrik.package',
'fabrik');
$table = $formModel->getTable();
if ($app->isClient('administrator'))
{
$url = 'index.php?option=com_' . $package .
'&task=details.view&tmpl=component&formid=' .
$form->id . '&listid=' . $table->id
. '&rowid=' . $formModel->getRowId().
'&iframe=1&print=1';
}
else
{
//$this->pdfURL = 'index.php?option=com_' .
$this->package . '&view=details&formid=' .
$model->getId() . '&rowid=' . $model->getRowId() .
'&format=pdf';
$url = COM_FABRIK_LIVESITE . 'index.php?option=com_' .
$package . '&view=details&tmpl=component&formid=' .
$form->id . '&listid=' . $table->id
. '&rowid=' . $formModel->getRowId() .
'&iframe=1&print=1';
$url .= '&Itemid=' . Worker::itemId();
}
/* $$$ hugh - @TODO - FIXME - if they were using rowid=-1, we don't
need this, as rowid has already been transmogrified
* to the correct (PK based) rowid. but how to tell if original rowid
was -1???
*/
if ($input->get('usekey') !== null)
{
$url .= '&usekey=' . $input->get('usekey');
}
$url = Route::_($url);
// $$$ rob for some reason Route wasn't doing this ???
//$url = str_replace('&', '&',
$url);
self::$printURL = $url;
return self::$printURL;
}
/**
* Writes Email icon
*
* @param object $formModel Form model
* @param object $params Parameters
*
* @return string Email icon/link html
*/
public static function emailIcon($formModel, $params)
{
$layout =
self::getLayout('form.fabrik-email-icon');
$displayData = new stdClass;
$displayData->popup = $params->get('popup', 1);
$displayData->status =
"status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=400,height=250,directories=no,location=no";
$displayData->link = self::emailURL($formModel);
$displayData->icons = $params->get('icons', true);
return $layout->render($displayData);
}
/**
* Create URL for form email button
*
* @param object $formModel form model
*
* @since 3.0.6
*
* @return string
*/
public static function emailURL($formModel)
{
$app = Factory::getApplication();
$input = $app->input;
$package = $app->getUserState('com_fabrik.package',
'fabrik');
if ($app->isClient('administrator'))
{
$url =
'index.php?option=com_fabrik&task=emailform.display&tmpl=component&formid='
. $formModel->get('id') . '&rowid='
. $formModel->getRowId();
}
else
{
$url = 'index.php?option=com_' . $package .
'&view=emailform&tmpl=component&formid=' .
$formModel->get('id') . '&rowid=' .
$formModel->getRowId();
}
if ($input->get('usekey') !== null)
{
$url .= '&usekey=' . $input->get('usekey');
}
$url .= '&referrer=' .
urlencode(Uri::getInstance()->toString());
self::$emailURL = Route::_($url);
return self::$emailURL;
}
/**
* Get a list of condition options - used in advanced search
*
* @param string $listId list ref
* @param string $sel selected value
*
* @return string html select list
*/
public static function conditionList($listId, $sel = '')
{
$conditions = array();
$conditions[] = HTMLHelper::_('select.option', 'AND',
Text::_('COM_FABRIK_AND'));
$conditions[] = HTMLHelper::_('select.option', 'OR',
Text::_('COM_FABRIK_OR'));
$name = 'fabrik___filter[list_' . $listId .
'][join][]';
return HTMLHelper::_('select.genericlist', $conditions, $name,
'class="form-select-sm" size="1" ',
'value', 'text', $sel);
}
/**
* Get a select list of fabrik lists
*
* @param string $sel selected value
*
* @return mixed html select list or error
*/
public static function tableList($sel = '')
{
$db = Worker::getDbo(true);
$query = $db->getQuery(true);
$query->select('id,
label')->from('#__fabrik_lists')->where('published
= 1')->order('label');
$db->setQuery($query);
$rows = $db->loadObjectList();
return HTMLHelper::_('select.genericlist', $rows,
'fabrik__swaptable', 'class="form-select" ',
'id', 'label', $sel);
}
/**
* Load the css and js files once only (using calendar-eightsix)
*
* @deprecated - behavior.calendar is loaded in framework();
*
* @return void
*/
public static function loadCalendar()
{
}
/**
* Fabrik script to load in a style sheet
* takes into account if you are viewing the page in raw format
* if so sends js code back to web page to inject css file into document
head
* If not raw format then apply standard J stylesheet
*
* @param string $file stylesheet URL
* @param array $attribs not used
*
* @return null
*/
public static function stylesheet($file, $attribs = [])
{
// $$$ hugh - moved this to top of function, as we now apply livesite in
either usage cases below.
if (!strstr($file, COM_FABRIK_LIVESITE))
{
$file = COM_FABRIK_LIVESITE . $file;
}
$opts = http_build_query($attribs);
if (!empty($opts)) $file .= $opts;
if (self::cssAsAsset())
{
// Send an inline script back which will inject the css file into the
doc head
// Note your ajax call must have 'evalScripts':true set in its
properties
if (!in_array($file, self::$ajaxCssFiles))
{
if (!strstr($file, 'fabrik.css'))
{
$opts = new stdClass;
echo "<script type=\"text/javascript\">
function loadMyJs(file) {
let s = document.createElement('script');
s.setAttribute('src', file);
s.setAttribute('async', true);
document.head.appendChild(s);
return;
}
loadMyJs('".$file."');
</script>\n";
self::$ajaxCssFiles[] = $file;
}
}
}
else
{
$document = Factory::getDocument();
/* $$$ rob 27/04/2011 changed from HTMLHelper::stylesheet as that
doesn't work loading
* php style sheets with querystrings in them
*/
$document->addStylesheet($file);
}
}
/**
* Will the CSS be loaded as Asset.css()
*
* @since 3.0.6
*
* @return bool
*/
public static function cssAsAsset()
{
$app = Factory::getApplication();
$input = $app->input;
$tpl = $input->get('tmpl');
$iFrame = $input->get('iframe');
$print = $input->get('print');
$format = $input->get('format');
return $input->get('format') == 'raw' || ($tpl ==
'component' && $iFrame != 1) && $print != 1
&& $format !== 'pdf';
}
/**
* Check for a custom css file and include it if it exists
*
* @param string $path NOT including JPATH_SITE (so relative too root
dir) may include querystring
*
* @return bool if loaded or not
*/
public static function stylesheetFromPath($path)
{
if (strstr($path, '?'))
{
$file = explode('?', $path);
$file = $file[0];
}
else
{
$file = $path;
}
if (File::exists(JPATH_SITE . '/' . $file))
{
self::stylesheet($path);
return true;
}
return false;
}
/**
* Generates an HTML radio list
*
* @param array &$arr An array of objects
* @param string $tag_name The value of the HTML name attribute
* @param string $tag_attribs Additional HTML attributes for the
<select> tag
* @param mixed $selected The key that is selected
* @param string $key The name of the object variable for
the option value
* @param string $text The name of the object variable for
the option text
* @param int $options_per_row number of options to show per row
@since 2.0.5
*
* @return string HTML for the select list
*/
public static function radioList(&$arr, $tag_name, $tag_attribs,
$selected = null, $key = 'value', $text = 'text',
$options_per_row = 0)
{
return self::aList('radio', $arr, $tag_name, $tag_attribs,
$selected, $key, $text, $options_per_row);
}
/**
* Generates an HTML radio OR checkbox list
*
* @param string $type Radio/checkbox
* @param array &$arr An array of objects
* @param string $tag_name The value of the HTML name attribute
* @param string $tag_attribs Additional HTML attributes for the
<select> tag
* @param mixed $selected The key that is selected
* @param string $key The name of the object variable for
the option value
* @param string $text The name of the object variable for
the option text
* @param int $options_per_row Number of options to show per row
@since 2.0.5
* @param bool $editable Editable or not
*
* @return string HTML for the select list
*/
public static function aList($type, &$arr, $tag_name, $tag_attribs,
$selected = null,
$key = 'value', $text = 'text', $options_per_row = 0,
$editable = true)
{
reset($arr);
$html = array();
if ($options_per_row > 1)
{
$percentageWidth = floor(floatval(100) / $options_per_row) - 2;
$div = "<div class=\"fabrik_subelement\"
style=\"float:left;width:" . $percentageWidth .
"%\">\n";
}
else
{
$div = '<div class="fabrik_subelement">';
}
if ($editable)
{
$selectText = $type == 'checkbox' ? '
checked="checked"' : '
selected="selected"';
}
else
{
$selectText = '';
}
for ($i = 0, $n = count($arr); $i < $n; $i++)
{
$k = $arr[$i]->$key;
$t = $arr[$i]->$text;
$id = isset($arr[$i]->id) ? @$arr[$i]->id : null;
$extra = '';
$extra .= $id ? ' id="' . $arr[$i]->id .
'"' : '';
$found = false;
if (is_array($selected))
{
foreach ($selected as $obj)
{
if (is_object($obj))
{
$k2 = $obj->$key;
if ($k === $k2)
{
$found = true;
$extra .= $selected;
break;
}
}
else
{
if ($k === $obj)
{
// Checkbox from db join
$extra .= $selectText;
$found = true;
break;
}
}
}
}
else
{
$extra .= $k === $selected ? ' checked="checked"' :
'';
$found = $k == $selected;
}
$html[] = $div;
if ($editable)
{
$tmpName = $type === 'checkbox' ? $tag_name . '[' .
$i . ']' : $tag_name;
$html[] = '<label class="' . $type .
'">';
$html[] = '<input type="' . $type . '"
value="' . $k . '" name="' . $tmpName .
'" class="fabrikinput" ' . $extra .
'/>';
}
if ($editable || $found)
{
$html[] = '<span>' . $t . '</span>';
}
if ($editable)
{
$html[] = '</label>';
}
$html[] = '</div>';
}
$html[] = "";
return implode("\n", $html);
}
/**
* Keep session alive, for example, while editing or creating an article.
*
* @return void
*/
public static function keepalive()
{
// Test since 2.0b3 don't do anything if loading from Fabrik win
if (self::inAjaxLoadedPage())
{
return;
}
HTMLHelper::_('behavior.keepalive');
}
/**
* Load the MCL canvas layer library
*
* @return array Scripts needed to load MCL
*/
public static function mcl()
{
// Cant used compressed version as its not up to date
$src = array(
'media/com_fabrik/js/lib/mcl/CANVAS.js',
'media/com_fabrik/js/lib/mcl/CanvasItem.js',
'media/com_fabrik/js/lib/mcl/Cmorph.js',
'media/com_fabrik/js/lib/mcl/Layer.js',
'media/com_fabrik/js/lib/mcl/LayerHash.js',
'media/com_fabrik/js/lib/mcl/Thread.js'
);
if (!self::$mcl)
{
self::script($src);
self::$mcl = true;
}
$src = array(
'lib/mcl/CANVAS',
'lib/mcl/CanvasItem',
'lib/mcl/Cmorph',
'lib/mcl/Layer',
'lib/mcl/LayerHash',
'lib/mcl/Thread'
);
return $src;
}
/**
* Append a js file to the main require.js list of files to load.
* Will use the -min.js or .js file based on debug settings
*
* @param array &$srcs Already loaded scripts from framework()
* @param string $file JS File path relative to root without .js
extension e.g. 'media/com_fabrik/js/list'
*
* @since 3.0b
*
* @return void
*/
public static function addToFrameWork(&$srcs, $file)
{
$ext = self::isDebug() ? '.js' : '-min.js';
$srcs[] = $file . $ext;
}
/**
* Get the media folder
*
* @return string media folder
*/
public static function getMediaFolder()
{
return self::isDebug() ? 'media/com_fabrik/js' :
'media/com_fabrik/js/dist';
}
public static function calendar()
{
// Only load once
if (isset(static::$loaded[__METHOD__]))
{
return;
}
$document = Factory::getDocument();
$tag = Factory::getApplication()->getLanguage()->getTag();
$attribs = array('title' =>
Text::_('JLIB_HTML_BEHAVIOR_GREEN'), 'media' =>
'all');
HTMLHelper::_('stylesheet',
'com_fabrik/calendar-jos.css', array('version' =>
'auto', 'relative' => true), $attribs);
HTMLHelper::_('script',
'media/com_fabrik/js/dist/calendar.js');
HTMLHelper::_('script',
'media/com_fabrik/js/dist/calendar-setup.js');
$translation = static::calendartranslation();
if ($translation)
{
$document->addScriptDeclaration($translation);
}
static::$loaded[__METHOD__] = true;
}
/**
* Internal method to translate the JavaScript Calendar
*
* @return string JavaScript that translates the object
*
* @since 1.5
*/
protected static function calendartranslation()
{
static $jsscript = 0;
// Guard clause, avoids unnecessary nesting
if ($jsscript)
{
return false;
}
$jsscript = 1;
// To keep the code simple here, run strings through Text::_() using
array_map()
$callback = array('Joomla\CMS\Language\Text', '_');
$weekdays_full = array_map(
$callback, array(
'SUNDAY', 'MONDAY', 'TUESDAY',
'WEDNESDAY', 'THURSDAY', 'FRIDAY',
'SATURDAY', 'SUNDAY',
)
);
$weekdays_short = array_map(
$callback,
array(
'SUN', 'MON', 'TUE', 'WED',
'THU', 'FRI', 'SAT', 'SUN',
)
);
$months_long = array_map(
$callback, array(
'JANUARY', 'FEBRUARY', 'MARCH',
'APRIL', 'MAY', 'JUNE',
'JULY', 'AUGUST', 'SEPTEMBER',
'OCTOBER', 'NOVEMBER', 'DECEMBER',
)
);
$months_short = array_map(
$callback, array(
'JANUARY_SHORT', 'FEBRUARY_SHORT',
'MARCH_SHORT', 'APRIL_SHORT', 'MAY_SHORT',
'JUNE_SHORT',
'JULY_SHORT', 'AUGUST_SHORT',
'SEPTEMBER_SHORT', 'OCTOBER_SHORT',
'NOVEMBER_SHORT', 'DECEMBER_SHORT',
)
);
// This will become an object in Javascript but define it first in PHP
for readability
$today = " " . Text::_('JLIB_HTML_BEHAVIOR_TODAY') .
" ";
$text = array(
'INFO' =>
Text::_('JLIB_HTML_BEHAVIOR_ABOUT_THE_CALENDAR'),
'ABOUT' => "DHTML Date/Time Selector\n"
. "(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n"
. "For latest version visit:
http://www.dynarch.com/projects/calendar/\n"
. "Distributed under GNU LGPL. See
http://gnu.org/licenses/lgpl.html for details."
. "\n\n"
. Text::_('JLIB_HTML_BEHAVIOR_DATE_SELECTION')
. Text::_('JLIB_HTML_BEHAVIOR_YEAR_SELECT')
. Text::_('JLIB_HTML_BEHAVIOR_MONTH_SELECT')
. Text::_('JLIB_HTML_BEHAVIOR_HOLD_MOUSE'),
'ABOUT_TIME' => "\n\n"
. "Time selection:\n"
. "- Click on any of the time parts to increase it\n"
. "- or Shift-click to decrease it\n"
. "- or click and drag for faster selection.",
'PREV_YEAR' =>
Text::_('JLIB_HTML_BEHAVIOR_PREV_YEAR_HOLD_FOR_MENU'),
'PREV_MONTH' =>
Text::_('JLIB_HTML_BEHAVIOR_PREV_MONTH_HOLD_FOR_MENU'),
'GO_TODAY' =>
Text::_('JLIB_HTML_BEHAVIOR_GO_TODAY'),
'NEXT_MONTH' =>
Text::_('JLIB_HTML_BEHAVIOR_NEXT_MONTH_HOLD_FOR_MENU'),
'SEL_DATE' =>
Text::_('JLIB_HTML_BEHAVIOR_SELECT_DATE'),
'DRAG_TO_MOVE' =>
Text::_('JLIB_HTML_BEHAVIOR_DRAG_TO_MOVE'),
'PART_TODAY' => $today,
'DAY_FIRST' =>
Text::_('JLIB_HTML_BEHAVIOR_DISPLAY_S_FIRST'),
'WEEKEND' =>
Factory::getApplication()->getLanguage()->getWeekEnd(),
'CLOSE' =>
Text::_('JLIB_HTML_BEHAVIOR_CLOSE'),
'TODAY' =>
Text::_('JLIB_HTML_BEHAVIOR_TODAY'),
'TIME_PART' =>
Text::_('JLIB_HTML_BEHAVIOR_SHIFT_CLICK_OR_DRAG_TO_CHANGE_VALUE'),
'DEF_DATE_FORMAT' => "%Y-%m-%d",
'TT_DATE_FORMAT' =>
Text::_('JLIB_HTML_BEHAVIOR_TT_DATE_FORMAT'),
'WK' =>
Text::_('JLIB_HTML_BEHAVIOR_WK'),
'TIME' =>
Text::_('JLIB_HTML_BEHAVIOR_TIME'),
);
return 'Calendar._DN = ' . json_encode($weekdays_full) .
';'
. ' Calendar._SDN = ' . json_encode($weekdays_short) .
';'
. ' Calendar._FD = 0;'
. ' Calendar._MN = ' . json_encode($months_long) .
';'
. ' Calendar._SMN = ' . json_encode($months_short) .
';'
. ' Calendar._TT = ' . json_encode($text) . ';';
}
/**
* Load Fabrik's framework (js and base css file)
*
* @return array Framework js files
*/
public static function framework()
{
if (!self::$framework)
{
$app = Factory::getApplication();
Html::modalLayoutInterfaces();
$liveSiteSrc = array();
$liveSiteReq = array();
$fbConfig = ComponentHelper::getParams('com_fabrik');
$mediaFolder = self::getMediaFolder();
$src = array();
HTMLHelper::_('jquery.framework', true);
HTMLHelper::_('bootstrap.framework');
self::loadBootstrapCSS();
/* Load mootools & jquery-ui as it is not loaded by Joomla any more
*/
if(!self::isDebug()){
HTMLHelper::_('script',
'media/com_fabrik/js/lib/jquery-ui/jquery-ui.min.js');
//jquery-ui for fabrik v1.13.2 - 2022-07-14
//HTMLHelper::_('script',
'media/vendor/jquery-ui/jquery-ui.min.js'); //jquery-ui for
joomla v1.9.2 - 2016-01-22
HTMLHelper::_('script',
'media/com_fabrik/js/dist/mootools-core.js');
HTMLHelper::_('script',
'media/com_fabrik/js/dist/mootools-more.js');
} else {
HTMLHelper::_('script',
'media/com_fabrik/js/lib/jquery-ui/jquery-ui.js'); //jquery-ui
for fabrik v1.13.2 - 2022-07-14
//HTMLHelper::_('script',
'media/vendor/jquery-ui/jquery-ui.js'); //jquery-ui for joomla
v1.9.2 - 2016-01-22
HTMLHelper::_('script',
'media/com_fabrik/js/mootools-core.js');
HTMLHelper::_('script',
'media/com_fabrik/js/mootools-more.js');
}
HTMLHelper::_('behavior.formvalidator');
$liveSiteReq['Chosen'] = $mediaFolder .
'/chosen-loader';
$liveSiteReq['Fabrik'] = $mediaFolder . '/fabrik';
$liveSiteReq['FloatingTips'] = $mediaFolder .
'/tipsBootStrapMock';
if ($fbConfig->get('advanced_behavior', '0') !==
'0')
{
$chosenOptions =
$fbConfig->get('advanced_behavior_options', '{}');
$chosenOptions = json_decode($chosenOptions);
if (is_object($chosenOptions) &&
!isset($chosenOptions->placeholder_text_multiple))
{
$chosenOptions->placeholder_text_multiple =
Text::_('JGLOBAL_TYPE_OR_SELECT_SOME_OPTIONS');
}
if (is_object($chosenOptions) &&
!isset($chosenOptions->placeholder_text_single))
{
$chosenOptions->placeholder_text_single =
Text::_('JGLOBAL_SELECT_AN_OPTION');
}
if (is_object($chosenOptions) &&
!isset($chosenOptions->no_results_text))
{
$chosenOptions->no_results_text =
Text::_('JGLOBAL_SELECT_NO_RESULTS_MATCH');
}
$chosenOptions = empty($chosenOptions) ? new stdClass :
ArrayHelper::fromObject($chosenOptions);
if(self::isDebug()){
HTMLHelper::_('stylesheet',
'media/com_fabrik/css/chosen.css');
HTMLHelper::_('script',
'media/com_fabrik/js/chosen.jquery.js');
}
else {
HTMLHelper::_('stylesheet',
'media/com_fabrik/css/chosen.min.css');
HTMLHelper::_('script',
'media/com_fabrik/js/dist/chosen.jquery.js');
//HTMLHelper::_('script', 'jui/ajax-chosen.min',
false, true, false, false, self::isDebug());
}
}
if ($app->isClient('administrator') &&
$app->input->get('format') !== 'pdf') {
/* For some reason this navbar is being shown for fabrik menu items, I
gave up after 5 hours of debug, this is easier
* trob: this is breaking domPDF on backend lists (somehow the style
loading as array), so don't do it if format=pdf
*/
Factory::getDocument()->addStyleDeclaration("button.navbar-toggler.toggler-burger
{display : none !important;}");
}
if ($fbConfig->get('advanced_behavior', '0') !==
'0')
{
$liveSiteSrc[] = "var chosenInterval = window.setInterval(function
() {
if (Fabrik.buildChosen) {
window.clearInterval(chosenInterval);
Fabrik.buildChosen('select.advancedSelect', " .
json_encode($chosenOptions) . ");
}
}, 100);";
}
if (!self::inAjaxLoadedPage())
{
// Require.js now added in fabrik system plugin onAfterRender()
Text::script('COM_FABRIK_LOADING');
$src['Window'] = $mediaFolder . '/window.js';
self::styleSheet(COM_FABRIK_LIVESITE .
'media/com_fabrik/css/fabrik.css');
$liveSiteSrc[] = "\tFabrik.liveSite = '" .
COM_FABRIK_LIVESITE . "';";
$liveSiteSrc[] = "\tFabrik.package = '" .
$app->getUserState('com_fabrik.package', 'fabrik') .
"';";
$liveSiteSrc[] = "\tFabrik.debug = " . (self::isDebug() ?
'true;' : 'false;');
// need to put jLayouts in session data, and add it in the system
plugin buildjs(), so just add %%jLayouts%% placeholder
//$liveSiteSrc[] = "\tFabrik.jLayouts = " .
json_encode(ArrayHelper::toObject(self::$jLayoutsJs)) . ";";
$liveSiteSrc[] = "\tFabrik.jLayouts = %%jLayouts%%;\n";
$liveSiteSrc[] = "\tFabrik.bootstrapped = true;";
$liveSiteSrc[] = self::tipInt();
$liveSiteSrc = implode("\n", $liveSiteSrc);
}
else
{
$liveSiteSrc[] = "\tFabrik.bootstrapped = true;";
$liveSiteSrc[] = "\tif (!Fabrik.jLayouts) {
Fabrik.jLayouts = {};
}
Fabrik.jLayouts = jQuery.extend(Fabrik.jLayouts, %%jLayouts%%);";
}
self::script($liveSiteReq, $liveSiteSrc, '-min.js');
self::$framework = $src;
}
self::addToSessionLayoutInterfaces();
return self::$framework;
}
/**
* Build JS to initiate tips, and observer application state changes,
* reloading the tips if needed.
*
* @return string
*/
public static function tipInt()
{
$tipOpts = self::tipOpts();
$tipJs = array();
$tipJs[] = "\tFabrik.tips = new FloatingTips('.fabrikTip',
" . json_encode($tipOpts) . ");";
$tipJs[] = "\tFabrik.addEvent('fabrik.list.updaterows',
function () {";
$tipJs[] = "\t\t// Reattach new tips after list redraw";
$tipJs[] = "\t\tFabrik.tips.attach('.fabrikTip');";
$tipJs[] = "\t});";
$tipJs[] =
"\tFabrik.addEvent('fabrik.plugin.inlineedit.editing',
function () {";
$tipJs[] = "\t\tFabrik.tips.hideAll();";
$tipJs[] = "\t});";
$tipJs[] =
"\tFabrik.addEvent('fabrik.list.inlineedit.setData',
function () {";
$tipJs[] = "\t\tFabrik.tips.attach('.fabrikTip');";
$tipJs[] = "\t});";
// Reload tips if a form is loaded (e.g. a list view with ajax links on
which loads a form in a popup)
// see: https://github.com/Fabrik/fabrik/issues/1394
$tipJs[] = "\tFabrik.addEvent('fabrik.form.loaded',
function () {";
$tipJs[] = "\t\tFabrik.tips.attach('.fabrikTip');";
$tipJs[] = "\t});";
$tipJs[] = "\tFabrik.addEvent('fabrik.list.loaded',
function () {";
$tipJs[] = "\t\tFabrik.tips.attach('.fabrikTip');";
$tipJs[] = "\t});";
// Load tips
//$tipJs[] = "\tFabrik.tips.attach('.fabrikTip');";
return implode("\n", $tipJs);
}
/**
* Checks the js_base_url global config, to see if admin has set a base
URI they want to use to
* fetch JS assets from. Allows for putting JS files in a fast CDN like
Amazon. If not set,
* return COM_FABRIK_LIVESITE.
*
* @return string
*/
public static function getJSAssetBaseURI()
{
if (!isset(static::$baseJSAssetURI))
{
$usersConfig = ComponentHelper::getParams('com_fabrik');
$requirejsBaseURI = $usersConfig->get('requirejs_base_uri',
COM_FABRIK_LIVESITE);
if (empty($requirejsBaseURI))
{
$requirejsBaseURI = COM_FABRIK_LIVESITE;
}
$requirejsBaseURI = rtrim($requirejsBaseURI, '/') .
'/';
static::$baseJSAssetURI = $requirejsBaseURI;
}
return static::$baseJSAssetURI;
}
/**
* Ini the require JS configuration
* Stores the shim and config to the session, which Fabrik system plugin
* then uses to inject scripts into document.
*
* @param array $shim Shim js files
* @param array $paths Additional require js paths
*
* @since 3.1
*
* @return void
*/
public static function iniRequireJs($shim = array(), $paths = array())
{
$session = Factory::getSession();
self::$allRequirePaths = (object) array_merge((array)
self::requirePaths(), $paths);
$framework = array();
$deps = array();
// $j3 = Worker::j3();
// $j3 = true;
$requirejsBaseURI = self::getJSAssetBaseURI();
// Load any previously created shim (e.g form which then renders list in
outro text)
$newShim = $session->get('fabrik.js.shim', array());
foreach ($shim as $k => &$s)
{
if (is_array($newShim) && array_key_exists($k, $newShim))
{
$s->deps = array_unique(array_merge($s->deps,
$newShim[$k]->deps));
}
$newShim[$k] = $s;
}
$navigator = Browser::getInstance();
// if ($navigator->getBrowser() == 'msie' && !$j3)
// {
// $deps[] = 'lib/flexiejs/flexie';
// }
$deps[] = 'fab/utils';
$deps[] = 'jquery';
$deps[] = 'fab/mootools-ext';
$deps[] = 'lib/Event.mock';
// if (!$j3)
// {
// $deps[] = 'lib/art';
// $deps[] = 'fab/tips';
// $deps[] = 'fab/icons';
// $deps[] = 'fab/icongen';
// }
self::addRequireJsShim($framework, 'fab/fabrik', $deps, false);
self::addRequireJsShim($framework,
'fab/autocomplete-bootstrap', array('fab/fabrik'),
false);
self::addRequireJsShim($framework, 'jQueryUI',
array('jquery'), false);
$newShim = array_merge($framework, $newShim);
$config = array();
$config[] = "define('jquery', [], function() {
return jQuery;
});";
// Required for full calendar
$config[] = "define('moment', [], function() {
return moment;
});";
$opts = array(
'baseUrl' => $requirejsBaseURI,
'paths' => self::$allRequirePaths,
'shim' => $newShim,
'waitSeconds' => 30
);
// Force script reloads if in burst is on.
if (self::getBurstJs())
{
$opts['urlArgs'] = 'bust=' . time();
}
$config[] = "requirejs.config(";
$config[] = json_encode($opts, self::isDebug() &&
defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : false);
$config[] = ");";
$config[] = "\n";
// Store in session - included in fabrik system plugin
$session->set('fabrik.js.shim', $newShim);
$session->set('fabrik.js.config', $config);
}
/**
* Should we 'burst' the loading of JS files. If true then
loaded
* js files will be appended with a random query string ensuring they
* are not loaded from cache
*
* @return boolean
* @throws \Exception
*/
protected static function getBurstJs()
{
$app = Factory::getApplication();
$config = ComponentHelper::getParams('com_fabrik');
return (bool) $app->input->get('burst',
$config->get('burst_js', 0));
}
/**
* Helper for create RequireJS shim dependencies
*
* @param array $framework Array to append the dependency to
* @param string $key RequireJs key - the file to load
* @param array $dependencies The dependencies to load before the $key
file
* @param bool $useMin Should we append -min to the $key if we are
not in debug mode
*/
protected static function addRequireJsShim(&$framework, $key,
$dependencies, $useMin = true)
{
$ext = self::isDebug() || !$useMin ? '' :
'-min';
$info = new stdClass;
$info->deps = $dependencies;
$framework[$key . $ext] = $info;
}
public static function mediaFile($file)
{
return self::isDebug() ? 'media/com_fabrik/js/' . $file :
'media/com_fabrik/js/dist/' . $file;
}
/**
* Get the js file path map that requireJS uses
*
* @since 3.1
*
* @return stdClass
*/
protected static function requirePaths()
{
if (empty(self::$allRequirePaths))
{
$r = new stdClass;
$r->fab = 'media/com_fabrik/js';
$r->lib = 'media/com_fabrik/js/lib';
$r->element = 'plugins/fabrik_element';
$r->list = 'plugins/fabrik_list';
$r->form = 'plugins/fabrik_form';
$r->cron = 'plugins/fabrik_cron';
$r->viz = 'plugins/fabrik_visualization';
$r->admin =
'administrator/components/com_fabrik/views';
$r->adminfields =
'administrator/components/com_fabrik/models/fields';
$r->jQueryUI =
'media/com_fabrik/js/lib/jquery-ui/jquery-ui';
$r->chosen = 'media/com_fabrik/js/dist/chosen.jquery';
//$r->ajaxChosen = 'media/jui/js/ajax-chosen.min';
// We are now loading compressed js fabrik files from the
media/com_fabrik/js/dist folder
// This avoids AMD issues where we were loading fab/form or
fab/form-min.
if (!self::isDebug())
{
$r->fab .= '/dist';
}
$r->punycode = 'media/system/js/punycode';
self::$allRequirePaths = $r;
}
return self::$allRequirePaths;
}
/**
* Load mootools lib
*
* @deprecated use ::framework instead
*
* @return void
*/
public static function mootools()
{
self::framework();
}
/**
* Load J!'s bootstrap CSS if requested. Special case for iframes in
non J! pages loading us.
*
* @return void
*/
public static function loadBootstrapCSS($force = false)
{
$app = Factory::getApplication();
if ($force || $app->input->get('loadbootstrapcss',
'') !== '')
{
$doc = Factory::getDocument();
Bootstrap::loadCss(true, $doc->direction);
}
}
/**
* Get tip options to control its fx - set in Fabrik global configuration
*
* @return stdClass
*/
public static function tipOpts()
{
$usersConfig = ComponentHelper::getParams('com_fabrik');
$opts = new stdClass;
$opts->tipfx = 'Fx.Transitions.' .
$usersConfig->get('tipfx', 'Linear');
if ($usersConfig->get('tipfx', 'Linear') !==
'Linear')
{
$opts->tipfx .= '.' .
$usersConfig->get('tipfx_ease', 'easeIn');
}
$opts->duration = $usersConfig->get('tipfx_duration',
'500');
$opts->distance = (int)
$usersConfig->get('tipfx_distance', '20');
$opts->fadein = (bool)
$usersConfig->get('tipfx_fadein', false);
return $opts;
}
/**
* Add a script declaration to the session. Inserted into doc via system
plugin
*
* @param string $script Js code to add
*
* @return null
*/
public static function addScriptDeclaration($script)
{
self::addToSessionScripts($script);
}
/**
* Add a rendered LayoutInterface to the Fabrik.jLayouts object
*
* @param string $name Reference to layout, used in JavaScript
* @param string $layoutName Dot syntax path to layout file
* @param stdClass $data Template data
* @param array $paths Additional layout paths
* @param array $options Options
*/
public static function jLayoutJs($name, $layoutName, object $data = null,
$paths = array(), $options = array())
{
if (!array_key_exists($name, self::$jLayoutsJs))
{
$layout = self::getLayout($layoutName, $paths,
$options);
self::$jLayoutsJs[$name] = $layout->render($data);
}
}
/**
* Add a CSS style declaration, either to the head or inline if format=raw
*
* @param string $style CSS
*
* @return void
*/
public static function addStyleDeclaration($style)
{
$app = Factory::getApplication();
if ($app->input->get('format') == 'raw')
{
echo '<style type="text/css">' . $style .
'</style>';
}
else
{
Factory::getDocument()->addStyleDeclaration($style);
}
}
/**
* Sometimes you want to load a page in an iframe and want to use
tmpl=component - in this case
* append iframe=1 to the url to ensure that we don't try to add the
scripts via FBAsset()
*
* @return bool
*/
public static function inAjaxLoadedPage()
{
$app = Factory::getApplication();
$package = $app->getUserState('com_fabrik.package',
'fabrik');
// Are we in fabrik or a content view, if not return false (things like
com_config need to load in Mootools)
$app = Factory::getApplication();
$input = $app->input;
$option = $input->get('option');
if ($option !== 'com_' . $package && $option !==
'com_content')
{
return false;
}
if (class_exists('JSite'))
{
$app = Factory::getApplication();
$menus = $app->getMenu();
$menu = $menus->getActive();
if (is_object($menu) && ($menu->browserNav == 2))
{
return false;
}
}
return $input->get('format') == 'raw'
|| ($input->get('tmpl') == 'component' &&
$input->get('iframe') != 1 &&
$input->get('format') !== 'pdf');
}
/**
* Returns true if either J! or Fabrik debug is enabled
* Use this for things like choosing whether to include compressed or
uncompressed JS, etc.
* Do NOT use for actual debug output.
*
* @param bool $enabled Set to true if Fabrik debug global option must
be set to true
*
* @return bool
*/
public static function isDebug($enabled = false)
{
static $debug = null;
if (!isset($debug))
{
$app = Factory::getApplication();
$config = ComponentHelper::getParams('com_fabrik');
/*
if ($app->input->get('format', 'html') ===
'raw')
{
$debug = false;
return false;
}
*/
if ($enabled && $config->get('use_fabrikdebug') ==
0)
{
$debug = false;
return false;
}
if ($config->get('use_fabrikdebug') == 2)
{
$debug = true;
return true;
}
$config = Factory::getApplication()->getConfig();
$debug = (int) $config->get('debug') ||
$app->input->get('fabrikdebug', 0) == 1;
}
return $debug;
}
/**
* Returns true if either J! system debug is true, and &fabrikdebug=2,
* will then bypass ALL redirects, so we can see J! profile info.
*
* @return bool
*/
public static function isDebugSubmit()
{
$app = Factory::getApplication();
$config = ComponentHelper::getParams('com_fabrik');
if ($config->get('use_fabrikdebug') == 0)
{
return false;
}
$jConfig = Factory::getApplication()->getConfig();
$debug = (int) $jConfig->get('debug');
return $debug === 1 &&
$app->input->get('fabrikdebug', 0) == 2;
}
/**
* Wrapper for HTMLHelperScript() loading with require.js
* If not debugging will replace file names .js => -min.js
*
* @param mixed $file String or array of files to load, relative
path to root for local files
* e.g.
'administrator/components/com_fabrik/models/fields/tables.js'
* @param string $onLoad Optional js to run once the Js file has
been loaded
* @param string $minSuffix The minimised file suffix to use, replaces
'.js'
*
* @return void
*/
public static function script($file, $onLoad = '', $minSuffix =
'-min.js')
{
if (empty($file))
{
return;
}
if (is_array($onLoad))
{
$onLoad = implode("\n", $onLoad);
}
$ext = self::isDebug() ? '.js' : $minSuffix;
$paths = self::requirePaths();
$files = (array) $file;
// Replace with minified files if found
foreach ($files as &$file)
{
if (!(StringHelper::stristr($file, 'http://') ||
StringHelper::stristr($file, 'https://')))
{
/**
* Fix for new media compressed JS paths, which we switched from
./js/foo-mins.js to ./js/dist/foo.js.
* Some code feeds us the new dist path, but some still uses just
media/com_fabrik/js. So, if we're
* not in debug mode, and the path is media/com_fabrik/js and
doesn't have /dist, add it.
**/
if (!self::isDebug())
{
if (strpos($file, 'media/com_fabrik/js/') !== false)
{
if (strpos($file, 'media/com_fabrik/js/lib/') === false)
{
if (strpos($file, 'media/com_fabrik/js/dist/') === false)
{
$file = str_replace('media/com_fabrik/js/',
'media/com_fabrik/js/dist/', $file);
}
}
}
}
if (File::exists(COM_FABRIK_BASE . $file))
{
$compressedFile = str_replace('.js', $ext, $file);
if (File::exists(COM_FABRIK_BASE . $compressedFile) ||
File::exists($compressedFile))
{
$file = $compressedFile;
}
}
}
// Set file name based on requirejs basePath
$pathMatched = false;
foreach ($paths as $requireKey => $path)
{
if (strstr($file, $path))
{
$file = str_replace($path, '', $file);
$file = str_replace('.js', '', $file);
$file = $requireKey . $file;
$pathMatched = true;
}
}
if (!$pathMatched)
{
if (!(StringHelper::stristr($file, 'http://') ||
StringHelper::stristr($file, 'https://')))
{
$file = COM_FABRIK_LIVESITE . $file;
}
}
}
// Need to load element for ajax popup forms in IE.
$needed = array();
// if (!Worker::j3())
// {
// $needed[] = self::isDebug() ? 'fab/icongen' :
'fab/icongen-min';
// $needed[] = self::isDebug() ? 'fab/icons' :
'fab/icons-min';
// }
foreach ($needed as $need)
{
if (!in_array($need, $files))
{
array_unshift($files, $need);
}
}
$files = array_unique($files);
// Set names from $files keys if assoc array. In general it is for
require js files
$names = array_keys($files) !== range(0, count($files) - 1) ?
array_keys($files) : array();
$files = "['" . implode("', '",
$files) . "']";
$require[] = 'requirejs(' . ($files) . ', function ('
. implode(", ", $names) . ') {';
$require[] = $onLoad;
$require[] = '});';
$require[] = "\n";
$require = implode("\n", $require);
self::addToSessionScripts($require);
}
/**
* Add jLayouts to session - will then be added via Fabrik System plugin
*
* @return void
*/
protected static function addToSessionLayoutInterfaces()
{
$key = 'fabrik.js.jlayouts';
$session = Factory::getSession();
/*
* No need to figure out what's already there, unlike
addToSessionScripts,
* we're just updating the whole thing each time framework is added.
*/
$session->set($key, self::$jLayoutsJs);
}
/**
* Add script to session - will then be added via Fabrik System plugin
*
* @param string $js JS code
*
* @return void
*/
protected static function addToSessionScripts($js)
{
$key = 'fabrik.js.scripts';
$session = Factory::getSession();
if ($session->has($key))
{
$scripts = $session->get($key);
}
else
{
$scripts = array();
}
$scripts[] = $js;
$session->set($key, $scripts);
}
/**
* Add script to session - will then be added (in head) via Fabrik System
plugin
*
* @param string $js JS code
*
* @return void
*/
protected static function addToSessionHeadScripts($js)
{
$key = 'fabrik.js.head.scripts';
$session = Factory::getSession();
if ($session->has($key))
{
$scripts = $session->get($key);
}
else
{
$scripts = array();
}
$scripts[] = $js;
$session->set($key, $scripts);
}
/**
* Add jLayouts to session - will then be added via Fabrik System plugin
*
* @return void
*/
public static function addToSessionCacheIds($id)
{
$key = 'fabrik.js.cacheids';
$session = Factory::getSession();
if ($session->has($key))
{
$cacheIds = $session->get($key);
}
else
{
$cacheIds = array();
}
$cacheIds[] = $id;
$session->set($key, array_values(array_unique($cacheIds)));
}
/**
* Load the slimbox / media box css and js files
*
* @return void
*/
public static function slimbox()
{
$input = Factory::getApplication()->input;
if ($input->get('format') === 'raw')
{
return;
}
if (!self::$modal)
{
$fbConfig = ComponentHelper::getParams('com_fabrik');
if ($fbConfig->get('include_lightbox_js', 1) == 0)
{
return;
}
if ($fbConfig->get('use_mediabox', 1))
{
$folder = 'components/com_fabrik/libs/mediabox-advanced/';
$mbStyle = $fbConfig->get('mediabox_style',
'Dark');
HTMLHelper::stylesheet($folder . 'mediabox-' . $mbStyle .
'.css');
self::script($folder . 'mediaboxAdv.js');
}
else
{
// if (Worker::j3())
// {
HTMLHelper::stylesheet('components/com_fabrik/libs/slimbox2/css/slimbox2.css');
self::script('components/com_fabrik/libs/slimbox2/js/slimbox2.js');
/*
}
else
{
HTMLHelper::stylesheet('components/com_fabrik/libs/slimbox1.64/css/slimbox.css');
self::script('components/com_fabrik/libs/slimbox1.64/js/slimbox.js');
}
*/
}
self::$modal = true;
}
}
/**
* Load the slide-show css and js files
*
* @return void
*/
public static function slideshow()
{
$folder = 'media/com_fabrik/js/lib/slick/';
$ext = self::isDebug() ? '.js' : '.min.js';
self::script($folder . 'slick' . $ext);
Html::stylesheet(COM_FABRIK_LIVESITE .
'media/com_fabrik/js/lib/slick/slick.css');
Html::stylesheet(COM_FABRIK_LIVESITE .
'media/com_fabrik/js/lib/slick/slick-theme.css');
$folder = 'media/com_fabrik/js/lib/elevatezoom-plus/';
$ext = self::isDebug() ? '.js' : '.js';
self::script($folder . 'jquery.ez-plus' . $ext);
}
/**
* Attach tooltips to document
*
* @param string $selector String class name of tips
* @param array $params Array parameters
* @param string $selectorPrefix Limit the tips selection to those
contained within an id
*
* @return void
*/
public static function tips($selector = '.hasTip', $params =
array(), $selectorPrefix = 'document')
{
$sig = md5(serialize(array($selector, $params)));
if (isset(self::$tips[$sig]) && (self::$tips[$sig]))
{
return;
}
// Setup options object
$opt['maxTitleChars'] =
(isset($params['maxTitleChars']) &&
($params['maxTitleChars'])) ? (int)
$params['maxTitleChars'] : 50;
$opt['offsets'] = (isset($params['offsets'])) ?
(int) $params['offsets'] : null;
$opt['showDelay'] = (isset($params['showDelay']))
? (int) $params['showDelay'] : null;
$opt['hideDelay'] = (isset($params['hideDelay']))
? (int) $params['hideDelay'] : null;
$opt['className'] = (isset($params['className']))
? $params['className'] : null;
$opt['fixed'] = (isset($params['fixed'])
&& ($params['fixed'])) ? '\\true' :
'\\false';
$opt['onShow'] = (isset($params['onShow'])) ?
'\\' . $params['onShow'] : null;
$opt['onHide'] = (isset($params['onHide'])) ?
'\\' . $params['onHide'] : null;
$options = json_encode($opt);
// Attach tooltips to document
// Force the zindex to 9999 so that it appears above the popup window.
$tooltipInit = 'window.addEvent("fabrik.load", function()
{if(typeOf(' . $selectorPrefix . ') !== \'null\'
&& ' . $selectorPrefix
. '.getElements(\'' . $selector
. '\').length !== 0) {window.JTooltips = new Tips(' .
$selectorPrefix . '.getElements(\'' . $selector .
'\'), ' . $options
. ');$$(".tool-tip").setStyle("z-index",
999999);}});';
/* self::addScriptDeclaration($tooltipInit); */
self::$tips[$sig] = true;
}
/**
* Add a debug out put section
*
* @param mixed $content String/object
* @param string $title Debug title
*
* @return void
*/
public static function debug($content, $title = 'output:')
{
$config = ComponentHelper::getParams('com_fabrik');
$app = Factory::getApplication();
$input = $app->input;
if ($config->get('use_fabrikdebug') == 0)
{
return;
}
if ($input->getBool('fabrikdebug', 0, 'request')
!= 1)
{
return;
}
if ($input->get('format') == 'raw')
{
return;
}
$jconfig = Factory::getApplication()->getConfig();
$secret = $jconfig->get('secret');
echo '<div class="fabrikDebugOutputTitle">' .
$title . '</div>';
echo '<div class="fabrikDebugOutput
fabrikDebugHidden">';
if (is_object($content) || is_array($content))
{
$content = print_r($content, true);
$content = str_replace($secret, 'xxxxxxxxx', $content);
echo '<pre>' . htmlspecialchars($content) .
'</pre>';
}
else
{
$content = str_replace($secret, 'xxxxxxxxx', $content);
// Remove any <pre> tags provided by e.g. JQuery::dump
$content = preg_replace('/(^\s*<pre(
.*)?>)|(<\/pre>\s*$)/i', '', $content);
echo '<pre>' . htmlspecialchars($content) .
'</pre>';
}
echo '</div>';
if (!isset(self::$debug))
{
self::$debug = true;
$style =
".fabrikDebugOutputTitle{padding:5px;background:#efefef;color:#333;border:1px
solid #999;cursor:pointer}";
$style .=
".fabrikDebugOutput{padding:5px;background:#efefef;color:#999;}";
$style .= ".fabrikDebugOutput
pre{padding:5px;background:#efefef;color:#999;}";
$style .= ".fabrikDebugHidden{display:none}";
self::addStyleDeclaration($style);
$script = "window.addEvent('domready', function() {
document.getElements('.fabrikDebugOutputTitle').each(function
(title) {
title.addEvent('click', function (e) {
title.getNext().toggleClass('fabrikDebugHidden');
});
});
})";
self::addScriptDeclaration($script);
}
}
/**
* Create html for ajax folder browser (used by file-upload and image
elements)
*
* @param array $folders array of folders to show
* @param string $path start path
* @param string $tpl view template
*
* @return string html snippet
*/
public static function folderAjaxSelect($folders, $path = '',
$tpl = '')
{
$str = array();
$str[] = '<a href="#" class="btn btn-default
toggle" title="' .
Text::_('COM_FABRIK_BROWSE_FOLDERS') . '">';
$str[] = self::image('orderneutral.png', 'form',
$tpl, array('alt' =>
Text::_('COM_FABRIK_BROWSE_FOLDERS'), 'icon-class'
=> 'icon-menu-2'));
$str[] = '</a>';
$str[] = '<div
class="folderselect-container">';
$str[] = '<span class="breadcrumbs"><a
href="#">' . Text::_('HOME') .
'</a><span> / </span>';
$i = 1;
$path = explode("/", $path);
foreach ($path as $p)
{
if (!empty($p))
{
$str[] = '<a href="#" class="crumb' . $i .
'">' . $p . '</a><span> /
</span>';
$i++;
}
}
$str[] = '</span>';
$str[] = '<ul class="folderselect">';
settype($folders, 'array');
foreach ($folders as $folder)
{
if (trim($folder) != '')
{
$str[] = '<li class="fileupload_folder"><a
href="#">' . $folder . '</a></li>';
}
}
// For html validation
if (empty($folder))
{
$str[] = '<li></li>';
}
$str[] = '</ul></div>';
return implode("\n", $str);
}
/**
* Add auto-complete JS code to head
*
* @param string $htmlId Of element to turn into autocomplete
* @param int $elementId Element id
* @param int $formId Form id
* @param string $plugin Plugin name
* @param array $opts * onSelection - function to run when
option selected
* * max - max number of items to show in
selection list
*
* @return void
*/
public static function autoComplete($htmlId, $elementId, $formId, $plugin
= 'field', $opts = array())
{
/*
$input = Factory::getApplication()->input;
if ($input->get('format') === 'raw')
{
return;
}
*/
$json = self::autoCompleteOptions($htmlId, $elementId, $formId, $plugin,
$opts);
$str = json_encode($json);
Text::script('COM_FABRIK_NO_AUTOCOMPLETE_RECORDS');
Text::script('COM_FABRIK_AUTOCOMPLETE_AJAX_ERROR');
$jsFile = 'autocomplete';
$className = 'AutoComplete';
// if (Worker::j3())
// {
$jsFile = $plugin === 'cascadingdropdown' ?
'autocomplete-bootstrap-cdd' :
'autocomplete-bootstrap';
$className = $plugin === 'cascadingdropdown' ?
'FabCddAutocomplete' : 'AutoComplete';
// }
$needed = array();
$needed[] = 'fab/' . $jsFile;
$needed[] = 'lib/Event.mock';
$needed = implode("', '", $needed);
self::addScriptDeclaration(
"require(['$needed'], function ($className) {
new $className('$htmlId', $str);
});"
);
}
/**
* Gets auto complete js options (needed separate from autoComplete as db
js class needs these values for repeat
* group duplication)
*
* @param string $htmlId Element to turn into autocomplete
* @param int $elementId Element id
* @param int $formId Form id
* @param string $plugin Plugin type
* @param array $opts * onSelection - function to run when
option selected
* * max - max number of items to show in
selection list
*
* @return array Autocomplete options (needed for elements so when
duplicated we can create a new
* FabAutocomplete object
*/
public static function autoCompleteOptions($htmlId, $elementId, $formId,
$plugin = 'field', $opts = array())
{
$json = new stdClass;
if (!array_key_exists('minTriggerChars', $opts))
{
$usersConfig =
ComponentHelper::getParams('com_fabrik');
$json->minTriggerChars = (int)
$usersConfig->get('autocomplete_min_trigger_chars',
'3');
}
if (!array_key_exists('max', $opts))
{
$usersConfig =
ComponentHelper::getParams('com_fabrik');
$json->max = (int)
$usersConfig->get('autocomplete_max_rows', '10');
}
if (!array_key_exists('autoLoadSingleResult', $opts))
{
$usersConfig =
ComponentHelper::getParams('com_fabrik');
$json->autoLoadSingleResult = (int)
$usersConfig->get('autocomplete_autoload_single',
'0');
}
$app = Factory::getApplication();
$package = $app->getUserState('com_fabrik.package',
'fabrik');
//$json->url = COM_FABRIK_LIVESITE . 'index.php?option=com_'
. $package . '&format=raw';
$json->url = 'index.php?option=com_' . $package .
'&format=raw';
$json->url .= $app->isClient('administrator') ?
'&task=plugin.pluginAjax' :
'&view=plugin&task=pluginAjax';
$json->url .= '&' . Session::getFormToken() .
'=1';
$json->url .= '&g=element&element_id=' . $elementId
. '&formid=' . $formId . '&plugin=' .
$plugin . '&method=autocomplete_options&package=' .
$package;
$c = ArrayHelper::getValue($opts, 'onSelection');
if ($c != '')
{
$json->onSelections = $c;
}
foreach ($opts as $k => $v)
{
$json->$k = $v;
}
$json->formRef = ArrayHelper::getValue($opts, 'formRef',
'form_' . $formId);
$json->container = ArrayHelper::getValue($opts, 'container',
'fabrikElementContainer');
$json->menuclass = ArrayHelper::getValue($opts, 'menuclass',
'auto-complete-container');
return $json;
}
/**
* Load the auto-complete script once
*
* @deprecated since 3.1b
*
* @return void
*/
public static function autoCompleteScript()
{
}
public static function atWho($selector, $placeHolders = array())
{
array_filter($placeHolders);
$key = $selector . implode('.', $placeHolders);
if (!array_key_exists($key, self::$atWho))
{
$replacements = Worker::globalReplacements();
$replacements = array_keys($replacements);
$replacements = array_map(function ($v)
{
$v = str_replace(array('{', '}'),
array('', ''), $v);
return $v;
}, $replacements);
$placeHolders = array_merge($placeHolders, $replacements);
$placeHolders = json_encode($placeHolders);
$script[] = "jQuery('$selector').atwho({
'at': '{',
'insertTpl' : '\${atwho-at}\${name}}',
data: $placeHolders,
limit: 5,
});";
self::$atWho[$key] = true;
$css = self::isDebug() ? 'jquery.atwho.css' :
'jquery.atwho.min.css';
Html::stylesheet('media/com_fabrik/js/lib/at/' . $css);
$needed[] = self::isDebug() ? '\'lib/caret/caret\''
: '\'lib/caret/caret-min\'';
$needed[] = self::isDebug() ? '\'lib/at/atwho\'' :
'\'lib/at/atwho-min\'';
$needed = implode(", ", $needed);
$script = implode("\n", $script);
self::addScriptDeclaration(
"requirejs([$needed], function (j, f) {
$script
});"
);
}
}
/**
* Load the Facebook Graph API
*
* @param string $appId Application id
* @param string $locale locale e.g 'en_US'
* @param array $meta meta tags to add
*
* @return string
*/
public static function facebookGraphAPI($appId, $locale =
'en_US', $meta = array())
{
if (!isset(self::$facebookgraphapi))
{
self::$facebookgraphapi = true;
$document = Factory::getDocument();
$data = array('custom' => array());
$typeFound = false;
foreach ($meta as $k => $v)
{
if (is_array($v))
{
$v = implode(',', $v);
}
$v = strip_tags($v);
// $$$ rob og:type required
if ($k == 'og:type')
{
$typeFound = true;
if ($v == '')
{
$v = 'article';
}
}
$data['custom'][] = '<meta property="' . $k
. '" content="' . $v . '"/>';
}
if (!$typeFound)
{
$data['custom'][] = '<meta
property="og:type" content="article"/>';
}
$document->setHeadData($data);
}
$retStr = <<<EOT
<!-- Load Facebook SDK for JavaScript -->
<div id="fb-root"></div>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src =
'https://connect.facebook.net/$locale/sdk.js#xfbml=1&version=v3.0&appId=$appId&autoLogAppEvents=1';
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script',
'facebook-jssdk'));</script>
EOT;
return $retStr;
}
/**
* Add path for image() function
*
* @param string $path to add to list of folders to search
* @param string $type of path set to load (currently only image
is used)
* @param string $view are we looking at loading form or list
images?
* @param bool $highPriority should the added $path take precedence
over previously added paths (default true)
*
* @since 3.0
*
* @return array paths
*/
public static function addPath($path = '', $type =
'image', $view = 'form', $highPriority = true)
{
if (!array_key_exists($type, self::$helperpaths))
{
self::$helperpaths[$type] = array();
$app = Factory::getApplication();
$template = $app->getTemplate();
switch ($type)
{
case 'image':
if ($app->isClient('administrator'))
{
self::$helperpaths[$type][] = JPATH_SITE . DIRECTORY_SEPARATOR .
'administrator/templates/' . $template . '/images/';
}
self::$helperpaths[$type][] = COM_FABRIK_BASE . 'templates/'
. $template . '/html/com_fabrik/' . $view .
'/%s/images/';
self::$helperpaths[$type][] = COM_FABRIK_BASE . 'templates/'
. $template . '/html/com_fabrik/' . $view . '/images/';
self::$helperpaths[$type][] = COM_FABRIK_BASE . 'templates/'
. $template . '/html/com_fabrik/images/';
self::$helperpaths[$type][] = COM_FABRIK_BASE . 'templates/'
. $template . '/custom/images/';
self::$helperpaths[$type][] = COM_FABRIK_FRONTEND .
'/views/' . $view . '/tmpl/%s/images/';
self::$helperpaths[$type][] = COM_FABRIK_BASE .
'media/com_fabrik/images/';
self::$helperpaths[$type][] = COM_FABRIK_BASE . 'images/';
self::$helperpaths[$type][] = COM_FABRIK_BASE .
'images/stories/';
self::$helperpaths[$type][] = COM_FABRIK_BASE .
'media/system/images/';
break;
}
}
if (!array_key_exists($path, self::$helperpaths[$type]) && $path
!== '')
{
$highPriority ? array_unshift(self::$helperpaths[$type], $path) :
self::$helperpaths[$type][] = $path;
}
return self::$helperpaths[$type];
}
/**
* Search various folder locations for an image
*
* @param string $file file name
* @param string $type type e.g. form/list/element
* @param string $tmpl template folder name
*
* @return string full path name if found, original filename if not
found
*/
public static function getImagePath($file, $type = 'form', $tmpl
= '')
{
$file = StringHelper::ltrim($file, DIRECTORY_SEPARATOR);
$paths = self::addPath('', 'image', $type, true);
foreach ($paths as $path)
{
$path = sprintf($path, $tmpl);
$src = $path . $file;
if (File::exists($src))
{
return $src;
}
}
return '';
}
/**
* Search various folder locations for a template image
*
* @param string $file File name
* @param string $type Type e.g. form/list/element
* @param string $tmpl Template folder name
* @param array|string $properties Assoc list of properties or string
(if you just want to set the image alt tag)
* @param bool $srcOnly Src only (default false)
* @param array $opts Additional render options:
* forceImage: regardless of in J3 site
- render an <img> if set to true
* (bypasses bootstrap icon loading)
*
* @since 3.0
*
* @return string image
*/
public static function image($file, $type = 'form', $tmpl =
'', $properties = array(), $srcOnly = false, $opts = array())
{
if (is_string($properties))
{
$properties = array('alt' => $properties);
}
// if there's a file of this name in our paths, or forceImage is
set, don't use icon, use image
$src = self::getImagePath($file, $type, $tmpl);
$forceImage = ArrayHelper::getValue($opts, 'forceImage', false)
|| !empty($src);
// if (Worker::j3() && $forceImage !== true)
if ($forceImage !== true)
{
unset($properties['alt']);
$class = ArrayHelper::getValue($properties, 'icon-class',
'');
$class = 'icon-' . File::stripExt($file) . ($class ? '
' . $class : '');
unset($properties['icon-class']);
$class .= ' ' . ArrayHelper::getValue($properties,
'class', '');
unset($properties['class']);
$p = self::propertiesFromArray($properties);
if (!$srcOnly)
{
return Html::icon($class, '', $p);
}
else
{
return $class;
}
}
$src = str_replace(COM_FABRIK_BASE, COM_FABRIK_LIVESITE, $src);
$src = str_replace("\\", "/", $src);
if ($srcOnly)
{
return $src;
}
if (isset($properties['class']))
{
$properties['class'] .= ' fabrikImg';
}
else
{
$properties['class'] = 'fabrikImg';
}
$p = self::propertiesFromArray($properties);
return $src == '' ? '' : '<img
src="' . $src . '" ' . $p . '/>';
}
/**
* Build HTML properties from an associated array
*
* @param array $properties Properties
*
* @return string
*/
public static function propertiesFromArray($properties)
{
$bits = array();
$p = '';
foreach ($properties as $key => $val)
{
if ($key === 'title')
{
$val = htmlspecialchars($val, ENT_QUOTES);
}
$bits[$key] = $val;
}
foreach ($bits as $key => $val)
{
if (!\FabrikWorker::isJSON($val))
{
$val = str_replace('"', "'", $val);
$p .= $key . '="' . $val . '" ';
}
}
return $p;
}
/**
* Build array of items for use in grid()
*
* @param array $values Option values
* @param array $labels Option labels
* @param array $selected Selected options
* @param string $name Input name
* @param string $type Checkbox/radio etc
* @param bool $elementBeforeLabel Element before or after the label
- deprecated - not used in Joomla 3
* @param array $classes Label classes
* @param bool $buttonGroup Should it be rendered as a
bootstrap button group (radio only)
* @param array $inputDataAttributes Input data attributes e.g.
array('data-foo="bar")
*
* @return array Grid items
*/
public static function gridItems($values, $labels, $selected, $name, $type
= 'checkbox',
$elementBeforeLabel = true, $classes = array(), $buttonGroup = false,
$inputDataAttributes = array())
{
$items = array();
$layout =
self::getLayout('fabrik-grid-item');
$displayData = new stdClass;
$displayData->type = $type;
$displayData->name = $name;
$displayData->classes = $classes;
$displayData->inputDataAttributes = implode(' ',
$inputDataAttributes);
$displayData->selected = $selected;
$displayData->elementBeforeLabel = $elementBeforeLabel;
$displayData->buttonGroup = $buttonGroup;
for ($i = 0; $i < count($values); $i++)
{
$displayData->i = $i;
$displayData->label = $labels[$i];
// For values like '1"'
$displayData->value = htmlspecialchars($values[$i], ENT_QUOTES);
$items[] = $layout->render($displayData);
}
return $items;
}
/**
* Make a grid of items
*
* @param array $values Option values
* @param array $labels Option labels
* @param array $selected Selected options
* @param string $name Input name
* @param string $type Checkbox/radio etc.
* @param bool $elementBeforeLabel Element before or after the label
- deprecated - not used in Joomla 3
* @param int $optionsPerRow Number of suboptions to show per
row
* @param array $classes Array of arrays, for
'label' and 'container' classes
* @param bool $buttonGroup Should it be rendered as a
bootstrap button group (radio only)
* @param array $dataAttributes Additional
array('data-foo="bar"), like YesNo needs
data-bs-toggle="button"
* @param array $inputDataAttributes Input data attributes e.g.
array('data-foo="bar")
*
* @return string grid
*/
public static function grid($values, $labels, $selected, $name, $type =
'checkbox',
$elementBeforeLabel = true, $optionsPerRow = 4, $classes = array(),
$buttonGroup = false, $dataAttributes = array(),
$inputDataAttributes = array())
{
$elementBeforeLabel = true;
$containerClasses = array_key_exists('container', $classes) ?
implode(' ', $classes['container']) : '';
$dataAttributes = implode(' ', $dataAttributes);
$items = self::gridItems($values, $labels, $selected, $name, $type,
$elementBeforeLabel, $classes, $buttonGroup, $inputDataAttributes);
$grid = array();
$optionsPerRow = empty($optionsPerRow) ? 4 : $optionsPerRow;
$w = floor(100 / $optionsPerRow);
if ($buttonGroup && $type == 'radio')
{
$grid[] = '<div class="btn-group"
role="group" ' . $dataAttributes . '>';
foreach ($items as $i => $s)
{
$grid[] = $s;
}
$grid[] = '</div>';
}
else
{
$grid = self::bootstrapGrid($items, $optionsPerRow, 'form-check
fabrikgrid_' . $type);
}
return $grid;
}
/**
* Wrap items in bootstrap grid markup
*
* @param array $items Content to wrap
* @param int $columns Number of columns in the grid
* @param string $spanClass Additional class to add to cells
* @param bool $explode Should the results be exploded to a string
or returned as an array
*
* @return mixed string/array based on $explode parameter
*/
public static function bootstrapGrid($items, $columns, $spanClass =
'', $explode = false, $spanId = null)
{
$layout =
self::getLayout('fabrik-bootstrap-grid');
$displayData = new stdClass;
$displayData->items = $items;
$displayData->columns = $columns;
$displayData->spanClass = $spanClass;
$displayData->spanId = $spanId;
$displayData->explode = $explode;
$grid = $layout->render($displayData);
return $explode ? $grid : explode("\n", $grid);
}
/**
* Does the browser support Canvas elements
*
* @since 3.0.9
*
* @return boolean
*/
public static function canvasSupport()
{
$navigator = Browser::getInstance();
return !($navigator->getBrowser() == 'msie' &&
$navigator->getMajor() < 9);
}
/**
* Run Joomla content plugins over text
*
* @param string &$text Content
* @param bool $cloak Cloak emails
*
* @return void
*
* @since 3.0.7
*/
public static function runContentPlugins(&$text, $cloak = false)
{
$app = Factory::getApplication();
$input = $app->input;
$opt = $input->get('option');
$view = $input->get('view');
$format = $input->get('format');
$input->set('option', 'com_content');
$input->set('view', 'article');
$input->set('format', 'html');
jimport('joomla.html.html.content');
/**
* J!'s email cloaking will cloak email addresses in form inputs,
which is a Bad Thing<tm>.
* What we really need to do is work out a way to prevent ONLY cloaking
of emails in form inputs,
* but that's not going to be trivial. So band-aid is to turn it
off in form and list views, so
* addresses only get cloaked in details view.
* In addition, if we are in a details PDF view we should not run the
email cloak plugin.
*/
if (!$cloak)
{
$text .= '{emailcloak=off}';
}
$text = HTMLHelper::_('content.prepare', $text);
if (!$cloak)
{
$text = StringHelper::rtrimword($text, '{emailcloak=off}');
}
$input->set('option', $opt);
$input->set('view', $view);
$input->set('format', $format);
}
/**
* Run text through J!'s email cloaking
* @param $text
*
* @return mixed
*/
public static function cloakEmails($text)
{
$text = HTMLHelper::_('email.cloak',$text);
return $text;
}
/**
* Get content item template
*
* @param int $contentTemplate Joomla article id
* @param string $part which part, intro, full, or both
* @param bool $runPlugins run content plugins on the text
*
* @since 3.0.7
*
* @return string content item html
*/
public static function getContentTemplate($contentTemplate, $part =
'both', $runPlugins = false)
{
$app = Factory::getApplication();
if ($app->isClient('administrator'))
{
$db = Factory::getContainer()->get('DatabaseDriver');
$query = $db->getQuery(true);
$query->select('introtext, ' .
$db->quoteName('fulltext'))->from('#__content')->where('id
= ' . (int) $contentTemplate);
$db->setQuery($query);
$res = $db->loadObject();
}
else
{
BaseDatabaseModel::addIncludePath(COM_FABRIK_BASE .
'components/com_content/models');
$articleModel =
Factory::getApplication()->bootComponent('com_fabrik')->getMVCFactory()->createModel('Article',
'ContentModel');
$res = $articleModel->getItem($contentTemplate);
}
if ($part == 'intro')
{
$res = $res->introtext;
}
else
{
if ($part == 'full')
{
$res = $res->fulltext;
}
else
{
$res = $res->introtext . ' ' . $res->fulltext;
}
}
if ($runPlugins === true)
{
self::runContentPlugins($res, false);
}
return $res;
}
/**
* Read a template file
*
* @param string $templateFile Path to template
*
* @return string template content
*/
public static function getTemplateFile($templateFile)
{
return file_get_contents($templateFile);
}
/**
* Run a PHP template as a require. Return buffered output, or false if
require returns false.
*
* @param string $tmpl Path to template
* @param array $data Optional element data in standard format, for
eval'd code to use
* @param object $model Optional model object, depending on context, for
eval'd code to use
*
* @return mixed email message or false
*/
public static function getPHPTemplate($tmpl, $data = array(), $model =
null)
{
// Start capturing output into a buffer
ob_start();
$result = require $tmpl;
$message = ob_get_contents();
ob_end_clean();
if ($result === false)
{
return false;
}
else
{
return $message;
}
}
/**
* Get base tag url
*
* @param string $fullName Full name (key value to remove from
querystring)
* @param string $rootUrl Optional root to use rather than REQUEST_URI
*
* @return string
*/
public static function tagBaseUrl($fullName, $rootUrl = null)
{
$url = filter_var(ArrayHelper::getValue($_SERVER,
'REQUEST_URI', 'index.php'), FILTER_SANITIZE_URL);
$bits = explode('?', $url);
$root = isset($rootUrl) ? $rootUrl : ArrayHelper::getValue($bits, 0,
'', 'string');
$bits = ArrayHelper::getValue($bits, 1, '',
'string');
$bits = explode("&", $bits);
$rootBits = array();
if (isset($rootUrl))
{
$rootBits = explode('?', $rootUrl);
$rootBits = ArrayHelper::getValue($rootBits, 1, '',
'string');
$rootBits = explode("&", $rootBits);
}
for ($b = count($bits) - 1; $b >= 0; $b--)
{
if (in_array($bits[$b], $rootBits))
{
unset($bits[$b]);
continue;
}
$parts = explode("=", $bits[$b]);
if (count($parts) > 1)
{
$key =
StringHelper::ltrimword(StringHelper::safeColNameToArrayKey($parts[0]),
'&');
if ($key == $fullName)
{
unset($bits[$b]);
}
if ($key == $fullName . '[value]')
{
unset($bits[$b]);
}
if ($key == $fullName . '[condition]')
{
unset($bits[$b]);
}
}
}
$url = empty($bits) ? $root : $root . StringHelper::qsSepChar($root) .
implode('&', $bits);
return $url;
}
/**
* Tagify a string
*
* @param array $data Data to tagify
* @param string $baseUrl Base Href url
* @param string $name Key name for querystring
* @param string $icon HTML bootstrap icon
*
* @return string tagified string
*/
public static function tagify($data, $baseUrl = '', $name =
'', $icon = '')
{
$url = $baseUrl;
$tags = array();
if (!is_array($data))
{
return $tags;
}
if ($url == '')
{
$url = self::tagBaseUrl();
}
// Remove duplicates from tags
$data = array_unique($data);
foreach ($data as $key => $d)
{
$d = trim($d);
if ($d != '')
{
if (trim($baseUrl) == '')
{
$qs = strstr($url, '?');
if (substr($url, -1) === '?')
{
$thisUrl = $url . $name . '[value]=' . $d;
}
else
{
$thisUrl = strstr($url, '?') ? $url . '&' .
$name . '[value]=' . urlencode($d) : $url . '?' . $name
. '[value]=' . urlencode($d);
}
$thisUrl .= '&' . $name .
'[condition]=CONTAINS';
$thisUrl .= '&resetfilters=1';
}
else
{
$thisUrl = str_replace('{tag}', urlencode($d), $url);
$thisUrl = str_replace('{key}', urlencode($key), $url);
}
$tags[] = '<a href="' . $thisUrl . '"
class="fabrikTag">' . $icon . $d .
'</a>';
}
}
return $tags;
}
/**
* Return a set of attributes for an <a> tag
*
* @param string $title Title to use for popup image
* @param string $group Grouping tag for next/prev, if applicable
*
* @return string
*/
public static function getLightboxAttributes($title = "", $group
= "")
{
$fbConfig = ComponentHelper::getParams('com_fabrik');
$lightBoxScript = $fbConfig->get('use_mediabox',
'0');
$attributes = array();
switch ($lightBoxScript)
{
case 0:
case 1:
default:
$attributes[] = 'rel="lightbox[' . $group .
']"';
break;
case 2:
$attributes[] = "data-rokbox";
if (!empty($title))
{
$attributes[] = 'data-rockbox-caption="' .
addslashes($title) . '"';
}
if (!empty($group))
{
$attributes[] = 'data-rokbox-album="' .
addslashes($group) . '"';
}
break;
case 3:
$rel = 'data-rel="lightcase';
if (!empty($group))
{
$rel .= ':' . addslashes($group);
}
$rel .= '"';
$attributes[] = $rel;
if (!empty($title))
{
$attributes[] = 'title="' . addslashes($title)
. '"';
}
break;
}
return implode(' ', $attributes);
}
/**
* Make an <a> tag
*
* @param string $href URL
* @param string $lbl Link text
* @param array $opts Link properties key = value
* @param bool $normalize if true, tweak scheme to match J! URI
*
* @since 3.1
*
* @return string <a> tag or empty string if not $href
*/
public static function a($href, $lbl = '', $opts = array(),
$normalize = false)
{
if (empty($href) || StringHelper::strtolower($href) ==
'http://' || StringHelper::strtolower($href) ==
'https://')
{
return '';
}
if (Worker::isEmail($href))
{
return '<a href="mailto:' . $href .
'">' . $lbl . '</a>';
}
if ($normalize)
{
$parsedUrl = parse_url(Uri::root());
if ($parsedUrl['scheme'] === 'https')
{
$href = str_ireplace('http://', 'https://', $href);
}
}
if (empty($lbl))
{
// If label is empty, set as a copy of the link
$lbl = $href;
}
$smart_link = ArrayHelper::getValue($opts, 'smart_link',
false);
$target = ArrayHelper::getValue($opts, 'target', false);
if ($smart_link || $target == 'mediabox')
{
$smarts = self::getSmartLinkType($href);
// Not sure that the type option is now needed.
$opts['rel'] = 'lightbox[' .
$smarts['type'] . ' ' . $smarts['width'] .
' ' . $smarts['height'] . ']';
}
unset($opts['smart_link']);
$a[] = '<a href="' . $href . '"';
foreach ($opts as $key => $value)
{
$a[] = ' ' . $key . '="' . trim($value) .
'"';
}
$a[] = '>' . $lbl . '</a>';
return implode('', $a);
}
/**
* Get an array containing info about the media link
*
* @param string $link to examine
*
* @return array width, height, type of link
*/
public static function getSmartLinkType($link)
{
/* $$$ hugh - not really sure how much of this is necessary, like setting
different widths
* and heights for different social video sites. I copied the numbers
from the examples page
* for mediabox: http://iaian7.com/webcode/mediaboxAdvanced
*/
$ret = array('width' => '800', 'height'
=> '600', 'type' => 'mediabox');
if (preg_match('#^http://([\w\.]+)/#', $link, $matches))
{
$site = $matches[1];
/*
* @TODO should probably make this a little more intelligent, like
optional www,
* and check for site specific spoor in the URL (like
'/videoplay' for google,
* '/photos' for flicker, etc).
*/
switch ($site)
{
case 'www.flickr.com':
$ret['width'] = '400';
$ret['height'] = '300';
$ret['type'] = 'social';
break;
case 'video.google.com':
$ret['width'] = '640';
$ret['height'] = '400';
$ret['type'] = 'social';
break;
case 'www.metacafe.com':
$ret['width'] = '400';
$ret['height'] = '350';
$ret['type'] = 'social';
break;
case 'vids.myspace.com':
$ret['width'] = '430';
$ret['height'] = '346';
$ret['type'] = 'social';
break;
case 'myspacetv.com':
$ret['width'] = '430';
$ret['height'] = '346';
$ret['type'] = 'social';
break;
case 'www.revver.com':
$ret['width'] = '480';
$ret['height'] = '392';
$ret['type'] = 'social';
break;
case 'www.seesmic.com':
$ret['width'] = '425';
$ret['height'] = '353';
$ret['type'] = 'social';
break;
case 'www.youtube.com':
$ret['width'] = '480';
$ret['height'] = '380';
$ret['type'] = 'social';
break;
case 'www.veoh.com':
$ret['width'] = '540';
$ret['height'] = '438';
$ret['type'] = 'social';
break;
case 'www.viddler.com':
$ret['width'] = '437';
$ret['height'] = '370';
$ret['type'] = 'social';
break;
case 'vimeo.com':
$ret['width'] = '400';
$ret['height'] = '302';
$ret['type'] = 'social';
break;
case '12seconds.tv':
$ret['width'] = '431';
$ret['height'] = '359';
$ret['type'] = 'social';
break;
}
if ($ret['type'] == 'mediabox')
{
$ext = StringHelper::strtolower(File::getExt($link));
switch ($ext)
{
case 'swf':
case 'flv':
case 'mp4':
$ret['width'] = '640';
$ret['height'] = '360';
$ret['type'] = 'flash';
break;
case 'mp3':
$ret['width'] = '400';
$ret['height'] = '20';
$ret['type'] = 'audio';
break;
}
}
}
return $ret;
}
public static function formvalidation()
{
// Only load once
if (isset(static::$loaded[__METHOD__]))
{
return;
}
// Add validate.js language strings
Text::script('JLIB_FORM_FIELD_INVALID');
// Include MooTools More framework
static::framework('more');
$debug =
Factory::getApplication()->getConfig()->get('debug');
HTMLHelper::_('script', 'system/fields/validate.js',
['version' => 'auto', 'relative' =>
true, 'detectDebug' => $debug]);
static::$loaded[__METHOD__] = true;
}
/**
* Get the element's LayoutInterface file
* Its actually an instance of LayoutFile which inverses the ordering
added include paths.
* In LayoutFile the addedPath takes precedence over the default paths,
which makes more sense!
*
* @param string $name Layout file name (eg. fabrik-element-label)
* @param array $paths Optional paths to add as includes
* @param array $options Layout options
*
* @return LayoutFile
*/
public static function getLayout($name, $paths = array(), $options =
array())
{
$defaultOptions = array(
'debug' => false,
'component' => 'com_fabrik',
'client' => 'site'
);
$options = array_merge($defaultOptions, $options);
$basePath = COM_FABRIK_FRONTEND . '/layouts';
$layout = new LayoutFile($name, $basePath, $options);
$layout->addIncludePaths(JPATH_SITE . '/layouts');
$layout->addIncludePaths(JPATH_THEMES . '/' .
Factory::getApplication()->getTemplate() . '/html/layouts');
$layout->addIncludePaths(JPATH_THEMES . '/' .
Factory::getApplication()->getTemplate() .
'/html/layouts/com_fabrik');
foreach ($paths as $path)
{
$layout->addIncludePath($path);
}
return $layout;
}
/**
* Render an icon using LayoutInterfaces
*
* @param string $icon Icon class name
* @param string $label Label
* @param string $properties Additional html properties
* @param bool $nameOnly Return just the icon name
*
* @return string
*/
public static function icon($icon, $label = '', $properties =
'', $nameOnly = false)
{
$icon = Html::getLayout('fabrik-icon')
->render((object) array(
'icon' => $icon,
'properties' => $properties,
'nameOnly' => $nameOnly
));
if ($label != '' && !$nameOnly)
{
$icon .= ' ' . $label;
}
return $icon;
}
/**
* Add the js jLayout objects for rendering the modal
*
* @return void
*/
public static function modalLayoutInterfaces()
{
Html::jLayoutJs('modal-close', 'modal.fabrik-close');
Html::jLayoutJs('icon-expand', 'fabrik-icon',
(object) array('icon' => 'icon-expand'));
Html::jLayoutJs('icon-full-screen', 'fabrik-icon',
(object) array('icon' => 'icon-out-2
icon-fullscreen'));
}
/**
* Get framework specific grid span class
*
* @param string $spanSize numeric span size
*
* @return void
*/
public static function getGridSpan($size, $viewport = 'medium')
{
static $spans;
$size = (int)$size;
if (!is_array($spans))
{
$spans = array();
}
if (!array_key_exists($viewport, $spans))
{
$spans[$viewport] = array();
}
if (!array_key_exists($size, $spans[$viewport]))
{
$layout =
self::getLayout('fabrik-grid-span');
$displayData = new stdClass;
$displayData->spanSize = $size;
$displayData->viewport = $viewport;
$spans[$viewport][$size] = $layout->render($displayData);
}
return $spans[$viewport][$size];
}
/**
* Load markup into DOMDocument, checking for entities.
*
* The loadXML() chokes if data has & in it. But we can't
htmlspecialchar() it, as that removes
* the HTML markup we're looking for. So we need to ONLY change
&'s which aren't already part of
* any HTML entities which may be in the data. So use a negative
lookahead regex, which finds & followed
* by anything except non-space the ;.
*
* It also chokes if the data already contains any HTML entities which XML
doesn't like, like é,
* so first we need to do an html_entity_decode() to get rid of those!
*
* @param string $html HTML to load
*
* @return \DOMDocument
*/
public static function loadDOMDocument($html)
{
// libxml_use_internal_errors won't supress the empty string
warning, so ...
if (empty($html))
{
$html = '<span></span>';
}
// suppress output of warnings about DOM structure
$previous = libxml_use_internal_errors(true);
$doc = new \DOMDocument;
$html = html_entity_decode($html);
$html = preg_replace('/&(?!\S+;)/',
'&', $html);
$doc->loadXML($html);
libxml_clear_errors();
libxml_use_internal_errors($previous);
return $doc;
}
}
fabrik/fabrik/Helpers/Image.php000064400000006457151165341600012413
0ustar00<?php
/**
* Image manipulation helper
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use \RuntimeException;
/**
* Image manipulation class
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
* @since 1.0
*/
class Image
{
/**
* Get an array of available graphics libraries
*
* @return array
*/
public static function getLibs()
{
$libs = array();
$gds = self::testGD();
foreach ($gds as $key => $val)
{
$libs[] = HTMLHelper::_('select.option', $key, $val);
}
$im = self::testImagemagick();
foreach ($im as $key => $val)
{
$libs[] = HTMLHelper::_('select.option', $key, $val);
}
return $libs;
}
/**
* load in the correct image library
*
* @param string $lib image lib to load
*
* @throws RuntimeException
*
* @return \Fabrik\Helpers\Image\Image image lib
*/
public static function loadLib($lib)
{
if ($lib === 'value')
{
throw new RuntimeException("Fabrik: No image image processing
library is available, make sure GD is installed in PHP and check your
upload element settings!");
}
$className = '\Fabrik\Helpers\Image\Image' . strtolower($lib);
try {
$class = new $className;
}
catch (RuntimeException $e)
{
throw new RuntimeException("Fabrik: can't load image class:
$className");
}
return $class;
}
/**
* Test if the GD library is available
*
* @return array
*/
protected static function testGD()
{
$gd = array();
$gdVersion = null;
$gdInfo = null;
if (function_exists('gd_info'))
{
$gdInfo = gd_info();
$gdVersion = $gdInfo['GD Version'];
}
else
{
ob_start();
@phpinfo(INFO_MODULES);
$output = ob_get_contents();
ob_end_clean();
$matches[1] = '';
if ($output !== '')
{
if (preg_match("/GD Version[ \t]*(<[^>]+>[
\t]*)+([^<>]+)/s", $output, $matches))
{
$gdVersion = $matches[2];
}
else
{
return $gd;
}
}
}
if (function_exists('imagecreatetruecolor') &&
function_exists('imagecreatefromjpeg'))
{
$gdVersion = isset($gdVersion) ? $gdVersion : 2;
$gd['gd2'] = "GD: " . $gdVersion;
}
elseif (function_exists('imagecreatefromjpeg'))
{
$gdVersion = isset($gdVersion) ? $gdVersion : 1;
$gd['gd1'] = "GD: " . $gdVersion;
}
return $gd;
}
/**
* Test if Imagemagick is installed on the server
*
* @return array
*/
protected static function testImagemagick()
{
$im = array();
if (function_exists('NewMagickWand'))
{
$im['IM'] = 'Magick wand';
}
else
{
/*
$status = '';
$output = array();
@exec('convert -version', $output, $status);
$im = array();
if ($status && class_exists('Imagick'))
{
if (preg_match("/imagemagick[ \t]+([0-9\.]+)/i", $output[0],
$matches))
{
$im['IM'] = $matches[0];
}
}
unset($output, $status);
*/
if (class_exists('Imagick'))
{
$im['IM'] = 'Imagick';
}
}
return $im;
}
}
fabrik/fabrik/Helpers/Image/Image.php000064400000017004151165341610013424
0ustar00<?php
/**
* @package Joomla
* @subpackage Fabrik.image
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers\Image;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Folder;
use Fabrik\Helpers\ArrayHelper;
use Fabrik\Helpers\StringHelper;
/**
* Base image manipulation class
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005 Fabrik. All rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
* @since 1.0
*/
class Image
{
/**
* Thumbnail image path
*
* @var string
*/
protected $thumbPath = null;
/**
* Storage class file/amazons3 etc.
*
* @var object
*/
public $storage = null;
/**
* Set the filesystem storage manager
*
* @param object &$storage storage object
*
* @return void
*/
public function setStorage(&$storage)
{
$this->storage = $storage;
}
/**
* Get the image type git/jpg/png
*
* @param string $filename image file path
*
* @return string
*/
public function getImgType($filename)
{
$info = getimagesize($filename);
switch ($info[2])
{
case 1:
return 'gif';
break;
case 2:
return 'jpg';
break;
case 3:
return 'png';
break;
default:
$pathInfo = pathInfo($filename);
if (ArrayHelper::getValue($pathInfo, 'extension',
'') === 'pdf')
{
return 'pdf';
};
return false;
break;
}
}
/**
* Resize an image to a specific width/height
*
* @param int $maxWidth maximum image Width (px)
* @param int $maxHeight maximum image Height (px)
* @param string $origFile current images folder path (must have
trailing end slash)
* @param string $destFile destination folder path for resized image
(must have trailing end slash)
* @param int $quality Percentage image save quality 100 = no
compression, 0 = max compression
*
* @return object image
*/
public function resize($maxWidth, $maxHeight, $origFile, $destFile,
$quality = 100)
{
}
/**
* Grab an image from a remote URI and store in cache, then serve cached
image
*
* @param string $src Remote URI to image
* @param string $path Local folder to store the image in e.g.
'cache/com_fabrik/images'
* @param string $file Local filename
* @param integer $lifeTime Number of days to cache the image for
*
* @return boolean|string Local URI to cached image
*/
public static function cacheRemote($src, $path, $file, $lifeTime = 29)
{
/**
* $$$ @FIXME we may need to find something other than
file_get_contents($src)
* to use for this, as it requires allow_url_fopen to be enabled in PHP
to fetch a URL,
* which a lot of shared hosts don't allow.
*
* -Rob - well File::read is deprecated and in the code it says to use
file_get_contents
* The Joomla updater won't work with out file_get_contents so I
think we should make it a requirement
* Wiki updated here -
http://fabrikar.com/forums/index.php?wiki/prerequisites/
*
* hugh - Okie Dokie.
*/
/**
* $$$ @FIXME - hugh - as we're producing files with names like:
*
*
center=34.732267,-86.587593.zoom=10.size=300x250.maptype=roadmap.mobile=true.markers=34.732267,-86.587593.sensor=false.png
*
* ... we should probably clean $file, replace non alphanumeric chars
with
* underscores, as filenames with things like commas, = signs etc. could
be problematic, both in
* the file system, and on the IMG URL.
*
* EDIT - hopefully just md5()'ing the file should fix the above,
needed to do it as we finally had
* someone report a problem with invalid file name, see ...
*
* https://github.com/Fabrik/fabrik/pull/1307
*
* So ... just preserve original extension (if any) and append it to
md5() of file name.
*/
$ext = pathinfo($file, PATHINFO_EXTENSION);
$file = md5($file);
if (!empty($ext))
{
$file .= '.' . $ext;
}
$folder = JPATH_SITE . '/' . ltrim($path, '/');
// For SSL a user agent may need to be set.
ini_set('user_agent', 'Mozilla/4.0 (compatible; MSIE
6.0)');
if (!Folder::exists($folder))
{
Folder::create($folder);
}
// make sure we have one, and only one, / on the end of folder. Really
should add a helper for this which looks for legacy \ as well!
$folder = rtrim($folder, '/') . '/';
$cacheFile = $folder . $file;
// result to test file_put_contents() with
$res = false;
// Check for cached version
if (File::exists($cacheFile))
{
// Check its age- Google T&C allow you to store for no more than 30
days.
$createDate = Factory::getDate(filemtime($cacheFile));
$now = Factory::getDate();
$interval = $now->diff($createDate);
$daysOld = (float) $interval->format('%R%a');
if ($daysOld < -$lifeTime)
{
// Remove out of date
File::delete($cacheFile);
// Grab image from Google and store
$res = file_put_contents($cacheFile, file_get_contents($src));
}
else
{
$res = true;
}
}
else
{
// No cached image, grab image from remote URI and store locally
$res = file_put_contents($cacheFile, file_get_contents($src));
}
if ($res === false)
{
$src = false;
}
else
{
$src = COM_FABRIK_LIVESITE . $path . $file;
}
return $src;
}
/**
* Exif to number
*
* @param string $value Value
* @param string $format Format
*
* @return string
*/
public static function exifToNumber($value, $format)
{
$pos = StringHelper::strpos($value, '/');
if ($pos === false)
{
return sprintf($format, $value);
}
else
{
$bits = explode('/', $value, 2);
$base = ArrayHelper::getValue($bits, 0);
$divider = ArrayHelper::getValue($bits, 1);
return ($divider == 0) ? sprintf($format, 0) : sprintf($format, ($base /
$divider));
}
}
/**
* Exif to coordinate
*
* @param string $reference Reference
* @param string $coordinate Coordinates
*
* @return string
*/
public static function exifToCoordinate($reference, $coordinate)
{
$prefix = ($reference == 'S' || $reference == 'W') ?
'-' : '';
return $prefix
. sprintf('%.6F',
self::exifToNumber($coordinate[0], '%.6F') +
(((self::exifToNumber($coordinate[1], '%.6F') * 60) +
(self::exifToNumber($coordinate[2], '%.6F'))) / 3600)
);
}
/**
* Get coordinates
*
* @param string $filename File name
*
* @return array|boolean
*/
public static function getExifCoordinates($filename)
{
if (extension_loaded('exif'))
{
$exif = exif_read_data($filename, 'EXIF');
if (isset($exif['GPSLatitudeRef']) &&
isset($exif['GPSLatitude']) &&
isset($exif['GPSLongitudeRef']) &&
isset($exif['GPSLongitude']))
{
return array(self::exifToCoordinate($exif['GPSLatitudeRef'],
$exif['GPSLatitude']),
self::exifToCoordinate($exif['GPSLongitudeRef'],
$exif['GPSLongitude']));
}
}
return false;
}
/**
* Set coordinates to DMS
*
* @param string $coordinate Image coordinate
* @param number $pos Position
* @param number $neg Negative
*
* @return string
*/
public static function coordinate2DMS($coordinate, $pos, $neg)
{
$sign = $coordinate >= 0 ? $pos : $neg;
$coordinate = abs($coordinate);
$degree = intval($coordinate);
$coordinate = ($coordinate - $degree) * 60;
$minute = intval($coordinate);
$second = ($coordinate - $minute) * 60;
return sprintf("%s %d° %02d′
%05.2f″", $sign, $degree, $minute, $second);
}
}
fabrik/fabrik/Helpers/Image/Imagegd.php000064400000025077151165341610013750
0ustar00<?php
/**
* @package Joomla
* @subpackage Fabrik.image
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers\Image;
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Filesystem\File;
use Fabrik\Helpers\StringHelper;
/**
* GD image manipulation class
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
* @since 1.0
*/
class Imagegd extends Image
{
/**
* Create an image object from a file path
*
* @param string $file file to create image from
*
* @throws \Exception
*
* @return array (image, header string)
*/
public function imageFromFile($file)
{
$fromFile = $this->storage->preRenderPath($file);
// Load image
$img = null;
$ext = $this->getImgType($fromFile);
if (!$ext)
{
return array(false, false);
}
ini_set('display_errors', true);
$memory = \FabrikWorker::getMemoryLimit(true);
$intMemory = \FabrikWorker::getMemoryLimit();
if ($intMemory < (64 * 1024 * 1024))
{
ini_set('memory_limit', '50M');
}
if ($ext == 'jpg' || $ext == 'jpeg')
{
$img = @imagecreatefromjpeg($fromFile);
$header = "image/jpeg";
}
elseif ($ext == 'png')
{
$img = @imagecreatefrompng($fromFile);
$header = "image/png";
// Only if your version of GD includes GIF support
}
elseif ($ext == 'gif')
{
if (function_exists('imagecreatefromgif'))
{
$img = @imagecreatefromgif($fromFile);
$header = "image/gif";
}
else
{
throw new \Exception("imagecreate from gif not available");
}
}
if ($intMemory < (64 * 1024 * 1024))
{
ini_set('memory_limit', $memory);
}
return array($img, $header);
}
/**
* Create a gd image from a file
*
* @param string $source path to file
*
* @return image
*/
protected function imageCreateFrom($source)
{
$ext = StringHelper::strtolower(File::getExt($source));
switch ($ext)
{
case 'jpg':
case 'jpeg':
$source = imagecreatefromjpeg($source);
break;
case 'png':
$source = imagecreatefrompng($source);
break;
case 'gif':
$source = imagecreatefromgif($source);
break;
}
return $source;
}
/**
* Convert an image object into a file
*
* @param string $destCropFile file path
* @param object $image image object to save
*
* @return bool True on success
*/
public function imageToFile($destCropFile, $image)
{
$ext = StringHelper::strtolower(File::getExt($destCropFile));
ob_start();
switch ($ext)
{
case 'jpg':
case 'jpeg':
$source = imagejpeg($image, null, 100);
break;
case 'png':
$source = imagepng($image, null);
break;
case 'gif':
$source = imagegif($image, null);
break;
}
$image_p = ob_get_contents();
ob_end_clean();
return $this->storage->write($destCropFile, $image_p);
}
/**
* Rotate an image
*
* @param string $source filepath
* @param string $dest output path, if empty defaults to source
* @param int $degrees number of degrees to rotate
*
* @return array (image object, rotated images width, rotated images
height)
*/
public function rotate($source, $dest = '', $degrees = 0)
{
if (empty($dest))
{
$dest = $source;
}
$source = $this->imageCreateFrom($source);
$app = Factory::getApplication();
// Rotates the image
$rotate = imagerotate($source, $degrees, 0);
if ($rotate === false)
{
$app->enqueueMessage('Image rotation failed',
'notice');
}
$this->imageToFile($dest, $rotate);
list($width, $height) = getimagesize($dest);
return array($rotate, $width, $height);
}
/*
* Check for EXIF orientation data, and rotate image accordingly
*
* @param string path to image file
*/
public function rotateImageFromExif($src, $dest)
{
if (function_exists('exif_read_data'))
{
$exif = exif_read_data($src);
if ($exif && isset($exif['Orientation']))
{
$orientation = $exif['Orientation'];
if ($orientation != 1)
{
$deg = 0;
switch ($orientation)
{
case 3:
$deg = 180;
break;
case 6:
$deg = 270;
break;
case 8:
$deg = 90;
break;
}
if ($deg)
{
self::rotate($src, $dest, $deg);
}
}
}
}
}
/**
* Scale an image
*
* @param string $file file to scale
* @param string $dest save location
* @param int $percentage scale percentage
* @param int $destX start scale from x coord
* @param int $destY start scale from y coord
*
* @return object image
*/
public function scale($file, $dest = '', $percentage = 100,
$destX = 0, $destY = 0)
{
list($image, $header) = $this->imageFromFile($file);
jimport('joomla.filesystem.file');
list($width, $height) = getimagesize($file);
$new_width = $width * ((float) $percentage / 100);
$new_height = $height * ((float) $percentage / 100);
$image_p = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($image_p, $image, $destX, $destY, 0, 0, $new_width,
$new_height, $width, $height);
if ($dest != '')
{
$this->imageToFile($dest, $image_p);
}
return $image_p;
}
/**
* Resize an image to a specific width/height
*
* @param int $maxWidth maximum image Width (px)
* @param int $maxHeight maximum image Height (px)
* @param string $origFile current images folder path (must have
trailing end slash)
* @param string $destFile destination folder path for resized image
(must have trailing end slash)
* @param int $quality Percentage image save quality 100 = no
compression, 0 = max compression
*
* @throws Error
*
* @return object image
*/
public function resize($maxWidth, $maxHeight, $origFile, $destFile,
$quality = 100)
{
// Check if the file exists
if (!$this->storage->exists($origFile))
{
throw new RuntimeException("Fabrik: no file found for
$origFile");
}
// Load image
list($img, $header) = $this->imageFromFile($origFile);
if (!$img)
{
return $img;
}
$ext = StringHelper::strtolower(end(explode('.', $origFile)));
// If an image was successfully loaded, test the image for size
if ($img)
{
// Handle image transparency for original image
if (function_exists('imagealphablending'))
{
imagealphablending($img, false);
imagesavealpha($img, true);
}
// Get image size and scale ratio
$width = imagesx($img);
$height = imagesy($img);
$scale = min($maxWidth / $width, $maxHeight / $height);
// If the image is larger than the max shrink it
if ($scale < 1)
{
$new_width = floor($scale * $width);
$new_height = floor($scale * $height);
// Create a new temporary image
$tmp_img = imagecreatetruecolor($new_width, $new_height);
// Handle image transparency for resized image
if (function_exists('imagealphablending'))
{
imagealphablending($tmp_img, false);
imagesavealpha($tmp_img, true);
}
// Copy and resize old image into new image
imagecopyresampled($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height,
$width, $height);
imagedestroy($img);
$img = $tmp_img;
}
}
// Create error image if necessary
if (!$img)
{
throw new Error("resize: no image created for $origFile, extension
= $ext, destination = $destFile");
}
// Save the file
$this->writeImg($img, $destFile, $header, $quality);
$this->thumbPath = $destFile;
}
/**
* Crop an image to specific dimensions
*
* @param string $origFile path to image to crop from
* @param string $destFile path to cropped file
* @param int $srcX x coord on $origFile to start crop from
* @param int $srcY y coord on $origFile to start crop from
* @param int $dstW cropped image width
* @param int $dstH cropped image height
* @param int $dstX destination x coord of destination point
* @param int $dstY destination y coord of destination point
* @param string $bg hex background colour
*
* @return void
*/
public function crop($origFile, $destFile, $srcX, $srcY, $dstW, $dstH,
$dstX = 0, $dstY = 0, $bg = '#FFFFFF')
{
// Convert hex to rgb colours.
list($r, $g, $b) = sscanf($bg, '#%2x%2x%2x');
list($origImg, $header) = $this->imageFromFile($origFile);
$destImg = imagecreatetruecolor($dstW, $dstH);
$bg = imagecolorallocate($destImg, $r, $g, $b);
// Draw a bg rectangle
imagefilledrectangle($destImg, 0, 0, (int) $dstW, (int) $dstH, $bg);
$this->writeImg($destImg, $destFile, $header);
$srcW = imagesx($destImg);
$srcH = imagesy($destImg);
$origW = imagesx($origImg);
$origH = imagesy($origImg);
// If the orig image is smaller than the destination then increase its
canvas and fill it with the bg
if ($origW < $srcW || $origH < $srcH)
{
$srcBg = imagecreatetruecolor($srcW, $srcH);
imagefilledrectangle($srcBg, 0, 0, (int) $srcW, (int) $srcH, $bg);
imagecopyresampled($srcBg, $origImg, 0, 0, 0, 0, $origW, $origH, $origW,
$origH);
$origImg = $srcBg;
}
imagecopyresampled($destImg, $origImg, $dstX, $dstY, $srcX, $srcY, $dstW,
$dstH, $srcW, $srcH);
$this->writeImg($destImg, $destFile, $header);
}
/**
* Write an image to the server
*
* @param object $img image object
* @param string $destFile file path to save to
* @param string $header image type
* @param int $quality Percentage image save quality 100 = no
compression, 0 = max compression
*
* @throws Error
*
* @return void
*/
public function writeImg($img, $destFile, $header, $quality = 100)
{
if ($quality < 0)
{
$quality = 0;
}
if ($quality > 100)
{
$quality = 100;
}
if ($header == "image/jpeg")
{
ob_start();
imagejpeg($img, null, $quality);
$image = ob_get_contents();
ob_end_clean();
$this->storage->write($destFile, $image);
}
else
{
if ($header == "image/png")
{
$quality = round((100 - $quality) * 9 / 100);
ob_start();
imagepng($img, null, $quality);
$image = ob_get_contents();
ob_end_clean();
$this->storage->write($destFile, $image);
}
else
{
if (function_exists("imagegif"))
{
ob_start();
imagegif($img, null, $quality);
$image = ob_get_contents();
ob_end_clean();
$this->storage->write($destFile, $image);
}
else
{
throw new Error('trying to save a gif by imagegif support not
present in the GD library');
}
}
}
}
}
fabrik/fabrik/Helpers/Image/Imagegd2.php000064400000011034151165341610014016
0ustar00<?php
/**
* @package Joomla
* @subpackage Fabrik.image
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers\Image;
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Filesystem\File;
use \RuntimeException;
use Fabrik\Helpers\StringHelper;
/**
* GD2 image manipulation class
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
* @since 1.0
*/
class Imagegd2 extends Imagegd
{
/**
* Resize an image to a specific width/height
*
* @param int $maxWidth maximum image Width (px)
* @param int $maxHeight maximum image Height (px)
* @param string $origFile current images folder path (must have
trailing end slash)
* @param string $destFile destination folder path for resized image
(must have trailing end slash)
* @param int $quality Percentage image save quality 100 = no
compression, 0 = max compression
*
* @return object image
*/
public function resize($maxWidth, $maxHeight, $origFile, $destFile,
$quality = 100)
{
$app = Factory::getApplication();
// Check if the file exists
if (!$this->storage->exists($origFile))
{
throw new RuntimeException("no file found for $origFile");
}
$fromFile = $this->storage->preRenderPath($origFile);
// Load image
$img = null;
$ext = $this->getImgType($fromFile);
if (!$ext)
{
return;
}
ini_set('display_errors', true);
$memory = \FabrikWorker::getMemoryLimit(true);
$intMemory = \FabrikWorker::getMemoryLimit();
if ($intMemory < (64 * 1024 * 1024))
{
ini_set('memory_limit', '50M');
}
if ($ext == 'jpg' || $ext == 'jpeg')
{
$img = @imagecreatefromjpeg($fromFile);
$header = "image/jpeg";
}
elseif ($ext == 'png')
{
$img = @imagecreatefrompng($fromFile);
$header = "image/png";
// Only if your version of GD includes GIF support
}
elseif ($ext == 'gif')
{
if (function_exists('imagecreatefromgif'))
{
$img = @imagecreatefromgif($fromFile);
$header = "image/gif";
}
else
{
$app->enqueueMessage("imagecreate from gif not
available");
}
}
// If an image was successfully loaded, test the image for size
if ($img)
{
// Handle image transparency for original image
if (function_exists('imagealphablending'))
{
imagealphablending($img, false);
imagesavealpha($img, true);
}
// Get image size and scale ratio
$width = imagesx($img);
$height = imagesy($img);
$scale = min($maxWidth / $width, $maxHeight / $height);
// If the image is larger than the max shrink it
if ($scale < 1)
{
$new_width = floor($scale * $width);
$new_height = floor($scale * $height);
// Create a new temporary image
$tmp_img = imagecreatetruecolor($new_width, $new_height);
// Handle image transparency for resized image
if (function_exists('imagealphablending'))
{
imagealphablending($tmp_img, false);
imagesavealpha($tmp_img, true);
}
// Copy and resize old image into new image
imagecopyresampled($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height,
$width, $height);
imagedestroy($img);
$img = $tmp_img;
}
}
if (!$img)
{
$app->enqueueMessage("no image created for $origFile, extension
= $ext , destination = $destFile ");
}
/* save the file
* write them out to output buffer first so that we can use File to write
them
to the server (potential using J ftp layer) */
if ($header == "image/jpeg")
{
ob_start();
imagejpeg($img, null, $quality);
$image = ob_get_contents();
ob_end_clean();
$this->storage->write($destFile, $image);
}
else
{
if ($header == "image/png")
{
ob_start();
$quality = round((100 - $quality) * 9 / 100);
imagepng($img, null, $quality);
$image = ob_get_contents();
ob_end_clean();
$this->storage->write($destFile, $image);
}
else
{
if (function_exists("imagegif"))
{
ob_start();
imagegif($img, null, $quality);
$image = ob_get_contents();
ob_end_clean();
$this->storage->write($destFile, $image);
}
else
{
$app->enqueueMessage("GD gif support not available: could not
resize image");
}
}
}
$this->thumbPath = $destFile;
if ($intMemory < (64 * 1024 * 1024))
{
ini_set('memory_limit', $memory);
}
}
}
fabrik/fabrik/Helpers/Image/Imageim.php000064400000012301151165341610013745
0ustar00<?php
/**
* @package Joomla
* @subpackage Fabrik.image
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers\Image;
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use \Fabrik\Helpers\StringHelper;
use \NewMagickWand;
/**
* Image magic image manipulation class
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
* @since 1.0
*/
class Imageim extends Image
{
/**
* Resize an image to a specific width/height
*
* @param int $maxWidth maximum image Width (px)
* @param int $maxHeight maximum image Height (px)
* @param string $origFile current images folder path (must have
trailing end slash)
* @param string $destFile destination folder path for resized image
(must have trailing end slash)
* @param int $quality Percentage image save quality 100 = no
compression, 0 = max compression
*
* @return object image
*/
public function resize($maxWidth, $maxHeight, $origFile, $destFile,
$quality = 100)
{
// Check if the file exists
if (!$this->storage->exists($origFile))
{
throw new RuntimeException("no file found for $origFile");
}
$fromFile = $this->storage->preRenderPath($origFile);
$ext = $this->getImgType($fromFile);
if (!$ext)
{
// False so not an image type so cant resize
// $$$ hugh - testing making thumbs for PDF's, so need a little
tweak here
$origInfo = pathinfo($fromFile);
if (StringHelper::strtolower($origInfo['extension']) !=
'pdf')
{
return;
}
}
ini_set('display_errors', true);
// See if the imagick image lib is installed
if (class_exists('Imagick'))
{
/* $$$ hugh - having a go at handling PDF thumbnails, which should work
as long as the server
* has ghostscript (GS) installed. Don't have a generic test for
GS being available, so
* it'll just fail if no GS.
*/
$origInfo = pathinfo($fromFile);
if (StringHelper::strtolower($origInfo['extension']) ==
'pdf')
{
$pdfThumbType = 'png';
// OK, it's a PDF, so first we need to add the page number we want
to the source filename
$pdfFile = $fromFile . '[0]';
/*
if (is_callable('exec'))
{
$destFile = str_replace('.pdf', '.png',
$destFile); // Output File
$convert = "convert " . $pdfFile . " -colorspace
RGB -resize " . $maxWidth . " " . $destFile; // Command
creating
exec($convert); // Execution of complete command.
}
else
{
*/
// Now just load it, set format, resize, save and garbage collect.
// Hopefully IM will call the right delegate (ghostscript) to load the
PDF.
$im = new \Imagick($pdfFile);
$im->setImageFormat($pdfThumbType);
$im->thumbnailImage($maxWidth, $maxHeight, true);
$im->writeImage($destFile);
// as destroy() is deprecated
$im->clear();
/*
}
*/
}
else
{
$im = new \Imagick;
/* Read the image file */
$im->readImage($fromFile);
/* Thumbnail the image ( width 100, preserve dimensions ) */
$im->thumbnailImage($maxWidth, $maxHeight, true);
/* Write the thumbnail to disk */
$im->writeImage($destFile);
/* Free resources associated to the Imagick object */
$im->destroy();
}
$this->thumbPath = $destFile;
}
else
{
$resource = NewMagickWand();
if (!MagickReadImage($resource, $fromFile))
{
echo "ERROR!";
print_r(MagickGetException($resource));
}
$resource = MagickTransformImage($resource, '0x0',
$maxWidth . 'x' . $maxWidth);
$this->thumbPath = $destFile;
MagickWriteImage($resource, $destFile);
}
}
/*
* Check for EXIF orientation data, and rotate image accordingly
*
* @param string path to image file
*/
public function rotateImageFromExif($src, $dest)
{
if (function_exists('exif_read_data'))
{
$exif = exif_read_data($src);
if ($exif && isset($exif['Orientation']))
{
$orientation = $exif['Orientation'];
if ($orientation != 1)
{
$deg = 0;
switch ($orientation)
{
case 3:
$deg = 180;
break;
case 6:
$deg = 270;
break;
case 8:
$deg = 90;
break;
}
if ($deg)
{
self::rotate($src, $dest, $deg);
}
}
}
}
}
/**
* Rotate an image
*
* @param string $source filepath
* @param string $dest output path, if empty defaults to source
* @param int $degrees number of degrees to rotate
*
* @return array (image object, rotated images width, rotated images
height)
*/
public function rotate($source, $dest = '', $degrees = 0)
{
if (empty($dest))
{
$dest = $source;
}
$source = $this->imageCreateFrom($source);
$app = Factory::getApplication();
// Rotates the image
$rotate = imagerotate($source, $degrees, 0);
if ($rotate === false)
{
$app->enqueueMessage('Image rotation failed',
'notice');
}
$this->imageToFile($dest, $rotate);
list($width, $height) = getimagesize($dest);
return array($rotate, $width, $height);
}
}
fabrik/fabrik/Helpers/LayoutFile.php000064400000005661151165341610013443
0ustar00<?php
/**
* @package Joomla.Libraries
* @subpackage Layout
*
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Fabrik\Helpers;
use Joomla\CMS\Filesystem\Path;
use Joomla\CMS\Layout\FileLayout;
defined('JPATH_BASE') or die;
/**
* Base class for rendering a display layout
* loaded from from a layout file
*
* @package Joomla.Libraries
* @subpackage Layout
* @see
http://docs.joomla.org/Sharing_layouts_across_views_or_extensions_with_JLayout
* @since 3.0
*/
class LayoutFile extends FileLayout
{
/**
* Method to finds the full real file path, checking possible overrides
*
* @return string The full path to the layout file
*
* @since 3.0
*/
protected function getPath()
{
\JLoader::import('joomla.filesystem.path');
$layoutId = $this->getLayoutId();
$includePaths = $this->getIncludePaths();
$suffixes = $this->getSuffixes();
$this->addDebugMessage('<strong>Layout:</strong>
' . $this->layoutId);
if (!$layoutId)
{
$this->addDebugMessage('<strong>There is no active
layout</strong>');
return;
}
if (!$includePaths)
{
$this->addDebugMessage('<strong>There are no folders to
search for layouts:</strong> ' . $layoutId);
return;
}
$hash = md5(
json_encode(
array(
'paths' => $includePaths,
'suffixes' => $suffixes,
)
)
);
if (isset(static::$cache[$layoutId][$hash]))
{
$this->addDebugMessage('<strong>Cached
path:</strong> ' . static::$cache[$layoutId][$hash]);
return static::$cache[$layoutId][$hash];
}
$this->addDebugMessage('<strong>Include
Paths:</strong> ' . print_r($includePaths, true));
// Search for suffixed versions. Example: tags.j31.php
if ($suffixes)
{
$this->addDebugMessage('<strong>Suffixes:</strong>
' . print_r($suffixes, true));
foreach ($suffixes as $suffix)
{
$rawPath = str_replace('.', '/',
$this->layoutId) . '.' . $suffix . '.php';
$this->addDebugMessage('<strong>Searching layout
for:</strong> ' . $rawPath);
if ($foundLayout = Path::find($this->includePaths, $rawPath))
{
$this->addDebugMessage('<strong>Found
layout:</strong> ' . $this->fullPath);
static::$cache[$layoutId][$hash] = $foundLayout;
return static::$cache[$layoutId][$hash];
}
}
}
// Standard version
$rawPath = str_replace('.', '/', $this->layoutId)
. '.php';
$this->addDebugMessage('<strong>Searching layout
for:</strong> ' . $rawPath);
$foundLayout = Path::find($this->includePaths, $rawPath);
if (!$foundLayout)
{
$this->addDebugMessage('<strong>Unable to find layout:
</strong> ' . $layoutId);
static::$cache[$layoutId][$hash] = '';
return;
}
$this->addDebugMessage('<strong>Found
layout:</strong> ' . $foundLayout);
static::$cache[$layoutId][$hash] = $foundLayout;
return static::$cache[$layoutId][$hash];
}
}
fabrik/fabrik/Helpers/LogHelper.php000064400000010440151165341610013236
0ustar00<?php
/**
* @package Fabrik\Helpers
* @subpackage
*
* @copyright A copyright
* @license A "Slug" license name e.g. GPL2
*/
namespace Fabrik\Helpers;
defined('_JEXEC') or die;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Factory;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Session\Session;
use Joomla\CMS\User\User;
use Joomla\Utilities\ArrayHelper;
use GuzzleHttp\Client;
/**
* Helper for the log form plugin. Used when needing to log changes to
data outside of a
* form submission.
*
* Call ...
*
* \Fabrik\Helpers\LogHelper::setOrigData($formId, $rowId);
*
* ... before changing the data for a row, and ...
*
* \Fabrik\Helpers\LogHelper::logRowChange($formId, $rowId);
*
* ... after changing data. Will get settings from log plugin on that
formid, and
* log accordingly.
*/
class LogHelper
{
private static $init = null;
/**
* @var null JConfig
* @since version
*/
private static $config = null;
/**
* @var User
* @since version
*/
private static $user = null;
/**
* @var CMSApplication
* @since version
*/
private static $app = null;
private static $lang = null;
private static $date = null;
/**
* @var Session
* @since version
*/
private static $session = null;
private static $formModel = null;
private static $origData = [];
public static function __initStatic($config = array())
{
if (!isset(self::$init))
{
self::$config = ArrayHelper::getValue($config, 'config',
Factory::getApplication()->getConfig());
self::$user = ArrayHelper::getValue($config, 'user',
Factory::getUser());
self::$app = ArrayHelper::getValue($config, 'app',
Factory::getApplication());
self::$lang = ArrayHelper::getValue($config, 'lang',
Factory::getApplication()->getLanguage());
self::$date = ArrayHelper::getValue($config, 'date',
Factory::getDate());
self::$session = ArrayHelper::getValue($config, 'session',
Factory::getSession());
self::$formModel = ArrayHelper::getValue($config, 'formModel',
null);
self::$init = true;
}
}
/**
* @param $formId
*
* @return \FabrikFEModelForm
*
* @since version
*/
private static function getFormModel($formId, $rowId)
{
Table::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_fabrik/tables');
BaseDatabaseModel::addIncludePath(COM_FABRIK_FRONTEND .
'/models', 'FabrikFEModel');
/** @var \FabrikFEModelForm $formModel */
$formModel =
Factory::getApplication()->bootComponent('com_fabrik')->getMVCFactory()->createModel('Form',
'FabrikFEModel');
$formModel->setId($formId);
$formModel->setRowId($rowId);
$formModel->origRowId = $rowId;
$formModel->unsetData();
$formModel->_origData = self::getOrigData($formId, $rowId);
self::$app->input->set('rowid', $rowId);
return $formModel;
}
/**
* @param $formModel \FabrikFEModelForm
*
*
* @since version
*/
private static function getLogPlugin($formModel)
{
$pluginManager =
Factory::getApplication()->bootComponent('com_fabrik')->getMVCFactory()->createModel('Pluginmanager',
'FabrikFEModel');
$params = $formModel->getParams();
$logPlugin = $pluginManager->getPlugin('log',
'form');
$plugins = $params->get('plugins');
foreach ($plugins as $c => $type)
{
if ($type === 'log')
{
$logPlugin->setModel($formModel);
$logPlugin->setParams($params, $c);
}
}
return $logPlugin;
}
private static function getOrigData($formId, $rowId)
{
if (array_key_exists($formId, self::$origData))
{
if (array_key_exists($rowId, self::$origData[$formId]))
{
return self::$origData[$formId][$rowId];
}
}
return null;
}
public static function setOrigData($formId, $rowId)
{
if (!array_key_exists($formId, self::$origData))
{
self::$origData[$formId] = [];
}
if (!array_key_exists($rowId, self::$origData[$formId]))
{
$formModel = self::getFormModel($formId, $rowId);
self::$origData[$formId][$rowId] = $formModel->getOrigData();
//$logPlugin = self::getLogPlugin($formModel);
//$logPlugin->onBeforeProcess();
}
}
public static function logRowChange($formId, $rowId)
{
$formModel = self::getFormModel($formId, $rowId);
$logPlugin = self::getLogPlugin($formModel);
$logPlugin->setOrigData(self::getOrigData($formId, $rowId));
$logPlugin->onAfterProcess();
}
}
fabrik/fabrik/Helpers/Pagination.php000064400000031522151165341610013452
0ustar00<?php
/**
* Makes the list navigation html to traverse the list data
*
* @package Joomla
* @subpackage Fabrik
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Layout\LayoutInterface;
use Joomla\CMS\Version;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Pagination\PaginationObject;
use Joomla\CMS\Language\Text;
use \stdClass;
/**
* Makes the list navigation html to traverse the list data
*
* @param int the total number of records in the table
* @param int number of records to show per page
* @param int which record number to start at
*/
jimport('joomla.html.pagination');
class FabrikPaginationObject extends
\Joomla\CMS\Pagination\PaginationObject {
public $key = null;
}
/**
* Extension to the normal page-nav functions
* $total, $limitstart, $limit
*
* @package Fabrik
* @since 3.0
*/
class Pagination extends \Joomla\CMS\Pagination\Pagination
{
/**
* Action url
*
* @var string
*/
public $url = '';
/**
* Pagination ID
*
* @var string
*/
protected $id = '';
/**
* Show the total number of records found
*
* @var bool
*/
public $showTotal = false;
/**
* Add an 'all' option to the display # dropdown
*
* @var bool
*/
public $showAllOption = false;
/**
* The lists unique reference
*
* @var string
*/
protected $listRef = null;
/**
* Show 'x of y pages'
*
* @var bool
*/
public $showDisplayNum = true;
/**
* Add a 'show all' option to display # select list
*
* @var bool
*/
public $viewAll = false;
/* dynamic properties to make php8.2 happy */
public $showNav = null;
public $startLimit = null;
public $tmpl = null;
// public $key = null;
/**
* Set the pagination ID
*
* @param int $id id
*
* @return void
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Return the pagination footer
*
* @param int $listRef List reference
* @param string $tmpl List template
*
* @return string Pagination footer
*/
public function getListFooter($listRef = '', $tmpl =
'default')
{
$app = Factory::getApplication();
$this->listRef = $listRef;
$this->tmpl = $tmpl;
$list = array();
$list['limit'] = $this->limit;
$list['limitstart'] = $this->limitstart;
$list['total'] = $this->total;
$list['limitfield'] = $this->showDisplayNum ?
$this->getLimitBox($tmpl) : '';
$list['pagescounter'] = $this->getPagesCounter();
if ($this->showTotal)
{
$list['pagescounter'] .= ' ' .
Text::_('COM_FABRIK_TOTAL') . ': ' .
$list['total'];
}
$list['pageslinks'] = $this->getPagesLinks($listRef, $tmpl);
$chromePath = JPATH_THEMES . '/' .
$app->getTemplate() . '/html/pagination.php';
if (file_exists($chromePath))
{
require_once $chromePath;
if (function_exists('pagination_list_footer'))
{
// Cant allow for it to be overridden
}
}
return $this->_list_footer($list);
}
/**
* Creates a dropdown box for selecting how many records to show per page
*
* @param string $tmpl List template
*
* @return string The html for the limit # input box
*/
public function getLimitBox($tmpl = 'default')
{
$paths = array();
$displayData = new stdClass;
$displayData->id = $this->id;
$displayData->startLimit = $this->startLimit;
$displayData->showAllOption = $this->showAllOption;
$displayData->viewAll = $this->viewAll;
$displayData->limit = $this->limit;
$layout =
$this->getLayout('pagination.fabrik-pagination-limitbox');
return $layout->render($displayData);
}
/**
* Method to create an active pagination link to the item
*
* @param PaginationObject $item The object with which to make an active
link.
*
* @return string HTML link
*/
protected function _item_active($item)
{
$displayData = new stdClass;
$displayData->item = $item;
$layout =
$this->getLayout('pagination.fabrik-pagination-item-active');
return $layout->render($displayData);
}
/**
* Method to create an inactive pagination string
*
* @param PaginationObject $item The item to be processed
*
* @return string
*
* @since 1.5
*/
protected function _item_inactive( $item)
{
$displayData = new stdClass;
$displayData->item = $item;
$layout =
$this->getLayout('pagination.fabrik-pagination-item-inactive');
return $layout->render($displayData);
}
/**
* Create and return the pagination page list string, i.e. Previous, Next,
1 2 3 ... x.
*
* @param int $listRef Unique list reference
* @param string $tmpl List template name
*
* @return string Pagination page list string.
*
* @since 11.1
*/
public function getPagesLinks($listRef = 0, $tmpl = 'default')
{
// Build the page navigation list
$data = $this->_buildDataObject();
$list = array();
$itemOverride = false;
$listOverride = false;
$chromePath = COM_FABRIK_FRONTEND . '/views/list/tmpl/' .
$tmpl . '/default_pagination.php';
if (File::exists($chromePath))
{
require_once $chromePath;
if (function_exists('fabrik_pagination_item_active')
&& function_exists('fabrik_pagination_item_inactive'))
{
// Can't allow this as the js code we use for the items is
different
$itemOverride = true;
}
if (function_exists('fabrik_pagination_list_render'))
{
$listOverride = true;
}
}
// Build the select list
$items = ['all', 'start', 'previous',
'pages', 'next', 'end'];
$activeFound = false;
foreach ($items as $dataitem) {
if ($dataitem !== 'pages') {
$activeFound |= $data->$dataitem->active;
$list[$dataitem]['active'] = $data->$dataitem->active;
$list[$dataitem]['data'] = $itemOverride ?
fabrik_pagination_item_active($data->$dataitem, $this->listRef) :
$this->_item_active($data->$dataitem);
} else {
foreach ($data->$dataitem as $i => $page)
{
$activeFound |= $page->active;
$list['pages'][$i]['active'] = $page->active;
$list['pages'][$i]['data'] = $itemOverride ?
fabrik_pagination_item_active($page, $this->listRef) :
$this->_item_active($page);
}
}
}
if (!$activeFound) {
$list['pages'][$this->limitstart == 0 ? 1 :
$this->limitstart/$this->limit + 1]['active'] = true;
}
if ($this->total > $this->limit)
{
return ($listOverride) ? fabrik_pagination_list_render($list,
$this->listRef) : $this->_list_render($list);
}
else
{
return '';
}
}
/**
* Create the html for a list footer
*
* @param array $list Pagination list data structure.
*
* @return string HTML for a list start, previous, next,end
*/
protected function _list_render($list)
{
$displayData = new stdClass;
$displayData->list = $list;
$layout =
$this->getLayout('pagination.fabrik-pagination-links');
return $layout->render($displayData);
}
/**
* THIS SEEMS GOOFY TO HAVE TO OVERRIDE DEFAULT FUNCTION - BUT!
* THE ORIGINAL SETS THE PAGE TO EMPTY IF ITS 0 - APPARENTLY TO DO WITH
* ROUTING - THIS HAS BEEN REMOVED HERE
*
* PERHAPS THE FABRIK ROUTING ISN'T RIGHT?
*
* OCCURS EVEN WITHOUT SEF URLS ON THOUGH? :s
*
* Create and return the pagination data object
*
* @return object Pagination data object
*/
protected function _buildDataObject()
{
// Initialize variables
$data = new stdClass;
$this->url =
preg_replace("/limitstart{$this->id}=(.*)?(&|)/",
'', $this->url);
$this->url = StringHelper::rtrimword($this->url,
"&");
// $$$ hugh - need to work out if we need & or ?
$sepchar = strstr($this->url, '?') ?
'&' : '?';
$data->all = new
FabrikPaginationObject(Text::_('COM_FABRIK_VIEW_ALL'));
$data->all->key = 'all';
if (!$this->viewAll)
{
$data->all->base = '0';
$data->all->link = Route::_("{$sepchar}limitstart=");
}
// Set the start and previous data objects
$data->start = new
FabrikPaginationObject(Text::_('COM_FABRIK_START'));
$data->start->key = 'start';
$data->previous = new
FabrikPaginationObject(Text::_('COM_FABRIK_PREV'));
$data->previous->key = 'previous';
if ($this->get('pages.current') > 1)
{
$page = ($this->get('pages.current') - 2) *
$this->limit;
$data->start->base = '0';
$data->start->link = Route::_($this->url .
"{$sepchar}limitstart{$this->id}=0");
$data->previous->base = $page;
$data->previous->link = Route::_($this->url .
"{$sepchar}limitstart{$this->id}=" . $page);
$data->start->link = str_replace('resetfilters=1',
'', $data->start->link);
$data->previous->link = str_replace('resetfilters=1',
'', $data->previous->link);
$data->start->link = str_replace('clearordering=1',
'', $data->start->link);
$data->previous->link = str_replace('clearordering=1',
'', $data->previous->link);
}
// Set the next and end data objects
$data->next = new
FabrikPaginationObject(Text::_('COM_FABRIK_NEXT'));
$data->next->key = 'next';
$data->end = new
FabrikPaginationObject(Text::_('COM_FABRIK_END'));
$data->end->key = 'end';
if ($this->get('pages.current') <=
$this->get('pages.total'))
{
$next = $this->get('pages.current') *
$this->limit;
$end = ($this->get('pages.total') - 1) *
$this->limit;
$data->next->base = $next;
$data->next->link = Route::_($this->url .
"{$sepchar}limitstart{$this->id}=" . $next);
$data->end->base = $end;
$data->end->link = Route::_($this->url .
"{$sepchar}limitstart{$this->id}=" . $end);
$data->next->link = str_replace('resetfilters=1',
'', $data->next->link);
$data->end->link = str_replace('resetfilters=1',
'', $data->end->link);
$data->next->link = str_replace('clearordering=1',
'', $data->next->link);
$data->end->link = str_replace('clearordering=1',
'', $data->end->link);
}
$data->pages = array();
$stop = $this->get('pages.stop');
for ($i = $this->get('pages.start'); $i <= $stop; $i++)
{
$offset = ($i - 1) * $this->limit;
$data->pages[$i] = new FabrikPaginationObject($i);
$data->pages[$i]->key = $i;
if ($i != $this->get('pages.current') || $this->viewAll)
{
$data->pages[$i]->base = $offset;
$data->pages[$i]->link = Route::_($this->url .
"{$sepchar}limitstart{$this->id}=" . $offset);
$data->pages[$i]->link = str_replace('resetfilters=1',
'', $data->pages[$i]->link);
$data->pages[$i]->link = str_replace('clearordering=1',
'', $data->pages[$i]->link);
}
}
return $data;
}
/**
* Create the HTML for a list footer
*
* @param array $list Pagination list data structure.
*
* @return string HTML for a list footer
*/
protected function _list_footer($list)
{
$limitLabel = $this->showDisplayNum ?
Text::_('COM_FABRIK_DISPLAY_NUM') : '';
// Initialize variables
$paths = array();
$displayData = new stdClass;
$displayData->id = $this->id;
$displayData->label = $limitLabel;
$displayData->value = $list['limitstart'];
$displayData->list = $list['limitfield'];
$displayData->pagesCounter = $list['pagescounter'];
$displayData->listName = 'limit' . $this->id;
$displayData->links = $list['pageslinks'];
$displayData->showNav = $this->showNav;
$displayData->showTotal = $this->showTotal;
$displayData->limit = $this->limit;
$layout =
$this->getLayout('pagination.fabrik-pagination-footer');
return $layout->render($displayData);
}
/**
* Returns a property of the object or the default value if the property
is not set.
* Avoids deprecated notices in 3.1 whilst maintaining backwards compat
*
* @param string $property The name of the property.
* @param mixed $default The default value.
*
* @return mixed The value of the property.
*
* @since 12.2
* @deprecated 13.3 Access the properties directly.
*/
public function get($property, $default = null)
{
if (strpos($property, '.'))
{
$prop = explode('.', $property);
$prop[1] = ucfirst($prop[1]);
$property = implode($prop);
}
if (isset($this->$property))
{
return $this->$property;
}
return $default;
}
/**
* Get a pagination LayoutInterface file
*
* @param string $type form/details/list
* @param array $paths Optional paths to add as includes
*
* @return LayoutFile
*/
public function getLayout($name, $paths = array(), $options = array())
{
$paths[] = JPATH_THEMES . '/' .
Factory::getApplication()->getTemplate() .
'/html/layouts/com_fabrik/list_' . $this->id;
$paths[] = COM_FABRIK_FRONTEND . '/views/list/tmpl/' .
$this->tmpl . '/layouts';
$layout = Html::getLayout($name, $paths, $options);
return $layout;
}
}
fabrik/fabrik/Helpers/Pdf.php000064400000016042151165341610012072
0ustar00<?php
/**
* PDF Set up helper
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
jimport('joomla.filesystem.file');
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Dompdf\Dompdf;
use Dompdf\Options;
/**
* PDF Set up helper
*
* @package Joomla
* @subpackage Fabrik.helpers
* @since 3.1rc3
*/
class Pdf
{
/**
* @param $html
* @param string $size
* @param string $orientation
*/
public static function renderPdf($html, $size = 'A4',
$orientation = 'portrait')
{
$config = ComponentHelper::getParams('com_fabrik');
if ($config->get('fabrik_pdf_lib', 'dompdf') ===
'dompdf')
{
$pdf = self::renderDomPdf($html, $size, $orientation);
}
else
{
$pdf = self::renderMPdf($html, $size, $orientation);
}
return $pdf;
}
public static function renderMPdf($html, $size = 'A4',
$orientation = 'portrait')
{
$size = ucfirst($size);
switch ($orientation)
{
case 'landscape':
$orientation = 'L';
$size .= '-' . $orientation;
break;
case 'portrait':
default:
$orientation = 'P';
break;
}
Pdf::fullPaths($html);
$html =
mb_convert_encoding($html,'HTML-ENTITIES','UTF-8');
try
{
$mpdf = new \Mpdf\Mpdf(
[
'tempDir' =>
Factory::getApplication()->getConfig()->get('tmp_path',
JPATH_ROOT . '/tmp'),
'mode' => 'utf-8',
'format' => $size,
'orientation' => $orientation
]
);
$mpdf->WriteHTML($html);
return $mpdf->Output('',
\Mpdf\Output\Destination::STRING_RETURN);
}
catch (\Mpdf\MpdfException $e)
{
// mmmphh
return '';
}
}
public static function renderDomPdf($html, $size = 'A4',
$orientation = 'portrait')
{
Pdf::fullPaths($html);
$html =
mb_convert_encoding($html,'HTML-ENTITIES','UTF-8');
$domPdf = self::iniDomPdf(true);
$domPdf->set_paper($size, $orientation);
$domPdf->load_html($html);
$domPdf->render();
return $domPdf->output();
}
/**
* Init selected PDF
*/
public static function iniPdf()
{
$config = ComponentHelper::getParams('com_fabrik');
if ($config->get('fabrik_pdf_lib', 'dompdf') ===
'dompdf')
{
return self::iniDomPdf(false);
}
}
/**
* Set up DomPDF engine
*
* @param bool $puke throw exception if not installed (true) or just
return false
*
* @return bool
*/
public static function iniDomPdf($puke = false)
{
if (!Worker::canPdf($puke))
{
return false;
}
$config = Factory::getApplication()->getConfig();
$options = new Options();
$options->set('isRemoteEnabled', true);
/**
* need to enable HTML5 parser to work around a bug in DOMPDF:
* https://github.com/dompdf/dompdf/issues/1494#issuecomment-332116978
*/
$options->setIsHtml5ParserEnabled(true);
$options->set('fontCache',
$config->get('tmp_path'));
$options->set('tempDir',
$config->get('tmp_path'));
return new Dompdf($options);
}
/**
* Parse relative images a hrefs and style sheets to full paths
*
* @param string &$data data
*
* @return void
*/
public static function fullPaths(&$data)
{
$data = str_replace('xmlns=', 'ns=', $data);
libxml_use_internal_errors(true);
$base_root = COM_FABRIK_LIVESITE_ROOT . '/'; // scheme, host,
port, without trailing /,add it
$subdir =
str_replace(COM_FABRIK_LIVESITE_ROOT,'',COM_FABRIK_LIVESITE); //
subdir /xx/
$subdir = ltrim($subdir,'/');
$schemeString = '://'; //if no schemeString found assume path
is relative
try
{
$doc = new \DOMDocument();
$doc->strictErrorChecking = FALSE;
// prepend encoding, otherwise UTF-8 will get munged into special chars
$data = '<?xml version="1.0"
encoding="UTF-8"?>' . $data;
// load the document
$doc->loadHTML($data);
// img tags
$imgs = $doc->getElementsByTagName('img');
foreach ($imgs as $img)
{
$src = $img->getAttribute('src');
if (!strstr($src, $schemeString))
{
$base = empty($subdir) || strstr($src, $subdir) ? $base_root :
$base_root . $subdir;
$src = $base . ltrim($src,'/');
$img->setAttribute('src', $src);
}
}
// a tags
$as = $doc->getElementsByTagName('a');
foreach ($as as $a)
{
$href = $a->getAttribute('href');
if (!strstr($href, $schemeString) && !strstr($href,
'mailto:') && !strstr($href, 'tel:'))
{
$base = empty($subdir) || strstr($href, $subdir) ? $base_root :
$base_root . $subdir;
$href = $base . ltrim($href,'/');
$a->setAttribute('href', $href);
}
}
// link tags
$links = $doc->getElementsByTagName('link');
foreach ($links as $link)
{
$rel = $link->getAttribute('rel');
$href = $link->getAttribute('href');
if ($rel == 'stylesheet' && !strstr($href,
$schemeString))
{
$base = empty($subdir) || strstr($href, $subdir) ? $base_root :
$base_root . $subdir;
$href = $base . ltrim($href,'/');
$link->setAttribute('href', $href);
}
}
$data = $doc->saveHTML();
/*
$ok = simplexml_import_dom($doc);
//$ok = new \SimpleXMLElement($data);
if ($ok)
{
$imgs = $ok->xpath('//img');
foreach ($imgs as &$img)
{
if (!strstr($img['src'], $schemeString))
{
$base = empty($subdir) || strstr($img['src'], $subdir) ?
$base_root : $base_root . $subdir;
$img['src'] = $base .
ltrim($img['src'],'/');
}
}
// Links
$as = $ok->xpath('//a');
foreach ($as as &$a)
{
if (!strstr($a['href'], $schemeString) &&
!strstr($a['href'], 'mailto:'))
{
$base = empty($subdir) ||
strstr($a['href'], $subdir) ? $base_root : $base_root . $subdir;
$a['href'] = $base .
ltrim($a['href'],'/');
}
}
// CSS files.
$links = $ok->xpath('//link');
foreach ($links as &$link)
{
if ($link['rel'] == 'stylesheet' &&
!strstr($link['href'], $schemeString))
{
$base = empty($subdir) || strstr($link['href'], $subdir) ?
$base_root : $base_root . $subdir;
$link['href'] = $base .
ltrim($link['href'],'/');
}
}
$data = $ok->asXML();
}
*/
}
catch (\Exception $err)
{
// Oho malformed html - if we are debugging the site then show the
errors
// otherwise continue, but it may mean that images/css/links are
incorrect
$errors = libxml_get_errors();
$config = ComponentHelper::getParams('com_fabrik');
// Don't show the errors if we want to debug the actual pdf html
if (JDEBUG && $config->get('pdf_debug', false) ===
true)
{
echo "<pre>";
print_r($errors);
echo "</pre>";
exit;
}
//Create the full path via general str_replace
//todo: relative URL starting without /
else
{
$base = $base_root . $subdir;
$data = str_replace('href="/', 'href="' .
$base, $data);
$data = str_replace('src="/', 'src="' .
$base, $data);
$data = str_replace("href='/", "href='" .
$base, $data);
$data = str_replace("src='/", "src='" .
$base, $data);
}
}
}
}
fabrik/fabrik/Helpers/Php.php000064400000014063151165341610012111
0ustar00<?php
/**
* @package Regular Labs Library
* @version 22.10.1331
*
* @author Peter van Westen <info@regularlabs.com>
* @link http://regularlabs.com
* @copyright Copyright © 2022 Regular Labs All Rights Reserved
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
*/
/**
* This is a derivative of the Php class from Peter van Weston at Regular
Labs,
* it is highly modified for Fabrik's needs but the underlying
* architecture is copyright Peter van Westen. The following applies to
* the derivations.
*
* @package Joomla
* @subpackage Fabrik
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
use Joomla\CMS\Factory;
use Joomla\CMS\Version;
use Joomla\CMS\Document\Document;
use Joomla\CMS\Filesystem\File;
class Php
{
public static function Eval($params = [])
{
if (empty($params)) {
return null;
}
if (array_key_exists('code', $params) === false) {
/* we must have some code to deal with */
return null;
}
$params['className'] = self::getClassName($params);
if (empty($params['className'])) {
// Something went wrong!
return true;
}
$result = null;
ob_start();
$newClass = new $params['className'];
$result = $newClass->doExecute($params['vars'] ?? [],
$params['thisVars'] ?? []);
$output = ob_get_contents();
ob_end_clean();
if (is_null($result) === false) {
return $result;
}
return $output;
}
private static function createFunctionInMemory($string)
{
eval($string);
}
private static function generateClassContents($params)
{
$content = [];
/* Process the passed in variables */
$init_variables = [];
$thisVars = $params['thisVars'] ?? [];
$vars = $params['vars'] ?? [];
$privateThisVars = [];
foreach(array_keys($thisVars) as $thisVarName) {
$privateThisVars[] = 'private
$'.$thisVarName.';';
}
$initBasicVars = [];
foreach(array_keys($vars) as $varName) {
$initBasicVars[] = 'private
$'.$varName.';';
}
$useLines = [];
/* Check for complicated code structure */
$codeTypes = ['preCode' => [], 'postCode'
=> []];
if (is_array($params['code']) === false)
$params['code'] = ['preCode' =>
$params['code']];
/* Split the code into seperate lines */
foreach (array_keys($codeTypes) as $codeType) {
if (empty($params['code'][$codeType])) continue;
$codeTypes[$codeType] = array_map('trim',
preg_split('/\r\n|\r|\n/',
$params['code'][$codeType]));
/* Capture any use statements */
foreach ($codeTypes[$codeType] as $idx => $codeLine) {
if (strpos($codeLine, 'use ') === 0) {
/* Found one, while we are at it remove any double
backslashes, these were recommended early on with F4 */
$useLines[] = str_replace('\\\\',
'\\', $codeLine);
unset($codeTypes[$codeType][$idx]);
}
}
}
/* Opening stuff */
$content[] = 'defined(\'_JEXEC\') or die;';
/* the use lines from the original source */
$content = array_merge($content, $useLines);
/* Define the class */
$content[] = 'class
'.$params['className'].'{';
/* Our new function */
$content[] = 'function doExecute($vars, $thisVars) {';
/* Insert any $thisVars setup */
if (count($thisVars)) {
$content = array_merge($content, [
'foreach ($thisVars as $thisVarKey =>
&$thisVarValue) {',
' $this->{$thisVarKey} =
&$thisVarValue;',
'};'
]);
}
/* Insert any regular var setup */
if (count($vars)) {
$content = array_merge($content, [
'foreach ($vars as $varKey => &$varValue)
{',
' ${$varKey} = &$varValue;',
'};'
]);
}
/* Now the actual code */
$content = array_merge($content, $codeTypes['preCode']);
if (!empty($params['code']['file'])) {
$content[] =
'require_once("'.$params['code']['file'].'");';
}
$content = array_merge($content, $codeTypes['postCode']);
/* In case the code left us out of php mode */
$content[] = '?><?php';
/* Close the doExecute function */
$content[] = '}';
/* And close off the class */
$content[] = "};";
$content = implode(PHP_EOL, $content);
// Remove Zero Width spaces / (non-)joiners
$content = str_replace(
[
"\xE2\x80\x8B",
"\xE2\x80\x8C",
"\xE2\x80\x8D",
],
'',
$content
);
return $content;
}
private static function getClassName(&$params)
{
$code = '';
if (is_array($params['code'])) {
foreach ($params['code'] as $codeKey => $codePart)
{
$code .= $params['code'][$codeKey] ??
'';
}
$md5 = md5($code);
} else {
$md5 = md5($params['code']);
}
$params['className'] = 'FabrikEvalClass_' .
$md5;
if (class_exists($params['className'])) {
return $params['className'];
}
$contents = self::generateClassContents($params);
self::createFunctionInMemory($contents);
if (!class_exists($params['className'])) {
// Something went wrong!
return false;
}
return $params['className'];
}
}
fabrik/fabrik/Helpers/sms_gateways/clickatell.php000064400000003672151165341620016204
0ustar00<?php
/**
* Clickatell SMS gateway class
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Factory;
use Joomla\CMS\Object\CMSObject;
use Clickatell\Api\ClickatellRest;
use Fabrik\Helpers\ArrayHelper;
/**
* Clickatell SMS gateway class
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @since 3.0
*/
class Clickatell extends CMSObject
{
/**
* Send SMS
*
* @param string $message sms message
* @param array $opts options
*
* @return void
*/
public function process($message = '', $opts)
{
// Clickatell only uses token, no SID, use whichever param isn't
empty
$sid = ArrayHelper::getValue($opts, 'sms-username');
$token = ArrayHelper::getValue($opts, 'sms-password');
if (empty($token) && !empty($sid))
{
$token = $sid;
}
// no sms-from setting for Clickatell, just set up 'to' array
$smsto = ArrayHelper::getValue($opts, 'sms-to');
$smstos = empty($smsto) ? array() : explode(",", $smsto);
// Clickatell is picky about numbers, no spaces or dashes
foreach ($smstos as &$smsto)
{
$smsto = preg_replace("/[^0-9]/","", $smsto);
}
$client = new ClickatellRest($token);
// Clickatell API doesn't throw exceptions, but something else might
try {
$response = $client->sendMessage(
$smstos,
$message
);
}
catch (\Exception $e)
{
Factory::getApplication()->enqueueMessage($e->getMessage(),
'error');
return false;
}
// check the response array
foreach ($response as $item)
{
if ($item->error !== false)
{
// @TODO add language for this
Factory::getApplication()->enqueueMessage('SMS failed with
error code: ' . $item->errorCode, 'error');
return false;
}
}
return true;
}
}
fabrik/fabrik/Helpers/sms_gateways/itagg.php000064400000004416151165341620015165
0ustar00<?php
/**
* Itagg SMS gateway class
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Object\CMSObject;
use Fabrik\Helpers\ArrayHelper;
use Fabrik\Helpers\Sms;
use Fabrik\Helpers\StringHelper;
/**
* Itagg SMS gateway class
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @since 3.0
*/
class Itagg extends CMSObject
{
/**
* URL To Post SMS to
*
* @var string
*/
protected $url = 'https://secure.itagg.com/smsg/sms.mes';
/**
* Send SMS
*
* @param string $message sms message
* @param array $opts Options
*
* @return void
*/
public function process($message, $opts)
{
$username = ArrayHelper::getValue($opts, 'sms-username');
$password = ArrayHelper::getValue($opts, 'sms-password');
$smsfrom = ArrayHelper::getValue($opts, 'sms-from');
$smsto = ArrayHelper::getValue($opts, 'sms-to');
$smstos = explode(",", $smsto);
$message = urlencode($message);
foreach ($smstos as $smsto)
{
if (substr($smsto, 0, 1) == '+' &&
StringHelper::substr($smsto, 1, 2) != '44')
{
// Global sms
$route = 8;
}
else
{
// UK (itagg)
$route = 7;
}
$smsto = urlencode($smsto);
$url = $this->url;
$vars = 'usr=' . $username . '&pwd=' . $password
. '&from=rob&to=' . $smsto .
'&type=text&route=' . $route . '&txt=' .
$message;
$itaggapi = "https://secure.itagg.com/smsg/sms.mes";
/*
$params="usr=XXX&pwd=YYY&from=steve&to=07712345678,447912345678,3912345678&type=text&rout
e=7&txt=hello+via+POST"; */
$ch = curl_init();
if (!$ch)
{
throw new RuntimeException("cant ini curl session", 500);
exit;
}
curl_setopt($ch, CURLOPT_URL, $itaggapi);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$returned = curl_exec($ch);
curl_close($ch);
// This will be the OK / error message
if ($returned === true)
{
echo "sent ok";
}
$res = Sms::doRequest('POST', $url, $vars);
}
}
}
fabrik/fabrik/Helpers/sms_gateways/kapow.php000064400000002453151165341620015212
0ustar00<?php
/**
* Send an SMS via the kapow sms gateway
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Object\CMSObject;
use Fabrik\Helpers\ArrayHelper;
use Fabrik\Helpers\Sms;
/**
* Kapow SMS gateway class
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @since 3.0
*/
class Kapow extends CMSObject
{
/**
* URL To Post SMS to
*
* @var string
*/
protected $url =
'http://www.kapow.co.uk/scripts/sendsms.php?username=%s&password=%s&mobile=%s&sms=%s';
/**
* Send SMS
*
* @param string $message sms message
* @param array $opts Options
*
* @return void
*/
public function process($message, $opts)
{
$username = ArrayHelper::getValue($opts, 'sms-username');
$password = ArrayHelper::getValue($opts, 'sms-password');
$smsfrom = ArrayHelper::getValue($opts, 'sms-from');
$smsto = ArrayHelper::getValue($opts, 'sms-to');
$smstos = explode(',', $smsto);
foreach ($smstos as $smsto)
{
$url = sprintf($this->url, $username, $password, $smsto, $message);
Sms::doRequest('GET', $url, '');
}
}
}
fabrik/fabrik/Helpers/sms_gateways/smssza.php000064400000002466151165341620015415
0ustar00<?php
/**
* Send an SMS via the SMSS (ZA) gateway
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Object\CMSObject;
use Fabrik\Helpers\ArrayHelper;
use Fabrik\Helpers\Sms;
/**
* SMSS (ZA) SMS gateway class
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @since 3.0
*/
class Smssza extends CMSObject
{
/**
* URL To Post SMS to
*
* @var string
*/
protected $url =
'http://148.251.196.36/app/smsapi/index.php?key=%s&type=text&contacts=%s&senderid=%s&msg=%s&time=';
/**
* Send SMS
*
* @param string $message sms message
* @param array $opts Options
*
* @return void
*/
public function process($message, $opts)
{
$username = ArrayHelper::getValue($opts, 'sms-username');
$password = ArrayHelper::getValue($opts, 'sms-password');
$smsfrom = ArrayHelper::getValue($opts, 'sms-from');
$smsto = ArrayHelper::getValue($opts, 'sms-to');
$url = sprintf($this->url, $username, $smsto, $smsfrom,
urlencode($message));
$response = Sms::doRequest('GET', $url, '');
return strstr($response, 'api_') !== false;
}
}
fabrik/fabrik/Helpers/sms_gateways/textopoly.php000064400000002471151165341620016140
0ustar00<?php
/**
* Textopoly SMS gateway class
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Object\CMSObject;
use Fabrik\Helpers\ArrayHelper;
use Fabrik\Helpers\Sms;
/**
* Textopoly SMS gateway class
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @since 3.0
*/
class Textopoly extends CMSObject
{
/**
* URL To Post SMS to
*
* @var string
*/
protected $url =
'http://sms.mxtelecom.com/SMSSend?user=%s&pass=%s&smsfrom=%s&smsto=%s&smsmsg=%s';
/**
* Send SMS
*
* @param string $message sms message
* @param array $opts Options
*
* @return void
*/
public function process($message, $opts)
{
$username = ArrayHelper::getValue($opts, 'sms-username');
$password = ArrayHelper::getValue($opts, 'sms-password');
$smsfrom = ArrayHelper::getValue($opts, 'sms-from');
$smsto = ArrayHelper::getValue($opts, 'sms-to');
$smstos = explode(',', $smsto);
foreach ($smstos as $smsto)
{
$url = sprintf($this->url, $username, $password, $smsfrom, $smsto,
$message);
$response = Sms::doRequest('GET', $url, '');
}
}
}
fabrik/fabrik/Helpers/sms_gateways/twilio.php000064400000002742151165341620015401
0ustar00<?php
/**
* Twilio SMS gateway class
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Factory;
use Joomla\CMS\Object\CMSObject;
use Fabrik\Helpers\ArrayHelper;
use Twilio\Rest\Client;
use Twilio\Exceptions\TwilioException;
/**
* Twilio SMS gateway class
*
* @package Joomla.Plugin
* @subpackage Fabrik.form.sms
* @since 3.0
*/
class Twilio extends CMSObject
{
/**
* Send SMS
*
* @param string $message sms message
* @param array $opts options
*
* @return void
*/
public function process($message = '', $opts)
{
$sid = ArrayHelper::getValue($opts, 'sms-username');
$token = ArrayHelper::getValue($opts, 'sms-password');
$smsto = ArrayHelper::getValue($opts, 'sms-to');
// From a valid Twilio number
$smsfrom = ArrayHelper::getValue($opts, 'sms-from');
$smstos = empty($smsto) ? array() : explode(",", $smsto);
$client = new Twilio\Rest\Client($sid, $token);
foreach ($smstos as $smsto)
{
try {
$client->messages->create(
trim($smsto),
array(
'from' => $smsfrom,
'body' => $message
)
);
}
catch (TwilioException $e)
{
Factory::getApplication()->enqueueMessage($e->getMessage(),
'error');
return false;
}
}
return true;
}
}
fabrik/fabrik/Helpers/Sms.php000064400000003451151165341620012124
0ustar00<?php
/**
* Send sms's
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Factory;
use \RuntimeException;
/**
* Send sms's
*
* @package Joomla
* @subpackage Fabrik.helpers
* @since 3.0
*/
class Sms
{
/**
* Send sms
*
* @param string $method post/get
* @param string $url url to request
* @param string $vars querystring vars to post
* @param string $auth auth
* @param string $callback method
*
* @return mixed data or curl error
*/
public static function doRequest($method, $url, $vars, $auth =
'', $callback = false)
{
$app = Factory::getApplication();
if (!function_exists('curl_init'))
{
throw new
RuntimeException(Text::_('COM_FABRIK_ERR_CURL_NOT_INSTALLED'));
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_USERAGENT,
$app->input->server->getString('HTTP_USER_AGENT'));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
if ($method == 'POST')
{
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
}
if (!empty($auth))
{
curl_setopt($ch, CURLOPT_USERPWD, $auth);
}
$data = curl_exec($ch);
curl_close($ch);
if ($data)
{
if ($callback)
{
return call_user_func($callback, $data);
}
else
{
return $data;
}
}
else
{
return curl_error($ch);
}
}
}
fabrik/fabrik/Helpers/StringHelper.php000064400000064116151165341630013776
0ustar00<?php
/**
* String helpers
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Language\Text;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Factory;
use PHPLicengine\Api\Api;
use PHPLicengine\Service\Bitlink;
use stdClass;
/**
* String helpers
*
* @package Joomla
* @subpackage Fabrik.helpers
* @since 3.0
*/
class StringHelper extends \Joomla\String\StringHelper
{
/**
* UTF-8 aware - replace the first word
*
* @param string $str The string to be trimmed
* @param string $word The word to trim
* @param string $whitespace Ignore but preserve leading whitespace
*
* @return string the trimmed string
*/
public static function ltrimword($str, $word = false, $whitespace = false)
{
if ($word === false)
{
return $str;
}
if ($whitespace)
{
$word = preg_quote($word, '#');
$str = preg_replace("#^(\s*)($word)(.*)#i", "$1$3",
$str);
}
else
{
$pos = StringHelper::strpos($str, $word);
if ($pos === 0)
{
$str = StringHelper::substr($str, StringHelper::strlen($word));
}
}
return $str;
}
/**
* Right trim a word from a string
*
* @param string &$str The string to be trimmed
* @param string $word The word to trim
*
* @return string the trimmed string
*/
public static function rtrimword(&$str, $word = false)
{
$l = StringHelper::strlen($word);
$end = StringHelper::substr($str, -$l);
if ($end === $word)
{
return StringHelper::substr($str, 0, StringHelper::strlen($str) - $l);
}
else
{
return $str;
}
}
/**
* UTF-8 aware - remove the first word
* CASE INSENSITIVE
*
* @param string $str The string to be trimmed
* @param string $word The word to trim
*
* @return string the trimmed string
*/
public static function ltrimiword($str, $word = false)
{
$pos = stripos($str, $word);
if ($pos === 0)
{
$str = StringHelper::substr($str, StringHelper::strlen($word));
}
return $str;
}
/**
* Formats a string to return a safe db col name e.g.
* table.field is returned as `table`.`field`
* table is return as `table`
*
* @param string $col Col name to format
*
* @return string in `table`.field` format
*/
public static function safeColName($col)
{
$db = Worker::getDbo();
$col = str_replace('`', '', $col);
$splitter = '';
if (strstr($col, '___'))
{
$splitter = '___';
}
if (strstr($col, '.'))
{
$splitter = '.';
}
if ($splitter == '')
{
return $db->quoteName($col);
}
if (strstr($col, $splitter))
{
$col = explode($splitter, $col);
foreach ($col as &$c)
{
$c = $db->quoteName($c);
}
return implode('.', $col);
}
return $col;
}
/**
* Inverse of safeColName takes `table`.`field`
* and returns table___field
*
* @param string $col In `table`.`field` format
*
* @return string in table___field format
*/
public static function safeColNameToArrayKey($col)
{
$col = str_replace(array('`.`', '.'),
'___', $col);
$col = str_replace('`', '', $col);
return $col;
}
/**
* Takes tablename.element or tablename___elementname
* (with or without quotes) and returns elementname
*
* @param string $col Column name to shorten
*
* @return string element name
*/
public static function shortColName($col)
{
if (strstr((string)$col, '.'))
{
$bits = explode('.', $col);
$col = array_pop($bits);
}
elseif (strstr((string)$col, '___'))
{
$bits = explode('___', $col);
$col = array_pop($bits);
}
$col = str_replace('`', '', (string)$col);
return $col;
}
/**
* Get a shortened version of the element label - so that the admin pages
* don't get too stretched when we populate drop-downs with the label
*
* @param string $label Complete element label
*
* @return string shortened element label
*/
public static function getShortDdLabel($label)
{
$label = strip_tags($label);
preg_replace('/<[a-z][a-z0-9]*[^<>]*>/',
'', $label);
if (StringHelper::strlen($label) > 50)
{
$label = StringHelper::substr($label, 0, 47) . '...';
}
$label = trim($label);
return $label;
}
/**
* Sanitize db fields names, can't just do regex on A-Z as languages
like Chinese should be allowed
*
* @param string $str Field name
*
* @since 3.0.7
*
* @return string
*/
public static function dbFieldName($str)
{
$name = InputFilter::getInstance()->clean($str, 'CMD');
// Chinese characters?
if ($name === '')
{
$name = str_replace(array(' ', '.', '-'),
'', $str);
}
return $name;
}
/**
* Is it a raw element name, i.e. ends in _raw
*
* @param string $str Element name
*
* @since 3.3
*
* @return bool
*/
public static function isRawName($str) {
return substr($str, -4, 4) == '_raw';
}
/**
* Strip _raw off the end
*
* @param string $str Element name
*
* @since 3.3
*
* @return bool
*/
public static function stripRawName($str)
{
return self::rtrimword($str, '_raw');
}
/**
* Clean variable names for use as fabrik element names
* whitespace compressed and replaced with '_'
* replace all non-alphanumeric chars except _ and - with '_'
* 28/06/2011 replaces umlauts with eu
* 22/11/2011 added IGNORE to default enc otherwise iconv chops everything
after first unconvertable char
* 05/02/2012 changed name to iclean, removed strtolower() and added
clean() as wrapper that does strtolower
*
* @param string $str To clean
* @param string $fromEnc From encoding
* @param string $toEnc To encoding
*
* @return string cleaned
*/
public static function iclean($str, $fromEnc = "UTF-8", $toEnc =
"ASCII//IGNORE//TRANSLIT")
{
// Replace umlauts
$out = '';
for ($i = 0; $i < StringHelper::strlen($str); $i++)
{
$ch = ord($str[$i]);
switch ($ch)
{
case 195:
$out .= '';
break;
case 164:
$out .= 'ae';
break;
case 188:
$out .= 'ue';
break;
case 182:
$out .= 'oe';
break;
case 132:
$out .= 'Ae';
break;
case 156:
$out .= 'Ue';
break;
case 150:
$out .= 'Oe';
break;
// Fix for cleaning value of 1
case 0:
$out = '1';
break;
default:
$out .= chr($ch);
}
}
$str = $out;
if (function_exists('iconv'))
{
/* $$$ rob added @ in case its farsi which creates a notice:
* https://github.com/Fabrik/fabrik/issues/72
*/
// Replace accented characters with ascii equivalent e.g. é => e
$str1 = (@iconv($fromEnc, $toEnc, $str));
if ($str1)
{
$str = $str1;
}
$str = (str_replace("'", '', $str));
}
// Compress internal whitespace and replace with _
$str = preg_replace('/\s+/', '_', $str);
// Replace all non-alphanumeric chars except _ and - with '_'
return preg_replace('/\W+/', '_', $str);
}
/**
* Wrapper for iclean(), that does strtolower on output of clean()
*
* @param string $str To clean
* @param string $fromEnc From encoding
* @param string $toEnc To encoding
*
* @return string cleaned
*/
public static function clean($str, $fromEnc = "UTF-8", $toEnc =
"ASCII//IGNORE//TRANSLIT")
{
return StringHelper::strtolower(self::iclean($str, $fromEnc, $toEnc));
}
/**
* truncateHtml can truncate a string up to a number of characters while
preserving whole words and HTML tags
*
* (ripped off from Cake PHP framework)
*
* @param string $text String to truncate.
* @param integer $length Length of returned string, including ellipsis.
* @param string $ending Ending to be appended to the trimmed string.
* @param boolean $exact If false, $text will not be cut mid-word
* @param boolean $considerHtml If true, HTML tags would be handled
correctly
*
* @return string Trimmed string.
*/
public static function truncateHtml($text, $length = 100, $ending =
'...', $exact = false, $considerHtml = true)
{
if ($considerHtml)
{
// If the plain text is shorter than the maximum length, return the
whole text
if (strlen(preg_replace('/<.*?>/', '', $text))
<= $length)
{
return $text;
}
// Splits all html-tags to scanable lines
preg_match_all('/(<.+?>)?([^<>]*)/s', $text,
$lines, PREG_SET_ORDER);
$totalLength = strlen($ending);
$open_tags = array();
$truncate = '';
foreach ($lines as $lineMatchings)
{
// If there is any html-tag in this line, handle it and add it
(uncounted) to the output
if (!empty($lineMatchings[1]))
{
// If it's an "empty element" with or without
xhtml-conform closing slash
if
(preg_match('/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is',
$lineMatchings[1]))
{
// Do nothing if tag is a closing tag
}
else if (preg_match('/^<\s*\/([^\s]+?)\s*>$/s',
$lineMatchings[1], $tagMatchings))
{
// Delete tag from $open_tags list
$pos = array_search($tagMatchings[1], $open_tags);
if ($pos !== false)
{
unset($open_tags[$pos]);
}
// If tag is an opening tag
}
else if (preg_match('/^<\s*([^\s>!]+).*?>$/s',
$lineMatchings[1], $tagMatchings))
{
// Add tag to the beginning of $open_tags list
array_unshift($open_tags, strtolower($tagMatchings[1]));
}
// Add html-tag to $truncate'd text
$truncate .= $lineMatchings[1];
}
// Calculate the length of the plain text part of the line; handle
entities as one character
$contentLength =
strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i',
' ', $lineMatchings[2]));
if ($totalLength+$contentLength> $length)
{
// The number of characters which are left
$left = $length - $totalLength;
$entitiesLength = 0;
// Search for html entities
if
(preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i',
$lineMatchings[2], $entities, PREG_OFFSET_CAPTURE))
{
// Calculate the real length of all entities in the legal range
foreach ($entities[0] as $entity)
{
if ($entity[1]+1-$entitiesLength <= $left)
{
$left--;
$entitiesLength += strlen($entity[0]);
}
else
{
// No more characters left
break;
}
}
}
$truncate .= substr($lineMatchings[2], 0, $left + $entitiesLength);
// Maximum length is reached, so get off the loop
break;
}
else
{
$truncate .= $lineMatchings[2];
$totalLength += $contentLength;
}
// If the maximum length is reached, get off the loop
if($totalLength>= $length)
{
break;
}
}
}
else
{
if (strlen($text) <= $length)
{
return $text;
}
else
{
$truncate = substr($text, 0, $length - strlen($ending));
}
}
// If the words shouldn't be cut in the middle...
if (!$exact)
{
// ...search the last occurrence of a space...
$spacePos = strrpos($truncate, ' ');
if (isset($spacePos)) {
// ...and cut the text in this position
$truncate = substr($truncate, 0, $spacePos);
}
}
// add the defined ending to the text
$truncate .= $ending;
if($considerHtml)
{
// Close all unclosed html-tags
foreach ($open_tags as $tag)
{
$truncate .= '</' . $tag . '>';
}
}
return $truncate;
}
/**
* Truncate text possibly setting a tip to show all of the text
*
* @param string $text text to truncate
* @param array $opts optional options array
*
* @return string
*/
public static function truncate($text, $opts = array())
{
$origText = $text;
$wordCount = ArrayHelper::getValue($opts, 'wordcount', 10);
$showTip = ArrayHelper::getValue($opts, 'tip', true);
$title = ArrayHelper::getValue($opts, 'title', '');
$strippedText = htmlspecialchars(strip_tags($text), ENT_QUOTES);;
if (ArrayHelper::getValue($opts, 'html_format', false))
{
$summary = self::truncateHtml($text, $wordCount);
}
else if (ArrayHelper::getValue($opts, 'chars', false))
{
if (!empty($wordCount))
{
$summary = mb_strimwidth($text, 0, $wordCount, "...");
}
else
{
$summary = $text;
}
}
else
{
$text = htmlspecialchars(strip_tags($text), ENT_QUOTES);
$text = explode(' ', $text);
$summary = array_slice($text, 0, $wordCount);
if (count($text) > $wordCount)
{
$summary[] = " ...";
}
$summary = implode(' ', $summary);
}
if ($showTip && $origText != $summary)
{
Html::tips();
if ($title !== '')
{
$title .= "::";
}
$tip = htmlspecialchars('<div
class="truncate_text">' . $title . $strippedText .
'</div>');
$jOpts = new stdClass;
$jOpts->notice = true;
$jOpts->position = ArrayHelper::getValue($opts, 'position',
'top');
$jOpts = json_encode($jOpts);
$summary = '<span class="fabrikTip" opts=\''
. $jOpts . '\' title="' . $tip . '">'
. $summary . '</span>';
}
return $summary;
}
/**
* Removes a querystring key from a url/querystring
*
* @param string $url Or querystring
* @param string $key To remove
*
* @return string url/querystring
*/
public static function removeQSVar($url, $key)
{
$pair = explode('?', $url);
if (count($pair) === 2)
{
$url = $pair[0];
$bits = ArrayHelper::getValue($pair, 1);
}
else
{
$url = '';
$bits = ArrayHelper::getValue($pair, 0);
}
$glue = strstr($bits, '&') ? '&' :
'&';
$bits = explode($glue, $bits);
$a = array();
foreach ($bits as $bit)
{
if (strstr($bit, '='))
{
list($thisKey, $val) = explode('=', $bit);
if ($thisKey !== $key)
{
$a[] = $bit;
}
}
}
if (!empty($a))
{
$url .= '?' . implode($glue, $a);
}
return $url;
}
/**
* Encode a query string (that already has &s in it)
*
* @param $qs
*
* @return string
*/
public static function encodeqs($qs)
{
if (empty($qs))
{
return '';
}
$new_qs = array();
foreach (explode('&', $qs) as $arg)
{
$bits = explode('=', $arg);
$key = ArrayHelper::getValue($bits, 0, '');
$val = ArrayHelper::getValue($bits, 1, '');
$new_qs[] = $key . '=' . urlencode($val);
}
return implode('&', $new_qs);
}
/**
* Takes a complete URL, and urlencodes any query string args
*
* @param string $url To encode
*
* @return encoded url
*/
public static function encodeurl($url)
{
if (strstr($url, '?'))
{
list($site, $qs) = explode('?', $url);
if (!empty($qs))
{
$url = $site . '?' . self::encodeqs($qs);
}
}
if (strstr($url, '{'))
{
/* $$$ hugh special case for some Google URL's that use encoded
JSON objects in the path part of the URL
* so we need to re-encode {, }, " and :. Except of course for the
: in http(s):.
*/
list($http, $rest) = explode(':', $url, 2);
if (!empty($rest))
{
$patterns = array('#\{#', '#\}#',
'#"#', '#\\\\#', '#:#');
$replacements = array('%7B', '%7D',
'%22', '%5C', '%3A');
$rest = preg_replace($patterns, $replacements, $rest);
$url = $http . ':' . $rest;
}
}
return $url;
}
/**
* Prepare a string for presentation in html.
*
* @param string &$string To convert for html
*
* @return void
*/
public static function forHtml(&$string)
{
// Special chars such as <>
$string = htmlspecialchars($string, ENT_QUOTES);
// Show umlauts correctly in ajax error messages.
$string = mb_convert_encoding($string, 'HTML-ENTITIES',
"UTF-8");
}
/**
* See if it looks like a string uses {table___element} placeholders
* Doesn't do any sanity testing to see if it's actually a valid
element
* name, just goes by pattern patching word___word
*
* @param string $str String to test
*
* @return bool
*
* @since 3.0.1
*/
public static function usesElementPlaceholders($str)
{
return preg_match("#\{\w+___\w+\}#", $str);
}
/**
* Convert standard Fabrik coords string into lat, long, zoom object.
* Copied from map element, as we end up needing this elsewhere.
*
* @param string $v coordinates
* @param int $zoomLevel default zoom level
*
* @return object coords array and zoom level int
*/
public static function mapStrToCoords($v, $zoomLevel = 4)
{
$o = new stdClass;
$o->coords = array('', '');
$o->zoomlevel = (int) $zoomLevel;
if (strstr($v, ','))
{
$ar = explode(':', $v);
$o->zoomlevel = count($ar) == 2 ? array_pop($ar) : $zoomLevel;
$v = self::ltrimword($ar[0], '(');
$v = rtrim($v, ')');
$v = str_replace(' ', '', $v);
$o->coords = explode(',', $v);
}
else
{
$o->coords = array(0, 0);
}
// $$$ hugh - added these as I always think it's what they are!
$o->lat = $o->coords[0];
$o->long = $o->coords[1];
$o->zoom = $o->zoomlevel;
return $o;
}
/**
* Covert HEX colour to RGB colour
*
* @param string $hex HEX colour string
*
* @return string RGB string
*/
public static function hex2rgb($hex)
{
$hex = str_replace('#', '', $hex);
if (strlen($hex) === 3)
{
$r = hexdec(substr($hex, 0, 1) . substr($hex, 0, 1));
$g = hexdec(substr($hex, 1, 1) . substr($hex, 1, 1));
$b = hexdec(substr($hex, 2, 1) . substr($hex, 2, 1));
}
else
{
$r = hexdec(substr($hex, 0, 2));
$g = hexdec(substr($hex, 2, 2));
$b = hexdec(substr($hex, 4, 2));
}
return $r . ',' . $g . ',' . $b;
}
/**
* Translator Text wrapper - removes tags and compares raw text
* so "<p>STRING_TO_TRANSLATE</p>" is translated
even if wrapped in a <p> tag.
*
* @param string $text Text to translate
*
* @return string
*/
public static function translate($text)
{
if (empty($text)) return $text;
$plain = strip_tags($text);
$translated = Text::_($plain);
if ($translated !== $plain)
{
$text = str_replace($plain, $translated, $text);
}
return $text;
}
/**
* Is the string a CONCAT statement?
*
* @param string $text Text to test
*
* @return bool
*/
public static function isConcat($text)
{
return preg_match('/^\s*(CONCAT|CONCAT_WS)\b/i',
preg_quote($text));
}
/**
* Strip whitespace (or only spaces) from a string
*
* @param string $text Text to strip
* @param bool $only_spaces If true, only strip spaces (not tabs,
etc), default is false
*
* @return string
*/
public static function stripSpace($text, $only_spaces = false)
{
if ($only_spaces)
{
return str_replace(' ', '', $text);
}
else
{
return preg_replace('#\s+#', '', $text);
}
}
/**
* See if date string is a valid date in MySQL format.
*
* NOTE - I could have sworn we had a function somewhere to do this, but I
can't find it!
* Needed it in the main system plugin, for handling J! search plugin
dates, as J!
* will pitch a fatal error if we pass it an invalid date string. So if
there is
* already a way of doing this, feel free to dump this func and modify the
system plugin
* in onDoContentSearch().
*
* @param bool $time_optional if set to true, the time part is
optional
*
* @return bool
*/
public static function isMySQLDate($date, $time_optional = false)
{
$date_re =
'(((\d{4})(-)(0[13578]|10|12)(-)(0[1-9]|[12][0-9]|3[01]))|((\d{4})(-)(0[469]|1??1)(-)([0][1-9]|[12][0-9]|30))|';
$date_re .=
'((\d{4})(-)(02)(-)(0[1-9]|1[0-9]|2[0-8]))|(([02468]??[048]00)(-)(02)(-)(29))|(([13579][26]00)(-)(02)(-)(29))|';
$date_re .=
'(([0-9][0-9][0][48])(-)(0??2)(-)(29))|(([0-9][0-9][2468][048])(-)(02)(-)(29))|(([0-9][0-9][13579][26])(-)(02??)(-)(29)))';
$time_re = '(\s([0-1][0-9]|2[0-4]):([0-5][0-9]):([0-5][0-9]))';
if ($time_optional)
{
return preg_match("#^" . $date_re . "$#", $date) ||
preg_match("#^" . $date_re . $time_re . "$#", $date);
}
else
{
return preg_match("#^" . $date_re . $time_re . "$#",
$date);
}
}
/**
* Replace last occurrence of a string
*
* @param string $search Text to search for
* @param string $replace Text to replace the search string
* @param string $subject The text to search in
*
* @return string
*/
public static function replaceLast($search, $replace, $subject)
{
$pos = strripos($subject, $search);
if ($pos !== false)
{
$subject = substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
/**
* DB value quote a single string or an array of strings, first checking
to see if they are
* already quoted. Which the J! $db->quote() doesn't do,
unfortunately.
* Does NOT modify the input. Does not quote if value starts with SELECT.
*
* @param unknown $values
* @param bool $commaSeparated individually quote a comma separated
string of values
*
* @return mixed quoted values
*/
public static function safeQuote($values, $commaSeparated = true) {
$values2 = $values;
if ($commaSeparated)
{
$values2 = explode(',', $values2);
}
if (is_array($values2))
{
foreach ($values2 as &$v)
{
$v = self::safeQuoteOne($v);
}
}
else
{
$values2 = self::safeQuoteOne($values2);
}
if ($commaSeparated)
{
$values2 = implode(',', $values2);
}
return $values2;
}
/**
* Return DB value quoted single string. Does not quote if value starts
with SELECT,
* or if value is already single quoted.
*
* @param string $value
*
* @return mixed quoted values
*/
public static function safeQuoteOne($value)
{
$value = trim($value);
if (is_string($value) &&
!preg_match('/^\s*SELECT\s+/i', $value))
{
if (!preg_match("#^'.*'$#", $value))
{
$db = Factory::getContainer()->get('DatabaseDriver');
$value = $db->quote($value);
}
}
return $value;
}
/**
* Wrapper for safeQuoteName because I'm a dumbass and got my mords
wuddled when I created
* the safeNameQuote() function.
*
* @param unknown $values
* @param bool $commaSeparated individually quote a comma separated
string of values
*
* @return mixed quoted values
*/
public static function safeQuoteName($values, $commaSeparated = true)
{
return self::safeNameQuote($values, $commaSeparated);
}
/**
* DB name quote a single string or an array of strings, first checking to
see if they are
* already quoted. Which the J! $db->quote() doesn't do,
unfortunately.
* Does NOT modify the input. Does not quote if value starts with CONCAT.
*
* @param string|array $values
* @param bool $commaSeparated individually quote a comma
separated string of values
*
* @return mixed quoted values
*/
public static function safeNameQuote($values, $commaSeparated = true)
{
$values2 = $values;
if ($commaSeparated)
{
$values2 = explode(',', $values2);
}
if (is_array($values2))
{
foreach ($values2 as &$v)
{
$v = self::safeNameQuoteOne($v);
}
}
else
{
$values2 = self::safeNameQuoteOne($values2);
}
if ($commaSeparated)
{
$values2 = implode(',', $values2);
}
return $values2;
}
/**
* Return DB value quoted single string. Does not quote if value starts
with SELECT,
* or if value is already single quoted.
*
* @param string $value
*
* @return mixed quoted values
*/
public static function safeNameQuoteOne($value)
{
$value = trim($value);
if (is_string($value) &&
!preg_match('/^\s*(CONCAT|CONCAT_WS)\s*\(/i', $value))
{
if (!preg_match("#^`.*`$#", $value))
{
$db = Factory::getContainer()->get('DatabaseDriver');
$value = $db->quoteName($value);
}
}
return $value;
}
/**
* Return appropriate query string sepchar
*
* @param string $url
*
* @return string query string sepchar
*/
public static function qsSepChar($url)
{
if (strstr($url, '?'))
{
if (substr($url, -1) === '?')
{
return '';
}
else
{
return '&';
}
}
else
{
return '?';
}
}
/**
* Get a validated server remote address (I.P.). If not valid return
''
*
* @return string
*/
public static function filteredIp()
{
return filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP)
!== false ? $_SERVER['REMOTE_ADDR'] : '';
}
public static function getRowClass($value, $prefix)
{
// when called in form context, could be a single value array
if (is_array($value))
{
$value = empty($value) ? '' : reset($value);
}
$value = preg_replace('/[^A-Z|a-z|0-9]/', '-',
$value);
$value = self::ltrim($value, '-');
$value = self::rtrim($value, '-');
// $$$ rob 24/02/2011 can't have numeric class names so prefix with
element name
// $$$ hugh can't have class names which start with a number, so
need preg_match, not is_numeric()
if (preg_match('#^\d#', $value))
{
$value = $prefix . $value;
}
else
{
// 12/10/2016 - for consistency, start adding the prefixed version every
time
$value .= " " . $prefix . $value;
}
return $value;
}
/**
* Apply nl2br only outside of chevroned tags, eq. not between <...>
*
* @param $string
*
* @return mixed
*/
public static function safeNl2br($string)
{
//
https://stackoverflow.com/questions/4603780/preg-replace-only-outside-tags-were-not-talking-full-html-parsing-jus
$parts =
preg_split('/(<(?:[^"\'>]|"[^"<]*"|\'[^\'<]*\')*>)/',
$string, -1, PREG_SPLIT_DELIM_CAPTURE);
for ($i=0, $n=count($parts); $i<$n; $i+=2) {
$parts[$i] = nl2br($parts[$i]);
}
return implode('', $parts);
}
/**
* Bitlify a link
*
* @param string $link the link to shorten
* @param string $username Bitly username - NOT USED
* @param string $apikey Bitly API key
* @param string $encode urlencode
*/
public static function bitlify ($link, $login, $apikey, $encode = true)
{
if (!strstr($link, 'bit.ly/') && $link !==
'')
{
$api = new Api($apikey);
$bitlink = new Bitlink($api);
$result = $bitlink->createBitlink(['long_url' =>
$link]);
if ($api->isCurlError())
{
Worker::log('fabrik.helpers.bitlify.error',$api->getCurlErrno().':
'.$api->getCurlError());
}
else
{
if ($result->isError())
{
Worker::log('fabrik.helpers.bitlify.error',
print($result->getResponse()));
}
else
{
if ($result->isSuccess())
{
$link = $result->getResponseObject()->link;
}
else
{
Worker::log('fabrik.helpers.bitlify.error',
print($result->getResponse()));
}
}
}
}
return $link;
}
}
fabrik/fabrik/Helpers/Stripe.php000064400000002437151165341630012634
0ustar00<?php
/**
* PDF Set up helper
*
* @package Joomla
* @subpackage Fabrik.helpers
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
/**
* Stripe set up helper
*
* @package Joomla
* @subpackage Fabrik.helpers
* @since 3.1rc3
*/
class Stripe
{
/**
* Setup Stripe API
*
* @param object $puke throw exception if not installed (true) or just
return false
*
* @return bool
*/
public static function setupStripe(\Joomla\Registry\Registry $params,
$plugin)
{
$testMode = $params->get($plugin . '_test_mode',
'0') === '1';
if ($testMode)
{
$secretKey = trim($params->get($plugin .
'_test_secret_key', ''));
}
else
{
$secretKey = trim($params->get($plugin . '_secret_key',
''));
}
if (empty($secretKey))
{
return false;
}
\Stripe\Stripe::setApiKey($secretKey);
\Stripe\Stripe::setApiVersion('2018-01-23');
\Stripe\Stripe::setAppInfo(
"Joomla Fabrik " . $plugin,
"3.8.0",
"http://fabrikar.com"
);
/*
try
{
$balance = \Stripe\Balance::retrieve();
}
catch (\Exception $e)
{
return false;
}
*/
return true;
}
}
fabrik/fabrik/Helpers/Uploader.php000064400000015506151165341630013142
0ustar00<?php
/**
* Fabrik upload helper
*
* @package Joomla
* @subpackage Fabrik
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Factory;
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Folder;
use Joomla\Registry\Registry;
use RuntimeException;
/**
* Fabrik upload helper
*
* @package Joomla
* @subpackage Fabrik
* @since 3.0
*/
class Uploader extends CMSObject
{
/**
* Form model
*
* @var object
*/
protected $form = null;
/**
* Move uploaded file error
*
* @var bool
*/
public $moveError = false;
/**
* Upload
*
* @param object $formModel form model
*/
public function __construct($formModel)
{
$this->form = $formModel;
}
/**
* Perform upload of files
*
* @return bool true if error occurred
*/
public function upload()
{
$groups = $this->form->getGroupsHiarachy();
foreach ($groups as $groupModel)
{
$elementModels = $groupModel->getPublishedElements();
foreach ($elementModels as $elementModel)
{
if ($elementModel->isUpload())
{
$elementModel->processUpload();
}
}
}
}
/**
* Moves a file from one location to another
*
* @param string $pathFrom File to move
* @param string $pathTo Location to move file to
* @param bool $overwrite Should we overwrite existing files
*
* @deprecated (don't think its used)
*
* @return bool do we overwrite any existing files found at pathTo?
*/
public function move($pathFrom, $pathTo, $overwrite = true)
{
if (file_exists($pathTo))
{
if ($overwrite)
{
unlink($pathTo);
$ok = rename($pathFrom, $pathTo);
}
else
{
$ok = false;
}
}
else
{
$ok = rename($pathFrom, $pathTo);
}
return $ok;
}
/**
* Make a recursive folder structure
*
* @param string $folderPath Path to folder - e.g. /images/stories
* @param hex $mode Folder permissions
*
* @return void
*/
public function _makeRecursiveFolders($folderPath, $mode = 0755)
{
if (!Folder::exists($folderPath))
{
if (!Folder::create($folderPath, $mode))
{
throw new RuntimeException("Could not make dir $folderPath
");
}
}
}
/**
* Iterates through $_FILE data to see if any files have been uploaded
*
* @deprecated (don't see it being used)
*
* @return bool true if files uploaded
*/
public function check()
{
if (isset($_FILES) and !empty($_FILES))
{
foreach ($_FILES as $f)
{
if ($f['name'] != '')
{
return true;
}
}
}
return false;
}
/**
* Checks if the file can be uploaded
*
* @param array $file File information
* @param string &$err An error message to be returned
* @param Registry &$params Params
*
* @return bool
*/
public static function canUpload($file, &$err, &$params)
{
if (empty($file['name']))
{
$err = 'Please input a file for upload';
return false;
}
/**
* If we're AJAX uploading and WiP is set, don't check
is_uploaded_file, because it won't be,
* we uploaded it direct from the form through AJAX to our own tmp
location, now we're just moving it
*/
if (!($params->get('ajax_upload', '0') ===
'1' && $params->get('upload_use_wip',
'0') === '1') &&
!is_uploaded_file($file['tmp_name']))
{
// Handle potential malicious attack
$err = Text::_('File has not been uploaded');
return false;
}
jimport('joomla.filesystem.file');
$format =
StringHelper::strtolower(File::getExt($file['name']));
$allowable = explode(',',
StringHelper::strtolower($params->get('ul_file_types')));
$format = StringHelper::ltrimword($format, '.');
$format2 = ".$format";
if (!in_array($format, $allowable) && !in_array($format2,
$allowable))
{
$err = 'WARNFILETYPE';
return false;
}
$maxSize = (int) $params->get('upload_maxsize', 0);
if ($maxSize > 0 && (int) $file['size'] >
$maxSize)
{
$err = 'WARNFILETOOLARGE';
return false;
}
$ignored = array();
$user = Factory::getUser();
$imginfo = null;
if ($params->get('restrict_uploads', 1))
{
$images = explode(',',
$params->get('image_extensions'));
if (in_array($format, $images))
{
// If its an image run it through getimagesize
if (($imginfo = getimagesize($file['tmp_name'])) === false)
{
$err = 'WARNINVALIDIMG';
return false;
}
}
elseif (!in_array($format, $ignored))
{
// If its not an image...and we're not ignoring it
}
}
$xss_check = file_get_contents($file['tmp_name'], false, null,
0, 256);
$html_tags = array('abbr', 'acronym',
'address', 'applet', 'area',
'audioscope', 'base', 'basefont',
'bdo', 'bgsound', 'big',
'blackface',
'blink', 'blockquote', 'body',
'bq', 'br', 'button', 'caption',
'center', 'cite', 'code', 'col',
'colgroup', 'comment', 'custom',
'dd',
'del', 'dfn', 'dir', 'div',
'dl', 'dt', 'em', 'embed',
'fieldset', 'fn', 'font', 'form',
'frame', 'frameset', 'h1', 'h2',
'h3', 'h4',
'h5', 'h6', 'head', 'hr',
'html', 'iframe', 'ilayer', 'img',
'input', 'ins', 'isindex',
'keygen', 'kbd', 'label', 'layer',
'legend',
'li', 'limittext', 'link',
'listing', 'map', 'marquee',
'menu', 'meta', 'multicol', 'nobr',
'noembed', 'noframes', 'noscript',
'nosmartquotes', 'object', 'ol',
'optgroup', 'option', 'param',
'plaintext', 'pre', 'rt', 'ruby',
's', 'samp', 'script', 'select',
'server', 'shadow', 'sidebar',
'small', 'spacer', 'span',
'strike', 'strong', 'style', 'sub',
'sup', 'table', 'tbody', 'td',
'textarea',
'tfoot', 'th', 'thead', 'title',
'tr', 'tt', 'ul', 'var',
'wbr', 'xml', 'xmp', '!DOCTYPE',
'!--');
foreach ($html_tags as $tag)
{
// A tag is '<tagname ', so we need to add < and a space
or '<tagname>'
if (StringHelper::stristr($xss_check, '<' . $tag . '
') || StringHelper::stristr($xss_check, '<' . $tag .
'>'))
{
$err = 'WARNIEXSS';
return false;
}
}
return true;
}
/**
* Recursive file name incrementation until no file with existing name
* exists
*
* @param string $origFileName Initial file name
* @param string $newFileName This recursions file name
* @param int $version File version
* @params object $storage Storage adapter
*
* @return string New file name
*/
public static function incrementFileName($origFileName, $newFileName,
$version, $storage)
{
if ($storage->exists($newFileName))
{
$bits = explode('.', $newFileName);
$ext = array_pop($bits);
$f = implode('.', $bits);
$f = StringHelper::rtrim($f, $version - 1);
$newFileName = $f . $version . "." . $ext;
$version++;
$newFileName = self::incrementFileName($origFileName, $newFileName,
$version, $storage);
}
return $newFileName;
}
}
fabrik/fabrik/Helpers/Worker.php000064400000230161151165341630012634
0ustar00<?php
/**
* Generic tools that all models use
*
* @package Joomla
* @subpackage Fabrik
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
namespace Fabrik\Helpers;
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Access\Access;
use Joomla\CMS\Language\LanguageHelper;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Version;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Cache\Cache;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Factory;
use Joomla\CMS\Mail\Mail;
use Joomla\CMS\Mail\MailHelper;
use Joomla\CMS\Crypt\Crypt;
use Joomla\CMS\Crypt\Key;
use Joomla\CMS\Crypt\Cipher\SimpleCipher;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Path;
use Joomla\Database\DatabaseDriver;
use Joomla\CMS\Date\Date;
use Joomla\CMS\Language\Text;
use Fabrik\Helpers\FCipher;
use FabTable;
use Joomla\CMS\Application\CMSApplication;
use Fabrik\Helpers\Php;
/**
* Generic tools that all models use
* This code used to be in models/parent.php
*
* @package Joomla
* @subpackage Fabrik.helpers
* @since 3.0
*/
class Worker
{
/**
* Fabrik database objects
*
* @var JDatabaseDriver[]
*/
public static $database = null;
/**
* Fabrik db connections
*
* @var array
*/
public static $connection = null;
/**
* Plugin manager
*
* @var object
*/
public static $pluginManager = null;
/**
* Strtotime final date format
*
* @var string
*/
static protected $finalFormat = null;
/**
* Add slashes in parse message
*
* @var bool
*/
protected $parseAddSlashes = false;
/**
* Search data to replace placeholders
*
* @var array
*/
protected $_searchData = array();
/**
* Get array of valid view types
*
* @return array
*/
public static function getViewTypes()
{
return array(
'article',
'cron',
'csv',
'details',
'element',
'form',
'list',
'package',
'visualization'
);
}
/**
* Returns true if $view is a valid view type
*
* @param string $view View type
*
* @return bool
*/
public static function isViewType($view)
{
$view = strtolower(trim($view));
$viewTypes = self::getViewTypes();
return in_array($view, $viewTypes);
}
/**
* Returns true if $file has an image extension type
*
* @param string $file Filename
*
* @return bool
*/
public static function isImageExtension($file)
{
$path_parts = pathinfo($file);
if (array_key_exists('extension', $path_parts))
{
$image_extensions_eregi = 'bmp|gif|jpg|jpeg|png';
return preg_match('/' . $image_extensions_eregi .
'/i', $path_parts['extension']) > 0;
}
return false;
}
/**
* Get audio mime type array, keyed by file extension
*
* @return array
*/
public static function getAudioMimeTypes()
{
return array(
'mp3' => 'audio/x-mpeg',
'm4a' => 'audio/x-m4a'
);
}
/**
* Get audio mime type array, keyed by file extension
*
* @return array
*/
public static function getImageMimeTypes()
{
return array(
'png' => 'image/png',
'gif' => 'image/gif',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'bmp' => 'image/bmp',
'webp' => 'image/webp'
);
}
/**
* Get document mime type array, keyed by file extension
*
* @return array
*/
public static function getDocMimeTypes()
{
return array(
'pdf' => 'application/pdf',
'epub' => 'document/x-epub'
);
}
/**
* Get video mime type array, keyed by file extension
*
* @return array
*/
public static function getVideoMimeTypes()
{
return array(
'mp4' => 'video/mp4',
'm4v' => 'video/x-m4v',
'mov' => 'video/quicktime'
);
}
/**
* Get Audio Mime type
*
* @param string $file Filename
*
* @return bool|string
*/
public static function getAudioMimeType($file)
{
$path_parts = pathinfo($file);
$types = self::getAudioMimeTypes();
return ArrayHelper::getValue(
$types,
ArrayHelper::getValue($path_parts, 'extension',
''),
false
);
}
/**
* Get Audio Mime type
*
* @param string $file Filename
*
* @return bool|string
*/
public static function getImageMimeType($file)
{
$path_parts = pathinfo($file);
$types = self::getImageMimeTypes();
return ArrayHelper::getValue(
$types,
ArrayHelper::getValue($path_parts, 'extension',
''),
false
);
}
/**
* Get Video Mime type
*
* @param string $file Filename
*
* @return bool|string
*/
public static function getVideoMimeType($file)
{
$path_parts = pathinfo($file);
$types = self::getVideoMimeTypes();
return ArrayHelper::getValue(
$types,
ArrayHelper::getValue($path_parts, 'extension',
''),
false
);
}
/**
* Get Doc Mime type
*
* @param string $file Filename
*
* @return bool|string
*/
public static function getDocMimeType($file)
{
$path_parts = pathinfo($file);
$types = self::getDocMimeTypes();
return ArrayHelper::getValue(
$types,
ArrayHelper::getValue($path_parts, 'extension',
''),
false
);
}
/**
* Get Podcast Mime type
*
* @param string $file Filename
*
* @return bool|string
*/
public static function getPodcastMimeType($file)
{
$mime_type = false;
if ($mime_type = self::getVideoMimeType($file))
{
return $mime_type;
}
elseif ($mime_type = self::getAudioMimeType($file))
{
return $mime_type;
}
elseif ($mime_type = self::getDocMimeType($file))
{
return $mime_type;
}
elseif ($mime_type = self::getImageMimeType($file))
{
return $mime_type;
}
return $mime_type;
}
/**
* Format a string to datetime
*
* http://fr.php.net/strftime
* (use as strftime)
*
* @param string $date String date to format
* @param string $format Date format strftime format
*
* @return array|void date info
*/
public static function strToDateTime($date, $format)
{
$weekdays = array('Sun' => '0', 'Mon'
=> '1', 'Tue' => '2', 'Wed'
=> '3', 'Thu' => '4', 'Fri'
=> '5', 'Sat' => '6');
if (!($date = self::str2Time($date, $format)))
{
return;
}
$shortMonths = array(Text::_('Jan'), Text::_('Feb'),
Text::_('Mar'), Text::_('Apr'),
Text::_('May'), Text::_('Jun'),
Text::_('Jul'),
Text::_('Aug'), Text::_('Sept'),
Text::_('Oct'), Text::_('Nov'),
Text::_('Dec'));
/*$$ rob set day default to 1, so that if you have a date format string
of %m-%Y the day is set to the first day of the month
* and not the last day of the previous month (which is what a 0 here
would represent)
*/
$dateTime = array('sec' => 0, 'min' => 0,
'hour' => 0, 'day' => 1, 'mon' => 0,
'year' => 0, 'timestamp' => 0);
foreach ($date as $key => $val)
{
switch ($key)
{
case 'd':
case 'e':
case 'j':
$dateTime['day'] = intval($val);
break;
case 'D':
$dateTime['day'] = intval($weekdays[$val]);
break;
case 'm':
case 'n':
$dateTime['mon'] = intval($val);
break;
case 'b':
$dateTime['mon'] = $shortMonths[$val] + 1;
break;
case 'Y':
$dateTime['year'] = intval($val);
break;
case 'y':
$dateTime['year'] = intval($val) + 2000;
break;
case 'G':
case 'g':
case 'H':
case 'h':
$dateTime['hour'] = intval($val);
break;
case 'M':
$dateTime['min'] = intval($val);
break;
case 'i':
$dateTime['min'] = intval($val);
break;
case 's':
case 'S':
$dateTime['sec'] = intval($val);
break;
}
}
$dateTime['timestamp'] = mktime($dateTime['hour'],
$dateTime['min'], $dateTime['sec'],
$dateTime['mon'], $dateTime['day'],
$dateTime['year']);
return $dateTime;
}
/**
* Check for, and convert, any 'special' formats for strtotime,
like 'yesterday', etc.
*
* @param string $date Date to check
* @param bool $gmt Set date to universal time?
*
* @return string date
*/
public static function specialStrToMySQL($date, $gmt = true)
{
/**
* $$$ hugh - if date is empty, just return today's date
*/
if (empty($date))
{
$d = Factory::getDate();
$date = $d->toSql(!$gmt);
return $date;
}
/**
* lets check if we have some special text as per :
* http://php.net/strtotime - this means we can use "+2 week"
as a url filter
* do this before we urldecode the date otherwise the + is replaced with
' ';
*/
$matches = array();
$matches2 = array();
$matches3 = array();
// E.g. now
preg_match("/(now|ago|midnight|yesterday|today)/i", $date,
$matches);
// E.g. +2 Week
preg_match("/[+|-][0-9]* (week\b|year\b|day\b|month\b)/i",
$date, $matches2);
// E.g. next Wednesday
preg_match("/[next|last]*
(monday\b|tuesday\b|wednesday\b|thursday\b|friday\b|saturday\b|sunday\b)/i",
$date, $matches3);
$matches = array_merge($matches, $matches2, $matches3);
if (!empty($matches))
{
$d = Factory::getDate($date);
$date = $d->toSql(!$gmt);
}
return $date;
}
/**
* String to time
*
* @param string $date Date representation
* @param string $format Date format
*
* @return array date bits keyed on date representations e.g. m/d/Y
*/
public static function str2Time($date, $format)
{
/**
* lets check if we have some special text as per :
* http://php.net/strtotime - this means we can use "+2 week"
as a url filter
* do this before we urldecode the date otherwise the + is replaced with
' ';
*/
$matches = array();
$matches2 = array();
$matches3 = array();
// E.g. now
preg_match("/[now|ago|midnight|yesterday|today]/i", $date,
$matches);
// E.g. +2 Week
preg_match("/[+|-][0-9]* (week\b|year\b|day\b|month\b)/i",
$date, $matches2);
// E.g. next Wednesday
preg_match("/[next|last]*
(monday\b|tuesday\b|wednesday\b|thursday\b|friday\b|saturday\b|sunday\b)/i",
$date, $matches3);
$matches = array_merge($matches, $matches2, $matches3);
if (!empty($matches))
{
$d = Factory::getDate($date);
$date = $d->format($format);
}
/* $$$ - hugh : urldecode (useful when ajax calls, may need better fix)
* as per http://fabrikar.com/forums/showthread.php?p=43314#post43314
*/
$date = urldecode($date);
// Strip any textual date representations from the string
$days = array('%A', '%a');
foreach ($days as $day)
{
if (strstr($format, $day))
{
$format = str_replace($day, '', $format);
$date = self::stripDay($date, $day == '%a' ? true : false);
}
}
$months = array('%B', '%b', '%h');
foreach ($months as $month)
{
if (strstr($format, $month))
{
$format = str_replace($month, '%m', $format);
$date = self::monthToInt($date, $month == '%B' ? false :
true);
}
}
// @TODO: some of these aren't right for strftime
self::$finalFormat = $format;
$search = array('%d', '%e',
'%D', '%j', '%m', '%b',
'%Y', '%y', '%g', '%H',
'%h', '%i', '%s', '%S',
'%M');
$replace = array('(\d{2})', '(\d{1,2})',
'(\w{3})', '(\d{1,2})', '(\d{2})',
'(\w{3})', '(\d{4})', '(\d{2})',
'(\d{1,2})', '(\d{2})',
'(\d{2})', '(\d{2})', '(\d{2})',
'(\d{2})', '(\d{2})');
$pattern = str_replace($search, $replace, $format);
if (!preg_match("#$pattern#", $date, $matches))
{
// Lets allow for partial date formats - e.g. just the date and ignore
the time
$format = explode('%', $format);
if (empty($format))
{
// No format left to test so return false
return false;
}
array_pop($format);
$format = trim(implode('%', $format));
self::$finalFormat = $format;
return self::str2Time($date, $format);
}
$dp = $matches;
if (!preg_match_all('#%(\w)#', $format, $matches))
{
return false;
}
$id = $matches['1'];
if (count($dp) != count($id) + 1)
{
return false;
}
$ret = array();
for ($i = 0, $j = count($id); $i < $j; $i++)
{
$ret[$id[$i]] = $dp[$i + 1];
}
return $ret;
}
/**
* Removed day of week name from string
*
* @param string $date The string date
* @param bool $abrv Abbreviated day?
*
* @return string date
*/
public static function stripDay($date, $abrv = false)
{
if ($abrv)
{
$date = str_replace(Text::_('SUN'), '', $date);
$date = str_replace(Text::_('MON'), '', $date);
$date = str_replace(Text::_('TUE'), '', $date);
$date = str_replace(Text::_('WED'), '', $date);
$date = str_replace(Text::_('THU'), '', $date);
$date = str_replace(Text::_('FRI'), '', $date);
$date = str_replace(Text::_('SAT'), '', $date);
}
else
{
$date = str_replace(Text::_('SUNDAY'), '', $date);
$date = str_replace(Text::_('MONDAY'), '', $date);
$date = str_replace(Text::_('TUESDAY'), '', $date);
$date = str_replace(Text::_('WEDNESDAY'), '',
$date);
$date = str_replace(Text::_('THURSDAY'), '', $date);
$date = str_replace(Text::_('FRIDAY'), '', $date);
$date = str_replace(Text::_('SATURDAY'), '', $date);
}
return $date;
}
/**
* Convert a month (could be in any language) into the month number (1 =
jan)
*
* @param string $date Data to convert
* @param bool $abrv Is the month is a short or full name version
*
* @return string
*/
public static function monthToInt($date, $abrv = false)
{
if ($abrv)
{
$date = str_replace(Text::_('JANUARY_SHORT'), '01',
$date);
$date = str_replace(Text::_('FEBRUARY_SHORT'), '02',
$date);
$date = str_replace(Text::_('MARCH_SHORT'), '03',
$date);
$date = str_replace(Text::_('APRIL_SHORT'), '04',
$date);
$date = str_replace(Text::_('MAY_SHORT'), '05',
$date);
$date = str_replace(Text::_('JUNE_SHORT'), '06',
$date);
$date = str_replace(Text::_('JULY_SHORT'), '07',
$date);
$date = str_replace(Text::_('AUGUST_SHORT'), '08',
$date);
$date = str_replace(Text::_('SEPTEMBER_SHORT'),
'09', $date);
$date = str_replace(Text::_('OCTOBER_SHORT'), 10, $date);
$date = str_replace(Text::_('NOVEMBER_SHORT'), 11, $date);
$date = str_replace(Text::_('DECEMBER_SHORT'), 12, $date);
}
else
{
$date = str_replace(Text::_('JANUARY'), '01',
$date);
$date = str_replace(Text::_('FEBRUARY'), '02',
$date);
$date = str_replace(Text::_('MARCH'), '03', $date);
$date = str_replace(Text::_('APRIL'), '04', $date);
$date = str_replace(Text::_('MAY'), '05', $date);
$date = str_replace(Text::_('JUNE'), '06', $date);
$date = str_replace(Text::_('JULY'), '07', $date);
$date = str_replace(Text::_('AUGUST'), '08', $date);
$date = str_replace(Text::_('SEPTEMBER'), '09',
$date);
$date = str_replace(Text::_('OCTOBER'), 10, $date);
$date = str_replace(Text::_('NOVEMBER'), 11, $date);
$date = str_replace(Text::_('DECEMBER'), 12, $date);
}
return $date;
}
/**
* Check a string is not reserved by Fabrik
*
* @param string $str To check
* @param bool $strict Include things like rowid, listid in the
reserved words, defaults to true
*
* @return bool
*/
public static function isReserved($str, $strict = true)
{
$reservedWords = array("task", "view",
"layout", "option", "formid",
"submit", "ul_max_file_size"
, "ul_file_types", "ul_directory",
'adddropdownvalue', 'adddropdownlabel',
'ul_end_dir');
/*
* $$$ hugh - a little arbitrary, but need to be able to exclude these so
people can create lists from things like
* log files, which include field names like rowid and itemid. So when
saving an element, we now set strict mode
* to false if it's not a new element.
*/
$strictWords = array("listid", 'rowid',
'itemid');
if ($strict)
{
$reservedWords = array_merge($reservedWords, $strictWords);
}
if (in_array(StringHelper::strtolower($str), $reservedWords))
{
return true;
}
return false;
}
/**
* Check a string is valid to use as an element name
*
* @param string $str To check
* @param bool $strict Include things like rowid, listid in the
reserved words, defaults to true
*
* @return bool
*/
public static function validElementName($str, $strict = true)
{
// check if it's a Fabrik reserved word
if (self::isReserved($str, $strict))
{
return false;
}
// check valid MySQL - start with letter or _, then only alphanumeric or
underscore
if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $str))
{
return false;
}
// check for various other gotchas, like ending in _raw, starting with
more than one _, etc.
if (preg_match('/^submit|^__|_raw$/', $str))
{
return false;
}
return true;
}
/**
* Get the crypt object
*
* @param string type type of encryption (aes, crypt or simple)
*
* @since 3.1
*
* @return Fabrik\Helpers\FCipher
*/
public static function getCrypt($type = 'simple')
{
return new FCipher($type);
}
/**
* Special case placeholder handling for repeat data. When something
(usually an element plugin) is doing
* replacements for elements which are in the "same" repeat
group, almost always they will want
* the value for the same repeat instance, not a comma seperated list of
all the values. So (say)
* the upload element is creating a file path, for an upload element in a
repeat group, of ...
* '/uploads/{repeat_table___userid}/', and there are 4 repeat
instance, it doesn't want a path of ...
* '/uploads/34,45,94,103/', it just wants the one value from
the same repeat count as the upload
* element. Or a calc element doing "return
'{repeat_table___first_name} {repeat_table___last_name}';".
Etc.
*
* Rather than make this a part of parseMessageForPlaceHolder, for now
I'm making it a sperate function,
* which just handles this one very specific data replacement. Will look
at merging it in with the main
* parsing once we have a better understanding of where / when / how to do
it.
*
* @param string $msg Text to parse
* @param array $searchData Data to search for placeholders
* @param object $el Element model of the element which is
doing the replacing
* @param int $repeatCounter Repeat instance
*
* @return string parsed message
*/
public function parseMessageForRepeats($msg, $searchData, $el,
$repeatCounter)
{
if (strstr($msg??'', '{') &&
!empty($searchData))
{
$groupModel = $el->getGroupModel();
if ($groupModel->canRepeat())
{
$elementModels = $groupModel->getPublishedElements();
$formModel = $el->getFormModel();
foreach ($elementModels as $elementModel)
{
$repeatElName = $elementModel->getFullName(true, false);
foreach (array($repeatElName, $repeatElName . '_raw') as
$tmpElName)
{
if (strstr($msg, '{' . $tmpElName . '}'))
{
if (array_key_exists($tmpElName, $searchData) &&
is_array($searchData[$tmpElName]) &&
array_key_exists($repeatCounter, $searchData[$tmpElName]))
{
$tmpVal = $searchData[$tmpElName][$repeatCounter];
if (is_array($tmpVal))
{
$tmpVal = implode(',', $tmpVal);
}
$msg = str_replace('{' . $tmpElName . '}',
$tmpVal??'', $msg);
}
}
}
}
}
}
return $msg;
}
/**
* Iterates through string to replace every
* {placeholder} with posted data
*
* @param mixed $msg Text|Array to parse
* @param array $searchData Data to search for placeholders
(default $_REQUEST)
* @param bool $keepPlaceholders If no data found for the place holder
do we keep the {...} string in the
* message
* @param bool $addSlashes Add slashed to the text?
* @param object $theirUser User to use in replaceWithUserData
(defaults to logged in user)
* @param bool $unsafe If true (default) will not replace
certain placeholders like $jConfig_secret
* must not be shown to users
*
* @return string parsed message
*/
public function parseMessageForPlaceHolder($msg, $searchData = null,
$keepPlaceholders = true, $addSlashes = false, $theirUser = null, $unsafe =
true)
{
$returnType = is_array($msg) ? 'array' : 'string';
$messages = (array) $msg;
foreach ($messages as &$msg)
{
$this->parseAddSlashes = $addSlashes;
if (!($msg == '' || is_array($msg) ||
StringHelper::strpos($msg, '{') === false))
{
$msg = str_replace(array('%7B', '%7D'),
array('{', '}'), $msg);
if (is_object($searchData))
{
$searchData = ArrayHelper::fromObject($searchData);
}
// Merge in request and specified search data
$f = InputFilter::getInstance();
$post = $f->clean($_REQUEST, 'array');
//J!4 & SEF: $_REQUEST is empty, take also inputVars
$app = Factory::getApplication();
$inputVars = $app->getInput()->getArray();
$inputVars = $f->clean($inputVars,'string');
$searchData = is_null($searchData) ? $inputVars :
array_merge($inputVars, $searchData);
$this->_searchData = is_null($searchData) ? $post :
array_merge($post, $searchData);
// Enable users to use placeholder to insert session token
$this->_searchData['Session::getFormToken'] =
Session::getFormToken();
// Replace with the user's data
$msg = self::replaceWithUserData($msg);
if (!is_null($theirUser))
{
// Replace with a specified user's data
$msg = self::replaceWithUserData($msg, $theirUser, 'your');
}
$msg = self::replaceWithGlobals($msg);
if (!$unsafe)
{
$msg = self::replaceWithUnsafe($msg);
$msg = self::replaceWithSession($msg);
}
$msg = preg_replace("/{}/", "", $msg);
// Replace {element name} with form data
$msg =
preg_replace_callback("/{([^}\s]+(\|\|[\w|\s]+|<\?php.*\?>)*)}/i",
array($this, 'replaceWithFormData'), $msg);
if (!$keepPlaceholders)
{
$msg = preg_replace("/{[^}\s]+}/i", '', $msg);
}
}
}
return $returnType === 'array' ? $messages :
ArrayHelper::getValue($messages, 0, '');
}
/**
* Replace {varname} with request data (called from J content plugin)
*
* @param string &$msg String to parse
*
* @return void
*/
public function replaceRequest(&$msg)
{
static $request;
if (!is_array($request))
{
$request = array();
$f = InputFilter::getInstance();
foreach ($_REQUEST as $k => $v)
{
if (is_string($v))
{
$request[$k] = $f->clean($v, 'CMD');
}
}
}
foreach ($request as $key => $val)
{
if (is_string($val))
{
// $$$ hugh - escape the key so preg_replace won't puke if key
contains /
$key = str_replace('/', '\/', $key);
$msg = preg_replace("/\{$key\}/", $val, $msg);
}
}
}
/**
* Called from parseMessageForPlaceHolder to iterate through string to
replace
* {placeholder} with user ($my) data
* AND
* {$their->var->email} placeholders
*
* @param string $msg Message to parse
* @param object $user Joomla user object
* @param string $prefix Search string to look for e.g. 'my'
to look for {$my->id}
*
* @return string parsed message
*/
public static function replaceWithUserData($msg, $user = null, $prefix =
'my')
{
$app = Factory::getApplication();
if (is_null($user))
{
$user = Factory::getUser();
}
if ($user->id == 0) return $msg;
$user->levels = $user->getAuthorisedViewLevels();
if (is_object($user))
{
foreach ($user as $key => $val)
{
if (substr($key, 0, 1) != '_' && !empty($val))
{
if (!is_object($val) && !is_array($val))
{
$msg = str_replace('{$' . $prefix . '->' .
$key . '}', $val, $msg);
$msg = str_replace('{$' . $prefix . '->' .
$key . '}', $val, $msg);
}
elseif (is_array($val))
{
$msg = str_replace('{$' . $prefix . '->' .
$key . '}', implode(',', $val), $msg);
$msg = str_replace('{$' . $prefix . '->' .
$key . '}', implode(',', $val), $msg);
}
}
}
}
/*
* $$$rob parse another users data into the string:
* format: is {$their->var->email} where var is the $app->input
var to search for
* e.g url - index.php?owner=62 with placeholder
{$their->owner->id}
* var should be an integer corresponding to the user id to load
*/
$matches = array();
preg_match('/{\$their-\>(.*?)}/', $msg, $matches);
foreach ($matches as $match)
{
$bits = explode('->', str_replace(array('{',
'}'), '', $match));
if (count($bits) !== 3)
{
continue;
}
$userId = $app->input->getInt(ArrayHelper::getValue($bits, 1));
// things like user elements might be single entry arrays
if (is_array($userId))
{
$userId = array_pop($userId);
}
if (!empty($userId))
{
$user = Factory::getUser($userId);
$val = $user->get(ArrayHelper::getValue($bits, 2));
$msg = str_replace($match, $val, $msg);
}
}
return $msg;
}
/**
* Called from parseMessageForPlaceHolder to iterate through string to
replace
* {placeholder} with global data
*
* @param string $msg Message to parse
*
* @return string parsed message
*/
public static function replaceWithGlobals($msg)
{
$replacements = self::globalReplacements();
foreach ($replacements as $key => $value)
{
if (!empty($value)) $msg = str_replace($key, $value, $msg);
}
return $msg;
}
/**
* Utility function for replacing language tags.
* {lang} - Joomla code for user's selected language, like en-GB
* {langtag} - as {lang} with with _ instead of -
* {shortlang} - first two letters of {lang}, like en
* {multilang} - multilang URL code
*
* @param string $msg Message to parse
*
* @return string parsed message
*/
public static function replaceWithLanguageTags($msg)
{
$replacements = self::langReplacements();
foreach ($replacements as $key => $value)
{
$msg = str_replace($key, $value, $msg);
}
return $msg;
}
/**
* Called from parseMessageForPlaceHolder to iterate through string to
replace
* {placeholder} with unsafe data
*
* @param string $msg Message to parse
*
* @return string parsed message
*/
public static function replaceWithUnsafe($msg)
{
$replacements = self::unsafeReplacements();
foreach ($replacements as $key => $value)
{
$msg = str_replace($key, $value, $msg);
}
return $msg;
}
/**
* Called from parseMessageForPlaceHolder to iterate through string to
replace
* {placeholder} with session data
*
* @param string $msg Message to parse
*
* @return string parsed message
*/
public static function replaceWithSession($msg)
{
if (strstr($msg, '{$session->'))
{
$session = Factory::getSession();
$sessionData = array(
'id' => $session->getId(),
'token' => $session->get('session.token'),
'formtoken' => Session::getFormToken()
);
foreach ($sessionData as $key => $value)
{
$msg = str_replace('{$session->' . $key . '}',
$value, $msg);
}
$msg = preg_replace_callback(
'/{\$session-\>(.*?)}/',
function($matches) use ($session) {
$bits = explode(':', $matches[1]);
if (count($bits) > 1)
{
$sessionKey = $bits[1];
$nameSpace = $bits[0];
}
else
{
$sessionKey = $bits[0];
$nameSpace = 'default';
}
$val = $session->get($sessionKey, '', $nameSpace);
if (is_string($val))
{
return $val;
}
else if (is_numeric($val))
{
return (string) $val;
}
return '';
},
$msg
);
}
return $msg;
}
/**
* Get an associative array of replacements for 'unsafe' value,
like $jConfig_secret, which we
* only want to use for stricty internal use that won't ever get
shown to the user
*
* @return array
* @throws \Exception
*/
public static function unsafeReplacements()
{
$config = Factory::getApplication()->getConfig();
$replacements = array(
'{$jConfig_absolute_path}' => JPATH_SITE,
'{$jConfig_secret}' => $config->get('secret')
);
return $replacements;
}
/**
* Get an associative array of replacements strings and values
*
* @return array
* @throws \Exception
*/
public static function globalReplacements()
{
$app = Factory::getApplication();
$itemId = self::itemId();
$config = Factory::getApplication()->getConfig();
$session = Factory::getSession();
$token = $session->get('session.token');
$replacements = array(
'{$jConfig_live_site}' => COM_FABRIK_LIVESITE,
'{$jConfig_offset}' => $config->get('offset'),
'{$Itemid}' => $itemId,
'{$jConfig_sitename}' =>
$config->get('sitename'),
'{$jConfig_mailfrom}' =>
$config->get('mailfrom'),
'{where_i_came_from}' =>
$app->input->server->get('HTTP_REFERER', '',
'string'),
'{date}' => date('Ymd'),
'{year}' => date('Y'),
'{mysql_date}' => date('Y-m-d H:i:s'),
'{session.token}' => $token
);
foreach ($_SERVER as $key => $val)
{
if (!is_object($val) && !is_array($val))
{
$replacements['{$_SERVER->' . $key . '}'] =
$val;
$replacements['{$_SERVER->' . $key . '}'] =
$val;
}
}
if ($app->isClient('administrator'))
{
$replacements['{formview}'] = 'task=form.view';
$replacements['{listview}'] = 'task=list.view';
$replacements['{detailsview}'] =
'task=details.view';
}
else
{
$replacements['{formview}'] = 'view=form';
$replacements['{listview}'] = 'view=list';
$replacements['{detailsview}'] = 'view=details';
}
return array_merge($replacements, self::langReplacements());
}
/**
* Returns array of language tag replacements
*
* @return array
*/
public static function langReplacements()
{
$langtag = Factory::getApplication()->getLanguage()->getTag();
$lang = str_replace('-', '_', $langtag);
$shortlang = explode('_', $lang);
$shortlang = $shortlang[0];
$multilang = Worker::getMultiLangURLCode();
$replacements = array(
'{lang}' => $lang,
'{langtag}' => $langtag,
'{multilang}' => $multilang,
'{shortlang}' => $shortlang,
);
return $replacements;
}
/**
* Called from parseMessageForPlaceHolder to iterate through string to
replace
* {placeholder} with posted data
*
* @param string $matches Placeholder e.g. {placeholder}
*
* @return string posted data that corresponds with placeholder
*/
protected function replaceWithFormData($matches)
{
// Merge any join data key val pairs down into the main data array
$joins = ArrayHelper::getValue($this->_searchData, 'join',
array());
foreach ($joins as $k => $data)
{
foreach ($data as $k => $v)
{
/*
* Only replace if we haven't explicitly set the key in
_searchData.
* Otherwise, calc element in repeat group uses all repeating groups
values rather than the
* current one that the plugin sets when it fire its Ajax request.
*/
if (!array_key_exists($k, $this->_searchData))
{
$this->_searchData[$k] = $v;
}
}
}
$match = $matches[0];
$orig = $match;
// Strip the {}
$match = StringHelper::substr($match, 1, StringHelper::strlen($match) -
2);
/* $$$ hugh - added dbprefix substitution
* Not 100% if we should do this on $match before copying to $orig, but
for now doing it
* after, so we don't potentially disclose dbprefix if no
substitution found.
*/
$config = Factory::getApplication()->getConfig();
$prefix = $config->get('dbprefix');
$match = str_replace('#__', $prefix, $match);
// $$$ rob test this format searchvalue||defaultsearchvalue
$bits = explode('||', $match);
if (count($bits) == 2)
{
$match = self::parseMessageForPlaceHolder('{' . $bits[0] .
'}', $this->_searchData, false);
if (in_array($match, array('',
'<ul></ul>',
'<ul><li></li></ul>')))
{
// experiment with eval'ed code in defaults
if (strstr($bits[1], '<?php'))
{
$code =
preg_replace('/^<\?php(.*)(\?>)$/s', '$1',
$bits[1]);
FabrikWorker::clearEval();
$bits[1] = Php::Eval(['code' => $code]);
FabrikWorker::logEval($default, 'Caught exception on eval of
' . $formModel->label . ': %s');
}
return $bits[1] !== '' ? $bits[1] : $orig;
}
else
{
return $match !== '' ? $match : $orig;
}
}
$match = preg_replace("/ /", "_", $match);
if (!strstr($match, '.'))
{
// For some reason array_key_exists wasn't working for nested
arrays??
$aKeys = array_keys($this->_searchData);
// Remove the table prefix from the post key
$aPrefixFields = array();
for ($i = 0; $i < count($aKeys); $i++)
{
$aKeyParts = explode('___', $aKeys[$i]);
if (count($aKeyParts) == 2)
{
$tablePrefix = array_shift($aKeyParts);
$field = array_pop($aKeyParts);
$aPrefixFields[$field] = $tablePrefix;
}
}
if (array_key_exists($match, $aPrefixFields))
{
$match = $aPrefixFields[$match] . '___' . $match;
}
// Test to see if the made match is in the post key arrays
$found = in_array($match, $aKeys, true);
if ($found)
{
// Get the post data
$match = $this->_searchData[$match];
if (is_array($match))
{
$newMatch = '';
// Deal with radio boxes etc. inside repeat groups
foreach ($match as $m)
{
if (is_array($m))
{
$newMatch .= ',' . implode(',', $m);
}
else
{
$newMatch .= ',' . $m;
}
}
$match = StringHelper::ltrim($newMatch, ',');
}
}
else
{
$match = '';
}
}
else
{
// Could be looking for URL field type e.g. for $_POST[url][link] the
match text will be url.link
$aMatch = explode('.', $match);
$aPost = $this->_searchData;
foreach ($aMatch as $sPossibleArrayKey)
{
if (is_array($aPost))
{
if (!isset($aPost[$sPossibleArrayKey]))
{
return $orig;
}
else
{
$aPost = $aPost[$sPossibleArrayKey];
}
}
}
$match = $aPost;
$found = true;
}
if (!empty($match) && $this->parseAddSlashes)
{
$match = htmlspecialchars($match, ENT_QUOTES, 'UTF-8');
}
return $found ? $match : $orig;
}
/**
* Internal function to recursive scan directories
*
* @param string $imagePath Image path
* @param string $folderPath Path to scan
* @param string &$folders Root path of this folder
* @param array &$images Value array of all existing folders
* @param array $aFolderFilter Value array of all existing images
* @param bool $makeOptions Make options out for the results
*
* @return void
*/
public static function readImages($imagePath, $folderPath, &$folders,
&$images, $aFolderFilter, $makeOptions = true)
{
$imgFiles = self::fabrikReadDirectory($imagePath, '.', false,
false, $aFolderFilter);
foreach ($imgFiles as $file)
{
$ff_ = $folderPath . $file . '/';
$ff = $folderPath . $file;
$i_f = $imagePath . '/' . $file;
if (is_dir($i_f) && $file != 'CVS' && $file !=
'.svn')
{
if (!in_array($file, $aFolderFilter))
{
$folders[] = HTMLHelper::_('select.option', $ff_);
self::readImages($i_f, $ff_, $folders, $images, $aFolderFilter);
}
}
elseif (preg_match('/bmp|gif|jpg|png/i', $file) &&
is_file($i_f))
{
// Leading / we don't need
$imageFile = StringHelper::substr($ff, 1);
$images[$folderPath][] = $makeOptions ?
HTMLHelper::_('select.option', $imageFile, $file) : $file;
}
}
}
/**
* Utility function to read the files in a directory
*
* @param string $path The file system path
* @param string $filter A filter for the names
* @param bool $recurse Recurse search into sub-directories
* @param bool $fullPath True if to prepend the full path to the
file name
* @param array $aFolderFilter Folder names not to recurse into
* @param bool $foldersOnly Return a list of folders only (true)
*
* @return array of file/folder names
*/
public static function fabrikReadDirectory($path, $filter = '.',
$recurse = false, $fullPath = false, $aFolderFilter = array(),
$foldersOnly = false)
{
$arr = array();
if (!@is_dir($path))
{
return $arr;
}
$handle = opendir($path);
while ($file = readdir($handle))
{
$dir = Path::clean($path . '/' . $file);
$isDir = is_dir($dir);
if ($file != "." && $file != "..")
{
if (preg_match("/$filter/", $file))
{
if (($isDir && $foldersOnly) || !$foldersOnly)
{
if ($fullPath)
{
$arr[] = trim(Path::clean($path . '/' . $file));
}
else
{
$arr[] = trim($file);
}
}
}
$goDown = true;
if ($recurse && $isDir)
{
foreach ($aFolderFilter as $sFolderFilter)
{
if (strstr($dir, $sFolderFilter))
{
$goDown = false;
}
}
if ($goDown)
{
$arr2 = self::fabrikReadDirectory($dir, $filter, $recurse,
$fullPath, $aFolderFilter, $foldersOnly);
$arrDiff = array_diff($arr, $arr2);
$arr = array_merge($arrDiff);
}
}
}
}
closedir($handle);
asort($arr);
return $arr;
}
/**
* Joomfish translations don't seem to work when you do an ajax call
* it seems to load the geographical location language rather than the
selected lang
* so for ajax calls that need to use jf translated text we need to get
the current lang and
* send it to the js code which will then append the lang=XX to the ajax
querystring
*
* Renamed to getShortLang as we don't support Joomfish any more
*
* @since 2.0.5
*
* @return string first two letters of lang code - e.g. nl from
'nl-NL'
*/
public static function getShortLang()
{
$lang = Factory::getApplication()->getLanguage();
$lang = explode('-', $lang->getTag());
return array_shift($lang);
}
/**
* If J! multiple languages is enabled, return the URL language code for
the currently selected language, which is
* set by the admin in the 'content languages'. If not multi
lang, return false;
*
* @return boolean || string
*/
public static function getMultiLangURLCode()
{
$multiLang = false;
if (Multilanguage::isEnabled())
{
$lang = Factory::getApplication()->getLanguage()->getTag();
$languages = LanguageHelper::getLanguages();
foreach ($languages as $language)
{
if ($language->lang_code === $lang)
{
$multiLang = $language->sef;
break;
}
}
}
return $multiLang;
}
/**
* Get the content filter used both in form and admin pages for content
filter
* takes values from J content filtering options
*
* @return array (bool should the filter be used, object the filter to
use)
*/
public static function getContentFilter()
{
$filter = false;
// Filter settings
jimport('joomla.application.component.helper');
// Get Config and Filters in Joomla 2.5
$config = ComponentHelper::getParams('com_config');
$filters = $config->get('filters');
// If no filter data found, get from com_content (Joomla 1.6/1.7 sites)
if (empty($filters))
{
$contentParams = ComponentHelper::getParams('com_content');
$filters = $contentParams->get('filters');
}
$user = Factory::getUser();
$userGroups = Access::getGroupsByUser($user->get('id'));
$blackListTags = array();
$blackListAttributes = array();
$whiteListTags = array();
$whiteListAttributes = array();
$whiteList = false;
$blackList = false;
$unfiltered = false;
// Cycle through each of the user groups the user is in.
// Remember they are include in the Public group as well.
foreach ($userGroups AS $groupId)
{
// May have added a group by not saved the filters.
if (!isset($filters->$groupId))
{
continue;
}
// Each group the user is in could have different filtering properties.
$filterData = $filters->$groupId;
$filterType = StringHelper::strtoupper($filterData->filter_type);
if ($filterType == 'NH')
{
// Maximum HTML filtering.
}
elseif ($filterType == 'NONE')
{
// No HTML filtering.
$unfiltered = true;
}
else
{
// Black or white list.
// Pre-process the tags and attributes.
$tags = explode(',', $filterData->filter_tags);
$attributes = explode(',',
$filterData->filter_attributes);
$tempTags = array();
$tempAttributes = array();
foreach ($tags as $tag)
{
$tag = trim($tag);
if ($tag)
{
$tempTags[] = $tag;
}
}
foreach ($attributes as $attribute)
{
$attribute = trim($attribute);
if ($attribute)
{
$tempAttributes[] = $attribute;
}
}
// Collect the black or white list tags and attributes.
// Each list is cumulative.
if ($filterType == 'BL' || $filterType == 'CBL')
{
$blackList = true;
$blackListTags = array_merge($blackListTags, $tempTags);
$blackListAttributes = array_merge($blackListAttributes,
$tempAttributes);
}
elseif ($filterType == 'WL')
{
$whiteList = true;
$whiteListTags = array_merge($whiteListTags, $tempTags);
$whiteListAttributes = array_merge($whiteListAttributes,
$tempAttributes);
}
}
}
// Remove duplicates before processing (because the black list uses both
sets of arrays).
$blackListTags = array_unique($blackListTags);
$blackListAttributes = array_unique($blackListAttributes);
$whiteListTags = array_unique($whiteListTags);
$whiteListAttributes = array_unique($whiteListAttributes);
// Unfiltered assumes first priority.
if ($unfiltered)
{
$doFilter = false;
// Don't apply filtering.
}
else
{
$doFilter = true;
// Black lists take second precedence.
if ($blackList)
{
// Remove the white-listed attributes from the black-list.
$tags = array_diff($blackListTags, $whiteListTags);
$filter = InputFilter::getInstance($tags,
array_diff($blackListAttributes, $whiteListAttributes), 1, 1);
}
// White lists take third precedence.
elseif ($whiteList)
{
// Turn off xss auto clean
$filter = InputFilter::getInstance($whiteListTags,
$whiteListAttributes, 0, 0, 0);
}
// No HTML takes last place.
else
{
$filter = InputFilter::getInstance();
}
}
return array($doFilter, $filter);
}
/**
* Clear PHP errors prior to running eval'd code
*
* @return void
*/
public static function clearEval()
{
/**
* "Clear" PHP's errors. NOTE that error_get_last() will
still return non-null after this
* if there were any errors, but $error['message'] will be
empty. See comment in logEval()
* below for details.
*/
if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
error_clear_last();
}
else
{
@trigger_error("");
}
}
/**
* Raise a J Error notice if the eval'd result is false and there is
a error
*
* @param mixed $val Evaluated result
* @param string $msg Error message, should contain %s as we sprintf in
the error_get_last()'s message property
*
* @return void
*/
public static function logEval($val, $msg)
{
/*
if ($val !== false)
{
return;
}
*/
$error = error_get_last();
/**
* $$$ hugh - added check for 'message' being empty, so we can
do ..
* @trigger_error('');
* ... prior to eval'ing code if we want to "clear"
anything pitched prior
* to the eval. For instance, in the PHP validation plugin. If we
don't "clear"
* the errors before running the eval'd validation code, we end up
reporting any
* warnings or notices pitched in our code prior to the validation
running, which
* can be REALLY confusing. After a trigger_error(), error_get_last()
won't return null,
* but 'message' will be empty.
*/
if (is_null($error) || empty($error['message']))
{
// No error set (eval could have actually returned false as a correct
value)
return;
}
$enqMsgType = 'error';
$indentHTML =
'<br/> Debug: ';
$errString = Text::_('COM_FABRIK_EVAL_ERROR_USER_WARNING');
// Give a technical error message to the developer
if (version_compare(phpversion(), '5.2.0', '>=')
&& $error && is_array($error))
{
$errString .= $indentHTML . sprintf($msg, $error['message']);
}
else
{
$errString .= $indentHTML . sprintf($msg, "unknown error - php
version < 5.2.0");
}
self::logError($errString, $enqMsgType);
}
/**
* Raise a J Error notice if in dev mode or log a J error otherwise
*
* @param string $errString Message to display / log
* @param string $msgType Joomla enqueueMessage message type e.g.
'error', 'warning' etc.
*
* @return void
*/
public static function logError($errString, $msgType)
{
if (Html::isDebug())
{
$app = Factory::getApplication();
$app->enqueueMessage($errString, $msgType);
}
else
{
switch ($msgType)
{
case 'message':
$priority = Log::INFO;
break;
case 'warning':
$priority = Log::WARNING;
break;
case 'error':
default:
$priority = Log::ERROR;
break;
}
Log::add($errString, $priority, 'com_fabrik');
}
}
/**
* Log to table jos_fabrik_logs
*
* @param string $type E.g. 'fabrik.fileupload.download'
* @param mixed $msg Array/object/string
* @param bool $jsonEncode Should we json encode the message?
*
* @return void
*/
public static function log($type, $msg, $jsonEncode = true)
{
if ($jsonEncode)
{
$msg = json_encode($msg);
}
$log = FabTable::getInstance('log',
'FabrikTable');
$log->message_type = $type;
$log->message = $msg;
$log->store();
}
/**
* Get a database object
*
* Returns the global {@link JDatabase} object, only creating it
* if it doesn't already exist.
*
* @param bool $loadJoomlaDb Force (if true) the loading of the main J
database,
* needed in admin to connect to J db whilst
still using fab db drivers "fabrik"
* replacement text
*
* @param mixed $cnnId If null then loads the fabrik default
connection, if an int then loads the
* specified connection by its id
*
* @return JDatabaseDriver object
*/
public static function getDbo($loadJoomlaDb = false, $cnnId = null)
{
$sig = (int) $loadJoomlaDb . '.' . $cnnId;
if (!self::$database)
{
self::$database = array();
self::$database = array();
}
if (!array_key_exists($sig, self::$database))
{
Table::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_fabrik/tables');
$conf = Factory::getApplication()->getConfig();
if (!$loadJoomlaDb)
{
$cnModel =
Factory::getApplication()->bootComponent('com_fabrik')->getMVCFactory()->createModel('Connection',
'FabrikFEModel');
$cn = $cnModel->getConnection($cnnId);
$host = $cn->host;
$user = $cn->user;
$password = $cn->password;
$database = $cn->database;
}
else
{
$host = $conf->get('host');
$user = $conf->get('user');
$password = $conf->get('password');
$database = $conf->get('db');
}
$dbPrefix = $conf->get('dbprefix');
$driver = $conf->get('dbtype');
// Test for swapping db table names
$options = array('driver' => $driver, 'host'
=> $host, 'user' => $user, 'password' =>
$password, 'database' => $database,
'prefix' => $dbPrefix);
self::$database[$sig] = DatabaseDriver::getInstance($options);
Worker::bigSelects(self::$database[$sig]);
}
return self::$database[$sig];
}
/**
* $$$ hugh - testing doing bigSelects stuff here
* Reason being, some folk on shared hosting plans with very restrictive
MySQL
* setups are hitting the 'big selects' problem on Fabrik
internal queries, not
* just on their List specific queries. So we need to apply 'big
selects' to our
* default connection as well, essentially enabling it for ALL queries we
do.
*
* @param JDatabaseDriver $fabrikDb
*
* @return void
*/
public static function bigSelects($fabrikDb)
{
$fbConfig = ComponentHelper::getParams('com_fabrik');
if ($fbConfig->get('enable_big_selects', 0) ==
'1')
{
/**
* Use of OPTION in SET deprecated from MySQL 5.1. onward
*
http://www.fabrikar.com/forums/index.php?threads/enable-big-selects-error.39463/#post-198293
* NOTE - technically, using verison_compare on MySQL version could
fail, if it's a "gamma"
* release, which PHP desn't grok!
*/
if (version_compare($fabrikDb->getVersion(), '5.1.0',
'>='))
{
$fabrikDb->setQuery("SET SQL_BIG_SELECTS=1,
GROUP_CONCAT_MAX_LEN=10240");
}
else
{
$fabrikDb->setQuery("SET OPTION SQL_BIG_SELECTS=1,
GROUP_CONCAT_MAX_LEN=10240");
}
try
{
$fabrikDb->execute();
} catch (\Exception $e)
{
// Fail silently
}
}
}
/**
* Helper function get get a connection
*
* @param mixed $item A list table or connection id
*
* @since 3.0b
*
* @return FabrikFEModelConnection connection
*/
public static function getConnection($item = null)
{
$app = Factory::getApplication();
$input = $app->input;
$jForm = $input->get('jform', array(), 'array');
if (is_object($item))
{
$item = is_null($item->connection_id) ? ArrayHelper::getValue($jForm,
'connection_id', -1) : $item->connection_id;
}
$connId = (int) $item;
if (!self::$connection)
{
self::$connection = array();
}
if (!array_key_exists($connId, self::$connection))
{
$connectionModel =
Factory::getApplication()->bootComponent('com_fabrik')->getMVCFactory()->createModel('Connection',
'FabrikFEModel');
$connectionModel->setId($connId);
if ($connId === -1)
{
// -1 for creating new table
$connectionModel->loadDefaultConnection();
$connectionModel->setId($connectionModel->getConnection()->id);
}
$connectionModel->getConnection();
self::$connection[$connId] = $connectionModel;
}
return self::$connection[$connId];
}
/**
* Get the plugin manager
*
* @since 3.0b
*
* @return FabrikFEModelPluginmanager Plugin manager
*/
public static function getPluginManager()
{
if (!self::$pluginManager)
{
self::$pluginManager =
Factory::getApplication()->bootComponent('com_fabrik')->getMVCFactory()->createModel('Pluginmanager',
'FabrikFEModel');
}
return self::$pluginManager;
}
/**
* Takes a string which may or may not be json and returns either
string/array/object
* will also turn valGROUPSPLITTERval2 to array
*
* @param string $data Json encoded string
* @param bool $toArray Force data to be an array
* @param bool $emptyish Set to false to return an empty array if
$data is an empty string, instead of an
* emptyish (one empty string entry) array
*
* @return mixed data
*/
public static function JSONtoData($data, $toArray = false, $emptyish =
true)
{
if (is_string($data))
{
if (!strstr($data, '{'))
{
// Was messing up date rendering @
http://www.podion.eu/dev2/index.php/2011-12-19-10-33-59/actueel
// return $toArray ? (array) $data : $data;
}
// Repeat elements are concatenated with the GROUPSPLITTER - convert to
json string before continuing.
if (strstr($data, GROUPSPLITTER))
{
$data = json_encode(explode(GROUPSPLITTER, $data));
}
/* half hearted attempt to see if string is actually json or not.
* issue was that if you try to decode '000123' its turned
into '123'
*/
if (strstr($data, '{') || strstr($data, '['))
{
$json = json_decode($data);
// Only works in PHP5.3
// $data = (json_last_error() == JSON_ERROR_NONE) ? $json : $data;
if (is_null($json))
{
/*
* if coming back from a failed validation - the json string may have
been htmlspecialchars_encoded in
* the form model getGroupView method
*/
$json = json_decode(stripslashes(htmlspecialchars_decode($data,
ENT_QUOTES)));
}
$data = is_null($json) ? $data : $json;
}
// If $data was an empty string and "emptyish" is not set, we
want an empty array, not an array with one empty string
if ($toArray && !$emptyish && $data === '')
{
$data = array();
}
}
$data = $toArray ? (array) $data : $data;
return $data;
}
/**
* Test if a string is a compatible date
*
* @param string $d Date to test
* @param bool $notNull don't allow null / empty dates
*
* @return bool
*/
public static function isNullDate($d)
{
if (is_string($d)) $d = trim($d);
$db = self::getDbo(true);
$aNullDates = array('0000-00-000000-00-00', '0000-00-00
00:00:00', '0000-00-00', '', 0,
$db->getNullDate(), null);
if ($d < '1000-01-01') return true;
return in_array($d, $aNullDates);
}
/**
* Test if a string is a compatible date
*
* @param string $d Date to test
* @param bool $notNull don't allow null / empty dates
*
* @return bool
*/
public static function isDate($d, $notNull = true)
{
// Catch for ','
if (empty($d) || strlen($d) < 2)
{
return false;
}
if ($notNull && self::isNullDate($d))
{
return false;
}
$cerl = error_reporting ();
error_reporting (0);
try
{
$dt = new Date($d);
} catch (\Exception $e)
{
error_reporting ($cerl);
self::clearEval();
return false;
}
error_reporting ($cerl);
return true;
}
public static function addMonthsInterval($months, Date $date)
{
$next = new Date($date->format('d-m-Y H:i:s'));
$next->modify('last day of +' . $months . '
month');
if ($date->format('d') > $next->format('d'))
{
return $date->diff($next);
}
else
{
return new DateInterval('P' . $months . 'M');
}
}
public static function addMonths($months, Date $date)
{
return $date->add(self::addMonthsInterval($months, $date));
}
/**
* Get a user's TZ offset in MySql format, suitable for CONVERT_TZ
*
* @param int userId userid or null (use logged on user if null)
*
* @return string symbolic timezone name (America/Chicago)
*/
public static function getUserTzOffsetMySql($userId = null)
{
$tz = self::getUserTzName($userId);
$tz = new \DateTimeZone($tz);
$date = new Date("now", $tz);
$offset = $tz->getOffset($date) . ' seconds';
$dateOffset = clone $date;
$dateOffset->sub(\DateInterval::createFromDateString($offset));
$interval = $dateOffset->diff($date);
return $interval->format('%R%H:%I');
}
/**
* Get a user's TZ offset in seconds
*
* @param int userId userid or null (use logged on user if null)
*
* @return int seconds offset
*/
public static function getUserTzOffset($userId = null)
{
$tz = self::getUserTzName($userId);
$tz = new \DateTimeZone($tz);
$date = new Date("now", $tz);
return $tz->getOffset($date);
}
/**
* Get a user's TZ name
*
* @param int userId userid or null (use logged on user if null)
*
* @return string symbolic timezone name (America/Chicago)
*/
public static function getUserTzName($userId = null)
{
if (empty($userId))
{
$user = Factory::getUser();
}
else
{
$user = Factory::getUser($userId);
}
$config = Factory::getApplication()->getConfig();
$tz = $user->getParam('timezone',
$config->get('offset'));
return $tz;
}
/**
* See if data is JSON or not.
*
* @param mixed $data Date to test
* @params bool $quotedString should we treat a single quoted string as
JSON
* @since 3.0.6
*
* @return bool
*/
public static function isJSON($data, $quotedString = true)
{
if (!is_string($data))
{
return false;
}
if (is_numeric($data))
{
return false;
}
if (!$quotedString)
{
$data = trim($data, '"');
}
return json_decode($data) !== null;
}
/**
* Is the email really an email (more strict than
MailHelper::isEmailAddress())
*
* @param string $email Email address
* @param bool $sms test for SMS phone number instead of email,
default false
*
* @since 3.0.4
*
* @return bool
*/
public static function isEmail($email, $sms = false)
{
if ($sms)
{
return self::isSMS($email);
}
$conf = Factory::getApplication()->getConfig();
$mailer = $conf->get('mailer');
if ($mailer === 'mail')
{
// Sendmail and Joomla isEmailAddress don't use the same conditions
return (MailHelper::isEmailAddress($email) &&
Mail::ValidateAddress($email));
}
return MailHelper::isEmailAddress($email);
}
/**
* Is valid SMS number format
* This is just a stub which return true for now!
*
* @param string $sms SMS number
*
* @since 3.4.0
*
* @return bool
*/
public static function isSMS($sms)
{
return true;
}
/**
* Function to send an email
*
* @param string $from From email address
* @param string $fromName From name
* @param mixed $recipient Recipient email address(es)
* @param string $subject email subject
* @param string $body Message body
* @param boolean $mode false = plain text, true = HTML
* @param mixed $cc CC email address(es)
* @param mixed $bcc BCC email address(es)
* @param mixed $attachment Attachment file name(s)
* @param mixed $replyTo Reply to email address(es)
* @param mixed $replyToName Reply to name(s)
* @param array $headers Optional custom headers, assoc array
keyed by header name
*
* @return boolean True on success
*
* @since 11.1
*/
public static function sendMail($from, $fromName, $recipient, $subject,
$body, $mode = false,
$cc = null, $bcc = null, $attachment = null, $replyTo = null,
$replyToName = null, $headers = array())
{
// do a couple of tweaks to improve spam scores
// Get a Mail instance
$mailer = Factory::getMailer();
// If html, make sure there's an <html> tag
if ($mode)
{
if (!stristr($body, '<html>'))
{
$body = '<html>' . $body . '</html>';
}
}
/**
* if simple single email recipient with no name part, fake out name part
to avoid TO_NO_BKRT hit in spam filters
* (don't do it for sendmail, as sendmail only groks simple emails
in To header!)
*/
$recipientName = '';
if ($mailer->Mailer !== 'sendmail' &&
is_string($recipient) && !strstr($recipient, '<'))
{
$recipientName = $recipient;
}
$mailer->setSubject($subject);
$mailer->setBody($body);
$mailer->Encoding = 'base64';
// Are we sending the email as HTML?
$mailer->isHtml($mode);
try
{
$mailer->addRecipient($recipient, $recipientName);
}
catch (\Exception $e)
{
self::log('fabrik.helper.sendmail.error',
'Exception in addRecipient: ' . $e->getMessage(), false);
return false;
}
try
{
$mailer->addCc($cc);
}
catch (\Exception $e)
{
self::log('fabrik.helper.sendmail.warning',
'Exception in addCc: ' . $e->getMessage());
// not sure if we should bail if Cc is bad, for now just soldier on
}
try
{
$mailer->addBcc($bcc);
}
catch (\Exception $e)
{
self::log('fabrik.helper.sendmail.warning',
'Exception in addBcc: ' . $e->getMessage(), false);
// not sure if we should bail if Bcc is bad, for now just
soldier on
}
if (!empty($attachment))
{
try
{
$mailer->addAttachment($attachment);
}
catch (\Exception $e)
{
self::log('fabrik.helper.sendmail.warning',
'Exception in addAttachment: ' . $e->getMessage(), false);
// most likely file didn't exist, ignore
}
}
$autoReplyTo = false;
// Take care of reply email addresses
if (is_array($replyTo))
{
$numReplyTo = count($replyTo);
for ($i = 0; $i < $numReplyTo; $i++)
{
try
{
$mailer->addReplyTo($replyTo[$i], $replyToName[$i]);
}
catch (\Exception $e)
{
self::log('fabrik.helper.sendmail.warning',
'Exception in addReplyTo: ' . $e->getMessage(), false);
// carry on
}
}
}
elseif (isset($replyTo))
{
try
{
$mailer->addReplyTo($replyTo, $replyToName);
}
catch (\Exception $e)
{
self::log('fabrik.helper.sendmail.warning',
'Exception in addReplyTo: ' . $e->getMessage(), false);
// carry on
}
}
else
{
$autoReplyTo = true;
}
try
{
$mailer->setSender(array($from, $fromName, $autoReplyTo));
}
catch (\Exception $e)
{
self::log('fabrik.helper.sendmail.error',
'Exception in setSender: ' . $e->getMessage(), false);
return false;
}
/**
* Set the plain text AltBody, which forces the PHP mailer class to make
this
* a multipart MIME type, with an alt body for plain text. If we
don't do this,
* the default behavior is to send it as just text/html, which causes
spam filters
* to downgrade it.
* @@@trob: insert \n before <br to keep newlines(strip_tag may then
strip <br> or <br /> etc, decode html
*/
if ($mode)
{
$body = str_ireplace(array("<br
/>","<br>","<br/>"), "\n<br
/>", $body);
$body = html_entity_decode($body);
$mailer->AltBody = MailHelper::cleanText(strip_tags($body));
}
foreach ($headers as $headerName => $headerValue) {
$mailer->addCustomHeader($headerName, $headerValue);
}
$config = ComponentHelper::getParams('com_fabrik');
if ($config->get('verify_peer', '1') ===
'0')
{
$mailer->SMTPOptions = array(
'ssl' =>
array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
}
try
{
$ret = $mailer->Send();
}
catch (\Exception $e)
{
self::log('fabrik.helper.sendmail.error',
'Exception in Send: ' . $e->getMessage(), false);
return false;
}
// if ACY mailing is installed, it returns an exception (!) rather
than false
if (is_bool($ret) === false && get_parent_class($ret) ===
'Exception')
{
self::log('fabrik.helper.sendmail.error',
'Exception in Send: ' . $ret->getMessage(), false);
$ret = false;
}
return $ret;
}
/**
* Get a JS go back action e.g 'onclick="history.back()"
*
* @return string
*/
public static function goBackAction()
{
jimport('joomla.environment.browser');
$uri = Uri::getInstance();
$url = filter_var(ArrayHelper::getValue($_SERVER,
'HTTP_REFERER'), FILTER_SANITIZE_URL);
if ($uri->getScheme() === 'https')
{
$goBackAction = 'onclick="parent.location=\'' . $url
. '\'"';
}
else
{
$goBackAction = 'onclick="parent.location=\'' . $url
. '\'"';
}
return $goBackAction;
}
/**
* Attempt to find the active menu item id - Only for front end
*
* - First checked $listId for menu items
* - Then checks if itemId in $input
* - Finally checked active menu item
*
* @param int $listId List id to attempt to get the menu item id for the
list.
*
* @return mixed NULL if nothing found, int if menu item found
*/
public static function itemId($listId = null)
{
static $listIds = array();
$app = Factory::getApplication();
if (!$app->isClient('administrator'))
{
// Attempt to get Itemid from possible list menu item.
if (!is_null($listId))
{
if (!array_key_exists($listId, $listIds))
{
$db =
Factory::getContainer()->get('DatabaseDriver');
$myLanguage = Factory::getApplication()->getLanguage();
$myTag = $myLanguage->getTag();
$qLanguage = !empty($myTag) ? ' AND ' . $db->q($myTag) .
' = ' . $db->qn('m.language') : '';
$query = $db->getQuery(true);
$query->select('m.id AS
itemId')->from('#__extensions AS e')
->leftJoin('#__menu AS m ON m.component_id =
e.extension_id')
->where('e.name = "com_fabrik" and e.type =
"component" and m.link LIKE "%listid=' . $listId .
'"' . $qLanguage);
$db->setQuery($query);
if ($itemId = $db->loadResult())
{
$listIds[$listId] = $itemId;
}
else{
$listIds[$listId] = false;
}
}
else{
if ($listIds[$listId] !== false)
{
return $listIds[$listId];
}
}
}
$itemId = (int) $app->input->getInt('itemId');
if ($itemId !== 0)
{
return $itemId;
}
$menus = $app->getMenu();
$menu = $menus->getActive();
if (is_object($menu))
{
return $menu->id;
}
}
return null;
}
/**
* Attempt to get a variable first from the menu params (if they exists)
if not from request
*
* @param string $name Param name
* @param mixed $val Default
* @param bool $mambot If set to true menu
params ignored
* @param string $priority Defaults that menu
priorities override request - set to 'request'
* to inverse this priority
* @param array $opts Options
'listid' -> if priority = menu then the menu list id must
* match this value to use
the menu param.
*
* @return string
*/
public static function getMenuOrRequestVar($name, $val = '',
$mambot = false, $priority = 'menu', $opts = array())
{
$app = Factory::getApplication();
$input = $app->input;
if ($priority === 'menu')
{
$val = $input->get($name, $val, 'string');
if (!$app->isClient('administrator'))
{
if (!$mambot)
{
$menus = $app->getMenu();
$menu = $menus->getActive();
if (is_object($menu))
{
$match = true;
if (array_key_exists('listid', $opts)) {
$menuListId =
ArrayHelper::getValue($menu->query, 'listid', '');
$checkListId = ArrayHelper::getValue($opts,
'listid', $menuListId);
$match = (int) $menuListId === (int)
$checkListId;
}
else if (array_key_exists('formid',
$opts)) {
$menuFormId =
ArrayHelper::getValue($menu->query, 'formid', '');
$checkFormId = ArrayHelper::getValue($opts,
'formid', $menuFormId);
$match = (int) $menuFormId === (int)
$checkFormId;
}
if ($match)
{
$val = $menu->getParams()->get($name,
$val);
}
}
}
}
}
else
{
if (!$app->isClient('administrator'))
{
$menus = $app->getMenu();
$menu = $menus->getActive();
// If there is a menu item available AND the view is not
rendered in a content plugin
if (is_object($menu) && !$mambot)
{
$match = true;
if (array_key_exists('listid', $opts)) {
$menuListId =
ArrayHelper::getValue($menu->query, 'listid', '');
$checkListId = ArrayHelper::getValue($opts,
'listid', $menuListId);
$match = (int) $menuListId === (int) $checkListId;
}
else if (array_key_exists('formid', $opts)) {
$menuFormId =
ArrayHelper::getValue($menu->query, 'formid', '');
$checkFormId = ArrayHelper::getValue($opts,
'formid', $menuFormId);
$match = (int) $menuFormId === (int) $checkFormId;
}
if ($match)
{
$val = $menu->getParams()->get($name, $val);
}
}
}
$val = $input->get($name, $val, 'string');
}
return $val;
}
/**
* Access control function for determining if the user can perform
* a designated function on a specific row
*
* @param object $params Item params to test
* @param object $row Data
* @param string $col Access control setting to compare against
*
* @return mixed - if ACL setting defined here return bool,
otherwise return -1 to continue with default acl
* setting
*/
public static function canUserDo($params, $row, $col)
{
if (!is_null($row))
{
$app = Factory::getApplication();
$input = $app->input;
$user = Factory::getUser();
$userCol = $params->get($col, '');
if ($userCol != '')
{
$userCol = StringHelper::safeColNameToArrayKey($userCol);
if ((is_array($row) && !array_key_exists($userCol, $row)) ||
(is_object($row) && !isset($row->{$userCol})))
{
return false;
}
else
{
$userColRaw = $userCol . '_raw';
if ((is_array($row) && array_key_exists($userColRaw, $row)) ||
(is_object($row) && property_exists($row,$userColRaw)))
{
$userCol .= '_raw';
}
$myId = $user->get('id');
// -1 for menu items that link to their own records
$userColVal = is_array($row) ? $row[$userCol] : $row->$userCol;
// User element stores as object
if (is_object($userColVal))
{
$userColVal = ArrayHelper::fromObject($userColVal);
}
// Could be coming back from a failed validation in which case val
might be an array
if (is_array($userColVal))
{
$userColVal = array_shift($userColVal);
}
if (empty($userColVal) && empty($myId))
{
return false;
}
if (intVal($userColVal) === intVal($myId) ||
$input->get('rowid') == -1)
{
return true;
}
}
}
}
return -1;
}
/**
* Can Fabrik render PDF - required the DOMPDF library to be installed in
Joomla libraries folder
*
* @param bool $puke throw an exception if can't
*
* @throws RuntimeException
*
* @return bool
*/
public static function canPdf($puke = true)
{
$config = ComponentHelper::getParams('com_fabrik');
$pdfLibrary = $config->get('fabrik_pdf_lib',
'dompdf');
if ($pdfLibrary === 'dompdf')
{
$file = COM_FABRIK_LIBRARY .
'/vendor/vendor/dompdf/dompdf/composer.json';
}
else
{
$file = COM_FABRIK_LIBRARY .
'/vendor/vendor/mpdf/mpdf/composer.json';
}
if (!File::exists($file))
{
if ($puke)
{
throw new \RuntimeException(Text::_($pdfLibrary === 'dompdf'
? 'COM_FABRIK_NOTICE_DOMPDF_NOT_FOUND' :
'COM_FABRIK_NOTICE_MPDF_NOT_FOUND'));
}
else
{
return false;
}
}
return true;
}
/**
* Get a cache handler
* $$$ hugh - added $listModel arg, needed so we can see if they have set
"Disable Caching" on the List
*
* @param object $listModel List Model
* @param string $group group name (will default to package)
* @param int $ttl time to live in minutes, defaults to J! config
*
* @since 3.0.7
*
* @return Cache
*/
public static function getCache($listModel = null, $group = null, $ttl =
null)
{
$config = Factory::getApplication()->getConfig();
$app = Factory::getApplication();
$package = isset($group) ? $group :
$app->getUserState('com_fabrik.package', 'fabrik');
$time = isset($ttl) ? (int) $ttl : (int)
$config->get('cachetime');
$base = JPATH_BASE . '/cache/';
$opts = array('defaultgroup' => 'com_' .
$package, 'cachebase' => $base, 'lifetime' =>
$time, 'language' => 'en-GB', 'storage'
=> 'file');
$cache = Cache::getInstance('callback', $opts);
$doCache = $config->get('caching', 0) > 0 ? true : false;
if ($doCache && $listModel !== null)
{
$doCache =
$listModel->getParams()->get('list_disable_caching',
'0') == '0';
}
$cache->setCaching($doCache);
return $cache;
}
/**
* Is caching enabled
*
* @param object $listModel List Model
* @param bool $noGuest disable caching for guests
*
* @since 3.8
*
* @return Cache
*/
public static function useCache($listModel = null, $noGuest = true,
$excludedFormats = null)
{
$config = Factory::getApplication()->getConfig();
$app = Factory::getApplication();
if (!isset($excludedFormats))
{
$excludedFormats = array('raw', 'csv',
'pdf', 'json', 'fabrikfeed',
'feed');
}
// check global J! system cache setting
$doCache = $config->get('caching', 0) > 0 ? true : false;
// if enabled, see if any other settingg disables it
if ($doCache)
{
// Check the Fabrik global option
$fabrikConfig = ComponentHelper::getParams('com_fabrik');
if ($fabrikConfig->get('disable_caching', '0')
=== '1')
{
return false;
}
// If a list model has been specified, see if caching is disabled for
this list
if ($listModel !== null)
{
if
($listModel->getParams()->get('list_disable_caching',
'0') === '1')
{
return false;
}
}
// Check if caching is disabled for guests
if ($noGuest)
{
if (Factory::getUser()->get('id') === '0')
{
return false;
}
}
if (in_array($app->input->get('format'),
$excludedFormats))
{
return false;
}
}
return $doCache;
}
/**
* Get the default values for a given Form
*
* @param string $form Form name e.g. list, form etc.
*
* @since 3.0.7
*
* @return array key field name, value default value
*/
public static function formDefaults($form)
{
Form::addFormPath(JPATH_COMPONENT . '/models/forms');
Form::addFieldPath(JPATH_COMPONENT . '/models/fields');
$form = Form::getInstance('com_fabrik.' . $form, $form,
array('control' => '', 'load_data' =>
true));
$fs = $form->getFieldset();
$json = array('params' => array());
foreach ($fs as $name => $field)
{
if (substr($name, 0, 7) === 'params_')
{
$name = str_replace('params_', '',
$name);
$json['params'][$name] = $field->value;
}
else
{
$json[$name] = $field->value;
}
}
return $json;
}
/**
* Are we in J3 or using a bootstrap tmpl
*
* @since 3.1
*
* @return bool
*/
/*
public static function j3()
{
// do we need this function any more?
return true;
}
*/
/**
* Are we in a form process task
*
* @since 3.2
*
* @return bool
*/
public static function inFormProcess()
{
$app = Factory::getApplication();
return $app->input->get('task') ==
'form.process' || ($app->isClient('administrator')
&& $app->input->get('task') ==
'process');
}
/**
* Are we in an AJAX validation process task
*
* @since 3.9.2
*
* @return bool
*/
public static function inAJAXValidation()
{
$app = Factory::getApplication();
return $app->input->get('task', '') ===
'form.ajax_validate';
}
/**
* Remove messages from JApplicationCMS
*
* @param CMSApplication $app Application to kill messages from
* @param string $type Message type e.g. 'warning',
'error'
*
* @return array Remaining messages.
*/
public static function killMessage(CMSApplication $app, $type)
{
$appReflection = new \ReflectionClass(get_class($app));
$messageQueue = $appReflection->getProperty('messageQueue');
$messageQueue->setAccessible(true);
$messages = $messageQueue->getValue($app);
foreach ($messages as $key => $message)
{
if ($message['type'] == $type)
{
unset($messages[$key]);
}
}
$messageQueue->setValue($app, $messages);
return $messages;
}
/**
* Loose casing to boolean
*
* @param mixed $var Var to test
* @param boolean $default if neither a truish or falsy match are found
*
* @return bool - Set to false if false is found.
*/
public static function toBoolean($var, $default)
{
if ($var === 'false' || $var === 0 || $var === false)
{
return false;
}
if ($var === 'true' || $var === 1 || $var === true)
{
return true;
}
return $default;
}
/**
* Get a getID3 instance - check if library installed, if not, toss an
exception
*
* @return object|bool - getid3 object or false if lib not installed
*/
public static function getID3Instance()
{
$getID3 = false;
if (File::exists(COM_FABRIK_LIBRARY .
'/libs/libs/getid3/getid3/getid3.php'))
{
ini_set('display_errors', true);
require_once COM_FABRIK_LIBRARY .
'/libs/libs/getid3/getid3/getid3.php';
require_once COM_FABRIK_LIBRARY .
'/libs/libs/getid3/getid3/getid3.lib.php';
\getid3_lib::IncludeDependency(COM_FABRIK_LIBRARY .
'/libs/libs/getid3/getid3/extension.cache.mysqli.php', __FILE__,
true);
$config = Factory::getApplication()->getConfig();
$host = $config->get('host');
$database = $config->get('db');
$username = $config->get('user');
$password = $config->get('password');
$getID3 = new \getID3_cached_mysqli($host, $database, $username,
$password);
}
return $getID3;
}
public static function getMemoryLimit($symbolic = false)
{
$memory = trim(ini_get('memory_limit'));
$memory = trim($memory);
if ($symbolic)
{
return $memory;
}
if ($memory === '-1')
{
return PHP_INT_MAX;
}
$last = strtolower($memory[strlen($memory)-1]);
$val = substr($memory, 0, -1);
switch($last) {
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $val;
}
}
fabrik/include.php000064400000015540151165341640010151 0ustar00<?php
/**
* Fabrik Autoloader Class
*
* @package Fabrik
* @copyright Copyright (C) 2014 fabrikar.com - All rights reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Factory;
use Joomla\String\Inflector;
use Joomla\String\Normalise;
/**'
* Autoloader Class
*
* @package Fabble
* @since 1.0
*/
class FabrikAutoloader
{
public function __construct()
{
spl_autoload_register(array($this, 'controller'));
spl_autoload_register(array($this, 'helper'));
spl_autoload_register(array($this, 'document'));
spl_autoload_register(array($this, 'view'));
// @TODO - at some point allow auto-loading of these as per Fabble
/*
spl_autoload_register(array($this, 'model'));
spl_autoload_register(array($this, 'view'));
spl_autoload_register(array($this, 'library'));
spl_autoload_register(array($this, 'plugin'));*/
}
/**
* Load plugin class
*
* @param string $class Class name
*/
private function plugin($class)
{
if (!strstr(strtolower($class), 'fabble\form\plugin\\')
&& !strstr(strtolower($class), 'fabble\lizt\plugin\\'))
{
return;
}
$class = str_replace('\\', '/',
str_replace('Fabble\\', '', $class));
$file = explode('/', $class);
$file = array_pop($file);
$path = JPATH_SITE . '/libraries/fabble/' . $class .
'/' . $file . '.php';
require_once $path;
}
/**
* Load model class
*
* @param string $class Class name
*/
private function model($class)
{
if (!strstr(strtolower($class), 'model'))
{
return;
}
$kls = explode('\\', $class);
$class = array_pop($kls);
$scope = Factory::getApplication()->scope;
$isFabble = strtolower(substr($class, 0, 11)) ===
'fabblemodel';
if ($this->appName($class) === $scope || $isFabble)
{
$path = JPATH_SITE . '/libraries/fabble/';
$defaultPath = JPATH_SITE . '/libraries/fabble/';
$plural = Inflector::getInstance();
$parts = Normalise::fromCamelCase($class, true);
unset($parts[0]);
$parts = array_values($parts);
foreach ($parts as &$part)
{
$part = strtolower($part);
if ($plural->isPlural($part))
{
$part = $plural->toSingular($part);
}
$part = StringHelper::ucfirst(strtolower($part));
}
$path .= implode('/', $parts) . '.php';
if (file_exists($path))
{
require_once $path;
$type = array_pop($parts);
if (!$isFabble)
{
class_alias('\\Fabble\\Model\\FabbleModel' .
StringHelper::ucfirst($type), $class);
}
return;
}
// IF no actual model name found try loading default model
$parts[count($parts) - 1] = 'Default';
$defaultPath .= implode('/', $parts) . '.php';
if (file_exists($defaultPath))
{
require_once $defaultPath;
$type = array_pop($parts);
class_alias("\\Fabble\\Model\\FabbleModel" .
StringHelper::ucfirst($type), $class);
return;
}
}
}
/**
* Load view class
*
* @param string $class Class name
*/
private function view($class)
{
/*
if (!strstr(strtolower($class), 'view'))
{
return;
}
$scope = Factory::getApplication()->scope;
// Load component specific files
if ($this->appName($class) === $scope)
{
$parts = Normalise::fromCamelCase($class, true);
$type = array_pop($parts);
$path = JPATH_SITE . '/libraries/fabble/Views/' .
StringHelper::ucfirst($type) . '.php';
$original = $type;
if (file_exists($path))
{
require_once $path;
class_alias('\\Fabble\\Views\\' . $original, $class);
return;
}
}
*/
if ($class !== 'FabrikView')
{
return;
}
$path = JPATH_SITE .
'/components/com_fabrik/views/FabrikView.php';
if (file_exists($path))
{
require_once $path;
}
}
private function appName($class)
{
$scope = Factory::getApplication()->scope;
return 'com_' . strtolower(substr($class, 0, strlen($scope) -
4));
}
/**
* Load controller file
*
* @param string $class Class name
*/
private function controller($class)
{
if (!str_starts_with($class, 'Fabrik') || strpos($class,
'\\') !== false)
{
return;
}
$parts = preg_split('/(?<=\\w)(?=[A-Z])/', $class);
if ($parts[1] == 'Admin') {
if ($parts[2] != 'Controller' || array_key_exists(3, $parts)
=== false) {
return;
}
$jpath = JPATH_ADMINISTRATOR;
$file = strtolower($parts[3]);
} else {
if ($parts[1] != 'Controller') {
return;
}
$jpath = JPATH_SITE;
$file = strtolower($parts[2]);
}
if (Factory::getApplication()->input->get('format') ==
'raw') {
$file .= '.raw';
}
$path = $jpath . '/components/com_fabrik/controllers/' . $file
. '.php';
if (file_exists($path))
{
require_once $path;
}
}
/**
* Load library files, and possible helpers
*
* @param string $class Class Name
*/
private function library($class)
{
if (strstr($class, '\\'))
{
return;
}
if (strtolower(substr($class, 0, 3)) === 'fab')
{
$class = (substr($class, 3));
// Change from camel cased (e.g. ViewHtml) into a lowercase array (e.g.
'view','html') taken from FOF
$class = preg_replace('/(\s)+/', '_', $class);
$class = strtolower(preg_replace('/(?<=\\w)([A-Z])/',
'_\\1', $class));
$class = explode('_', $class);
$file = (count($class) === 1) ? $class[0] : array_pop($class);
$path = JPATH_SITE . '/libraries/fabble/' .
implode('/', $class);
$classFile = $path . '/' . $file . '.php';
$helper = $path . '/helper.php';
if (file_exists($classFile))
{
include_once $classFile;
}
if (file_exists($helper))
{
include_once $helper;
}
}
}
/**
* Load helper file
**/
private function helper($class)
{
if (!strstr($class, 'Fabrik\Helpers'))
{
return;
}
$className = str_replace('\\', '/', $class);
//$file = explode('/', $class);
//$file = strtolower(array_pop($file));
$path = preg_replace('#Fabrik\/Helpers\/#',
'/libraries/fabrik/fabrik/fabrik/Helpers/', $className);
$path = JPATH_SITE . $path . '.php';
if (file_exists($path))
{
require_once $path;
if (is_callable(array($class, '__initStatic')))
{
$class::__initStatic();
}
}
}
/**
* Load document file
**/
private function document($class)
{
if (!strstr($class, 'Fabrik\Document'))
{
return;
}
$class = str_replace('\\', '/', $class);
//$file = explode('/', $class);
//$file = strtolower(array_pop($file));
$path = preg_replace('#Fabrik\/Document\/#',
'/libraries/fabrik/fabrik/fabrik/Document/', $class);
$path = JPATH_SITE . $path . '.php';
if (file_exists($path))
{
require_once $path;
}
}
}
/*
* If the Fabrik library package has been installed, or we have full github
code, we can use Composer autoload
*/
if (file_exists(JPATH_LIBRARIES .
'/fabrik/vendor/vendor/autoload.php'))
{
$loader = require JPATH_LIBRARIES .
'/fabrik/vendor/vendor/autoload.php';
}
$autoLoader = new FabrikAutoloader();
fabrik/fabrik.xml000064400000001140151165341640007764 0ustar00<?xml
version="1.0" encoding="UTF-8"?>
<extension type="library" method="upgrade"
version="4">
<name>Fabrik library</name>
<libraryname>fabrik/fabrik</libraryname>
<author>Fabrikar</author>
<creationDate>2024-06-26</creationDate>
<copyright>Copyright (C) 2005-2024 Fabrikar - All rights
reserved.</copyright>
<license>GNU General Public License version 3 or later; see
software_license.txt</license>
<version>4.2</version>
<description>Fabrik - Library files</description>
<files>
<folder>fabrik</folder>
<file>include.php</file>
<file>fabrik.xml</file>
</files>
</extension>