primo commit

This commit is contained in:
2024-12-17 17:34:10 +01:00
commit e650f8df99
16435 changed files with 2451012 additions and 0 deletions

9
libraries/.htaccess Normal file
View File

@ -0,0 +1,9 @@
# Apache 2.4+
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
# Apache 2.0-2.2
<IfModule !mod_authz_core.c>
Deny from all
</IfModule>

View File

@ -0,0 +1,227 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework;
defined('_JEXEC') or die();
class AutoLoader
{
/**
* Associative array where the key is a namespace prefix and the value
* is an array of base directories for classes in that namespace.
*
* @var array
*/
protected static $prefixes = [];
/**
* Associative array of prefixes for loading specialized camelCase classes
* where Uppercase letters in the class name indicate directory structure
*
* @var array
*/
protected static $camelPrefixes = [];
/**
* @var AutoLoader
*/
protected static $instance = null;
/**
* @param string $method
*
* @return void
*/
protected static function registerLoader(string $method)
{
if (static::$instance === null) {
static::$instance = new static();
}
spl_autoload_register([static::$instance, $method]);
}
/**
* Register a psr4 namespace
*
* @param ?string $prefix The namespace prefix.
* @param ?string $baseDir A base directory for class files in the
* namespace.
* @param ?bool $prepend If true, prepend the base directory to the stack
* instead of appending it; this causes it to be searched first rather
* than last.
*
* @return void
*/
public static function register(?string $prefix = null, ?string $baseDir = null, ?bool $prepend = false)
{
if ($prefix !== null && $baseDir !== null && is_dir($baseDir)) {
if (count(static::$prefixes) == 0) {
// Register function on first call
static::registerLoader('loadClass');
}
// normalize namespace prefix
$prefix = trim($prefix, '\\') . '\\';
// normalize the base directory with a trailing separator
$baseDir = rtrim($baseDir, '\\/') . '/';
// initialise the namespace prefix array
if (empty(static::$prefixes[$prefix])) {
static::$prefixes[$prefix] = [];
}
// retain the base directory for the namespace prefix
if ($prepend) {
$firstDir = static::$prefixes[$prefix][0] ?? null;
if ($firstDir != $baseDir) {
array_unshift(static::$prefixes[$prefix], $baseDir);
}
} else {
$lastDir = static::$prefixes[$prefix][count(static::$prefixes[$prefix]) - 1] ?? null;
if ($lastDir != $baseDir) {
static::$prefixes[$prefix][] = $baseDir;
}
}
}
}
/**
* Loads the namespaced class file for a given class name.
*
* @param string $class The fully-qualified class name.
*
* @return ?string The mapped file name on success, or boolean false on failure.
*/
protected function loadClass(string $class): ?string
{
$prefixes = explode('\\', $class);
$className = '';
while ($prefixes) {
$className = array_pop($prefixes) . $className;
$prefix = join('\\', $prefixes) . '\\';
if ($filePath = $this->loadMappedFile($prefix, $className)) {
return $filePath;
}
$className = '\\' . $className;
}
return null;
}
/**
* Load the mapped file for a namespace prefix and class.
*
* @param string $prefix The namespace prefix.
* @param string $className The relative class name.
*
* @return ?string false if no mapped file can be loaded | path that was loaded
*/
protected function loadMappedFile(string $prefix, string $className): ?string
{
// are there any base directories for this namespace prefix?
if (isset(static::$prefixes[$prefix]) === false) {
return null;
}
// look through base directories for this namespace prefix
foreach (static::$prefixes[$prefix] as $baseDir) {
$path = $baseDir . str_replace('\\', '/', $className) . '.php';
if (is_file($path)) {
require_once $path;
return $path;
}
}
return null;
}
/**
* Register a base directory for classes organized using camelCase.
* Class names beginning with the prefix will be automatically loaded
* if there is a matching file in the directory tree starting with $baseDir.
* File names and directory names are all expected to be lower case.
*
* Example:
*
* $prefix = 'Simplerenew'
* $baseDir = '/library/joomla'
*
* A class name of: SimplerenewViewAdmin
* Would be in : /library/joomla/view/admin.php
*
* This system is intended for situations where full name spacing is either
* unavailable or impractical due to integration with other systems.
*
* @param string $prefix
* @param string $baseDir
*
* @return void
*/
public static function registerCamelBase(string $prefix, string $baseDir)
{
if (is_dir($baseDir)) {
if (count(static::$camelPrefixes) == 0) {
// Register function on first call
static::registerLoader('loadCamelClass');
}
if (empty(static::$camelPrefixes[$prefix])) {
static::$camelPrefixes[$prefix] = $baseDir;
}
}
}
/**
* Autoload a class using the camelCase structure
*
* @param string $class
*
* @return ?string
*/
protected function loadCamelClass(string $class): ?string
{
if (!class_exists($class)) {
foreach (static::$camelPrefixes as $prefix => $baseDir) {
if (strpos($class, $prefix) === 0) {
$parts = preg_split('/(?<=[a-z])(?=[A-Z])/x', substr($class, strlen($prefix)));
$file = strtolower(join('/', $parts));
$filePath = $baseDir . '/' . $file . '.php';
if (is_file($filePath)) {
require_once $filePath;
return $filePath;
}
}
}
}
return null;
}
}

View File

@ -0,0 +1,224 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework;
defined('_JEXEC') or die();
class Base
{
public const MAP_UNDEFINED = 'undefined';
/**
* Retrieve all public properties and their values
* Although this duplicates get_object_vars(), it
* is mostly useful for internal calls when we need
* to filter out the non-public properties.
*
* @param bool $publicOnly
*
* @return array
*/
public function getProperties($publicOnly = true)
{
$reflection = new \ReflectionObject($this);
$properties = $reflection->getProperties(\ReflectionProperty::IS_PUBLIC);
if (!$publicOnly) {
$properties = array_merge(
$properties,
$reflection->getProperties(\ReflectionProperty::IS_PROTECTED)
);
}
$data = [];
foreach ($properties as $property) {
$name = $property->name;
$data[$name] = $this->{$name};
}
return $data;
}
/**
* Set the public properties from the passed array/object
*
* @param array|Base $data Values to copy to $this
* @param ?array $map Use properties from $data translated using a field map
*
* @return $this
* @throws Exception
*/
public function setProperties($data, ?array $map = null)
{
$properties = $this->getProperties();
if ($map !== null) {
$data = $this->map($data, array_keys($properties), $map);
} elseif (is_object($data)) {
$data = get_object_vars($data);
}
if (!is_array($data)) {
throw new Exception('Invalid argument given - ' . gettype($data));
}
foreach ($data as $k => $v) {
if (array_key_exists($k, $properties)) {
$this->{$k} = $v;
}
}
return $this;
}
/**
* Set all properties to null
*
* @param bool $publicOnly Pass false to include protected properties as well
*
* @return $this
*/
public function clearProperties($publicOnly = true)
{
$properties = array_keys($this->getProperties($publicOnly));
foreach ($properties as $property) {
$this->{$property} = null;
}
return $this;
}
/**
* Map values in a source object/array to Joomlashack Framework keys using a map
* of key equivalences. Any fields in $keys not present in $map will be
* mapped name to name. Map fields mapped to null will be ignored.
*
* Special mappings for field values are recognized with another array. e.g.:
*
* $map['status'] = array(
* 'state' => array(
* 'active' => 1,
* 'closed' => 0,
* Object::MAP_UNDEFINED => -1
* )
* )
* Will map the extension field 'status' to the source field 'state' and
* set status based on the value in the state field. If no match, Object::MAP_UNDEFINED
* will be used for the unknown value.
*
*
* @param array|object $source Source data to be mapped
* @param array $keys Extension keys for which values are being requested
* @param array $map Associative array where key=Extension Key, value=Source Key
*
* @return array An array of all specified keys with values filled in based on map
* @throws Exception
*/
public function map($source, array $keys, array $map = [])
{
if (!is_object($source) && !is_array($source)) {
throw new Exception('Expected array or object for source argument');
}
$result = array_fill_keys($keys, null);
foreach ($keys as $srKey) {
$value = null;
if (!array_key_exists($srKey, $map)) {
$field = $srKey;
$value = $this->getKeyValue($source, $field);
} else {
// This is a mapped key
$field = $map[$srKey];
if (!is_array($field)) {
$value = $this->getKeyValue($source, $field);
} else {
// Mapped to field value
$values = reset($map[$srKey]);
$field = key($map[$srKey]);
$srcValue = $this->getKeyValue($source, $field);
if (isset($values[$srcValue])) {
$value = $values[$srcValue];
} elseif (isset($values[self::MAP_UNDEFINED])) {
$value = $values[self::MAP_UNDEFINED];
}
}
}
$result[$srKey] = $value;
}
return $result;
}
/**
* Safely get a value from an object|array
*
* @param Base|array $data
* @param string $var
* @param mixed $default
*
* @return mixed
*/
public function getKeyValue($data, $var, $default = null)
{
if (is_object($data)) {
return $data->{$var} ?? $default;
}
return $data[$var] ?? $default;
}
/**
*
* Default string rendering for the object. Subclasses should feel
* free to override as desired.
*
* @return string
*/
public function asString()
{
return get_class($this);
}
/**
* Expose properties with defined getters for direct use
*
* @param $name
*
* @return mixed
*/
public function __get($name)
{
$method = 'get' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->$method();
}
return null;
}
/**
* @return string
*/
public function __toString()
{
return $this->asString();
}
}

View File

@ -0,0 +1,340 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2022-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework;
use Joomla\String\StringHelper;
defined('_JEXEC') or die();
abstract class Color
{
/**
* 140 color names recognized by browsers (Aug 2022)
*
* @var string[]
*/
protected static $colorNames = [
'aliceblue' => '#F0F8FF',
'antiquewhite' => '#FAEBD7',
'aqua' => '#00FFFF',
'aquamarine' => '#7FFFD4',
'azure' => '#F0FFFF',
'beige' => '#F5F5DC',
'bisque' => '#FFE4C4',
'black' => '#000000',
'blanchedalmond' => '#FFEBCD',
'blue' => '#0000FF',
'blueviolet' => '#8A2BE2',
'brown' => '#A52A2A',
'burlywood' => '#DEB887',
'cadetblue' => '#5F9EA0',
'chartreuse' => '#7FFF00',
'chocolate' => '#D2691E',
'coral' => '#FF7F50',
'cornflowerblue' => '#6495ED',
'cornsilk' => '#FFF8DC',
'crimson' => '#DC143C',
'cyan' => '#00FFFF',
'darkblue' => '#00008B',
'darkcyan' => '#008B8B',
'darkgoldenrod' => '#B8860B',
'darkgray' => '#A9A9A9',
'darkgreen' => '#006400',
'darkkhaki' => '#BDB76B',
'darkmagenta' => '#8B008B',
'darkolivegreen' => '#556B2F',
'darkorange' => '#FF8C00',
'darkorchid' => '#9932CC',
'darkred' => '#8B0000',
'darksalmon' => '#E9967A',
'darkseagreen' => '#8FBC8F',
'darkslateblue' => '#483D8B',
'darkslategray' => '#2F4F4F',
'darkturquoise' => '#00CED1',
'darkviolet' => '#9400D3',
'deeppink' => '#FF1493',
'deepskyblue' => '#00BFFF',
'dimgray' => '#696969',
'dodgerblue' => '#1E90FF',
'firebrick' => '#B22222',
'floralwhite' => '#FFFAF0',
'forestgreen' => '#228B22',
'fuchsia' => '#FF00FF',
'gainsboro' => '#DCDCDC',
'ghostwhite' => '#F8F8FF',
'gold' => '#FFD700',
'goldenrod' => '#DAA520',
'gray' => '#808080',
'green' => '#008000',
'greenyellow' => '#ADFF2F',
'honeydew' => '#F0FFF0',
'hotpink' => '#FF69B4',
'indianred' => '#CD5C5C',
'indigo' => '#4B0082',
'ivory' => '#FFFFF0',
'khaki' => '#F0E68C',
'lavender' => '#E6E6FA',
'lavenderblush' => '#FFF0F5',
'lawngreen' => '#7CFC00',
'lemonchiffon' => '#FFFACD',
'lightblue' => '#ADD8E6',
'lightcoral' => '#F08080',
'lightcyan' => '#E0FFFF',
'lightgoldenrodyellow' => '#FAFAD2',
'lightgrey' => '#D3D3D3',
'lightgreen' => '#90EE90',
'lightpink' => '#FFB6C1',
'lightsalmon' => '#FFA07A',
'lightseagreen' => '#20B2AA',
'lightskyblue' => '#87CEFA',
'lightslategray' => '#778899',
'lightsteelblue' => '#B0C4DE',
'lightyellow' => '#FFFFE0',
'lime' => '#00FF00',
'limegreen' => '#32CD32',
'linen' => '#FAF0E6',
'magenta' => '#FF00FF',
'maroon' => '#800000',
'mediumaquamarine' => '#66CDAA',
'mediumblue' => '#0000CD',
'mediumorchid' => '#BA55D3',
'mediumpurple' => '#9370D8',
'mediumseagreen' => '#3CB371',
'mediumslateblue' => '#7B68EE',
'mediumspringgreen' => '#00FA9A',
'mediumturquoise' => '#48D1CC',
'mediumvioletred' => '#C71585',
'midnightblue' => '#191970',
'mintcream' => '#F5FFFA',
'mistyrose' => '#FFE4E1',
'moccasin' => '#FFE4B5',
'navajowhite' => '#FFDEAD',
'navy' => '#000080',
'oldlace' => '#FDF5E6',
'olive' => '#808000',
'olivedrab' => '#6B8E23',
'orange' => '#FFA500',
'orangered' => '#FF4500',
'orchid' => '#DA70D6',
'palegoldenrod' => '#EEE8AA',
'palegreen' => '#98FB98',
'paleturquoise' => '#AFEEEE',
'palevioletred' => '#D87093',
'papayawhip' => '#FFEFD5',
'peachpuff' => '#FFDAB9',
'peru' => '#CD853F',
'pink' => '#FFC0CB',
'plum' => '#DDA0DD',
'powderblue' => '#B0E0E6',
'purple' => '#800080',
'red' => '#FF0000',
'rosybrown' => '#BC8F8F',
'royalblue' => '#4169E1',
'saddlebrown' => '#8B4513',
'salmon' => '#FA8072',
'sandybrown' => '#F4A460',
'seagreen' => '#2E8B57',
'seashell' => '#FFF5EE',
'sienna' => '#A0522D',
'silver' => '#C0C0C0',
'skyblue' => '#87CEEB',
'slateblue' => '#6A5ACD',
'slategray' => '#708090',
'snow' => '#FFFAFA',
'springgreen' => '#00FF7F',
'steelblue' => '#4682B4',
'tan' => '#D2B48C',
'teal' => '#008080',
'thistle' => '#D8BFD8',
'tomato' => '#FF6347',
'turquoise' => '#40E0D0',
'violet' => '#EE82EE',
'wheat' => '#F5DEB3',
'white' => '#FFFFFF',
'whitesmoke' => '#F5F5F5',
'yellow' => '#FFFF00',
'yellowgreen' => '#9ACD32',
];
/**
* Darken or lighten a color from a named or hex color string. Leading
* hash mark is optional and the result will be returned in the
* same format.
*
* $percent == 100 means no change.
* $percent > 100 means lighten
* $percent < 100 means darken
*
* Since the math will generate floating point numbers, and we need integers,
* by default the result will be the next highest integer. More subtle results
* may be obtained by using rounding.
*
* @see https://gist.github.com/stephenharris/5532899
*
* @param string $color
* @param float $percent
* @param bool $useRounding
*
* @return string
*/
public static function adjust(string $color, float $percent, ?bool $useRounding = false): string
{
$hexColor = static::nameToHex($color);
if (empty($hexColor)) {
// Bad color string given
return $color;
}
$hash = strpos($color, '#') === 0 ? '#' : '';
$rawHex = str_replace('#', '', $hexColor);
switch (strlen($rawHex)) {
case 3:
$color = array_map(
function ($hex) {
return $hex . $hex;
},
str_split($rawHex)
);
break;
case 6:
$color = str_split($rawHex, 2);
break;
default:
// It's just wrong, so just send it back
return $color;
}
$color = array_map('hexdec', $color);
foreach ($color as &$value) {
$value = $value * ($percent / 100);
}
$color = array_map(
function ($value) use ($useRounding) {
$value = $useRounding ? round($value) : ceil($value);
return str_pad(dechex($value), 2, '0', STR_PAD_LEFT);
},
$color
);
return $hash . join('', $color);
}
/**
* Determine if a color is brighter than some midpoint. By default,
* half of pure white (255/2) is used
*
* See: https://www.w3.org/TR/AERT/#color-contrast
*
* @param ?string $color
* @param ?float $midpoint
*
* @return bool
*/
public static function isTooBright(?string $color, float $midpoint = 127.5): bool
{
$rgb = static::hexToRgb(static::nameToHex($color));
if ($rgb) {
$whiteValue = (($rgb['r'] * .299) + ($rgb['g'] * .587) + ($rgb['b'] * .114));
return $whiteValue > $midpoint;
}
return false;
}
/**
* Converts a 3 or 6 character hex color to an rgb array
*
* @param ?string $hex
*
* @return ?string[]
*/
public static function hexToRgb(?string $hex): ?array
{
if ($hex) {
// Strip hash if needed
if (strpos($hex, '#') === 0) {
$hex = trim($hex, '#');
}
$hexType = StringHelper::strlen($hex);
if (in_array($hexType, [3, 6]) && preg_match('/[0-9a-fA-F]/', $hex)) {
// Valid hex code in short or full form
switch ($hexType) {
case 3:
$rgb = array_map(
function ($c) {
return str_repeat($c, 2);
},
StringHelper::str_split($hex, 1)
);
break;
case 6:
$rgb = StringHelper::str_split($hex, 2);
break;
}
return array_map(
'hexdec',
array_combine(
['r', 'g', 'b'],
$rgb
)
);
}
return null;
}
}
/**
* @param string $name
*
* @return ?string
*/
public static function nameToHex(string $name): ?string
{
$hex = null;
$hashtag = strpos($name, '#');
if ($hashtag === false) {
$hex = static::$colorNames[strtolower($name)] ?? $hex;
} elseif ($hashtag === 0) {
$hex = $name;
} elseif (in_array(strlen($name), [3, 6])) {
$hex = '#' . $name;
}
return $hex;
}
}

View File

@ -0,0 +1,195 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Content;
use Alledia\Framework\Base;
use Joomla\Registry\Registry;
defined('_JEXEC') or die();
class Tag extends Base
{
/**
* The unparsed tag string
*
* @var string
*/
protected $unparsedString = null;
/**
* The tag name
*
* @var string
*/
protected $name = null;
/**
* The tag content
*
* @var string
*/
protected $content = '';
/**
* The regex used to find the tag
*
* @var string
*/
protected $regex = null;
/**
* The tag params
*
* @var Registry
*/
public $params = null;
/**
* Constructor method, that defines the internal content
*
* @param string $name
* @param string $unparsedString
*
* @return void
*/
public function __construct($name, $unparsedString)
{
$this->name = $name;
$this->unparsedString = $unparsedString;
$this->regex = static::getRegex($this->name);
$this->parse();
}
/**
* Return the regex used to find tags inside a text.
*
* @param string $tagName
*
* @return string
*/
public static function getRegex($tagName)
{
return '/\{' . $tagName . '(?:(?!\{\/' . $tagName
. '\}).)*\}[\s]*([^{]*)[\s]*\{\/' . $tagName . '\}/i';
}
/**
* Parse this tag storing the content and params.
*
* @return void
*/
protected function parse()
{
$this->content = $this->parseContent();
$this->params = $this->parseParams();
}
/**
* Parse the {tagName}{/tagName} returning the content
*
* @return string
*/
protected function parseContent()
{
$content = '';
if (!empty($this->unparsedString)) {
if (strpos($this->unparsedString, '{' . $this->name) !== false) {
// Check if the source has the tag name
if (preg_match($this->regex, $this->unparsedString, $match)) {
$content = trim($match[1]);
}
}
}
return trim($content);
}
/**
* Parse inline parameters from the tag
*
* @return Registry
*/
protected function parseParams()
{
// Remove the tag name, extracting only the tag attributes
$inlineParams = preg_replace('/^{' . $this->name . '/', '', $this->unparsedString);
$inlineParams = trim(preg_replace('/}[a-z0-9\s]*{\/' . $this->name . '}/', '', $inlineParams));
// Parse the inline params
$regex = '/([a-z0-9_]*)(?:="([^"]*)")?\s?/i';
$parsed = new Registry();
if (preg_match_all($regex, $inlineParams, $vars)) {
$fullParams = $vars[0];
$paramNames = $vars[1];
$paramValues = $vars[2];
foreach ($fullParams as $i => $param) {
if (!empty($paramNames[$i])) {
$parsed->set(trim($paramNames[$i]), trim($paramValues[$i]));
}
}
}
return $parsed;
}
/**
* Return the unparsed string
*
* @return string
*/
public function toString()
{
return $this->unparsedString;
}
/**
* Returns the tag content
*
* @return string
*/
public function getContent()
{
return $this->content;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return Registry
*/
public function getParams()
{
return $this->params;
}
}

View File

@ -0,0 +1,94 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Content;
use Alledia\Framework\Base;
defined('_JEXEC') or die();
class Text extends Base
{
public $content = '';
/**
* Constructor method, that defines the internal content
*
* @param string $content
*/
public function __construct($content)
{
$this->content = $content;
}
/**
* Extract multiple {mytag} tags from the content
*
* @todo Recognize unclose tags like {dumbtag param1="12"}
*
* @param string $tagName
*
* @return array An array with all tags {tagName} found on the text
*/
protected function extractPluginTags($tagName)
{
preg_match_all(Tag::getRegex($tagName), $this->content, $matches);
return $matches[0];
}
/**
* Extract multiple {mytag} tags from the content, returning
* as Tag instances
*
* @param string $tagName
*
* @return Tag[] An array with all tags {tagName} found on the text
*/
public function getPluginTags($tagName)
{
$unparsedTags = $this->extractPluginTags($tagName);
$tags = [];
foreach ($unparsedTags as $unparsedTag) {
$tags[] = new Tag($tagName, $unparsedTag);
}
return $tags;
}
/**
* Extract multiple {mytag} tags from the content, returning
* as Tag instances
*
* @param string $tagName
*
* @return array An array with all tags {tagName} found on the text
* @deprecated 1.3.1 Use getPluginsTags instead
*/
public function getTags($tagName)
{
// Deprecated. Use getPluginTags instead
return $this->getPluginTags($tagName);
}
}

View File

@ -0,0 +1,93 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework;
defined('_JEXEC') or die();
class Exception extends \Exception
{
/**
* Set error message to include class::method() information. Could be used live
* but very helpful during development.
*
* @return string
*/
public function getTraceMessage()
{
$trace = $this->getTrace();
$caller = array_shift($trace);
$result = '';
if (!empty($caller['class'])) {
$result .= $caller['class'] . '::';
}
if (!empty($caller['function'])) {
$result .= $caller['function'] . '()';
}
return trim($result . ' ' . $this->message);
}
/**
* Get single line listing of call stack
*
* @return array
*/
public function getCallStack()
{
$trace = $this->getTrace();
$stack = [];
foreach ($trace as $caller) {
$row = 'Line ' . (empty($caller['line']) ? '' : $caller['line'] . ' - ');
if (!empty($caller['class'])) {
$row .= $caller['class'] . '::';
}
if (!empty($caller['function'])) {
$row .= $caller['function'] . '()';
}
if (!empty($caller['file'])) {
$row .= ' [' . $caller['file'] . ']';
}
$stack[] = $row;
}
return $stack;
}
/**
* Allow custom exceptions to be created. Note
* that
*
* @param string $file
*
* @return void
*/
public function setLocation(string $file, int $line)
{
$this->file = $file;
$this->line = $line;
}
}

View File

@ -0,0 +1,33 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Exception;
use Alledia\Framework\Exception;
defined('_JEXEC') or die();
class NotFound extends Exception
{
}

View File

@ -0,0 +1,125 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework;
use Alledia\Framework\Joomla\Extension\Licensed;
use JEventDispatcher;
use Joomla\CMS\Version;
use Joomla\Database\DatabaseDriver;
use Joomla\Event\DispatcherInterface;
use Joomla\Event\Event;
defined('_JEXEC') or die();
abstract class Factory extends \Joomla\CMS\Factory
{
/**
* Instances of extensions
*
* @var array
*/
protected static $extensionInstances = [];
/**
* @var JEventDispatcher|DispatcherInterface
*/
protected static $dispatcher = null;
/**
* Get an extension
*
* @param string $namespace The extension namespace
* @param string $type The extension type
* @param string $folder The extension folder (plugins only)
*
* @return Licensed The extension instance
*/
public static function getExtension($namespace, $type, $folder = null)
{
$key = $namespace . $type . $folder;
if (empty(static::$extensionInstances[$key])) {
$instance = new Joomla\Extension\Licensed($namespace, $type, $folder);
static::$extensionInstances[$key] = $instance;
}
return static::$extensionInstances[$key];
}
/**
* @return \JDatabaseDriver|DatabaseDriver
*/
public static function getDatabase()
{
if (is_callable([static::class, 'getContainer'])) {
return static::getContainer()->get('DatabaseDriver');
}
return static::getDbo();
}
/**
* @return JEventDispatcher|DispatcherInterface
*/
public static function getDispatcher()
{
if (Version::MAJOR_VERSION < 4) {
if (static::$dispatcher === null) {
static::$dispatcher = JEventDispatcher::getInstance();
}
return static::$dispatcher;
}
return static::getApplication()->getDispatcher();
}
/**
* @param string $eventName
* @param array $args
*
* @return array
*/
public static function triggerEvent(string $eventName, array $args)
{
try {
$dispatcher = static::getDispatcher();
} catch (\UnexpectedValueException $exception) {
// ignore for now
return [];
}
if (Version::MAJOR_VERSION < 4) {
$result = $dispatcher->trigger($eventName, $args);
} else {
$event = new Event($eventName, $args);
$result = $dispatcher->dispatch($eventName, $event);
$result = $result['result'] ?? [];
}
return $result;
}
}

View File

@ -0,0 +1,280 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework;
use Alledia\Framework\Joomla\Extension\Helper as ExtensionHelper;
use Joomla\CMS\Form\Form;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Version;
use Joomla\Database\DatabaseDriver;
use Joomla\Database\DatabaseQuery;
use ReflectionMethod;
defined('_JEXEC') or die();
abstract class Helper
{
/**
* @var int[]
*/
protected static $errorConstants = null;
/**
* Return an array of Alledia extensions
*
* @param ?string $license
*
* @return object[]
*/
public static function getAllediaExtensions(?string $license = ''): array
{
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select([
$db->quoteName('extension_id'),
$db->quoteName('type'),
$db->quoteName('element'),
$db->quoteName('folder'),
])
->from('#__extensions')
->where([
sprintf('%s LIKE %s', $db->quoteName('custom_data'), $db->quote('%"author":"Alledia"%')),
sprintf('%s LIKE %s', $db->quoteName('custom_data'), $db->quote('%"author":"OSTraining"%')),
sprintf('%s LIKE %s', $db->quoteName('custom_data'), $db->quote('%"author":"Joomlashack"%')),
sprintf('%s LIKE %s', $db->quoteName('manifest_cache'), $db->quote('%"author":"Alledia"%')),
sprintf('%s LIKE %s', $db->quoteName('manifest_cache'), $db->quote('%"author":"OSTraining"%')),
sprintf('%s LIKE %s', $db->quoteName('manifest_cache'), $db->quote('%"author":"Joomlashack"%')),
], 'OR')
->group($db->quoteName('extension_id'));
$rows = $db->setQuery($query)->loadObjectList();
$extensions = [];
foreach ($rows as $row) {
if ($fullElement = ExtensionHelper::getFullElementFromInfo($row->type, $row->element, $row->folder)) {
if ($extensionInfo = ExtensionHelper::getExtensionInfoFromElement($fullElement)) {
$extension = new Joomla\Extension\Licensed($extensionInfo['namespace'], $row->type, $row->folder);
if (
empty($license)
||
($license == 'pro' && $extension->isPro())
|| ($license == 'free' && $extension->isFree())
) {
$extensions[$row->extension_id] = $extension;
}
}
}
}
return $extensions;
}
/**
* @return string
*/
public static function getJoomlaVersionCssClass(): string
{
return sprintf('joomla%sx', Version::MAJOR_VERSION);
}
/**
* Create class alias for classes that may not exist
*
* @param array $classes
*
* @return void
*/
public static function createClassAliases(array $classes): void
{
foreach ($classes as $class => $classAlias) {
if (class_exists($classAlias) == false) {
class_alias($class, $classAlias);
}
}
}
/**
* Create common database class aliases for classes that don't exist
*
* @return void
*/
public static function createDatabaseClassAliases(): void
{
static::createClassAliases([
\JDatabaseQuery::class => DatabaseQuery::class,
\JDatabaseDriver::class => DatabaseDriver::class,
]);
}
/**
* @param string $className
* @param string $methodName
* @param array $params
*
* @return mixed
*/
public static function callMethod(string $className, string $methodName, ?array $params = [])
{
$result = true;
if (method_exists($className, $methodName)) {
$method = new ReflectionMethod($className, $methodName);
if ($method->isStatic()) {
$result = call_user_func_array("{$className}::{$methodName}", $params);
} else {
// Check if we have a singleton class
if (method_exists($className, 'getInstance')) {
$instance = $className::getInstance();
} else {
$instance = new $className();
}
$result = call_user_func_array([$instance, $methodName], $params);
}
}
return $result;
}
/**
* @param string $name
*
* @return Form
*/
public static function createForm(string $name): Form
{
$form = new Form($name);
$form->load('<?xml version="1.0" encoding="UTF-8"?><form/>');
return $form;
}
/**
* @param string $name
* @param ?string $appName
* @param ?array $options
*
* @return mixed
*/
public static function getContentModel(string $name, ?string $appName = null, array $options = [])
{
return static::getJoomlaModel($name, 'ContentModel', 'com_content', $appName, $options);
}
/**
* @param string $name
* @param ?string $appName
* @param ?array $options
*
* @return mixed
*/
public static function getCategoryModel(string $name, ?string $appName = null, ?array $options = [])
{
return static::getJoomlaModel($name, 'CategoriesModel', 'com_categories', $appName, $options);
}
/**
* @param string $name
* @param string $prefix
* @param string $component
* @param ?string $appName
* @param ?array $options
*
* @return mixed
* @throws \Exception
*/
public static function getJoomlaModel(
string $name,
string $prefix,
string $component,
?string $appName = null,
?array $options = []
) {
$defaultApp = 'Site';
$appNames = [$defaultApp, 'Administrator'];
$appName = ucfirst($appName ?: $defaultApp);
$appName = in_array($appName, $appNames) ? $appName : $defaultApp;
$basePath = $appName == 'Administrator' ? JPATH_ADMINISTRATOR : JPATH_SITE;
$componentPath = $basePath . '/components/' . $component;
Table::addIncludePath($componentPath . '/tables');
Form::addFormPath($componentPath . '/forms');
Form::addFormPath($componentPath . '/models/forms');
Form::addFieldPath($componentPath . '/models/fields');
Form::addFormPath($componentPath . '/model/form');
Form::addFieldPath($componentPath . '/model/field');
if (Version::MAJOR_VERSION < 4) {
BaseDatabaseModel::addIncludePath($componentPath . '/models');
$model = BaseDatabaseModel::getInstance($name, $prefix, $options);
} else {
$model = Factory::getApplication()->bootComponent($component)
->getMVCFactory()->createModel($name, $appName, $options);
}
return $model;
}
/**
* For use by custom error handlers created using
* set_error_handler() intended to catch php errors.
*
* @param int $number
* @param string $message
* @param string $file
* @param int $line
*
* @return Exception
*/
public static function errorToException(int $number, string $message, string $file, int $line): Exception
{
if (static::$errorConstants === null) {
static::$errorConstants = [];
$allErrors = get_defined_constants(true);
foreach ($allErrors['Core'] as $name => $value) {
if (strpos($name, 'E_') === 0) {
static::$errorConstants[$name] = $value;
}
}
}
$error = array_search($number, static::$errorConstants);
$message = sprintf('%s - %s', $error === false ? $number : $error, $message);
$exception = new Exception($message, 0);
$exception->setLocation($file, $line);
return $exception;
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla;
use Alledia\Framework\Factory;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Version;
defined('_JEXEC') or die();
abstract class AbstractTable extends Table
{
/**
* Joomla version agnostic loading of other component tables
*
* @param string $component
* @param string $name
* @param string $prefix
*
* @return ?Table
*/
public static function getComponentInstance($component, $name, $prefix): ?Table
{
if (Version::MAJOR_VERSION < 4) {
Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/' . $component . '/tables');
$table = Table::getInstance($name, $prefix);
} else {
try {
$table = Factory::getApplication()
->bootComponent($component)
->getMVCFactory()
->createTable($name, 'Administrator');
} catch (\Throwable $error) {
// Ignore
}
}
return $table ?? null;
}
}

View File

@ -0,0 +1,130 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla;
use Joomla\CMS\Form\Form;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\MVC\View\HtmlView;
use Joomla\CMS\Object\CMSObject;
defined('_JEXEC') or die();
abstract class AbstractView extends HtmlView
{
use TraitAllediaView;
/**
* @var BaseDatabaseModel
*/
protected $model = null;
/**
* Formally declare this since Joomla core does not
*
* @var Form
*/
protected $form = null;
/**
* @var CMSObject
*/
protected $state = null;
/**
* @inheritDoc
* @throws \Exception
*/
public function __construct($config = [])
{
$this->setup();
parent::__construct($config);
}
/**
* @inheritDoc
*/
public function setModel($model, $default = false)
{
$model = parent::setModel($model, $default);
if ($model && $default) {
$this->model = $model;
$this->state = $this->model->getState();
}
return $model;
}
/**
* @inheritDoc
*/
public function display($tpl = null)
{
if ($this->initSuccess) {
$this->displayHeader();
parent::display($tpl);
$this->displayFooter();
}
}
/**
* For use by subclasses
*
* @return void
*/
protected function displayHeader()
{
// Display custom text
}
/**
* For use by subclasses
*
* @return void
*/
protected function displayFooter()
{
// Display custom text
}
/**
* @param string $name
* @param string $layout
*
* @return string
* @throws \Exception
*/
public function loadDefaultTemplate(string $name, ?string $layout = 'default'): string
{
$currentLayout = $this->setLayout($layout);
$output = $this->loadTemplate($name);
$this->setLayout($currentLayout);
return $output;
}
}

View File

@ -0,0 +1,50 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Controller;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\MVC\Controller\AdminController;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\Input\Input;
defined('_JEXEC') or die();
class Admin extends AdminController
{
use TraitController;
/**
* @inheritDoc
*/
public function __construct(
$config = [],
MVCFactoryInterface $factory = null,
?CMSApplication $app = null,
?Input $input = null
) {
parent::__construct($config, $factory, $app, $input);
$this->customInit();
}
}

View File

@ -0,0 +1,44 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Controller;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
defined('_JEXEC') or die();
class Base extends BaseController
{
use TraitController;
/**
* @inheritDoc
*/
public function __construct($config = [], MVCFactoryInterface $factory = null)
{
parent::__construct($config, $factory);
$this->customInit();
}
}

View File

@ -0,0 +1,80 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Controller;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\MVC\Controller\FormController;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\Router\Route;
use Joomla\Input\Input;
defined('_JEXEC') or die();
class Form extends FormController
{
use TraitController;
/**
* @inheritDoc
*/
public function __construct(
$config = [],
MVCFactoryInterface $factory = null,
?CMSApplication $app = null,
?Input $input = null
) {
parent::__construct($config, $factory, $app, $input);
$this->customInit();
}
/**
* @inheritDoc
* @throws \Exception
*/
public function batch($model = null)
{
$this->checkToken();
$inflector = $this->getStringInflector();
$view = $this->app->input->getCmd('view', $this->default_view);
if ($inflector->isPlural($view)) {
$modelName = $inflector->toSingular($view);
$model = $this->getModel($modelName, '', []);
$linkQuery = http_build_query([
'option' => $this->app->input->getCmd('option'),
'view' => $view
]);
$this->setRedirect(Route::_('index.php?' . $linkQuery . $this->getRedirectToListAppend(), false));
return parent::batch($model);
}
return null;
}
}

View File

@ -0,0 +1,79 @@
<?php
/**
* @package OSCampus
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2015-2023 Joomlashack.com. All rights reserved
* @license http://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of OSCampus.
*
* OSCampus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* OSCampus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OSCampus. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Controller;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Response\JsonResponse;
defined('_JEXEC') or die();
abstract class Json extends Base
{
/**
* @inheritDoc
* @throws \Exception`
*/
public function checkToken($method = 'post', $redirect = false)
{
$valid = parent::checkToken($method, $redirect);
if (!$valid) {
throw new \Exception(Text::_('JINVALID_TOKEN'), 403);
}
return true;
}
/**
* Sends a json package to output. All php processing ended to prevent any
* plugin processing that might slow things down or waste memory.
*
* @param ?string|\Throwable $message
*
* @return void
*/
protected function returnJson($message = null)
{
$result = new JsonResponse();
if ($message) {
if ($message instanceof \Throwable) {
$result->success = false;
$result->message = $message->getMessage();
$result->data = [
'file' => $message->getFile(),
'line' => $message->getLine()
];
} else {
$result->message = $message;
}
}
header('Content-Type: application/json');
echo $result;
jexit();
}
}

View File

@ -0,0 +1,128 @@
<?php
/**
* @package OSCampus
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of OSCampus.
*
* OSCampus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* OSCampus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OSCampus. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Controller;
use Alledia\Framework\Factory;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\String\Inflector;
defined('_JEXEC') or die();
trait TraitController
{
/**
* For consistency between Joomla 3 & 4
*
* @var CMSApplication
* @since Joomla v4
*/
protected $app = null;
/**
* Standard return to calling url. In order:
* - Looks for base64 encoded 'return' URL variable
* - Uses current 'Itemid' URL variable
* - Uses current 'option', 'view', 'layout' URL variables
* - Goes to site default page
*
* @param ?array|string $message The message to queue up
* @param ?string $type message|notice|error
* @param ?string $return (optional) base64 encoded url for redirect
*
* @return void
*/
protected function callerReturn($message = null, ?string $type = null, ?string $return = null)
{
$url = $return ?: $this->app->input->getBase64('return');
if ($url) {
$url = base64_decode($url);
} else {
$url = new Uri('index.php');
if ($itemId = $this->app->input->getInt('Itemid')) {
$url->setVar('Itemid', $itemId);
} elseif ($option = $this->app->input->getCmd('option')) {
$url->setVar('option', $option);
}
if ($view = $this->app->input->getCmd('view')) {
$url->setVar('view', $view);
if ($layout = $this->app->input->getCmd('layout')) {
$url->setVar('layout', $layout);
}
}
}
if (is_array($message)) {
$message = join('<br>', $message);
}
$this->setRedirect(Route::_((string)$url), $message, $type);
}
/**
* Return to referrer if internal, home page if external
*
* @param string $message
* @param string $type
*
* @return void
*/
protected function errorReturn(string $message, string $type = 'error')
{
$referrer = $this->input->server->getString('HTTP_REFERER');
if (Uri::isInternal($referrer) == false) {
$referrer = 'index.php';
}
$this->app->enqueueMessage($message, $type);
$this->app->redirect($referrer);
}
/**
* Provide consistency between Joomla 3/Joomla 4 among other possibilities
*
* @return void
*/
protected function customInit()
{
if (empty($this->app)) {
$this->app = Factory::getApplication();
}
}
/**
* @return Inflector
*/
protected function getStringInflector(): Inflector
{
return Inflector::getInstance();
}
}

View File

@ -0,0 +1,149 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2022-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Events;
use Alledia\Framework\Factory;
use Joomla\Event\AbstractEvent;
use Joomla\Event\Dispatcher;
defined('_JEXEC') or die();
trait TraitObservable
{
/**
* @var \JEventDispatcher|Dispatcher
*/
protected static $coreDispatcher = null;
/**
* @var bool
*/
protected static $legacyDispatch = null;
/**
* @return \JEventDispatcher|Dispatcher
*/
public function getDispatcher()
{
if (static::$coreDispatcher === null) {
static::$coreDispatcher = Factory::getDispatcher();
static::$legacyDispatch = is_callable([static::$coreDispatcher, 'register']);
}
return static::$coreDispatcher;
}
/**
* $events is accepted in these forms:
*
* ['handler1', 'handler2',...]: array of specific methods to register
* 'handler' : a single method to register
* 'prefix*' : all public methods in $observable that begin with 'prefix'
* '*string' : all public methods in $observable that contain 'string'
*
* @param string|string[] $events
* @param ?object $observable
* @param ?bool $legacyListeners
*
* @return void
*/
public function registerEvents($events, object $observable = null, bool $legacyListeners = true): void
{
$observable = $observable ?: $this;
if (is_string($events) && strpos($events, '*') !== false) {
$startsWith = strpos($events, '*') !== 0;
$event = preg_replace('/[^a-z\d_]/i', '', $events);
// Look for methods that match the wildcarded name
$observableInfo = new \ReflectionClass($observable);
$methods = $observableInfo->getMethods(\ReflectionMethod::IS_PUBLIC);
$events = [];
foreach ($methods as $method) {
$position = strpos($method->name, $event);
if (
($startsWith && $position === 0)
|| ($startsWith == false && $position > 0)
) {
$events[] = $method->name;
}
}
} elseif (is_string($events)) {
$events = [$events];
}
if ($events && is_array($events)) {
$dispatcher = Factory::getDispatcher();
foreach ($events as $event) {
$handler = [$observable, $event];
if (is_callable([$dispatcher, 'register'])) {
$dispatcher->register($event, $handler);
} elseif (is_callable([$dispatcher, 'addListener'])) {
if ($legacyListeners) {
$dispatcher->addListener($event, $this->createLegacyHandler($handler));
} else {
$dispatcher->addListener($event, $handler);
}
}
}
}
}
/**
* @param callable $handler
*
* @return callable
*/
final protected function createLegacyHandler(callable $handler): callable
{
return function (AbstractEvent $event) use ($handler) {
$arguments = $event->getArguments();
// Extract any old results; they must not be part of the method call.
$allResults = [];
if (isset($arguments['result'])) {
$allResults = $arguments['result'];
unset($arguments['result']);
}
// Convert to indexed array for unpacking.
$arguments = \array_values($arguments);
$result = $handler(...$arguments);
// Ignore null results
if ($result === null) {
return;
}
// Restore the old results and add the new result from our method call
$allResults[] = $result;
$event['result'] = $allResults;
};
}
}

View File

@ -0,0 +1,154 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Extension;
defined('_JEXEC') or die();
use Alledia\Framework\Factory;
use Alledia\Framework\Joomla\Table\Base as BaseTable;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Table\Table;
abstract class AbstractComponent extends Licensed
{
/**
* @var self
*/
protected static $instance = null;
/**
* @var object
*/
protected $controller = null;
/**
* @inheritDoc
*/
public function __construct($namespace)
{
parent::__construct($namespace, 'component');
BaseDatabaseModel::addIncludePath(JPATH_COMPONENT . '/models');
Table::addIncludePath(JPATH_COMPONENT . '/tables');
$this->loadLibrary();
}
/**
* @param string $namespace
*
* @return self
*/
public static function getInstance($namespace = null)
{
if (empty(static::$instance)) {
static::$instance = new static($namespace);
}
return static::$instance;
}
/**
* @return void
* @throws \Exception
*/
public function init()
{
$this->loadController();
$this->executeRedirectTask();
}
/**
* @return void
* @throws \Exception
*/
public function loadController()
{
if (!is_object($this->controller)) {
$app = Factory::getApplication();
$client = $app->isClient('administrator') ? 'Admin' : 'Site';
$controllerClass = 'Alledia\\' . $this->namespace . '\\' . ucfirst($this->license)
. '\\Joomla\\Controller\\' . $client;
require JPATH_COMPONENT . '/controller.php';
$this->controller = $controllerClass::getInstance($this->namespace);
}
}
/**
* @return void
* @throws \Exception
*/
public function executeRedirectTask()
{
$app = Factory::getApplication();
$task = $app->input->getCmd('task');
$this->controller->execute($task);
$this->controller->redirect();
}
/**
* @param string $type
*
* @return ?BaseDatabaseModel
*/
public function getModel(string $type): ?BaseDatabaseModel
{
$class = sprintf(
'Alledia\\%s\\%s\\Joomla\\Model\\%s',
$this->namespace,
$this->isPro() ? 'Pro' : 'Free',
$type
);
if (class_exists($class)) {
return new $class();
}
return BaseDatabaseModel::getInstance($type, $this->namespace . 'Model');
}
/**
* @param string $type
*
* @return ?Table
*/
public function getTable(string $type): ?Table
{
$class = sprintf(
'Alledia\\%s\\%s\\Joomla\\Table\\%s',
$this->namespace,
$this->isPro() ? 'Pro' : 'Free',
$type
);
if (class_exists($class)) {
$db = Factory::getDbo();
return new $class($db);
}
return BaseTable::getInstance($type, $this->namespace . 'Table');
}
}

View File

@ -0,0 +1,108 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Extension;
defined('_JEXEC') or die();
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\Registry\Registry;
abstract class AbstractFlexibleModule extends Licensed
{
/**
* @var string
*/
public $title = null;
/**
* @var
*/
public $module = null;
/**
* @var
*/
public $position = null;
/**
* @var string
*/
public $content = null;
/**
* @var bool
*/
public $showtitle = null;
/**
* @var int
*/
public $menuid = null;
/**
* @var string
*/
public $style = null;
/**
* @inheritDoc
*/
public function __construct($namespace, $module = null)
{
parent::__construct($namespace, 'module');
$this->loadLibrary();
if (is_object($module)) {
$properties = [
'id',
'title',
'module',
'position',
'content',
'showtitle',
'menuid',
'name',
'style',
'params'
];
foreach ($properties as $property) {
if (isset($module->{$property})) {
$this->{$property} = $module->{$property};
}
}
if (!$this->params instanceof Registry) {
$this->params = new Registry($this->params);
}
}
}
/**
* Method to initialize the module
*/
public function init()
{
require ModuleHelper::getLayoutPath('mod_' . $this->element, $this->params->get('layout', 'default'));
}
}

View File

@ -0,0 +1,144 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Extension;
defined('_JEXEC') or die();
use Alledia\Framework\Factory;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\Registry\Registry;
/**
* @deprecated 1.4.1 Use AbstractFlexibleModule instead. This module doesn't
* work with multiple modules in the same page because of the Singleton pattern.
*
*/
abstract class AbstractModule extends Licensed
{
/**
* @var AbstractModule
*/
protected static $instance;
/**
* @var string
*/
public $title = null;
/**
* @var string
*/
public $module = null;
/**
* @var string
*/
public $position = null;
/**
* @var string
*/
public $content = null;
/**
* @var bool
*/
public $showtitle = null;
/**
* @var int
*/
public $menuid = null;
/**
* @var string
*/
public $style = null;
/**
* @inheritDoc
*/
public function __construct($namespace)
{
parent::__construct($namespace, 'module');
$this->loadLibrary();
}
/**
* Returns the instance of child classes
*
* @param string $namespace
* @param object $module
*
* @return Object
*/
public static function getInstance($namespace = null, $module = null)
{
if (empty(static::$instance)) {
$instance = new static($namespace);
if (is_object($module)) {
$instance->id = $module->id;
$instance->title = $module->title;
$instance->module = $module->module;
$instance->position = $module->position;
$instance->content = $module->content;
$instance->showtitle = $module->showtitle;
$instance->menuid = $module->menuid;
$instance->name = $module->name;
$instance->style = $module->style;
$instance->params = new Registry($module->params);
} else {
// @TODO: Raise warning/Error
}
$instance->loadLanguage();
static::$instance = $instance;
}
return static::$instance;
}
/**
* @return void
*/
public function init()
{
require ModuleHelper::getLayoutPath('mod_' . $this->element, $this->params->get('layout', 'default'));
}
/**
* @return void
*/
public function loadLanguage()
{
$language = Factory::getLanguage();
$language->load($this->module, JPATH_SITE);
}
}

View File

@ -0,0 +1,101 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Extension;
use Alledia\Framework\Factory;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Version;
// phpcs:disable PSR1.Files.SideEffects
defined('_JEXEC') or die();
// phpcs:enable PSR1.Files.SideEffects
abstract class AbstractPlugin extends CMSPlugin
{
/**
* Alledia Extension instance
*
* @var Licensed
*/
protected $extension;
/**
* Library namespace
*
* @var string
*/
protected $namespace;
/**
* Method used to load the extension data. It is not on the constructor
* because this way we can avoid loading the data if the plugin
* will not be used.
*
* @return void
*/
protected function init()
{
$this->loadExtension();
// Load the libraries, if existent
$this->extension->loadLibrary();
$this->loadLanguage();
}
/**
* Method to load the language files
*
* @return void
*/
public function loadLanguage($extension = '', $basePath = JPATH_ADMINISTRATOR)
{
parent::loadLanguage($extension, $basePath);
$systemStrings = 'plg_' . $this->_type . '_' . $this->_name . '.sys';
parent::loadLanguage($systemStrings, $basePath);
}
/**
* Method to load the extension data
*
* @return void
*/
protected function loadExtension()
{
if (!isset($this->extension)) {
$this->extension = Factory::getExtension($this->namespace, 'plugin', $this->_type);
}
}
/**
* Check if this extension is licensed as pro
*
* @return bool True for pro version
*/
protected function isPro()
{
return $this->extension->isPro();
}
}

View File

@ -0,0 +1,74 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Extension;
defined('_JEXEC') or die();
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
class Component extends Licensed
{
/**
* @var BaseController
*/
protected $controller;
/**
* @inheritDoc
*/
public function __construct($namespace)
{
parent::__construct($namespace, 'component');
$this->loadLibrary();
}
/**
* Load the main controller
*
* @return void
* @throws \Exception
*/
public function loadController()
{
if (!isset($this->controller)) {
jimport('legacy.controller.legacy');
$this->controller = BaseController::getInstance($this->namespace);
}
}
/**
* @return void
* @throws \Exception
*/
public function executeTask()
{
$task = Factory::getApplication()->input->getCmd('task');
$this->controller->execute($task);
$this->controller->redirect();
}
}

View File

@ -0,0 +1,515 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Extension;
defined('_JEXEC') or die();
use JFormFieldCustomFooter;
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\File;
use Joomla\Registry\Registry;
use SimpleXMLElement;
/**
* Generic extension class
*
* @todo : Make this class compatible with non-Alledia extensions
*/
class Generic
{
/**
* The extension namespace
*
* @var string
*/
public $namespace = null;
/**
* The extension type
*
* @var string
*/
public $type = null;
/**
* The extension id
*
* @var int
*/
public $id = null;
/**
* The extension name
*
* @var string
*/
public $name = null;
/**
* The extension params
*
* @var Registry
*/
public $params = null;
/**
* The extension enable state
*
* @var bool
*/
protected $enabled;
/**
* The element of the extension
*
* @var string
*/
protected $element;
/**
* @var string
*/
protected $folder = null;
/**
* Base path
*
* @var string
*/
protected $basePath;
/**
* The manifest information
*
* @var object
*/
public $manifest = null;
/**
* The manifest information as SimpleXMLElement
*
* @var SimpleXMLElement
*/
public $manifestXml = null;
/**
* The config information
*
* @var SimpleXMLElement
*/
public $config = null;
/**
* Class constructor, set the extension type.
*
* @param string $namespace The element of the extension
* @param string $type The type of extension
* @param string $folder The folder for plugins (only)
*/
public function __construct($namespace, $type, $folder = '', $basePath = JPATH_SITE)
{
$this->type = $type;
$this->element = strtolower($namespace);
$this->folder = $folder;
$this->basePath = rtrim($basePath, '/\\');
$this->namespace = $namespace;
$this->getManifest();
$this->getDataFromDatabase();
}
/**
* Get information about this extension from the database
*
* @return void
*/
protected function getDataFromDatabase()
{
$element = $this->getElementToDb();
// Load the extension info from database
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select([
$db->quoteName('extension_id'),
$db->quoteName('name'),
$db->quoteName('enabled'),
$db->quoteName('params')
])
->from('#__extensions')
->where($db->quoteName('type') . ' = ' . $db->quote($this->type))
->where($db->quoteName('element') . ' = ' . $db->quote($element));
if ($this->type === 'plugin') {
$query->where($db->quoteName('folder') . ' = ' . $db->quote($this->folder));
}
$db->setQuery($query);
$row = $db->loadObject();
if (is_object($row)) {
$this->id = $row->extension_id;
$this->name = $row->name;
$this->enabled = (bool)$row->enabled;
$this->params = new Registry($row->params);
} else {
$this->id = null;
$this->name = null;
$this->enabled = false;
$this->params = new Registry();
}
}
/**
* Check if the extension is enabled
*
* @return bool
*/
public function isEnabled()
{
return $this->enabled;
}
/**
* Get the path for the extension
*
* @return string The path
*/
public function getExtensionPath()
{
$folders = [
'component' => 'administrator/components/',
'plugin' => 'plugins/',
'template' => 'templates/',
'library' => 'libraries/',
'cli' => 'cli/',
'module' => 'modules/'
];
$basePath = $this->basePath . '/' . $folders[$this->type];
switch ($this->type) {
case 'plugin':
$basePath .= $this->folder . '/';
break;
case 'module':
if (!preg_match('/^mod_/', $this->element)) {
$basePath .= 'mod_';
}
break;
case 'component':
if (!preg_match('/^com_/', $this->element)) {
$basePath .= 'com_';
}
break;
}
$basePath .= $this->element;
return $basePath;
}
/**
* Get the full element
*
* @return string The full element
*/
public function getFullElement()
{
return Helper::getFullElementFromInfo($this->type, $this->element, $this->folder);
}
/**
* Get the element to match the database records.
* Only components and modules have the prefix.
*
* @return string The element
*/
public function getElementToDb()
{
$prefixes = [
'component' => 'com_',
'module' => 'mod_'
];
$fullElement = '';
if (array_key_exists($this->type, $prefixes)) {
if (!preg_match('/^' . $prefixes[$this->type] . '/', $this->element)) {
$fullElement = $prefixes[$this->type];
}
}
$fullElement .= $this->element;
return $fullElement;
}
/**
* Get manifest path for this extension
*
* @return string
*/
public function getManifestPath()
{
$extensionPath = $this->getExtensionPath();
// Templates or extension?
if ($this->type === 'template') {
$fileName = 'templateDetails.xml';
} else {
$fileName = $this->element . '.xml';
}
$path = $extensionPath . "/{$fileName}";
if (!is_file($path)) {
$path = $extensionPath . "/{$this->getElementToDb()}.xml";
}
return $path;
}
/**
* Get extension manifest as SimpleXMLElement
*
* @param bool $force If true, force to load the manifest, ignoring the cached one
*
* @return SimpleXMLElement
*/
public function getManifestAsSimpleXML($force = false)
{
if (!isset($this->manifestXml) || $force) {
$path = $this->getManifestPath();
if (File::exists($path)) {
$this->manifestXml = simplexml_load_file($path);
} else {
$this->manifestXml = false;
}
}
return $this->manifestXml;
}
/**
* Get extension information
*
* @param bool $force If true, force to load the manifest, ignoring the cached one
*
* @return object
*/
public function getManifest($force = false)
{
if (!isset($this->manifest) || $force) {
$xml = $this->getManifestAsSimpleXML($force);
if (!empty($xml)) {
$this->manifest = (object)json_decode(json_encode($xml));
} else {
$this->manifest = false;
}
}
return $this->manifest;
}
/**
* Get extension config file
*
* @param bool $force Force to reload the config file
*
* @return SimpleXMLElement
*/
public function getConfig($force = false)
{
if (!isset($this->config) || $force) {
$this->config = null;
$path = $this->getExtensionPath() . '/config.xml';
if (file_exists($path)) {
$this->config = simplexml_load_file($path);
}
}
return $this->config;
}
/**
* Returns the update URL from database
*
* @return string
*/
public function getUpdateURL()
{
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('sites.location')
->from('#__update_sites AS sites')
->leftJoin('#__update_sites_extensions AS extensions ON (sites.update_site_id = extensions.update_site_id)')
->where('extensions.extension_id = ' . $this->id);
return $db->setQuery($query)->loadResult();
}
/**
* Set the update URL
*
* @param string $url
*/
public function setUpdateURL($url)
{
$db = Factory::getDbo();
// Get the update site id
$join = $db->quoteName('#__update_sites_extensions') . ' AS extensions '
. 'ON (sites.update_site_id = extensions.update_site_id)';
$query = $db->getQuery(true)
->select('sites.update_site_id')
->from($db->quoteName('#__update_sites') . ' AS sites')
->leftJoin($join)
->where('extensions.extension_id = ' . $this->id);
$siteId = (int)$db->setQuery($query)->loadResult();
if (!empty($siteId)) {
$query = $db->getQuery(true)
->update($db->quoteName('#__update_sites'))
->set($db->quoteName('location') . ' = ' . $db->quote($url))
->where($db->quoteName('update_site_id') . ' = ' . $siteId);
$db->setQuery($query)->execute();
}
}
/**
* Store the params on the database
*
* @return void
*/
public function storeParams()
{
$db = Factory::getDbo();
$updateObject = (object)[
'params' => $this->params->toString(),
'extension_id' => $this->id
];
$db->updateObject('#__extensions', $updateObject, ['extension_id']);
}
/**
* Get extension name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Get extension id
*
* @return int
*/
public function getId()
{
return (int)$this->id;
}
/**
* @TODO: Move to the licensed class?
*
* @return string
*/
public function getFooterMarkup()
{
$manifest = $this->getManifestAsSimpleXML();
if ($manifest->alledia) {
$configPath = $this->getExtensionPath() . '/config.xml';
if (File::exists($configPath)) {
$config = $this->getConfig();
if (is_object($config)) {
$footerElement = $config->xpath('//field[@type="customfooter"]');
$footerElement = reset($footerElement);
}
}
if (empty($footerElement)) {
if (is_object($manifest)) {
if ($footerElement = $manifest->xpath('//field[@type="customfooter"]')) {
$footerElement = reset($footerElement);
} elseif ($media = (string)$manifest->media['destination']) {
$customField = sprintf(
'<field type="customfooter" name="customfooter" media="%s"/>',
$media
);
$footerElement = new SimpleXMLElement($customField);
}
}
}
if (empty($footerElement) == false) {
if (class_exists('JFormFieldCustomFooter') === false) {
$classPath = $this->getExtensionPath() . '/form/fields/customfooter.php';
if (is_file($classPath)) {
require_once $classPath;
}
}
if (class_exists('JFormFieldCustomFooter')) {
$field = new JFormFieldCustomFooter();
$field->fromInstaller = true;
return $field->getInputUsingCustomElement($footerElement);
}
}
}
return '';
}
/**
* Returns the extension's version collected from the manifest file
*
* @return string The extension's version
*/
public function getVersion()
{
if (!empty($this->manifest->version)) {
return $this->manifest->version;
}
return null;
}
}

View File

@ -0,0 +1,176 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Extension;
use Alledia\Framework\Factory;
defined('_JEXEC') or die();
/**
* Generic extension helper class
*/
abstract class Helper
{
/**
* @var array[]
*/
protected static $extensionInfo = [];
protected static $extensionTypes = [
'com' => 'component',
'plg' => 'plugin',
'mod' => 'module',
'lib' => 'library',
'tpl' => 'template',
'cli' => 'cli'
];
/**
* Build a string representing the element
*
* @param string $type
* @param string $element
* @param string $folder
*
* @return string
*/
public static function getFullElementFromInfo($type, $element, $folder = null)
{
$prefix = array_search($type, static::$extensionTypes);
if ($prefix) {
if (strpos($element, $prefix) === 0) {
$shortElement = substr($element, strlen($prefix) + 1);
}
$parts = [
$prefix,
$type == 'plugin' ? $folder : null,
$shortElement ?? $element
];
return join('_', array_filter($parts));
}
return null;
}
/**
* @param ?string $element
*
* @return ?array
*/
public static function getExtensionInfoFromElement(?string $element): ?array
{
if (isset(static::$extensionInfo[$element]) == false) {
static::$extensionInfo[$element] = false;
$parts = explode('_', $element, 3);
if (count($parts) > 1) {
$prefix = $parts[0];
$name = $parts[2] ?? $parts[1];
$group = empty($parts[2]) ? null : $parts[1];
$types = [
'com' => 'component',
'plg' => 'plugin',
'mod' => 'module',
'lib' => 'library',
'tpl' => 'template',
'cli' => 'cli'
];
if (array_key_exists($prefix, $types)) {
$result = [
'prefix' => $prefix,
'type' => $types[$prefix],
'name' => $name,
'group' => $group,
'namespace' => preg_replace_callback(
'/^(os[a-z])(.*)/i',
function ($matches) {
return strtoupper($matches[1]) . $matches[2];
},
$name
)
];
}
static::$extensionInfo[$element] = $result;
}
}
return static::$extensionInfo[$element] ?: null;
}
/**
* @param string $element
*
* @return bool
*/
public static function loadLibrary($element)
{
$extension = static::getExtensionForElement($element);
if (is_object($extension)) {
return $extension->loadLibrary();
}
return false;
}
/**
* @param string $element
*
* @return string
*/
public static function getFooterMarkup($element)
{
if (is_string($element)) {
$extension = static::getExtensionForElement($element);
} elseif (is_object($element)) {
$extension = $element;
}
if (!empty($extension)) {
return $extension->getFooterMarkup();
}
return '';
}
/**
* @param string $element
*
* @return Licensed
*/
public static function getExtensionForElement($element)
{
$info = static::getExtensionInfoFromElement($element);
if (!empty($info['type']) && !empty($info['namespace'])) {
return Factory::getExtension($info['namespace'], $info['type'], $info['group']);
}
return null;
}
}

View File

@ -0,0 +1,142 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Extension;
defined('_JEXEC') or die();
use Alledia\Framework\AutoLoader;
/**
* Licensed class, for extensions with Free and Pro versions
*/
class Licensed extends Generic
{
/**
* License type: free or pro
*
* @var string
*/
protected $license = null;
/**
* The path for the pro library
*
* @var string
*/
protected $proLibraryPath = null;
/**
* The path for the free library
*
* @var string
*/
protected $libraryPath = null;
/**
* @inheritDoc
*/
public function __construct($namespace, $type, $folder = '', $basePath = JPATH_SITE)
{
parent::__construct($namespace, $type, $folder, $basePath);
$this->license = strtolower($this->manifest->alledia->license ?? '');
$this->namespace = $this->manifest->alledia->namespace ?? '';
$this->getLibraryPath();
$this->getProLibraryPath();
}
/**
* Check if the license is pro
*
* @return bool
*/
public function isPro(): bool
{
return $this->license === 'pro';
}
/**
* Check if the license is free
*
* @return bool
*/
public function isFree(): bool
{
return !$this->isPro();
}
/**
* Get the include path for the free library, based on the extension type
*
* @return string The path for pro
*/
public function getLibraryPath()
{
if ($this->libraryPath === null) {
$basePath = $this->getExtensionPath();
$this->libraryPath = $basePath . '/library';
}
return $this->libraryPath;
}
/**
* Get the include path the pro library, based on the extension type
*
* @return string The path for pro
*/
public function getProLibraryPath()
{
if (empty($this->proLibraryPath)) {
$basePath = $this->getLibraryPath();
$this->proLibraryPath = $basePath . '/Pro';
}
return $this->proLibraryPath;
}
/**
* Loads the library, if existent (including the Pro Library)
*
* @return bool
*/
public function loadLibrary()
{
if ($this->namespace) {
$libraryPath = $this->getLibraryPath();
if (is_dir($libraryPath)) {
AutoLoader::register('Alledia\\' . $this->namespace, $libraryPath);
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,50 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Form\Field;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\FormHelper;
use Joomla\CMS\Version;
defined('_JEXEC') or die();
if (Version::MAJOR_VERSION < 4) {
class_alias('JFormFieldList', '\\Joomla\\CMS\\Form\\Field\\ListField');
FormHelper::loadFieldClass('List');
}
class ListField extends \Joomla\CMS\Form\Field\ListField
{
use TraitLayouts;
/**
* Set list field layout based on Joomla version
*/
public function setup(\SimpleXMLElement $element, $value, $group = null)
{
$this->setListLayout();
return parent::setup($element, $value, $group);
}
}

View File

@ -0,0 +1,91 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Form\Field;
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\Path;
use Joomla\CMS\Version;
defined('_JEXEC') or die();
/**
* Intended for use by form field classes to
* implement Joomla version targeted layout files
*/
trait TraitLayouts
{
/**
* @inheritDoc
*/
protected function getLayoutPaths()
{
if (is_callable('parent::getLayoutPaths')) {
$paths = parent::getLayoutPaths();
$fieldClass = (new \ReflectionClass($this));
$baseDirectory = dirname($fieldClass->getFileName());
array_unshift($paths, $baseDirectory . '/layouts');
return $paths;
}
return [];
}
/**
* @inheritDoc
*/
protected function getRenderer($layoutId = 'default')
{
if (is_callable('parent::getRenderer')) {
$paths = $this->getLayoutPaths();
if (Version::MAJOR_VERSION < 4) {
if (Path::find($paths, str_replace('.', '/', $layoutId) . '_j3.php')) {
$layoutId .= '_j3';
}
}
$renderer = parent::getRenderer($layoutId);
$renderer->setIncludePaths($paths);
return $renderer;
}
return null;
}
/**
* @return void
* @deprecated v3.3.1
*/
protected function setListLayout()
{
if (Version::MAJOR_VERSION >= 4) {
$this->layout = 'joomla.form.field.list-fancy-select';
}
}
}

View File

@ -0,0 +1,36 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Model;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
defined('_JEXEC') or die();
/**
* @deprecated v2.1.0: This is pretty much useless
*/
class Base extends BaseDatabaseModel
{
}

View File

@ -0,0 +1,162 @@
<?php
/**
* @package OSCampus
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2017-2023 Joomlashack.com. All rights reserved
* @license http://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of OSCampus.
*
* OSCampus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* OSCampus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OSCampus. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Model;
use Alledia\Framework\Factory;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\User\User;
defined('_JEXEC') or die();
trait TraitModel
{
/**
* @var CMSApplication
*/
protected $app = null;
/**
* @var string[]
*/
protected $accessList = [];
/**
* @return void
* @throws \Exception
*/
protected function setup()
{
$this->app = Factory::getApplication();
}
/**
* Create a where clause of OR conditions for a text search
* across one or more fields. Optionally accepts a text
* search like 'id: #' if $idField is specified
*
* @param string $text
* @param string|string[] $fields
* @param ?string $idField
*
* @return string
*/
public function whereTextSearch(string $text, $fields, ?string $idField = null): string
{
$text = trim($text);
if ($idField && stripos($text, 'id:') === 0) {
$id = (int)substr($text, 3);
return $idField . ' = ' . $id;
}
if (is_string($fields)) {
$fields = [$fields];
}
$searchText = Factory::getDbo()->quote('%' . $text . '%');
$ors = [];
foreach ($fields as $field) {
$ors[] = $field . ' LIKE ' . $searchText;
}
if (count($ors) > 1) {
return sprintf('(%s)', join(' OR ', $ors));
}
return array_pop($ors);
}
/**
* Provide a generic access search for selected field
*
* @param string $field
* @param ?User $user
*
* @return string
*/
public function whereAccess(string $field, ?User $user = null): string
{
$user = $user ?: Factory::getUser();
if ($user->authorise('core.manage') == false) {
$userId = $user->id;
if (isset($this->accessList[$userId]) == false) {
$this->accessList[$userId] = join(', ', array_unique($user->getAuthorisedViewLevels()));
}
if ($this->accessList[$userId]) {
return sprintf($field . ' IN (%s)', $this->accessList[$userId]);
}
}
return 'TRUE';
}
/**
* @param string $source
* @param string|string[] $relations
*
* @return void
*/
protected function garbageCollect(string $source, $relations)
{
$sourceParts = explode('.', $source);
$sourceField = array_pop($sourceParts);
$sourceTable = array_pop($sourceParts);
if ($sourceTable && $sourceField) {
$db = Factory::getDbo();
if (is_string($relations)) {
$relations = [$relations];
}
foreach ($relations as $target) {
$targetParts = explode('.', $target);
$targetField = array_pop($targetParts);
$targetTable = array_pop($targetParts);
if ($targetTable && $targetField) {
$query = $db->getQuery(true)
->delete($db->quoteName('#__oscampus_' . $targetTable))
->where(
sprintf(
'%s NOT IN (SELECT %s FROM %s)',
$db->quoteName($targetField),
$db->quoteName($sourceField),
$db->quoteName('#__oscampus_' . $sourceTable)
)
);
}
try {
$db->setQuery($query)->execute();
} catch (\Throwable $error) {
$this->app->enqueueMessage($error->getMessage() . '<br>' . $query, 'error');
}
}
}
}
}

View File

@ -0,0 +1,35 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Table;
use Alledia\Framework\Joomla\AbstractTable;
defined('_JEXEC') or die();
/**
* @deprecated v3.6.5 - use AbstractTable
*/
abstract class Base extends AbstractTable
{
}

View File

@ -0,0 +1,131 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2022-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\Toolbar;
use Alledia\Framework\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Toolbar\Toolbar;
use Joomla\CMS\Utility\Utility;
use Joomla\CMS\Version;
defined('_JEXEC') or die();
abstract class ToolbarHelper extends \Joomla\CMS\Toolbar\ToolbarHelper
{
/**
* @var bool
*/
protected static $exportLoaded = false;
/**
* Create a button that links to an external page
*
* @param string $url
* @param string $title
* @param ?string $icon
* @param ?mixed $attributes
*
* @return void
*/
public static function externalLink(string $url, string $title, ?string $icon = null, $attributes = [])
{
if (is_string($attributes)) {
$attributes = Utility::parseAttributes($attributes);
}
$icon = $icon ?: 'link';
$attributes['target'] = $attributes['target'] ?? '_blank';
$attributes['class'] = join(
' ',
array_filter(
array_merge(
explode(' ', $attributes['class'] ?? ''),
[
'btn',
'btn-small'
]
)
)
);
$button = HTMLHelper::_(
'link',
$url,
sprintf('<span class="icon-%s"></span> %s', $icon, $title),
$attributes
);
if (Version::MAJOR_VERSION > 3) {
$button = sprintf('<joomla-toolbar-button>%s</joomla-toolbar-button>', $button);
}
$bar = Toolbar::getInstance();
$bar->appendButton('Custom', $button, $icon);
}
/**
* Create a button that links to documentation
*
* @param string $url
* @param string $title
*
* @return void
*/
public static function shackDocumentation(string $url, string $title)
{
static::externalLink($url, $title, 'support', ['class' => 'btn-info', 'target' => 'shackdocs']);
}
/**
* Export button that ensures the task input field is cleared if
* the export does not return to refresh the page
*
* @param string $task
* @param string $alt
* @param string $icon
*
* @return void
* @throws \Exception
*/
public static function exportView(string $task, string $alt, string $icon = 'download')
{
static::custom($task, $icon, null, $alt, false);
if (static::$exportLoaded == false) {
Factory::getApplication()->getDocument()->addScriptDeclaration(<<<JSCRIPT
Joomla.submitbutton = function(task) {
Joomla.submitform(task);
let taskInput = document.querySelector('input[name="task"]');
if (taskInput) {
taskInput.value = '';
}
};
JSCRIPT
);
static::$exportLoaded = true;
}
}
}

View File

@ -0,0 +1,116 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla;
use Alledia\Framework\Extension;
use Alledia\Framework\Factory;
use Alledia\Framework\Joomla\Extension\Helper as ExtensionHelper;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Filesystem\Path;
use Joomla\CMS\Version;
defined('_JEXEC') or die();
trait TraitAllediaView
{
/**
* @var CMSApplication
*/
protected $app = null;
/**
* @var Extension
*/
protected $extension = null;
/**
* @var bool
*/
protected $initSuccess = null;
/**
* To be called before class constructor method by inheriting classes
*
* @return void
*/
protected function setup()
{
try {
$this->app = Factory::getApplication();
$this->document = Factory::getDocument();
$this->option = $this->app->input->get('option');
$info = ExtensionHelper::getExtensionInfoFromElement($this->option);
$this->extension = Factory::getExtension($info['namespace'], $info['type']);
$this->extension->loadLibrary();
$this->initSuccess = true;
} catch (\Throwable $error) {
if ($this->app) {
$this->app->enqueueMessage($error->getMessage(), 'error');
} else {
echo '<p>' . $error->getMessage() . '</p>';
}
$this->initSuccess = false;
}
}
/**
* Look for a valid layout file based on Joomla version
*
* @param string $layout
*
* @return string
* @throws \Exception
*/
protected function getVersionedLayoutName(string $layout): string
{
if (is_callable([$this, '_createFileName'])) {
$file = $layout;
if (Version::MAJOR_VERSION < 4) {
$file .= '.j' . Version::MAJOR_VERSION;
}
if ($file != $layout || $file == 'emptystate') {
// Verify layout file exists
$fileName = $this->_createFileName('template', ['name' => $file]);
$path = Path::find($this->_path['template'], $fileName);
if ($path) {
$layout = $file;
} else {
$layout = ($file == 'emptystate') ? 'default' : $layout;
}
}
return $layout;
}
throw new \Exception('TraitAllediaView must apply to a Joomla view', 500);
}
}

View File

@ -0,0 +1,103 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\View;
defined('_JEXEC') or die();
use Alledia\Framework\Factory;
use Alledia\Framework\Joomla\Extension\Helper as ExtensionHelper;
use Alledia\Framework\Joomla\Extension\Licensed;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\HTML\HTMLHelper;
/**
* @deprecated v2.0.5
*/
class Admin extends Base
{
/**
* @var string
*/
protected $option = null;
/**
* @var Licensed
*/
protected $extension = null;
/**
* @param array $config
*
* @throws \Exception
*/
public function __construct($config = [])
{
parent::__construct($config);
$info = ExtensionHelper::getExtensionInfoFromElement($this->option);
$this->option = Factory::getApplication()->input->get('option');
$this->extension = Factory::getExtension($info['namespace'], $info['type']);
}
public function display($tpl = null)
{
// Add default admin CSS
HTMLHelper::_('stylesheet', $this->option . '/admin-default.css', ['relative' => true]);
parent::display($tpl);
$this->displayFooter();
}
protected function displayFooter()
{
$output = '';
$layoutPath = $this->extension->getExtensionPath() . '/views/footer/tmpl/default.php';
if (!File::exists($layoutPath)) {
$layoutPath = $this->extension->getExtensionPath() . '/alledia_views/footer/tmpl/default.php';
if (!File::exists($layoutPath)) {
$layoutPath = null;
}
}
if (!is_null($layoutPath)) {
// Start capturing output into a buffer
ob_start();
// Include the requested template filename in the local scope
// (this will execute the view logic).
include $layoutPath;
// Done with the requested template; get the buffer and
// clear it.
$output = ob_get_contents();
ob_end_clean();
}
echo $output;
}
}

View File

@ -0,0 +1,86 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\View\Admin;
use Alledia\Framework\Extension;
use Alledia\Framework\Joomla\AbstractView;
use Joomla\CMS\Filesystem\File;
defined('_JEXEC') or die();
class AbstractBase extends AbstractView
{
/**
* @inheritDoc
*/
protected function displayFooter(?Extension $extension = null)
{
parent::displayFooter();
echo $this->displayAdminFooter($extension);
}
/**
* @param ?Extension $extension
*
* @return string
*/
protected function displayAdminFooter(?Extension $extension = null): string
{
$extension = $extension ?: ($this->extension ?? null);
if ($extension) {
$output = $extension->getFooterMarkup();
if (empty($output)) {
// Use alternative if no custom footer field
$layoutPath = $extension->getExtensionPath() . '/views/footer/tmpl/default.php';
if (!File::exists($layoutPath)) {
$layoutPath = $extension->getExtensionPath() . '/alledia_views/footer/tmpl/default.php';
}
if (File::exists($layoutPath)) {
ob_start();
include $layoutPath;
$output = ob_get_contents();
ob_end_clean();
}
}
}
return $output ?? '';
}
/**
* @inheritDoc
* @throws \Exception
*/
public function setLayout($layout)
{
$layout = $this->getVersionedLayoutName($layout);
return parent::setLayout($layout);
}
}

View File

@ -0,0 +1,70 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\View\Admin;
use Joomla\CMS\Form\Form;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\MVC\Model\AdminModel;
use Joomla\CMS\Version;
defined('_JEXEC') or die();
class AbstractForm extends AbstractBase
{
/**
* @var Form
*/
protected $form = null;
/**
* @var bool
*/
protected $useCoreUI = true;
/**
* @inheritDoc
*/
protected function setup()
{
parent::setup();
if (Version::MAJOR_VERSION < 4) {
HTMLHelper::_('behavior.tabstate');
}
}
/**
* @inheritDoc
*
*/
public function setModel($model, $default = false)
{
$model = parent::setModel($model, $default);
if ($model instanceof AdminModel && $default) {
$this->form = $model->getForm();
}
return $model;
}
}

View File

@ -0,0 +1,81 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\View\Admin;
defined('_JEXEC') or die();
use Joomla\CMS\Form\Form;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Pagination\Pagination;
use Joomla\CMS\Version;
abstract class AbstractList extends AbstractBase
{
/**
* @var object[]
*/
protected $items = null;
/**
* @var string
*/
protected $sidebar = null;
/**
* @var Pagination
*/
protected $pagination = null;
/**
* @var Form
*/
public $filterForm = null;
/**
* @var string[]
*/
public $activeFilters = null;
/**
* @var bool
*/
protected $isEmptyState = null;
public function display($tpl = null)
{
// Add default admin CSS
HTMLHelper::_('stylesheet', $this->option . '/admin-default.css', ['relative' => true]);
if (
Version::MAJOR_VERSION > 3
&& empty($this->items)
&& ($this->isEmptyState = $this->get('IsEmptyState'))
) {
$this->setLayout('emptystate');
}
parent::display($tpl);
}
}

View File

@ -0,0 +1,36 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\View;
use Joomla\CMS\MVC\View\HtmlView;
defined('_JEXEC') or die();
/**
* @deprecated v2.0.5
*/
class Base extends HtmlView
{
}

View File

@ -0,0 +1,67 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\View\Site;
use Alledia\Framework\Joomla\AbstractView;
use Joomla\Registry\Registry;
defined('_JEXEC') or die();
class AbstractBase extends AbstractView
{
/**
* @var Registry
*/
protected $params = null;
/**
* @inheritDoc
*/
public function setModel($model, $default = false)
{
$model = parent::setModel($model, $default);
$this->setParams();
return $model;
}
/**
* @return void
*/
protected function setParams()
{
$this->params = new Registry();
// Load component parameters first
$this->params->merge($this->extension->params);
if ($activeMenu = $this->app->getMenu()->getActive()) {
// We're on a menu - add/override its parameters
$this->params->merge($activeMenu->getParams());
$this->params->def('page_heading', $this->params->get('page_title') ?: $activeMenu->title);
}
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Joomla\View\Site;
defined('_JEXEC') or die();
use Joomla\CMS\Form\Form;
use Joomla\CMS\Pagination\Pagination;
abstract class AbstractList extends AbstractBase
{
/**
* @var object[]
*/
protected $items = null;
/**
* @var Pagination
*/
protected $pagination = null;
/**
* @var Form
*/
public $filterForm = null;
/**
* @var string[]
*/
public $activeFilters = null;
}

View File

@ -0,0 +1,104 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework;
use Exception;
use Joomla\CMS\Log\Log;
defined('_JEXEC') or die();
abstract class Loader
{
/**
* @var bool
*/
protected static $logRegistered = false;
/**
* Safelly include a PHP file, making sure it exists before import.
*
* This method will register a log message and display a warning for admins
* in case the file is missed.
*
* @param string $path The file path you want to include
*
* @return bool True, if the file exists and was loaded well.
* @throws Exception
*/
public static function includeFile($path)
{
if (!static::$logRegistered) {
Log::addLogger(
['text_file' => 'allediaframework.loader.errors.php'],
Log::ALL,
['allediaframework']
);
static::$logRegistered = true;
}
// Check if the file doesn't exist
if (!is_file($path)) {
$logMsg = 'Required file is missed: ' . $path;
// Generate a backtrace to know from where the request cames
if (version_compare(phpversion(), '5.4', '<')) {
$backtrace = debug_backtrace();
} else {
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
}
if (!empty($backtrace)) {
$logMsg .= sprintf(
' (%s:%s)',
$backtrace[0]['file'],
$backtrace[0]['line']
);
}
// Register the log
Log::add($logMsg, Log::ERROR, 'allediaframework');
// Warn admin users
$app = Factory::getApplication();
if ($app->isClient('administrator')) {
$app->enqueueMessage(
'Joomlashack Framework Loader detected that a required file was not found! Please, check the logs.',
'error'
);
}
// Stand up a flag to warn a required file is missed
if (!defined('ALLEDIA_FRAMEWORK_MISSED_FILE')) {
define('ALLEDIA_FRAMEWORK_MISSED_FILE', true);
}
return false;
}
include_once($path);
return true;
}
}

View File

@ -0,0 +1,117 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework\Network;
defined('_JEXEC') or die();
class Request
{
/**
* post
* POST request
*
* @access public
*
* @param string $url
* @param array $data
*
* @return string
*/
public function post($url, $data = [])
{
if ($this->hasCURL()) {
return $this->postCURL($url, $data);
} else {
return $this->postFOpen($url, $data);
}
}
/**
* hasCURL
* Does the server have the curl extension ?
*
* @access protected
* @return bool
*/
protected function hasCURL()
{
return function_exists('curl_init');
}
/**
* postCURL
* POST request with curl
*
* @access protected
*
* @param string $url
* @param array $data
*
* @return string
*/
protected function postCURL($url, $data = [])
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, count($data));
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$contents = curl_exec($ch);
curl_close($ch);
return $contents;
}
/**
* postFOpen
* POST request with fopen
*
* @access protected
*
* @param string $url
* @param array $data
*
* @return string
*/
protected function postFOpen($url, $data = [])
{
$stream = fopen($url, 'r', false, stream_context_create([
'http' => [
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => http_build_query(
$data
)
]
]));
$contents = stream_get_contents($stream);
fclose($stream);
return $contents;
}
}

View File

@ -0,0 +1,144 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Alledia\Framework;
defined('_JEXEC') or die();
class Profiler
{
/**
* @var int
*/
protected $startTime = 0;
/**
* @var int
*/
protected $initialMemory = 0;
/**
* @var int
*/
protected $maxLength = 80;
/**
* @var int
*/
protected $lastMemory = 0;
/**
* @return void
*/
public function start()
{
$this->initialMemory = memory_get_usage();
}
/**
* @param string $label
*
* @return void
*/
public function step($label = null)
{
$this->startStep($label);
$this->endStep();
}
/**
* @return void
*/
public function echoData()
{
echo "\n";
$total = memory_get_usage() - $this->initialMemory;
$data = '==== Mem: ' . number_format($total, 0, '.', ',') . ' bytes';
$diff = $total - $this->lastMemory;
$peak = memory_get_peak_usage();
$operator = '';
echo $data;
if ($diff != 0) {
$operator = $diff > 0 ? '+' : '-';
}
echo ' diff: ' . $operator . number_format(abs($diff), 0, '.', ',') . ' bytes'
. ' peak: ' . number_format($peak, '0', '.', ',') . ' bytes';
$this->lastMemory = $total;
echo "\n";
}
/**
* @param string $label
*/
public function startStep($label = null)
{
echo "\n";
$this->printHeader($label);
$this->echoData();
}
/**
* @return void
*/
public function endStep()
{
$this->echoData();
$this->printSeparator();
echo "\n";
}
/**
* @param string $label
* @param int $leftPadding
*
* @return void
*/
protected function printHeader($label = null, $leftPadding = 4)
{
if (!is_null($label)) {
$length = $leftPadding;
echo str_repeat('=', $length);
echo " $label ";
$length += strlen($label) + 2;
echo str_repeat('=', $this->maxLength - $length);
} else {
$this->printSeparator();
}
}
/**
* @return void
*/
protected function printSeparator()
{
echo str_repeat('=', $this->maxLength);
}
}

View File

@ -0,0 +1,99 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
use Joomla\CMS\HTML\HTMLHelper;
// phpcs:disable PSR1.Files.SideEffects
defined('_JEXEC') or die();
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
abstract class JhtmlAlledia
{
/**
* Joomla version agnostic modal select field rendering
*
* @param array $options
*
* @return string
* @deprecated v3.3.5: Use AllediaModal::renderSelectField()
*/
public static function renderModal(array $options): string
{
return HTMLHelper::_('alledia.modal.renderSelectField', $options);
}
/**
* @param string $title
* @param string $text
* @param string $body
*
* @return string
*/
public static function tooltip(string $title, string $text, string $body): string
{
HTMLHelper::_('bootstrap.tooltip', '.hasTooltip');
return sprintf(
'<span class="inactive tip-top hasTooltip" title="%s">%s</span>',
HTMLHelper::_('tooltipText', $title . ' :: ' . $text),
$body
);
}
/**
* Ensure Fontawesome is loaded
*
* @return void
*/
public static function fontawesome(): void
{
HTMLHelper::_(
'stylesheet',
'lib_allediaframework/fontawesome/css/all.min.css',
['relative' => true]
);
}
/**
* Truncate a string on word boundary within limit
* Recognize '-' and '_' along with standard whitespace
*
* @param string $string
* @param int $limit
* @param ?string $continued
*
* @return string
*/
public static function truncate(string $string, int $limit, ?string $continued = '...'): string
{
if (
mb_strlen($string) > $limit
&& mb_ereg('(.*?)[^\s_-]*\w$', trim(mb_substr($string, 0, $limit - strlen($continued) + 1) . 'a'), $match)
) {
return trim(trim($match[1]), '-_') . $continued;
}
return $string;
}
}

View File

@ -0,0 +1,394 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2021-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
use Alledia\Framework\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Version;
use Joomla\Utilities\ArrayHelper;
// phpcs:disable PSR1.Files.SideEffects
defined('_JEXEC') or die();
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
abstract class AllediaModal
{
/**
* @var string[]
*/
protected static $modalFunctions = [];
/**
* Joomla version agnostic modal select field rendering
*
* @param array $options = [
* 'id' => required: unique Field ID,
* 'name' => required: Field name,
* 'link' => required: button action,
* 'function' => required: parent window close modal function,
* 'itemType' => required: Unique item identifier
* 'title' => Modal window title - default: JSELECT,
* 'hint' => Input field value text - default: JGLOBAL_SELECT_AN_OPTION,
* 'button' => Button text - default: JSELECT,
* 'close' => Footer Close button text - default: JLIB_HTML_BEHAVIOR_CLOSE,
* 'value' => Currently selected value,
* 'height' => Modal height in pixels - default: 400,
* 'width' => Modal width in pixels - default: 800,
* 'bodyHeight' => 70,
* 'modalWidth' => 80,
* ]
*
* @return string
*/
public static function renderSelectField(array $options): string
{
$required = [
'id' => null,
'name' => null,
'link' => null,
'function' => null,
'itemType' => null,
];
$options = array_replace_recursive(
$required,
[
'title' => Text::_('JSELECT'),
'hint' => Text::_('JGLOBAL_SELECT_AN_OPTION'),
'button' => [
'select' => Text::_('JSELECT'),
'clear' => Text::_('JCLEAR')
],
'close' => Text::_('JLIB_HTML_BEHAVIOR_CLOSE'),
'value' => null,
'required' => false,
'height' => '400px',
'width' => '100%',
'bodyHeight' => 70,
'modalWidth' => 80,
],
$options
);
$requiredOptions = array_filter(array_intersect_key($options, $required));
$missing = array_diff_key($required, $requiredOptions);
if ($missing) {
return 'Missing Required options: ' . join(', ', array_keys($missing));
}
/**
* @var string $id
* @var string $name
* @var string $hint
* @var string $link
* @var string $function
* @var string $itemType
*/
extract($requiredOptions);
HTMLHelper::_('jquery.framework');
if (Version::MAJOR_VERSION < 4) {
HTMLHelper::_('script', 'system/modal-fields.js', ['version' => 'auto', 'relative' => true]);
} elseif ($doc = Factory::getDocument()) {
if (is_callable([$doc, 'getWebAssetManager'])) {
$wa = $doc->getWebAssetManager();
$wa->useScript('field.modal-fields');
}
} else {
return 'Unable to initialize Modal window';
}
if (empty(static::$modalFunctions[$function])) {
$script = <<<JSCRIPT
window.{$function} = function(id, name) {
window.processModalSelect('{$itemType}', '{$id}', id, name);
};
JSCRIPT;
Factory::getDocument()->addScriptDeclaration($script);
static::$modalFunctions[$function] = true;
}
$title = htmlspecialchars($options['title'], ENT_QUOTES);
$modalId = 'ModalSelect' . $itemType . '_' . $id;
// Begin field output
$html = '<span class="input-append input-group">';
// Read-only name field
$nameAttribs = [
'type' => 'text',
'id' => $id . '_name',
'value' => $options['hint'],
'class' => 'input-medium form-control',
'readonly' => 'readonly',
'size' => 35
];
$html .= sprintf('<input %s/>', ArrayHelper::toString($nameAttribs));
// Create read-only ID field
$idAttribs = [
'type' => 'hidden',
'id' => $id . '_id',
'name' => $name,
'value' => $options['value'],
'data-required' => (int)(bool)$options['required'],
'data-text' => $title
];
if ($options['required']) {
$idAttribs['class'] = 'required modal-value';
}
$html .= sprintf('<input %s/>', ArrayHelper::toString($idAttribs));
$html .= static::createSelectButton(
$options['value'],
$id,
$modalId,
$options['button']['select'],
$options['required']
);
$html .= static::createClearButton(
$options['value'],
$id,
$modalId,
$options['button']['clear'],
$options['required']
);
// Modal window
$html .= HTMLHelper::_(
'bootstrap.renderModal',
$modalId,
[
'title' => $title,
'url' => $link,
'height' => '400px',
'width' => '800px',
'bodyHeight' => '70',
'modalWidth' => '80',
'footer' => '<a role="button" class="btn" data-dismiss="modal" data-bs-dismiss="modal" aria-hidden="true">'
. Text::_('JLIB_HTML_BEHAVIOR_CLOSE')
. '</a>'
,
]
);
return $html;
}
/**
* @param string $value
* @param string $id
* @param string $modalId
* @param string $text
* @param bool $required
*
* @return string
*/
protected static function createSelectButton(
string $value,
string $id,
string $modalId,
string $text,
bool $required
): string {
$selectAttribs = [
'class' => 'btn btn-primary hasTooltip',
'id' => $id . ($required ? '_change' : '_select'),
'data-toggle' => 'modal',
'data-bs-toggle' => 'modal',
'data-bs-target' => '#' . $modalId,
'role' => 'button',
];
if (empty($required) && $value) {
$selectAttribs['class'] .= ' hidden';
}
return HTMLHelper::_(
'link',
'#' . $modalId,
'<span class="icon-list" aria-hidden="true"></span> ' . $text,
$selectAttribs
);
}
/**
* @param string $value
* @param string $id
* @param string $modalId
* @param string $text
* @param bool $required
*
* @return string
*/
protected static function createClearButton(
string $value,
string $id,
string $modalId,
string $text,
bool $required
): string {
if ($required == false) {
$clearAttribs = [
'class' => 'btn btn-secondary hasTooltip',
'id' => $id . '_clear',
'role' => 'button',
'onclick' => "window.processModalParent('{$id}');return false;",
];
if (empty($value)) {
$clearAttribs['class'] .= ' hidden';
}
return HTMLHelper::_(
'link',
'#' . $modalId,
'<span class="icon-remove" aria-hidden="true"></span> ' . $text,
$clearAttribs
);
}
return '';
}
/**
* @param string $text
* @param string $modalId
* @param array $params
*
* @return string
*/
public static function renderLink(string $text, string $modalId, array $params): string
{
$params = array_merge(
[
'title' => 'MODAL!',
'height' => '400px',
'width' => '800px',
'bodyHeight' => '70',
'modalWidth' => '80'
],
$params
);
$html = HTMLHelper::_('bootstrap.renderModal', $modalId, $params);
$html .= HTMLHelper::_(
'link',
'#' . $modalId,
$text,
[
'data-toggle' => 'modal',
'data-bs-toggle' => 'modal'
]
);
return $html;
}
/**
* @param ?string[] $attribs
* @param ?string $title
*
* @return string
*/
public static function footerSaveButton(array $attribs = [], ?string $title = null): string
{
$attribs = array_merge(
[
'class' => 'btn btn-primary',
'data-dismiss' => 'modal',
'data-bs-dismiss' => 'modal'
],
$attribs
);
return static::footerButton($title ?: Text::_('JSAVE'), $attribs);
}
/**
* @param ?string[] $attribs
* @param ?string $title
*
* @return string
*/
public static function footerApplyButton(array $attribs = [], ?string $title = null): string
{
$attribs = array_merge(
[
'class' => 'btn btn-success'
],
$attribs
);
return static::footerButton($title ?: Text::_('JAPPLY'), $attribs);
}
/**
* @param ?string[] $attribs
* @param ?string $title
*
* @return string
*/
public static function footerCloseButton(array $attribs = [], ?string $title = null): string
{
$attribs = array_merge(
[
'data-dismiss' => 'modal',
'data-bs-dismiss' => 'modal'
],
$attribs
);
return static::footerButton($title ?: Text::_('JLIB_HTML_BEHAVIOR_CLOSE'), $attribs);
}
/**
* @param string $title
* @param array $attribs
*
* @return string
*/
public static function footerButton(string $title, array $attribs = []): string
{
$attribs = array_merge(
[
'role' => 'button',
'class' => 'btn',
'aria-hidden' => 'true'
],
$attribs
);
return sprintf(
'<a %s>%s</a>',
ArrayHelper::toString($attribs),
$title
);
}
}

View File

@ -0,0 +1,88 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Version;
// phpcs:disable PSR1.Files.SideEffects
defined('_JEXEC') or die();
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
abstract class AllediaTab
{
/**
* @param string $selector
* @param ?array $params
*
* @return string
*/
public static function startTabSet(string $selector = 'myTab', array $params = []): string
{
if (Version::MAJOR_VERSION < 4) {
return HTMLHelper::_('bootstrap.startTabSet', $selector, $params);
}
return HTMLHelper::_('uitab.startTabSet', $selector, $params);
}
/**
* @param string $selector
* @param string $id
* @param string $title
*
* @return string
*/
public static function addTab(string $selector, string $id, string $title): string
{
if (Version::MAJOR_VERSION < 4) {
return HTMLHelper::_('bootstrap.addTab', $selector, $id, $title);
}
return HTMLHelper::_('uitab.addTab', $selector, $id, $title);
}
/**
* @return string
*/
public static function endTab(): string
{
if (Version::MAJOR_VERSION < 4) {
return HTMLHelper::_('bootstrap.endTab');
}
return HTMLHelper::_('uitab.endTab');
}
/**
* @return string
*/
public static function endTabset(): string
{
if (Version::MAJOR_VERSION < 4) {
return HTMLHelper::_('bootstrap.endTabSet');
}
return HTMLHelper::_('uitab.endTabSet');
}
}

View File

@ -0,0 +1,51 @@
<?php
/**
* @package AllediaFramework
* @contact www.joomlashack.com, help@joomlashack.com
* @copyright 2016-2023 Joomlashack.com. All rights reserved
* @license https://www.gnu.org/licenses/gpl.html GNU/GPL
*
* This file is part of AllediaFramework.
*
* AllediaFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* AllediaFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AllediaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
use Alledia\Framework\AutoLoader;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Version;
defined('_JEXEC') or die();
if (!defined('ALLEDIA_FRAMEWORK_LOADED')) {
define('ALLEDIA_FRAMEWORK_LOADED', 1);
define('ALLEDIA_FRAMEWORK_PATH', __DIR__);
if (!class_exists('\\Alledia\\Framework\\AutoLoader')) {
require_once ALLEDIA_FRAMEWORK_PATH . '/Framework/AutoLoader.php';
}
include ALLEDIA_FRAMEWORK_PATH . '/vendor/autoload.php';
AutoLoader::register('\\Alledia\\Framework', ALLEDIA_FRAMEWORK_PATH . '/Framework');
HTMLHelper::addIncludePath(ALLEDIA_FRAMEWORK_PATH . '/helpers/html');
class_alias('\\Alledia\\Framework\\Joomla\Extension\Licensed', '\\Alledia\\Framework\\Extension');
if (Version::MAJOR_VERSION < 4) {
// Add some shims for Joomla 3
class_alias('JHtmlSidebar', '\\Joomla\\CMS\\HTML\\Helpers\\Sidebar');
}
}
return defined('ALLEDIA_FRAMEWORK_LOADED');

View File

@ -0,0 +1,12 @@
<?php
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
exit(1);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitf6397224e3716ebcb1184d2811be11f8::getLoader();

View File

@ -0,0 +1,572 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var ?string */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
private $apcuPrefix;
/**
* @var self[]
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
/**
* @return string[]
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
* @private
*/
function includeFile($file)
{
include $file;
}

View File

@ -0,0 +1,352 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
* This class is copied in every Composer installed project and available to all
*
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array();
/**
* Returns a list of all package names which are present, either by being installed, replaced or provided
*
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
/**
* Returns a list of all package names with a specific type e.g. 'library'
*
* @param string $type
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackagesByType($type)
{
$packagesByType = array();
foreach (self::getInstalled() as $installed) {
foreach ($installed['versions'] as $name => $package) {
if (isset($package['type']) && $package['type'] === $type) {
$packagesByType[] = $name;
}
}
}
return $packagesByType;
}
/**
* Checks whether the given package is installed
*
* This also returns true if the package name is provided or replaced by another package
*
* @param string $packageName
* @param bool $includeDevRequirements
* @return bool
*/
public static function isInstalled($packageName, $includeDevRequirements = true)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
}
}
return false;
}
/**
* Checks whether the given package satisfies a version constraint
*
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
*
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
*
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
* @param string $packageName
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
* @return bool
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
/**
* Returns a version constraint representing all the range(s) which are installed for a given package
*
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
* whether a given version of a package is installed, and not just whether it exists
*
* @param string $packageName
* @return string Version constraint usable with composer/semver
*/
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
*/
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
*/
public static function getInstallPath($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @return array
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
/**
* Returns the raw installed.php data for custom implementations
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
*/
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
return self::$installed;
}
/**
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
public static function getAllRawData()
{
return self::getInstalled();
}
/**
* Lets you reload the static array from another file
*
* This is only useful for complex integrations in which a project needs to use
* this class but then also needs to execute another project's autoloader in process,
* and wants to ensure both projects have access to their version of installed.php.
*
* A typical case would be PHPUnit, where it would need to make sure it reads all
* the data it needs from this class, then call reload() with
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
* the project in which it runs can then also use this class safely, without
* interference between PHPUnit's dependencies and the project's dependencies.
*
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
}
}
}
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = require __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
$installed[] = self::$installed;
return $installed;
}
}

View File

@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,10 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
);

View File

@ -0,0 +1,10 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
return array(
'Pimple' => array($vendorDir . '/pimple/pimple/src'),
);

View File

@ -0,0 +1,9 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
return array(
);

View File

@ -0,0 +1,38 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitf6397224e3716ebcb1184d2811be11f8
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInitf6397224e3716ebcb1184d2811be11f8', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInitf6397224e3716ebcb1184d2811be11f8', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitf6397224e3716ebcb1184d2811be11f8::getInitializer($loader));
$loader->register(true);
return $loader;
}
}

View File

@ -0,0 +1,31 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInitf6397224e3716ebcb1184d2811be11f8
{
public static $prefixesPsr0 = array (
'P' =>
array (
'Pimple' =>
array (
0 => __DIR__ . '/..' . '/pimple/pimple/src',
),
),
);
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixesPsr0 = ComposerStaticInitf6397224e3716ebcb1184d2811be11f8::$prefixesPsr0;
$loader->classMap = ComposerStaticInitf6397224e3716ebcb1184d2811be11f8::$classMap;
}, null, ClassLoader::class);
}
}

View File

@ -0,0 +1,62 @@
{
"packages": [
{
"name": "pimple/pimple",
"version": "v3.5.0",
"version_normalized": "3.5.0.0",
"source": {
"type": "git",
"url": "https://github.com/silexphp/Pimple.git",
"reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/a94b3a4db7fb774b3d78dad2315ddc07629e1bed",
"reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1 || ^2.0"
},
"require-dev": {
"symfony/phpunit-bridge": "^5.4@dev"
},
"time": "2021-10-28T11:13:42+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.4.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-0": {
"Pimple": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Pimple, a simple Dependency Injection Container",
"homepage": "https://pimple.symfony.com",
"keywords": [
"container",
"dependency injection"
],
"support": {
"source": "https://github.com/silexphp/Pimple/tree/v3.5.0"
},
"install-path": "../pimple/pimple"
}
],
"dev": true,
"dev-package-names": []
}

View File

@ -0,0 +1,38 @@
<?php return array(
'root' => array(
'name' => 'alledia/allediaframework',
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => '251aa5c22ae6833e54fdadbfc3ebd0e6607853ad',
'type' => 'joomla-library',
'install_path' => __DIR__ . '/../../../',
'aliases' => array(),
'dev' => true,
),
'versions' => array(
'alledia/allediaframework' => array(
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => '251aa5c22ae6833e54fdadbfc3ebd0e6607853ad',
'type' => 'joomla-library',
'install_path' => __DIR__ . '/../../../',
'aliases' => array(),
'dev_requirement' => false,
),
'pimple/pimple' => array(
'pretty_version' => 'v3.5.0',
'version' => '3.5.0.0',
'reference' => 'a94b3a4db7fb774b3d78dad2315ddc07629e1bed',
'type' => 'library',
'install_path' => __DIR__ . '/../pimple/pimple',
'aliases' => array(),
'dev_requirement' => false,
),
'psr/container' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '*',
),
),
),
);

View File

@ -0,0 +1,26 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 70205)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}

View File

@ -0,0 +1,72 @@
* 3.4.0 (2021-03-06)
* Implement version 1.1 of PSR-11
* 3.3.1 (2020-11-24)
* Add support for PHP 8
* 3.3.0 (2020-03-03)
* Drop PHP extension
* Bump min PHP version to 7.2.5
* 3.2.3 (2018-01-21)
* prefixed all function calls with \ for extra speed
* 3.2.2 (2017-07-23)
* reverted extending a protected closure throws an exception (deprecated it instead)
* 3.2.1 (2017-07-17)
* fixed PHP error
* 3.2.0 (2017-07-17)
* added a PSR-11 service locator
* added a PSR-11 wrapper
* added ServiceIterator
* fixed extending a protected closure (now throws InvalidServiceIdentifierException)
* 3.1.0 (2017-07-03)
* deprecated the C extension
* added support for PSR-11 exceptions
* 3.0.2 (2015-09-11)
* refactored the C extension
* minor non-significant changes
* 3.0.1 (2015-07-30)
* simplified some code
* fixed a segfault in the C extension
* 3.0.0 (2014-07-24)
* removed the Pimple class alias (use Pimple\Container instead)
* 2.1.1 (2014-07-24)
* fixed compiler warnings for the C extension
* fixed code when dealing with circular references
* 2.1.0 (2014-06-24)
* moved the Pimple to Pimple\Container (with a BC layer -- Pimple is now a
deprecated alias which will be removed in Pimple 3.0)
* added Pimple\ServiceProviderInterface (and Pimple::register())
* 2.0.0 (2014-02-10)
* changed extend to automatically re-assign the extended service and keep it as shared or factory
(to keep BC, extend still returns the extended service)
* changed services to be shared by default (use factory() for factory
services)
* 1.0.0
* initial version

View File

@ -0,0 +1,19 @@
Copyright (c) 2009-2020 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,332 @@
Pimple
======
.. caution::
Pimple is now closed for changes. No new features will be added and no
cosmetic changes will be accepted either. The only accepted changes are
compatibility with newer PHP versions and security issue fixes.
.. caution::
This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read
the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good
way to learn more about how to create a simple Dependency Injection
Container (recent versions of Pimple are more focused on performance).
Pimple is a small Dependency Injection Container for PHP.
Installation
------------
Before using Pimple in your project, add it to your ``composer.json`` file:
.. code-block:: bash
$ ./composer.phar require pimple/pimple "^3.0"
Usage
-----
Creating a container is a matter of creating a ``Container`` instance:
.. code-block:: php
use Pimple\Container;
$container = new Container();
As many other dependency injection containers, Pimple manages two different
kind of data: **services** and **parameters**.
Defining Services
~~~~~~~~~~~~~~~~~
A service is an object that does something as part of a larger system. Examples
of services: a database connection, a templating engine, or a mailer. Almost
any **global** object can be a service.
Services are defined by **anonymous functions** that return an instance of an
object:
.. code-block:: php
// define some services
$container['session_storage'] = function ($c) {
return new SessionStorage('SESSION_ID');
};
$container['session'] = function ($c) {
return new Session($c['session_storage']);
};
Notice that the anonymous function has access to the current container
instance, allowing references to other services or parameters.
As objects are only created when you get them, the order of the definitions
does not matter.
Using the defined services is also very easy:
.. code-block:: php
// get the session object
$session = $container['session'];
// the above call is roughly equivalent to the following code:
// $storage = new SessionStorage('SESSION_ID');
// $session = new Session($storage);
Defining Factory Services
~~~~~~~~~~~~~~~~~~~~~~~~~
By default, each time you get a service, Pimple returns the **same instance**
of it. If you want a different instance to be returned for all calls, wrap your
anonymous function with the ``factory()`` method
.. code-block:: php
$container['session'] = $container->factory(function ($c) {
return new Session($c['session_storage']);
});
Now, each call to ``$container['session']`` returns a new instance of the
session.
Defining Parameters
~~~~~~~~~~~~~~~~~~~
Defining a parameter allows to ease the configuration of your container from
the outside and to store global values:
.. code-block:: php
// define some parameters
$container['cookie_name'] = 'SESSION_ID';
$container['session_storage_class'] = 'SessionStorage';
If you change the ``session_storage`` service definition like below:
.. code-block:: php
$container['session_storage'] = function ($c) {
return new $c['session_storage_class']($c['cookie_name']);
};
You can now easily change the cookie name by overriding the
``cookie_name`` parameter instead of redefining the service
definition.
Protecting Parameters
~~~~~~~~~~~~~~~~~~~~~
Because Pimple sees anonymous functions as service definitions, you need to
wrap anonymous functions with the ``protect()`` method to store them as
parameters:
.. code-block:: php
$container['random_func'] = $container->protect(function () {
return rand();
});
Modifying Services after Definition
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In some cases you may want to modify a service definition after it has been
defined. You can use the ``extend()`` method to define additional code to be
run on your service just after it is created:
.. code-block:: php
$container['session_storage'] = function ($c) {
return new $c['session_storage_class']($c['cookie_name']);
};
$container->extend('session_storage', function ($storage, $c) {
$storage->...();
return $storage;
});
The first argument is the name of the service to extend, the second a function
that gets access to the object instance and the container.
Extending a Container
~~~~~~~~~~~~~~~~~~~~~
If you use the same libraries over and over, you might want to reuse some
services from one project to the next one; package your services into a
**provider** by implementing ``Pimple\ServiceProviderInterface``:
.. code-block:: php
use Pimple\Container;
class FooProvider implements Pimple\ServiceProviderInterface
{
public function register(Container $pimple)
{
// register some services and parameters
// on $pimple
}
}
Then, register the provider on a Container:
.. code-block:: php
$pimple->register(new FooProvider());
Fetching the Service Creation Function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When you access an object, Pimple automatically calls the anonymous function
that you defined, which creates the service object for you. If you want to get
raw access to this function, you can use the ``raw()`` method:
.. code-block:: php
$container['session'] = function ($c) {
return new Session($c['session_storage']);
};
$sessionFunction = $container->raw('session');
PSR-11 compatibility
--------------------
For historical reasons, the ``Container`` class does not implement the PSR-11
``ContainerInterface``. However, Pimple provides a helper class that will let
you decouple your code from the Pimple container class.
The PSR-11 container class
~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``Pimple\Psr11\Container`` class lets you access the content of an
underlying Pimple container using ``Psr\Container\ContainerInterface``
methods:
.. code-block:: php
use Pimple\Container;
use Pimple\Psr11\Container as PsrContainer;
$container = new Container();
$container['service'] = function ($c) {
return new Service();
};
$psr11 = new PsrContainer($container);
$controller = function (PsrContainer $container) {
$service = $container->get('service');
};
$controller($psr11);
Using the PSR-11 ServiceLocator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sometimes, a service needs access to several other services without being sure
that all of them will actually be used. In those cases, you may want the
instantiation of the services to be lazy.
The traditional solution is to inject the entire service container to get only
the services really needed. However, this is not recommended because it gives
services a too broad access to the rest of the application and it hides their
actual dependencies.
The ``ServiceLocator`` is intended to solve this problem by giving access to a
set of predefined services while instantiating them only when actually needed.
It also allows you to make your services available under a different name than
the one used to register them. For instance, you may want to use an object
that expects an instance of ``EventDispatcherInterface`` to be available under
the name ``event_dispatcher`` while your event dispatcher has been
registered under the name ``dispatcher``:
.. code-block:: php
use Monolog\Logger;
use Pimple\Psr11\ServiceLocator;
use Psr\Container\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
class MyService
{
/**
* "logger" must be an instance of Psr\Log\LoggerInterface
* "event_dispatcher" must be an instance of Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
private $services;
public function __construct(ContainerInterface $services)
{
$this->services = $services;
}
}
$container['logger'] = function ($c) {
return new Monolog\Logger();
};
$container['dispatcher'] = function () {
return new EventDispatcher();
};
$container['service'] = function ($c) {
$locator = new ServiceLocator($c, array('logger', 'event_dispatcher' => 'dispatcher'));
return new MyService($locator);
};
Referencing a Collection of Services Lazily
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Passing a collection of services instances in an array may prove inefficient
if the class that consumes the collection only needs to iterate over it at a
later stage, when one of its method is called. It can also lead to problems
if there is a circular dependency between one of the services stored in the
collection and the class that consumes it.
The ``ServiceIterator`` class helps you solve these issues. It receives a
list of service names during instantiation and will retrieve the services
when iterated over:
.. code-block:: php
use Pimple\Container;
use Pimple\ServiceIterator;
class AuthorizationService
{
private $voters;
public function __construct($voters)
{
$this->voters = $voters;
}
public function canAccess($resource)
{
foreach ($this->voters as $voter) {
if (true === $voter->canAccess($resource)) {
return true;
}
}
return false;
}
}
$container = new Container();
$container['voter1'] = function ($c) {
return new SomeVoter();
}
$container['voter2'] = function ($c) {
return new SomeOtherVoter($c['auth']);
}
$container['auth'] = function ($c) {
return new AuthorizationService(new ServiceIterator($c, array('voter1', 'voter2'));
}
.. _Pimple 1.x documentation: https://github.com/silexphp/Pimple/tree/1.1

View File

@ -0,0 +1,29 @@
{
"name": "pimple/pimple",
"type": "library",
"description": "Pimple, a simple Dependency Injection Container",
"keywords": ["dependency injection", "container"],
"homepage": "https://pimple.symfony.com",
"license": "MIT",
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1 || ^2.0"
},
"require-dev": {
"symfony/phpunit-bridge": "^5.4@dev"
},
"autoload": {
"psr-0": { "Pimple": "src/" }
},
"extra": {
"branch-alias": {
"dev-master": "3.4.x-dev"
}
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="Pimple Test Suite">
<directory>./src/Pimple/Tests</directory>
</testsuite>
</testsuites>
<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
</listeners>
</phpunit>

View File

@ -0,0 +1,305 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple;
use Pimple\Exception\ExpectedInvokableException;
use Pimple\Exception\FrozenServiceException;
use Pimple\Exception\InvalidServiceIdentifierException;
use Pimple\Exception\UnknownIdentifierException;
/**
* Container main class.
*
* @author Fabien Potencier
*/
class Container implements \ArrayAccess
{
private $values = [];
private $factories;
private $protected;
private $frozen = [];
private $raw = [];
private $keys = [];
/**
* Instantiates the container.
*
* Objects and parameters can be passed as argument to the constructor.
*
* @param array $values The parameters or objects
*/
public function __construct(array $values = [])
{
$this->factories = new \SplObjectStorage();
$this->protected = new \SplObjectStorage();
foreach ($values as $key => $value) {
$this->offsetSet($key, $value);
}
}
/**
* Sets a parameter or an object.
*
* Objects must be defined as Closures.
*
* Allowing any PHP callable leads to difficult to debug problems
* as function names (strings) are callable (creating a function with
* the same name as an existing parameter would break your container).
*
* @param string $id The unique identifier for the parameter or object
* @param mixed $value The value of the parameter or a closure to define an object
*
* @return void
*
* @throws FrozenServiceException Prevent override of a frozen service
*/
#[\ReturnTypeWillChange]
public function offsetSet($id, $value)
{
if (isset($this->frozen[$id])) {
throw new FrozenServiceException($id);
}
$this->values[$id] = $value;
$this->keys[$id] = true;
}
/**
* Gets a parameter or an object.
*
* @param string $id The unique identifier for the parameter or object
*
* @return mixed The value of the parameter or an object
*
* @throws UnknownIdentifierException If the identifier is not defined
*/
#[\ReturnTypeWillChange]
public function offsetGet($id)
{
if (!isset($this->keys[$id])) {
throw new UnknownIdentifierException($id);
}
if (
isset($this->raw[$id])
|| !\is_object($this->values[$id])
|| isset($this->protected[$this->values[$id]])
|| !\method_exists($this->values[$id], '__invoke')
) {
return $this->values[$id];
}
if (isset($this->factories[$this->values[$id]])) {
return $this->values[$id]($this);
}
$raw = $this->values[$id];
$val = $this->values[$id] = $raw($this);
$this->raw[$id] = $raw;
$this->frozen[$id] = true;
return $val;
}
/**
* Checks if a parameter or an object is set.
*
* @param string $id The unique identifier for the parameter or object
*
* @return bool
*/
#[\ReturnTypeWillChange]
public function offsetExists($id)
{
return isset($this->keys[$id]);
}
/**
* Unsets a parameter or an object.
*
* @param string $id The unique identifier for the parameter or object
*
* @return void
*/
#[\ReturnTypeWillChange]
public function offsetUnset($id)
{
if (isset($this->keys[$id])) {
if (\is_object($this->values[$id])) {
unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]);
}
unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]);
}
}
/**
* Marks a callable as being a factory service.
*
* @param callable $callable A service definition to be used as a factory
*
* @return callable The passed callable
*
* @throws ExpectedInvokableException Service definition has to be a closure or an invokable object
*/
public function factory($callable)
{
if (!\is_object($callable) || !\method_exists($callable, '__invoke')) {
throw new ExpectedInvokableException('Service definition is not a Closure or invokable object.');
}
$this->factories->attach($callable);
return $callable;
}
/**
* Protects a callable from being interpreted as a service.
*
* This is useful when you want to store a callable as a parameter.
*
* @param callable $callable A callable to protect from being evaluated
*
* @return callable The passed callable
*
* @throws ExpectedInvokableException Service definition has to be a closure or an invokable object
*/
public function protect($callable)
{
if (!\is_object($callable) || !\method_exists($callable, '__invoke')) {
throw new ExpectedInvokableException('Callable is not a Closure or invokable object.');
}
$this->protected->attach($callable);
return $callable;
}
/**
* Gets a parameter or the closure defining an object.
*
* @param string $id The unique identifier for the parameter or object
*
* @return mixed The value of the parameter or the closure defining an object
*
* @throws UnknownIdentifierException If the identifier is not defined
*/
public function raw($id)
{
if (!isset($this->keys[$id])) {
throw new UnknownIdentifierException($id);
}
if (isset($this->raw[$id])) {
return $this->raw[$id];
}
return $this->values[$id];
}
/**
* Extends an object definition.
*
* Useful when you want to extend an existing object definition,
* without necessarily loading that object.
*
* @param string $id The unique identifier for the object
* @param callable $callable A service definition to extend the original
*
* @return callable The wrapped callable
*
* @throws UnknownIdentifierException If the identifier is not defined
* @throws FrozenServiceException If the service is frozen
* @throws InvalidServiceIdentifierException If the identifier belongs to a parameter
* @throws ExpectedInvokableException If the extension callable is not a closure or an invokable object
*/
public function extend($id, $callable)
{
if (!isset($this->keys[$id])) {
throw new UnknownIdentifierException($id);
}
if (isset($this->frozen[$id])) {
throw new FrozenServiceException($id);
}
if (!\is_object($this->values[$id]) || !\method_exists($this->values[$id], '__invoke')) {
throw new InvalidServiceIdentifierException($id);
}
if (isset($this->protected[$this->values[$id]])) {
@\trigger_error(\sprintf('How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "%s" should be protected?', $id), E_USER_DEPRECATED);
}
if (!\is_object($callable) || !\method_exists($callable, '__invoke')) {
throw new ExpectedInvokableException('Extension service definition is not a Closure or invokable object.');
}
$factory = $this->values[$id];
$extended = function ($c) use ($callable, $factory) {
return $callable($factory($c), $c);
};
if (isset($this->factories[$factory])) {
$this->factories->detach($factory);
$this->factories->attach($extended);
}
return $this[$id] = $extended;
}
/**
* Returns all defined value names.
*
* @return array An array of value names
*/
public function keys()
{
return \array_keys($this->values);
}
/**
* Registers a service provider.
*
* @param array $values An array of values that customizes the provider
*
* @return static
*/
public function register(ServiceProviderInterface $provider, array $values = [])
{
$provider->register($this);
foreach ($values as $key => $value) {
$this[$key] = $value;
}
return $this;
}
}

View File

@ -0,0 +1,38 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Exception;
use Psr\Container\ContainerExceptionInterface;
/**
* A closure or invokable object was expected.
*
* @author Pascal Luna <skalpa@zetareticuli.org>
*/
class ExpectedInvokableException extends \InvalidArgumentException implements ContainerExceptionInterface
{
}

View File

@ -0,0 +1,45 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Exception;
use Psr\Container\ContainerExceptionInterface;
/**
* An attempt to modify a frozen service was made.
*
* @author Pascal Luna <skalpa@zetareticuli.org>
*/
class FrozenServiceException extends \RuntimeException implements ContainerExceptionInterface
{
/**
* @param string $id Identifier of the frozen service
*/
public function __construct($id)
{
parent::__construct(\sprintf('Cannot override frozen service "%s".', $id));
}
}

View File

@ -0,0 +1,45 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Exception;
use Psr\Container\NotFoundExceptionInterface;
/**
* An attempt to perform an operation that requires a service identifier was made.
*
* @author Pascal Luna <skalpa@zetareticuli.org>
*/
class InvalidServiceIdentifierException extends \InvalidArgumentException implements NotFoundExceptionInterface
{
/**
* @param string $id The invalid identifier
*/
public function __construct($id)
{
parent::__construct(\sprintf('Identifier "%s" does not contain an object definition.', $id));
}
}

View File

@ -0,0 +1,45 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Exception;
use Psr\Container\NotFoundExceptionInterface;
/**
* The identifier of a valid service or parameter was expected.
*
* @author Pascal Luna <skalpa@zetareticuli.org>
*/
class UnknownIdentifierException extends \InvalidArgumentException implements NotFoundExceptionInterface
{
/**
* @param string $id The unknown identifier
*/
public function __construct($id)
{
parent::__construct(\sprintf('Identifier "%s" is not defined.', $id));
}
}

View File

@ -0,0 +1,55 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009-2017 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Psr11;
use Pimple\Container as PimpleContainer;
use Psr\Container\ContainerInterface;
/**
* PSR-11 compliant wrapper.
*
* @author Pascal Luna <skalpa@zetareticuli.org>
*/
final class Container implements ContainerInterface
{
private $pimple;
public function __construct(PimpleContainer $pimple)
{
$this->pimple = $pimple;
}
public function get(string $id)
{
return $this->pimple[$id];
}
public function has(string $id): bool
{
return isset($this->pimple[$id]);
}
}

View File

@ -0,0 +1,75 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Psr11;
use Pimple\Container as PimpleContainer;
use Pimple\Exception\UnknownIdentifierException;
use Psr\Container\ContainerInterface;
/**
* Pimple PSR-11 service locator.
*
* @author Pascal Luna <skalpa@zetareticuli.org>
*/
class ServiceLocator implements ContainerInterface
{
private $container;
private $aliases = [];
/**
* @param PimpleContainer $container The Container instance used to locate services
* @param array $ids Array of service ids that can be located. String keys can be used to define aliases
*/
public function __construct(PimpleContainer $container, array $ids)
{
$this->container = $container;
foreach ($ids as $key => $id) {
$this->aliases[\is_int($key) ? $id : $key] = $id;
}
}
/**
* {@inheritdoc}
*/
public function get(string $id)
{
if (!isset($this->aliases[$id])) {
throw new UnknownIdentifierException($id);
}
return $this->container[$this->aliases[$id]];
}
/**
* {@inheritdoc}
*/
public function has(string $id): bool
{
return isset($this->aliases[$id]) && isset($this->container[$this->aliases[$id]]);
}
}

View File

@ -0,0 +1,89 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple;
/**
* Lazy service iterator.
*
* @author Pascal Luna <skalpa@zetareticuli.org>
*/
final class ServiceIterator implements \Iterator
{
private $container;
private $ids;
public function __construct(Container $container, array $ids)
{
$this->container = $container;
$this->ids = $ids;
}
/**
* @return void
*/
#[\ReturnTypeWillChange]
public function rewind()
{
\reset($this->ids);
}
/**
* @return mixed
*/
#[\ReturnTypeWillChange]
public function current()
{
return $this->container[\current($this->ids)];
}
/**
* @return mixed
*/
#[\ReturnTypeWillChange]
public function key()
{
return \current($this->ids);
}
/**
* @return void
*/
#[\ReturnTypeWillChange]
public function next()
{
\next($this->ids);
}
/**
* @return bool
*/
#[\ReturnTypeWillChange]
public function valid()
{
return null !== \key($this->ids);
}
}

View File

@ -0,0 +1,44 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple;
/**
* Pimple service provider interface.
*
* @author Fabien Potencier
* @author Dominik Zogg
*/
interface ServiceProviderInterface
{
/**
* Registers services on the given container.
*
* This method should only be used to configure services and parameters.
* It should not get services.
*/
public function register(Container $pimple);
}

View File

@ -0,0 +1,38 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Tests\Fixtures;
class Invokable
{
public function __invoke($value = null)
{
$service = new Service();
$service->value = $value;
return $service;
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Tests\Fixtures;
class NonInvokable
{
public function __call($a, $b)
{
}
}

View File

@ -0,0 +1,52 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Tests\Fixtures;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
class PimpleServiceProvider implements ServiceProviderInterface
{
/**
* Registers services on the given container.
*
* This method should only be used to configure services and parameters.
* It should not get services.
*/
public function register(Container $pimple)
{
$pimple['param'] = 'value';
$pimple['service'] = function () {
return new Service();
};
$pimple['factory'] = $pimple->factory(function () {
return new Service();
});
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Tests\Fixtures;
/**
* @author Igor Wiedler <igor@wiedler.ch>
*/
class Service
{
public $value;
}

View File

@ -0,0 +1,77 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Tests;
use PHPUnit\Framework\TestCase;
use Pimple\Container;
/**
* @author Dominik Zogg <dominik.zogg@gmail.com>
*/
class PimpleServiceProviderInterfaceTest extends TestCase
{
public function testProvider()
{
$pimple = new Container();
$pimpleServiceProvider = new Fixtures\PimpleServiceProvider();
$pimpleServiceProvider->register($pimple);
$this->assertEquals('value', $pimple['param']);
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']);
$serviceOne = $pimple['factory'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
$serviceTwo = $pimple['factory'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
$this->assertNotSame($serviceOne, $serviceTwo);
}
public function testProviderWithRegisterMethod()
{
$pimple = new Container();
$pimple->register(new Fixtures\PimpleServiceProvider(), [
'anotherParameter' => 'anotherValue',
]);
$this->assertEquals('value', $pimple['param']);
$this->assertEquals('anotherValue', $pimple['anotherParameter']);
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']);
$serviceOne = $pimple['factory'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
$serviceTwo = $pimple['factory'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
$this->assertNotSame($serviceOne, $serviceTwo);
}
}

View File

@ -0,0 +1,610 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Tests;
use PHPUnit\Framework\TestCase;
use Pimple\Container;
/**
* @author Igor Wiedler <igor@wiedler.ch>
*/
class PimpleTest extends TestCase
{
public function testWithString()
{
$pimple = new Container();
$pimple['param'] = 'value';
$this->assertEquals('value', $pimple['param']);
}
public function testWithClosure()
{
$pimple = new Container();
$pimple['service'] = function () {
return new Fixtures\Service();
};
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']);
}
public function testServicesShouldBeDifferent()
{
$pimple = new Container();
$pimple['service'] = $pimple->factory(function () {
return new Fixtures\Service();
});
$serviceOne = $pimple['service'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
$serviceTwo = $pimple['service'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
$this->assertNotSame($serviceOne, $serviceTwo);
}
public function testShouldPassContainerAsParameter()
{
$pimple = new Container();
$pimple['service'] = function () {
return new Fixtures\Service();
};
$pimple['container'] = function ($container) {
return $container;
};
$this->assertNotSame($pimple, $pimple['service']);
$this->assertSame($pimple, $pimple['container']);
}
public function testIsset()
{
$pimple = new Container();
$pimple['param'] = 'value';
$pimple['service'] = function () {
return new Fixtures\Service();
};
$pimple['null'] = null;
$this->assertTrue(isset($pimple['param']));
$this->assertTrue(isset($pimple['service']));
$this->assertTrue(isset($pimple['null']));
$this->assertFalse(isset($pimple['non_existent']));
}
public function testConstructorInjection()
{
$params = ['param' => 'value'];
$pimple = new Container($params);
$this->assertSame($params['param'], $pimple['param']);
}
public function testOffsetGetValidatesKeyIsPresent()
{
$this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
$this->expectExceptionMessage('Identifier "foo" is not defined.');
$pimple = new Container();
echo $pimple['foo'];
}
/**
* @group legacy
*/
public function testLegacyOffsetGetValidatesKeyIsPresent()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Identifier "foo" is not defined.');
$pimple = new Container();
echo $pimple['foo'];
}
public function testOffsetGetHonorsNullValues()
{
$pimple = new Container();
$pimple['foo'] = null;
$this->assertNull($pimple['foo']);
}
public function testUnset()
{
$pimple = new Container();
$pimple['param'] = 'value';
$pimple['service'] = function () {
return new Fixtures\Service();
};
unset($pimple['param'], $pimple['service']);
$this->assertFalse(isset($pimple['param']));
$this->assertFalse(isset($pimple['service']));
}
/**
* @dataProvider serviceDefinitionProvider
*/
public function testShare($service)
{
$pimple = new Container();
$pimple['shared_service'] = $service;
$serviceOne = $pimple['shared_service'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
$serviceTwo = $pimple['shared_service'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
$this->assertSame($serviceOne, $serviceTwo);
}
/**
* @dataProvider serviceDefinitionProvider
*/
public function testProtect($service)
{
$pimple = new Container();
$pimple['protected'] = $pimple->protect($service);
$this->assertSame($service, $pimple['protected']);
}
public function testGlobalFunctionNameAsParameterValue()
{
$pimple = new Container();
$pimple['global_function'] = 'strlen';
$this->assertSame('strlen', $pimple['global_function']);
}
public function testRaw()
{
$pimple = new Container();
$pimple['service'] = $definition = $pimple->factory(function () {
return 'foo';
});
$this->assertSame($definition, $pimple->raw('service'));
}
public function testRawHonorsNullValues()
{
$pimple = new Container();
$pimple['foo'] = null;
$this->assertNull($pimple->raw('foo'));
}
public function testFluentRegister()
{
$pimple = new Container();
$this->assertSame($pimple, $pimple->register($this->getMockBuilder('Pimple\ServiceProviderInterface')->getMock()));
}
public function testRawValidatesKeyIsPresent()
{
$this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
$this->expectExceptionMessage('Identifier "foo" is not defined.');
$pimple = new Container();
$pimple->raw('foo');
}
/**
* @group legacy
*/
public function testLegacyRawValidatesKeyIsPresent()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Identifier "foo" is not defined.');
$pimple = new Container();
$pimple->raw('foo');
}
/**
* @dataProvider serviceDefinitionProvider
*/
public function testExtend($service)
{
$pimple = new Container();
$pimple['shared_service'] = function () {
return new Fixtures\Service();
};
$pimple['factory_service'] = $pimple->factory(function () {
return new Fixtures\Service();
});
$pimple->extend('shared_service', $service);
$serviceOne = $pimple['shared_service'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
$serviceTwo = $pimple['shared_service'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
$this->assertSame($serviceOne, $serviceTwo);
$this->assertSame($serviceOne->value, $serviceTwo->value);
$pimple->extend('factory_service', $service);
$serviceOne = $pimple['factory_service'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
$serviceTwo = $pimple['factory_service'];
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
$this->assertNotSame($serviceOne, $serviceTwo);
$this->assertNotSame($serviceOne->value, $serviceTwo->value);
}
public function testExtendDoesNotLeakWithFactories()
{
if (\extension_loaded('pimple')) {
$this->markTestSkipped('Pimple extension does not support this test');
}
$pimple = new Container();
$pimple['foo'] = $pimple->factory(function () {
return;
});
$pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) {
return;
});
unset($pimple['foo']);
$p = new \ReflectionProperty($pimple, 'values');
$p->setAccessible(true);
$this->assertEmpty($p->getValue($pimple));
$p = new \ReflectionProperty($pimple, 'factories');
$p->setAccessible(true);
$this->assertCount(0, $p->getValue($pimple));
}
public function testExtendValidatesKeyIsPresent()
{
$this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
$this->expectExceptionMessage('Identifier "foo" is not defined.');
$pimple = new Container();
$pimple->extend('foo', function () {
});
}
/**
* @group legacy
*/
public function testLegacyExtendValidatesKeyIsPresent()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Identifier "foo" is not defined.');
$pimple = new Container();
$pimple->extend('foo', function () {
});
}
public function testKeys()
{
$pimple = new Container();
$pimple['foo'] = 123;
$pimple['bar'] = 123;
$this->assertEquals(['foo', 'bar'], $pimple->keys());
}
/** @test */
public function settingAnInvokableObjectShouldTreatItAsFactory()
{
$pimple = new Container();
$pimple['invokable'] = new Fixtures\Invokable();
$this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['invokable']);
}
/** @test */
public function settingNonInvokableObjectShouldTreatItAsParameter()
{
$pimple = new Container();
$pimple['non_invokable'] = new Fixtures\NonInvokable();
$this->assertInstanceOf('Pimple\Tests\Fixtures\NonInvokable', $pimple['non_invokable']);
}
/**
* @dataProvider badServiceDefinitionProvider
*/
public function testFactoryFailsForInvalidServiceDefinitions($service)
{
$this->expectException(\Pimple\Exception\ExpectedInvokableException::class);
$this->expectExceptionMessage('Service definition is not a Closure or invokable object.');
$pimple = new Container();
$pimple->factory($service);
}
/**
* @group legacy
* @dataProvider badServiceDefinitionProvider
*/
public function testLegacyFactoryFailsForInvalidServiceDefinitions($service)
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Service definition is not a Closure or invokable object.');
$pimple = new Container();
$pimple->factory($service);
}
/**
* @dataProvider badServiceDefinitionProvider
*/
public function testProtectFailsForInvalidServiceDefinitions($service)
{
$this->expectException(\Pimple\Exception\ExpectedInvokableException::class);
$this->expectExceptionMessage('Callable is not a Closure or invokable object.');
$pimple = new Container();
$pimple->protect($service);
}
/**
* @group legacy
* @dataProvider badServiceDefinitionProvider
*/
public function testLegacyProtectFailsForInvalidServiceDefinitions($service)
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Callable is not a Closure or invokable object.');
$pimple = new Container();
$pimple->protect($service);
}
/**
* @dataProvider badServiceDefinitionProvider
*/
public function testExtendFailsForKeysNotContainingServiceDefinitions($service)
{
$this->expectException(\Pimple\Exception\InvalidServiceIdentifierException::class);
$this->expectExceptionMessage('Identifier "foo" does not contain an object definition.');
$pimple = new Container();
$pimple['foo'] = $service;
$pimple->extend('foo', function () {
});
}
/**
* @group legacy
* @dataProvider badServiceDefinitionProvider
*/
public function testLegacyExtendFailsForKeysNotContainingServiceDefinitions($service)
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Identifier "foo" does not contain an object definition.');
$pimple = new Container();
$pimple['foo'] = $service;
$pimple->extend('foo', function () {
});
}
/**
* @group legacy
* @expectedDeprecation How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "foo" should be protected?
*/
public function testExtendingProtectedClosureDeprecation()
{
$pimple = new Container();
$pimple['foo'] = $pimple->protect(function () {
return 'bar';
});
$pimple->extend('foo', function ($value) {
return $value.'-baz';
});
$this->assertSame('bar-baz', $pimple['foo']);
}
/**
* @dataProvider badServiceDefinitionProvider
*/
public function testExtendFailsForInvalidServiceDefinitions($service)
{
$this->expectException(\Pimple\Exception\ExpectedInvokableException::class);
$this->expectExceptionMessage('Extension service definition is not a Closure or invokable object.');
$pimple = new Container();
$pimple['foo'] = function () {
};
$pimple->extend('foo', $service);
}
/**
* @group legacy
* @dataProvider badServiceDefinitionProvider
*/
public function testLegacyExtendFailsForInvalidServiceDefinitions($service)
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Extension service definition is not a Closure or invokable object.');
$pimple = new Container();
$pimple['foo'] = function () {
};
$pimple->extend('foo', $service);
}
public function testExtendFailsIfFrozenServiceIsNonInvokable()
{
$this->expectException(\Pimple\Exception\FrozenServiceException::class);
$this->expectExceptionMessage('Cannot override frozen service "foo".');
$pimple = new Container();
$pimple['foo'] = function () {
return new Fixtures\NonInvokable();
};
$foo = $pimple['foo'];
$pimple->extend('foo', function () {
});
}
public function testExtendFailsIfFrozenServiceIsInvokable()
{
$this->expectException(\Pimple\Exception\FrozenServiceException::class);
$this->expectExceptionMessage('Cannot override frozen service "foo".');
$pimple = new Container();
$pimple['foo'] = function () {
return new Fixtures\Invokable();
};
$foo = $pimple['foo'];
$pimple->extend('foo', function () {
});
}
/**
* Provider for invalid service definitions.
*/
public function badServiceDefinitionProvider()
{
return [
[123],
[new Fixtures\NonInvokable()],
];
}
/**
* Provider for service definitions.
*/
public function serviceDefinitionProvider()
{
return [
[function ($value) {
$service = new Fixtures\Service();
$service->value = $value;
return $service;
}],
[new Fixtures\Invokable()],
];
}
public function testDefiningNewServiceAfterFreeze()
{
$pimple = new Container();
$pimple['foo'] = function () {
return 'foo';
};
$foo = $pimple['foo'];
$pimple['bar'] = function () {
return 'bar';
};
$this->assertSame('bar', $pimple['bar']);
}
public function testOverridingServiceAfterFreeze()
{
$this->expectException(\Pimple\Exception\FrozenServiceException::class);
$this->expectExceptionMessage('Cannot override frozen service "foo".');
$pimple = new Container();
$pimple['foo'] = function () {
return 'foo';
};
$foo = $pimple['foo'];
$pimple['foo'] = function () {
return 'bar';
};
}
/**
* @group legacy
*/
public function testLegacyOverridingServiceAfterFreeze()
{
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Cannot override frozen service "foo".');
$pimple = new Container();
$pimple['foo'] = function () {
return 'foo';
};
$foo = $pimple['foo'];
$pimple['foo'] = function () {
return 'bar';
};
}
public function testRemovingServiceAfterFreeze()
{
$pimple = new Container();
$pimple['foo'] = function () {
return 'foo';
};
$foo = $pimple['foo'];
unset($pimple['foo']);
$pimple['foo'] = function () {
return 'bar';
};
$this->assertSame('bar', $pimple['foo']);
}
public function testExtendingService()
{
$pimple = new Container();
$pimple['foo'] = function () {
return 'foo';
};
$pimple['foo'] = $pimple->extend('foo', function ($foo, $app) {
return "$foo.bar";
});
$pimple['foo'] = $pimple->extend('foo', function ($foo, $app) {
return "$foo.baz";
});
$this->assertSame('foo.bar.baz', $pimple['foo']);
}
public function testExtendingServiceAfterOtherServiceFreeze()
{
$pimple = new Container();
$pimple['foo'] = function () {
return 'foo';
};
$pimple['bar'] = function () {
return 'bar';
};
$foo = $pimple['foo'];
$pimple['bar'] = $pimple->extend('bar', function ($bar, $app) {
return "$bar.baz";
});
$this->assertSame('bar.baz', $pimple['bar']);
}
}

View File

@ -0,0 +1,76 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009-2017 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Tests\Psr11;
use PHPUnit\Framework\TestCase;
use Pimple\Container;
use Pimple\Psr11\Container as PsrContainer;
use Pimple\Tests\Fixtures\Service;
class ContainerTest extends TestCase
{
public function testGetReturnsExistingService()
{
$pimple = new Container();
$pimple['service'] = function () {
return new Service();
};
$psr = new PsrContainer($pimple);
$this->assertSame($pimple['service'], $psr->get('service'));
}
public function testGetThrowsExceptionIfServiceIsNotFound()
{
$this->expectException(\Psr\Container\NotFoundExceptionInterface::class);
$this->expectExceptionMessage('Identifier "service" is not defined.');
$pimple = new Container();
$psr = new PsrContainer($pimple);
$psr->get('service');
}
public function testHasReturnsTrueIfServiceExists()
{
$pimple = new Container();
$pimple['service'] = function () {
return new Service();
};
$psr = new PsrContainer($pimple);
$this->assertTrue($psr->has('service'));
}
public function testHasReturnsFalseIfServiceDoesNotExist()
{
$pimple = new Container();
$psr = new PsrContainer($pimple);
$this->assertFalse($psr->has('service'));
}
}

View File

@ -0,0 +1,131 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Tests\Psr11;
use PHPUnit\Framework\TestCase;
use Pimple\Container;
use Pimple\Psr11\ServiceLocator;
use Pimple\Tests\Fixtures;
/**
* ServiceLocator test case.
*
* @author Pascal Luna <skalpa@zetareticuli.org>
*/
class ServiceLocatorTest extends TestCase
{
public function testCanAccessServices()
{
$pimple = new Container();
$pimple['service'] = function () {
return new Fixtures\Service();
};
$locator = new ServiceLocator($pimple, ['service']);
$this->assertSame($pimple['service'], $locator->get('service'));
}
public function testCanAccessAliasedServices()
{
$pimple = new Container();
$pimple['service'] = function () {
return new Fixtures\Service();
};
$locator = new ServiceLocator($pimple, ['alias' => 'service']);
$this->assertSame($pimple['service'], $locator->get('alias'));
}
public function testCannotAccessAliasedServiceUsingRealIdentifier()
{
$this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
$this->expectExceptionMessage('Identifier "service" is not defined.');
$pimple = new Container();
$pimple['service'] = function () {
return new Fixtures\Service();
};
$locator = new ServiceLocator($pimple, ['alias' => 'service']);
$service = $locator->get('service');
}
public function testGetValidatesServiceCanBeLocated()
{
$this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
$this->expectExceptionMessage('Identifier "foo" is not defined.');
$pimple = new Container();
$pimple['service'] = function () {
return new Fixtures\Service();
};
$locator = new ServiceLocator($pimple, ['alias' => 'service']);
$service = $locator->get('foo');
}
public function testGetValidatesTargetServiceExists()
{
$this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
$this->expectExceptionMessage('Identifier "invalid" is not defined.');
$pimple = new Container();
$pimple['service'] = function () {
return new Fixtures\Service();
};
$locator = new ServiceLocator($pimple, ['alias' => 'invalid']);
$service = $locator->get('alias');
}
public function testHasValidatesServiceCanBeLocated()
{
$pimple = new Container();
$pimple['service1'] = function () {
return new Fixtures\Service();
};
$pimple['service2'] = function () {
return new Fixtures\Service();
};
$locator = new ServiceLocator($pimple, ['service1']);
$this->assertTrue($locator->has('service1'));
$this->assertFalse($locator->has('service2'));
}
public function testHasChecksIfTargetServiceExists()
{
$pimple = new Container();
$pimple['service'] = function () {
return new Fixtures\Service();
};
$locator = new ServiceLocator($pimple, ['foo' => 'service', 'bar' => 'invalid']);
$this->assertTrue($locator->has('foo'));
$this->assertFalse($locator->has('bar'));
}
}

View File

@ -0,0 +1,52 @@
<?php
/*
* This file is part of Pimple.
*
* Copyright (c) 2009 Fabien Potencier
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Pimple\Tests;
use PHPUnit\Framework\TestCase;
use Pimple\Container;
use Pimple\ServiceIterator;
use Pimple\Tests\Fixtures\Service;
class ServiceIteratorTest extends TestCase
{
public function testIsIterable()
{
$pimple = new Container();
$pimple['service1'] = function () {
return new Service();
};
$pimple['service2'] = function () {
return new Service();
};
$pimple['service3'] = function () {
return new Service();
};
$iterator = new ServiceIterator($pimple, ['service1', 'service2']);
$this->assertSame(['service1' => $pimple['service1'], 'service2' => $pimple['service2']], iterator_to_array($iterator));
}
}

88
libraries/bootstrap.php Normal file
View File

@ -0,0 +1,88 @@
<?php
/**
* Bootstrap file for the Joomla! CMS [with legacy libraries].
* Including this file into your application will make Joomla libraries available for use.
*
* @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Set the platform root path as a constant if necessary.
*
* @deprecated 4.4.0 will be removed in 6.0
* Use defined('_JEXEC') or die; to detect if the CMS is loaded correctly
**/
defined('JPATH_PLATFORM') or define('JPATH_PLATFORM', __DIR__);
// Detect the native operating system type.
$os = strtoupper(substr(PHP_OS, 0, 3));
defined('IS_WIN') or define('IS_WIN', ($os === 'WIN'));
defined('IS_UNIX') or define('IS_UNIX', (($os !== 'MAC') && ($os !== 'WIN')));
// Import the library loader if necessary.
if (!class_exists('JLoader')) {
require_once JPATH_LIBRARIES . '/loader.php';
// If JLoader still does not exist panic.
if (!class_exists('JLoader')) {
throw new RuntimeException('Joomla Platform not loaded.');
}
}
// Setup the autoloaders.
JLoader::setup();
// Create the Composer autoloader
/** @var \Composer\Autoload\ClassLoader $loader */
$loader = require JPATH_LIBRARIES . '/vendor/autoload.php';
// We need to pull our decorated class loader into memory before unregistering Composer's loader
class_exists('\\Joomla\\CMS\\Autoload\\ClassLoader');
$loader->unregister();
// Decorate Composer autoloader
spl_autoload_register([new \Joomla\CMS\Autoload\ClassLoader($loader), 'loadClass'], true, true);
/**
* Register the global exception handler. And set error level to server default error level.
* The error level may be changed later in boot up process, after application config will be loaded.
* Do not remove the variable, to allow to use it further, after including this file.
*/
$errorHandler = \Symfony\Component\ErrorHandler\ErrorHandler::register();
\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer::setTemplate(__DIR__ . '/../templates/system/fatal.php');
// Register the error handler which processes E_USER_DEPRECATED errors
if (error_reporting() & E_USER_DEPRECATED) {
set_error_handler(['Joomla\CMS\Exception\ExceptionHandler', 'handleUserDeprecatedErrors'], E_USER_DEPRECATED);
}
// Suppress phar stream wrapper for non .phar files
$behavior = new \TYPO3\PharStreamWrapper\Behavior();
\TYPO3\PharStreamWrapper\Manager::initialize(
$behavior->withAssertion(new \TYPO3\PharStreamWrapper\Interceptor\PharExtensionInterceptor())
);
if (in_array('phar', stream_get_wrappers())) {
stream_wrapper_unregister('phar');
stream_wrapper_register('phar', 'TYPO3\\PharStreamWrapper\\PharStreamWrapper');
}
// Define the Joomla version if not already defined.
defined('JVERSION') or define('JVERSION', (new \Joomla\CMS\Version())->getShortVersion());
// Set up the message queue logger for web requests
if (array_key_exists('REQUEST_METHOD', $_SERVER)) {
\Joomla\CMS\Log\Log::addLogger(['logger' => 'messagequeue'], \Joomla\CMS\Log\Log::ALL, ['jerror']);
}
// Register the Crypto lib
JLoader::register('Crypto', JPATH_LIBRARIES . '/php-encryption/Crypto.php');
// Register the PasswordHash library.
JLoader::register('PasswordHash', JPATH_LIBRARIES . '/phpass/PasswordHash.php');

77
libraries/cms.php Normal file
View File

@ -0,0 +1,77 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
trigger_error(
sprintf(
'Bootstrapping Joomla using the %1$s file is deprecated. Use %2$s instead.',
__FILE__,
__DIR__ . '/bootstrap.php'
),
E_USER_DEPRECATED
);
/**
* Set the platform root path as a constant if necessary.
*
* @deprecated 4.4.0 will be removed in 6.0
* Use defined('_JEXEC') or die; to detect if the CMS is loaded correctly
**/
if (!defined('JPATH_PLATFORM')) {
define('JPATH_PLATFORM', __DIR__);
}
// Import the library loader if necessary
if (!class_exists('JLoader')) {
require_once JPATH_LIBRARIES . '/loader.php';
}
// Make sure that the Joomla Platform has been successfully loaded
if (!class_exists('JLoader')) {
throw new RuntimeException('Joomla Platform not loaded.');
}
// Create the Composer autoloader
$loader = require JPATH_LIBRARIES . '/vendor/autoload.php';
// We need to pull our decorated class loader into memory before unregistering Composer's loader
class_exists('\\Joomla\\CMS\\Autoload\\ClassLoader');
$loader->unregister();
// Decorate Composer autoloader
spl_autoload_register([new \Joomla\CMS\Autoload\ClassLoader($loader), 'loadClass'], true, true);
// Suppress phar stream wrapper for non .phar files
$behavior = new \TYPO3\PharStreamWrapper\Behavior();
\TYPO3\PharStreamWrapper\Manager::initialize(
$behavior->withAssertion(new \TYPO3\PharStreamWrapper\Interceptor\PharExtensionInterceptor())
);
if (in_array('phar', stream_get_wrappers())) {
stream_wrapper_unregister('phar');
stream_wrapper_register('phar', 'TYPO3\\PharStreamWrapper\\PharStreamWrapper');
}
// Define the Joomla version if not already defined
if (!defined('JVERSION')) {
define('JVERSION', (new \Joomla\CMS\Version())->getShortVersion());
}
// Register a handler for uncaught exceptions that shows a pretty error page when possible
set_exception_handler(['Joomla\CMS\Exception\ExceptionHandler', 'handleException']);
// Set up the message queue logger for web requests
if (array_key_exists('REQUEST_METHOD', $_SERVER)) {
\Joomla\CMS\Log\Log::addLogger(['logger' => 'messagequeue'], \Joomla\CMS\Log\Log::ALL, ['jerror']);
}
// Register the Crypto lib
JLoader::register('Crypto', JPATH_LIBRARIES . '/php-encryption/Crypto.php');

345
libraries/f0f/LICENSE.txt Normal file
View File

@ -0,0 +1,345 @@
================================================================================
Historical note
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
On February 21st, 2013 FOF changed its license to GPLv2 or later.
================================================================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,780 @@
<?php
/**
* @package FrameworkOnFramework
* @subpackage autoloader
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2, or later
*/
defined('F0F_INCLUDED') or die();
/**
* An autoloader for F0F-powered components. It allows the autoloading of
* various classes related to the operation of a component, from Controllers
* and Models to Helpers and Fields. If a class doesn't exist, it will be
* created on the fly.
*
* @package FrameworkOnFramework
* @subpackage autoloader
* @since 2.1
*/
class F0FAutoloaderComponent
{
/**
* An instance of this autoloader
*
* @var F0FAutoloaderComponent
*/
public static $autoloader = null;
/**
* The path to the F0F root directory
*
* @var string
*/
public static $fofPath = null;
/**
* An array holding component names and their F0F-ness status
*
* @var array
*/
protected static $fofComponents = array();
/**
* Initialise this autoloader
*
* @return F0FAutoloaderComponent
*/
public static function init()
{
if (self::$autoloader == null)
{
self::$autoloader = new self;
}
return self::$autoloader;
}
/**
* Public constructor. Registers the autoloader with PHP.
*/
public function __construct()
{
self::$fofPath = realpath(__DIR__ . '/../');
spl_autoload_register(array($this,'autoload_fof_controller'));
spl_autoload_register(array($this,'autoload_fof_model'));
spl_autoload_register(array($this,'autoload_fof_view'));
spl_autoload_register(array($this,'autoload_fof_table'));
spl_autoload_register(array($this,'autoload_fof_helper'));
spl_autoload_register(array($this,'autoload_fof_toolbar'));
spl_autoload_register(array($this,'autoload_fof_field'));
}
/**
* Returns true if this is a F0F-powered component, i.e. if it has a fof.xml
* file in its main directory.
*
* @param string $component The component's name
*
* @return boolean
*/
public function isF0FComponent($component)
{
if (!isset($fofComponents[$component]))
{
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($component);
$fofComponents[$component] = file_exists($componentPaths['admin'] . '/fof.xml');
}
return $fofComponents[$component];
}
/**
* Creates class aliases. On systems where eval() is enabled it creates a
* real class. On other systems it merely creates an alias. The eval()
* method is preferred as class_aliases result in the name of the class
* being instanciated not being available, making it impossible to create
* a class instance without passing a $config array :(
*
* @param string $original The name of the original (existing) class
* @param string $alias The name of the new (aliased) class
* @param boolean $autoload Should I try to autoload the $original class?
*
* @return void
*/
private function class_alias($original, $alias, $autoload = true)
{
static $hasEval = null;
if (is_null($hasEval))
{
$hasEval = false;
if (function_exists('ini_get'))
{
$disabled_functions = ini_get('disabled_functions');
if (!is_string($disabled_functions))
{
$hasEval = true;
}
else
{
$disabled_functions = explode(',', $disabled_functions);
$hasEval = !in_array('eval', $disabled_functions);
}
}
}
if (!class_exists($original, $autoload))
{
return;
}
if ($hasEval)
{
$phpCode = "class $alias extends $original {}";
eval($phpCode);
}
else
{
class_alias($original, $alias, $autoload);
}
}
/**
* Autoload Controllers
*
* @param string $class_name The name of the class to load
*
* @return void
*/
public function autoload_fof_controller($class_name)
{
F0FPlatform::getInstance()->logDebug(__METHOD__ . "() autoloading $class_name");
static $isCli = null, $isAdmin = null;
if (is_null($isCli) && is_null($isAdmin))
{
list($isCli, $isAdmin) = F0FDispatcher::isCliAdmin();
}
if (strpos($class_name, 'Controller') === false)
{
return;
}
// Change from camel cased into a lowercase array
$class_modified = preg_replace('/(\s)+/', '_', $class_name);
$class_modified = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $class_modified));
$parts = explode('_', $class_modified);
// We need three parts in the name
if (count($parts) != 3)
{
return;
}
// We need the second part to be "controller"
if ($parts[1] != 'controller')
{
return;
}
// Get the information about this class
$component_raw = $parts[0];
$component = 'com_' . $parts[0];
$view = $parts[2];
// Is this an F0F 2.1 or later component?
if (!$this->isF0FComponent($component))
{
return;
}
// Get the alternate view and class name (opposite singular/plural name)
$alt_view = F0FInflector::isSingular($view) ? F0FInflector::pluralize($view) : F0FInflector::singularize($view);
$alt_class = F0FInflector::camelize($component_raw . '_controller_' . $alt_view);
// Get the component's paths
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($component);
// Get the proper and alternate paths and file names
$file = "/controllers/$view.php";
$altFile = "/controllers/$alt_view.php";
$path = $componentPaths['main'];
$altPath = $componentPaths['alt'];
// Try to find the proper class in the proper path
if (file_exists($path . $file))
{
@include_once $path . $file;
}
// Try to find the proper class in the alternate path
if (!class_exists($class_name) && file_exists($altPath . $file))
{
@include_once $altPath . $file;
}
// Try to find the alternate class in the proper path
if (!class_exists($alt_class) && file_exists($path . $altFile))
{
@include_once $path . $altFile;
}
// Try to find the alternate class in the alternate path
if (!class_exists($alt_class) && file_exists($altPath . $altFile))
{
@include_once $altPath . $altFile;
}
// If the alternate class exists just map the class to the alternate
if (!class_exists($class_name) && class_exists($alt_class))
{
$this->class_alias($alt_class, $class_name);
}
// No class found? Map to F0FController
elseif (!class_exists($class_name))
{
if ($view != 'default')
{
$defaultClass = F0FInflector::camelize($component_raw . '_controller_default');
$this->class_alias($defaultClass, $class_name);
}
else
{
$this->class_alias('F0FController', $class_name);
}
}
}
/**
* Autoload Models
*
* @param string $class_name The name of the class to load
*
* @return void
*/
public function autoload_fof_model($class_name)
{
F0FPlatform::getInstance()->logDebug(__METHOD__ . "() autoloading $class_name");
static $isCli = null, $isAdmin = null;
if (is_null($isCli) && is_null($isAdmin))
{
list($isCli, $isAdmin) = F0FDispatcher::isCliAdmin();
}
if (strpos($class_name, 'Model') === false)
{
return;
}
// Change from camel cased into a lowercase array
$class_modified = preg_replace('/(\s)+/', '_', $class_name);
$class_modified = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $class_modified));
$parts = explode('_', $class_modified);
// We need three parts in the name
if (count($parts) != 3)
{
return;
}
// We need the second part to be "model"
if ($parts[1] != 'model')
{
return;
}
// Get the information about this class
$component_raw = $parts[0];
$component = 'com_' . $parts[0];
$view = $parts[2];
// Is this an F0F 2.1 or later component?
if (!$this->isF0FComponent($component))
{
return;
}
// Get the alternate view and class name (opposite singular/plural name)
$alt_view = F0FInflector::isSingular($view) ? F0FInflector::pluralize($view) : F0FInflector::singularize($view);
$alt_class = F0FInflector::camelize($component_raw . '_model_' . $alt_view);
// Get the proper and alternate paths and file names
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($component);
$file = "/models/$view.php";
$altFile = "/models/$alt_view.php";
$path = $componentPaths['main'];
$altPath = $componentPaths['alt'];
// Try to find the proper class in the proper path
if (file_exists($path . $file))
{
@include_once $path . $file;
}
// Try to find the proper class in the alternate path
if (!class_exists($class_name) && file_exists($altPath . $file))
{
@include_once $altPath . $file;
}
// Try to find the alternate class in the proper path
if (!class_exists($alt_class) && file_exists($path . $altFile))
{
@include_once $path . $altFile;
}
// Try to find the alternate class in the alternate path
if (!class_exists($alt_class) && file_exists($altPath . $altFile))
{
@include_once $altPath . $altFile;
}
// If the alternate class exists just map the class to the alternate
if (!class_exists($class_name) && class_exists($alt_class))
{
$this->class_alias($alt_class, $class_name);
}
// No class found? Map to F0FModel
elseif (!class_exists($class_name))
{
if ($view != 'default')
{
$defaultClass = F0FInflector::camelize($component_raw . '_model_default');
$this->class_alias($defaultClass, $class_name);
}
else
{
$this->class_alias('F0FModel', $class_name, true);
}
}
}
/**
* Autoload Views
*
* @param string $class_name The name of the class to load
*
* @return void
*/
public function autoload_fof_view($class_name)
{
F0FPlatform::getInstance()->logDebug(__METHOD__ . "() autoloading $class_name");
static $isCli = null, $isAdmin = null;
if (is_null($isCli) && is_null($isAdmin))
{
list($isCli, $isAdmin) = F0FDispatcher::isCliAdmin();
}
if (strpos($class_name, 'View') === false)
{
return;
}
// Change from camel cased into a lowercase array
$class_modified = preg_replace('/(\s)+/', '_', $class_name);
$class_modified = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $class_modified));
$parts = explode('_', $class_modified);
// We need at least three parts in the name
if (count($parts) < 3)
{
return;
}
// We need the second part to be "view"
if ($parts[1] != 'view')
{
return;
}
// Get the information about this class
$component_raw = $parts[0];
$component = 'com_' . $parts[0];
$view = $parts[2];
if (count($parts) > 3)
{
$format = $parts[3];
}
else
{
$input = new F0FInput;
$format = $input->getCmd('format', 'html', 'cmd');
}
// Is this an F0F 2.1 or later component?
if (!$this->isF0FComponent($component))
{
return;
}
// Get the alternate view and class name (opposite singular/plural name)
$alt_view = F0FInflector::isSingular($view) ? F0FInflector::pluralize($view) : F0FInflector::singularize($view);
$alt_class = F0FInflector::camelize($component_raw . '_view_' . $alt_view);
// Get the proper and alternate paths and file names
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($component);
$protoFile = "/models/$view";
$protoAltFile = "/models/$alt_view";
$path = $componentPaths['main'];
$altPath = $componentPaths['alt'];
$formats = array($format);
if ($format != 'html')
{
$formats[] = 'raw';
}
foreach ($formats as $currentFormat)
{
$file = $protoFile . '.' . $currentFormat . '.php';
$altFile = $protoAltFile . '.' . $currentFormat . '.php';
// Try to find the proper class in the proper path
if (!class_exists($class_name) && file_exists($path . $file))
{
@include_once $path . $file;
}
// Try to find the proper class in the alternate path
if (!class_exists($class_name) && file_exists($altPath . $file))
{
@include_once $altPath . $file;
}
// Try to find the alternate class in the proper path
if (!class_exists($alt_class) && file_exists($path . $altFile))
{
@include_once $path . $altFile;
}
// Try to find the alternate class in the alternate path
if (!class_exists($alt_class) && file_exists($altPath . $altFile))
{
@include_once $altPath . $altFile;
}
}
// If the alternate class exists just map the class to the alternate
if (!class_exists($class_name) && class_exists($alt_class))
{
$this->class_alias($alt_class, $class_name);
}
// No class found? Map to F0FModel
elseif (!class_exists($class_name))
{
if ($view != 'default')
{
$defaultClass = F0FInflector::camelize($component_raw . '_view_default');
$this->class_alias($defaultClass, $class_name);
}
else
{
if (!file_exists(self::$fofPath . '/view/' . $format . '.php'))
{
$default_class = 'F0FView';
}
else
{
$default_class = 'F0FView' . ucfirst($format);
}
$this->class_alias($default_class, $class_name, true);
}
}
}
/**
* Autoload Tables
*
* @param string $class_name The name of the class to load
*
* @return void
*/
public function autoload_fof_table($class_name)
{
F0FPlatform::getInstance()->logDebug(__METHOD__ . "() autoloading $class_name");
static $isCli = null, $isAdmin = null;
if (is_null($isCli) && is_null($isAdmin))
{
list($isCli, $isAdmin) = F0FDispatcher::isCliAdmin();
}
if (strpos($class_name, 'Table') === false)
{
return;
}
// Change from camel cased into a lowercase array
$class_modified = preg_replace('/(\s)+/', '_', $class_name);
$class_modified = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $class_modified));
$parts = explode('_', $class_modified);
// We need three parts in the name
if (count($parts) != 3)
{
return;
}
// We need the second part to be "model"
if ($parts[1] != 'table')
{
return;
}
// Get the information about this class
$component_raw = $parts[0];
$component = 'com_' . $parts[0];
$view = $parts[2];
// Is this an F0F 2.1 or later component?
if (!$this->isF0FComponent($component))
{
return;
}
// Get the alternate view and class name (opposite singular/plural name)
$alt_view = F0FInflector::isSingular($view) ? F0FInflector::pluralize($view) : F0FInflector::singularize($view);
$alt_class = F0FInflector::camelize($component_raw . '_table_' . $alt_view);
// Get the proper and alternate paths and file names
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($component);
$file = "/tables/$view.php";
$altFile = "/tables/$alt_view.php";
$path = $componentPaths['admin'];
// Try to find the proper class in the proper path
if (file_exists($path . $file))
{
@include_once $path . $file;
}
// Try to find the alternate class in the proper path
if (!class_exists($alt_class) && file_exists($path . $altFile))
{
@include_once $path . $altFile;
}
// If the alternate class exists just map the class to the alternate
if (!class_exists($class_name) && class_exists($alt_class))
{
$this->class_alias($alt_class, $class_name);
}
// No class found? Map to F0FModel
elseif (!class_exists($class_name))
{
if ($view != 'default')
{
$defaultClass = F0FInflector::camelize($component_raw . '_table_default');
$this->class_alias($defaultClass, $class_name);
}
else
{
$this->class_alias('F0FTable', $class_name, true);
}
}
}
/**
* Autoload Helpers
*
* @param string $class_name The name of the class to load
*
* @return void
*/
public function autoload_fof_helper($class_name)
{
F0FPlatform::getInstance()->logDebug(__METHOD__ . "() autoloading $class_name");
static $isCli = null, $isAdmin = null;
if (is_null($isCli) && is_null($isAdmin))
{
list($isCli, $isAdmin) = F0FDispatcher::isCliAdmin();
}
if (strpos($class_name, 'Helper') === false)
{
return;
}
// Change from camel cased into a lowercase array
$class_modified = preg_replace('/(\s)+/', '_', $class_name);
$class_modified = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $class_modified));
$parts = explode('_', $class_modified);
// We need three parts in the name
if (count($parts) != 3)
{
return;
}
// We need the second part to be "model"
if ($parts[1] != 'helper')
{
return;
}
// Get the information about this class
$component_raw = $parts[0];
$component = 'com_' . $parts[0];
$view = $parts[2];
// Is this an F0F 2.1 or later component?
if (!$this->isF0FComponent($component))
{
return;
}
// Get the alternate view and class name (opposite singular/plural name)
$alt_view = F0FInflector::isSingular($view) ? F0FInflector::pluralize($view) : F0FInflector::singularize($view);
$alt_class = F0FInflector::camelize($component_raw . '_helper_' . $alt_view);
// Get the proper and alternate paths and file names
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($component);
$file = "/helpers/$view.php";
$altFile = "/helpers/$alt_view.php";
$path = $componentPaths['main'];
$altPath = $componentPaths['alt'];
// Try to find the proper class in the proper path
if (file_exists($path . $file))
{
@include_once $path . $file;
}
// Try to find the proper class in the alternate path
if (!class_exists($class_name) && file_exists($altPath . $file))
{
@include_once $altPath . $file;
}
// Try to find the alternate class in the proper path
if (!class_exists($alt_class) && file_exists($path . $altFile))
{
@include_once $path . $altFile;
}
// Try to find the alternate class in the alternate path
if (!class_exists($alt_class) && file_exists($altPath . $altFile))
{
@include_once $altPath . $altFile;
}
// If the alternate class exists just map the class to the alternate
if (!class_exists($class_name) && class_exists($alt_class))
{
$this->class_alias($alt_class, $class_name);
}
}
/**
* Autoload Toolbars
*
* @param string $class_name The name of the class to load
*
* @return void
*/
public function autoload_fof_toolbar($class_name)
{
F0FPlatform::getInstance()->logDebug(__METHOD__ . "() autoloading $class_name");
static $isCli = null, $isAdmin = null;
if (is_null($isCli) && is_null($isAdmin))
{
list($isCli, $isAdmin) = F0FDispatcher::isCliAdmin();
}
if (strpos($class_name, 'Toolbar') === false)
{
return;
}
// Change from camel cased into a lowercase array
$class_modified = preg_replace('/(\s)+/', '_', $class_name);
$class_modified = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $class_modified));
$parts = explode('_', $class_modified);
// We need two parts in the name
if (count($parts) != 2)
{
return;
}
// We need the second part to be "model"
if ($parts[1] != 'toolbar')
{
return;
}
// Get the information about this class
$component_raw = $parts[0];
$component = 'com_' . $parts[0];
$platformDirs = F0FPlatform::getInstance()->getPlatformBaseDirs();
// Get the proper and alternate paths and file names
$file = "/components/$component/toolbar.php";
$path = ($isAdmin || $isCli) ? $platformDirs['admin'] : $platformDirs['public'];
$altPath = ($isAdmin || $isCli) ? $platformDirs['public'] : $platformDirs['admin'];
// Try to find the proper class in the proper path
if (file_exists($path . $file))
{
@include_once $path . $file;
}
// Try to find the proper class in the alternate path
if (!class_exists($class_name) && file_exists($altPath . $file))
{
@include_once $altPath . $file;
}
// No class found? Map to F0FToolbar
if (!class_exists($class_name))
{
$this->class_alias('F0FToolbar', $class_name, true);
}
}
/**
* Autoload Fields
*
* @param string $class_name The name of the class to load
*
* @return void
*/
public function autoload_fof_field($class_name)
{
F0FPlatform::getInstance()->logDebug(__METHOD__ . "() autoloading $class_name");
// @todo
}
}

View File

@ -0,0 +1,116 @@
<?php
/**
* @package FrameworkOnFramework
* @subpackage autoloader
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2, or later
*/
defined('F0F_INCLUDED') or die();
/**
* The main class autoloader for F0F itself
*
* @package FrameworkOnFramework
* @subpackage autoloader
* @since 2.1
*/
class F0FAutoloaderFof
{
/**
* An instance of this autoloader
*
* @var F0FAutoloaderFof
*/
public static $autoloader = null;
/**
* The path to the F0F root directory
*
* @var string
*/
public static $fofPath = null;
/**
* Initialise this autoloader
*
* @return F0FAutoloaderFof
*/
public static function init()
{
if (self::$autoloader == null)
{
self::$autoloader = new self;
}
return self::$autoloader;
}
/**
* Public constructor. Registers the autoloader with PHP.
*/
public function __construct()
{
self::$fofPath = realpath(__DIR__ . '/../');
spl_autoload_register(array($this,'autoload_fof_core'));
}
/**
* The actual autoloader
*
* @param string $class_name The name of the class to load
*
* @return void
*/
public function autoload_fof_core($class_name)
{
// Make sure the class has a F0F prefix
if (substr($class_name, 0, 3) != 'F0F')
{
return;
}
// Remove the prefix
$class = substr($class_name, 3);
// Change from camel cased (e.g. ViewHtml) into a lowercase array (e.g. 'view','html')
$class = preg_replace('/(\s)+/', '_', $class);
$class = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $class));
$class = explode('_', $class);
// First try finding in structured directory format (preferred)
$path = self::$fofPath . '/' . implode('/', $class) . '.php';
if (@file_exists($path))
{
include_once $path;
}
// Then try the duplicate last name structured directory format (not recommended)
if (!class_exists($class_name, false))
{
reset($class);
$lastPart = end($class);
$path = self::$fofPath . '/' . implode('/', $class) . '/' . $lastPart . '.php';
if (@file_exists($path))
{
include_once $path;
}
}
// If it still fails, try looking in the legacy folder (used for backwards compatibility)
if (!class_exists($class_name, false))
{
$path = self::$fofPath . '/legacy/' . implode('/', $class) . '.php';
if (@file_exists($path))
{
include_once $path;
}
}
}
}

View File

@ -0,0 +1,74 @@
<?php
/**
* @package FrameworkOnFramework
* @subpackage config
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2, or later
*/
defined('F0F_INCLUDED') or die();
/**
* Configuration parser for the dispatcher-specific settings
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FConfigDomainDispatcher implements F0FConfigDomainInterface
{
/**
* Parse the XML data, adding them to the $ret array
*
* @param SimpleXMLElement $xml The XML data of the component's configuration area
* @param array &$ret The parsed data, in the form of a hash array
*
* @return void
*/
public function parseDomain(SimpleXMLElement $xml, array &$ret)
{
// Initialise
$ret['dispatcher'] = array();
// Parse the dispatcher configuration
$dispatcherData = $xml->dispatcher;
// Sanity check
if (empty($dispatcherData))
{
return;
}
$options = $xml->xpath('dispatcher/option');
if (!empty($options))
{
foreach ($options as $option)
{
$key = (string) $option['name'];
$ret['dispatcher'][$key] = (string) $option;
}
}
}
/**
* Return a configuration variable
*
* @param string &$configuration Configuration variables (hashed array)
* @param string $var The variable we want to fetch
* @param mixed $default Default value
*
* @return mixed The variable's value
*/
public function get(&$configuration, $var, $default)
{
if (isset($configuration['dispatcher'][$var]))
{
return $configuration['dispatcher'][$var];
}
else
{
return $default;
}
}
}

View File

@ -0,0 +1,41 @@
<?php
/**
* @package FrameworkOnFramework
* @subpackage config
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2, or later
*/
defined('F0F_INCLUDED') or die();
/**
* The Interface of an F0FConfigDomain class. The methods are used to parse and
* privision sensible information to consumers. F0FConfigProvider acts as an
* adapter to the F0FConfigDomain classes.
*
* @package FrameworkOnFramework
* @since 2.1
*/
interface F0FConfigDomainInterface
{
/**
* Parse the XML data, adding them to the $ret array
*
* @param SimpleXMLElement $xml The XML data of the component's configuration area
* @param array &$ret The parsed data, in the form of a hash array
*
* @return void
*/
public function parseDomain(SimpleXMLElement $xml, array &$ret);
/**
* Return a configuration variable
*
* @param string &$configuration Configuration variables (hashed array)
* @param string $var The variable we want to fetch
* @param mixed $default Default value
*
* @return mixed The variable's value
*/
public function get(&$configuration, $var, $default);
}

View File

@ -0,0 +1,262 @@
<?php
/**
* @package FrameworkOnFramework
* @subpackage config
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2, or later
*/
defined('F0F_INCLUDED') or die();
/**
* Configuration parser for the tables-specific settings
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FConfigDomainTables implements F0FConfigDomainInterface
{
/**
* Parse the XML data, adding them to the $ret array
*
* @param SimpleXMLElement $xml The XML data of the component's configuration area
* @param array &$ret The parsed data, in the form of a hash array
*
* @return void
*/
public function parseDomain(SimpleXMLElement $xml, array &$ret)
{
// Initialise
$ret['tables'] = array();
// Parse table configuration
$tableData = $xml->xpath('table');
// Sanity check
if (empty($tableData))
{
return;
}
foreach ($tableData as $aTable)
{
$key = (string) $aTable['name'];
$ret['tables'][$key]['behaviors'] = (string) $aTable->behaviors;
$ret['tables'][$key]['tablealias'] = $aTable->xpath('tablealias');
$ret['tables'][$key]['fields'] = array();
$ret['tables'][$key]['relations'] = array();
$fieldData = $aTable->xpath('field');
if (!empty($fieldData))
{
foreach ($fieldData as $field)
{
$k = (string) $field['name'];
$ret['tables'][$key]['fields'][$k] = (string) $field;
}
}
$relationsData = $aTable->xpath('relation');
if (!empty($relationsData))
{
foreach ($relationsData as $relationData)
{
$type = (string)$relationData['type'];
$itemName = (string)$relationData['name'];
if (empty($type) || empty($itemName))
{
continue;
}
$tableClass = (string)$relationData['tableClass'];
$localKey = (string)$relationData['localKey'];
$remoteKey = (string)$relationData['remoteKey'];
$ourPivotKey = (string)$relationData['ourPivotKey'];
$theirPivotKey = (string)$relationData['theirPivotKey'];
$pivotTable = (string)$relationData['pivotTable'];
$default = (string)$relationData['default'];
$default = !in_array($default, array('no', 'false', 0));
$relation = array(
'type' => $type,
'itemName' => $itemName,
'tableClass' => empty($tableClass) ? null : $tableClass,
'localKey' => empty($localKey) ? null : $localKey,
'remoteKey' => empty($remoteKey) ? null : $remoteKey,
'default' => $default,
);
if (!empty($ourPivotKey) || !empty($theirPivotKey) || !empty($pivotTable))
{
$relation['ourPivotKey'] = empty($ourPivotKey) ? null : $ourPivotKey;
$relation['theirPivotKey'] = empty($theirPivotKey) ? null : $theirPivotKey;
$relation['pivotTable'] = empty($pivotTable) ? null : $pivotTable;
}
$ret['tables'][$key]['relations'][] = $relation;
}
}
}
}
/**
* Return a configuration variable
*
* @param string &$configuration Configuration variables (hashed array)
* @param string $var The variable we want to fetch
* @param mixed $default Default value
*
* @return mixed The variable's value
*/
public function get(&$configuration, $var, $default)
{
$parts = explode('.', $var);
$view = $parts[0];
$method = 'get' . ucfirst($parts[1]);
if (!method_exists($this, $method))
{
return $default;
}
array_shift($parts);
array_shift($parts);
$ret = $this->$method($view, $configuration, $parts, $default);
return $ret;
}
/**
* Internal method to return the magic field mapping
*
* @param string $table The table for which we will be fetching a field map
* @param array &$configuration The configuration parameters hash array
* @param array $params Extra options; key 0 defines the table we want to fetch
* @param string $default Default magic field mapping; empty if not defined
*
* @return array Field map
*/
protected function getField($table, &$configuration, $params, $default = '')
{
$fieldmap = array();
if (isset($configuration['tables']['*']) && isset($configuration['tables']['*']['fields']))
{
$fieldmap = $configuration['tables']['*']['fields'];
}
if (isset($configuration['tables'][$table]) && isset($configuration['tables'][$table]['fields']))
{
$fieldmap = array_merge($fieldmap, $configuration['tables'][$table]['fields']);
}
$map = $default;
if (empty($params[0]))
{
$map = $fieldmap;
}
elseif (isset($fieldmap[$params[0]]))
{
$map = $fieldmap[$params[0]];
}
return $map;
}
/**
* Internal method to get table alias
*
* @param string $table The table for which we will be fetching table alias
* @param array &$configuration The configuration parameters hash array
* @param array $params Extra options; key 0 defines the table we want to fetch
* @param string $default Default table alias
*
* @return string Table alias
*/
protected function getTablealias($table, &$configuration, $params, $default = '')
{
$tablealias = $default;
if (isset($configuration['tables']['*'])
&& isset($configuration['tables']['*']['tablealias'])
&& isset($configuration['tables']['*']['tablealias'][0]))
{
$tablealias = (string) $configuration['tables']['*']['tablealias'][0];
}
if (isset($configuration['tables'][$table])
&& isset($configuration['tables'][$table]['tablealias'])
&& isset($configuration['tables'][$table]['tablealias'][0]))
{
$tablealias = (string) $configuration['tables'][$table]['tablealias'][0];
}
return $tablealias;
}
/**
* Internal method to get table behaviours
*
* @param string $table The table for which we will be fetching table alias
* @param array &$configuration The configuration parameters hash array
* @param array $params Extra options; key 0 defines the table we want to fetch
* @param string $default Default table alias
*
* @return string Table behaviours
*/
protected function getBehaviors($table, &$configuration, $params, $default = '')
{
$behaviors = $default;
if (isset($configuration['tables']['*'])
&& isset($configuration['tables']['*']['behaviors']))
{
$behaviors = (string) $configuration['tables']['*']['behaviors'];
}
if (isset($configuration['tables'][$table])
&& isset($configuration['tables'][$table]['behaviors']))
{
$behaviors = (string) $configuration['tables'][$table]['behaviors'];
}
return $behaviors;
}
/**
* Internal method to get table relations
*
* @param string $table The table for which we will be fetching table alias
* @param array &$configuration The configuration parameters hash array
* @param array $params Extra options; key 0 defines the table we want to fetch
* @param string $default Default table alias
*
* @return array Table relations
*/
protected function getRelations($table, &$configuration, $params, $default = '')
{
$relations = $default;
if (isset($configuration['tables']['*'])
&& isset($configuration['tables']['*']['relations']))
{
$relations = $configuration['tables']['*']['relations'];
}
if (isset($configuration['tables'][$table])
&& isset($configuration['tables'][$table]['relations']))
{
$relations = $configuration['tables'][$table]['relations'];
}
return $relations;
}
}

View File

@ -0,0 +1,302 @@
<?php
/**
* @package FrameworkOnFramework
* @subpackage config
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2, or later
*/
defined('F0F_INCLUDED') or die();
/**
* Configuration parser for the view-specific settings
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FConfigDomainViews implements F0FConfigDomainInterface
{
/**
* Parse the XML data, adding them to the $ret array
*
* @param SimpleXMLElement $xml The XML data of the component's configuration area
* @param array &$ret The parsed data, in the form of a hash array
*
* @return void
*/
public function parseDomain(SimpleXMLElement $xml, array &$ret)
{
// Initialise
$ret['views'] = array();
// Parse view configuration
$viewData = $xml->xpath('view');
// Sanity check
if (empty($viewData))
{
return;
}
foreach ($viewData as $aView)
{
$key = (string) $aView['name'];
// Parse ACL options
$ret['views'][$key]['acl'] = array();
$aclData = $aView->xpath('acl/task');
if (!empty($aclData))
{
foreach ($aclData as $acl)
{
$k = (string) $acl['name'];
$ret['views'][$key]['acl'][$k] = (string) $acl;
}
}
// Parse taskmap
$ret['views'][$key]['taskmap'] = array();
$taskmapData = $aView->xpath('taskmap/task');
if (!empty($taskmapData))
{
foreach ($taskmapData as $map)
{
$k = (string) $map['name'];
$ret['views'][$key]['taskmap'][$k] = (string) $map;
}
}
// Parse controller configuration
$ret['views'][$key]['config'] = array();
$optionData = $aView->xpath('config/option');
if (!empty($optionData))
{
foreach ($optionData as $option)
{
$k = (string) $option['name'];
$ret['views'][$key]['config'][$k] = (string) $option;
}
}
// Parse the toolbar
$ret['views'][$key]['toolbar'] = array();
$toolBars = $aView->xpath('toolbar');
if (!empty($toolBars))
{
foreach ($toolBars as $toolBar)
{
$taskName = isset($toolBar['task']) ? (string) $toolBar['task'] : '*';
// If a toolbar title is specified, create a title element.
if (isset($toolBar['title']))
{
$ret['views'][$key]['toolbar'][$taskName]['title'] = array(
'value' => (string) $toolBar['title']
);
}
// Parse the toolbar buttons data
$toolbarData = $toolBar->xpath('button');
if (!empty($toolbarData))
{
foreach ($toolbarData as $button)
{
$k = (string) $button['type'];
$ret['views'][$key]['toolbar'][$taskName][$k] = current($button->attributes());
$ret['views'][$key]['toolbar'][$taskName][$k]['value'] = (string) $button;
}
}
}
}
}
}
/**
* Return a configuration variable
*
* @param string &$configuration Configuration variables (hashed array)
* @param string $var The variable we want to fetch
* @param mixed $default Default value
*
* @return mixed The variable's value
*/
public function get(&$configuration, $var, $default)
{
$parts = explode('.', $var);
$view = $parts[0];
$method = 'get' . ucfirst($parts[1]);
if (!method_exists($this, $method))
{
return $default;
}
array_shift($parts);
array_shift($parts);
$ret = $this->$method($view, $configuration, $parts, $default);
return $ret;
}
/**
* Internal function to return the task map for a view
*
* @param string $view The view for which we will be fetching a task map
* @param array &$configuration The configuration parameters hash array
* @param array $params Extra options (not used)
* @param array $default ßDefault task map; empty array if not provided
*
* @return array The task map as a hash array in the format task => method
*/
protected function getTaskmap($view, &$configuration, $params, $default = array())
{
$taskmap = array();
if (isset($configuration['views']['*']) && isset($configuration['views']['*']['taskmap']))
{
$taskmap = $configuration['views']['*']['taskmap'];
}
if (isset($configuration['views'][$view]) && isset($configuration['views'][$view]['taskmap']))
{
$taskmap = array_merge($taskmap, $configuration['views'][$view]['taskmap']);
}
if (empty($taskmap))
{
return $default;
}
return $taskmap;
}
/**
* Internal method to return the ACL mapping (privilege required to access
* a specific task) for the given view's tasks
*
* @param string $view The view for which we will be fetching a task map
* @param array &$configuration The configuration parameters hash array
* @param array $params Extra options; key 0 defines the task we want to fetch
* @param string $default Default ACL option; empty (no ACL check) if not defined
*
* @return string The privilege required to access this view
*/
protected function getAcl($view, &$configuration, $params, $default = '')
{
$aclmap = array();
if (isset($configuration['views']['*']) && isset($configuration['views']['*']['acl']))
{
$aclmap = $configuration['views']['*']['acl'];
}
if (isset($configuration['views'][$view]) && isset($configuration['views'][$view]['acl']))
{
$aclmap = array_merge($aclmap, $configuration['views'][$view]['acl']);
}
$acl = $default;
if (isset($aclmap['*']))
{
$acl = $aclmap['*'];
}
if (isset($aclmap[$params[0]]))
{
$acl = $aclmap[$params[0]];
}
return $acl;
}
/**
* Internal method to return the a configuration option for the view. These
* are equivalent to $config array options passed to the Controller
*
* @param string $view The view for which we will be fetching a task map
* @param array &$configuration The configuration parameters hash array
* @param array $params Extra options; key 0 defines the option variable we want to fetch
* @param mixed $default Default option; null if not defined
*
* @return string The setting for the requested option
*/
protected function getConfig($view, &$configuration, $params, $default = null)
{
$ret = $default;
if (isset($configuration['views']['*'])
&& isset($configuration['views']['*']['config'])
&& isset($configuration['views']['*']['config'][$params[0]]))
{
$ret = $configuration['views']['*']['config'][$params[0]];
}
if (isset($configuration['views'][$view])
&& isset($configuration['views'][$view]['config'])
&& isset($configuration['views'][$view]['config'][$params[0]]))
{
$ret = $configuration['views'][$view]['config'][$params[0]];
}
return $ret;
}
/**
* Internal method to return the toolbar infos.
*
* @param string $view The view for which we will be fetching buttons
* @param array &$configuration The configuration parameters hash array
* @param array $params Extra options
* @param string $default Default option
*
* @return string The toolbar data for this view
*/
protected function getToolbar($view, &$configuration, $params, $default = '')
{
$toolbar = array();
if (isset($configuration['views']['*'])
&& isset($configuration['views']['*']['toolbar'])
&& isset($configuration['views']['*']['toolbar']['*']))
{
$toolbar = $configuration['views']['*']['toolbar']['*'];
}
if (isset($configuration['views']['*'])
&& isset($configuration['views']['*']['toolbar'])
&& isset($configuration['views']['*']['toolbar'][$params[0]]))
{
$toolbar = array_merge($toolbar, $configuration['views']['*']['toolbar'][$params[0]]);
}
if (isset($configuration['views'][$view])
&& isset($configuration['views'][$view]['toolbar'])
&& isset($configuration['views'][$view]['toolbar']['*']))
{
$toolbar = array_merge($toolbar, $configuration['views'][$view]['toolbar']['*']);
}
if (isset($configuration['views'][$view])
&& isset($configuration['views'][$view]['toolbar'])
&& isset($configuration['views'][$view]['toolbar'][$params[0]]))
{
$toolbar = array_merge($toolbar, $configuration['views'][$view]['toolbar'][$params[0]]);
}
if (empty($toolbar))
{
return $default;
}
return $toolbar;
}
}

View File

@ -0,0 +1,212 @@
<?php
/**
* @package FrameworkOnFramework
* @subpackage config
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2, or later
*/
defined('F0F_INCLUDED') or die();
/**
* Reads and parses the fof.xml file in the back-end of a F0F-powered component,
* provisioning the data to the rest of the F0F framework
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FConfigProvider
{
/**
* Cache of F0F components' configuration variables
*
* @var array
*/
public static $configurations = array();
/**
* Parses the configuration of the specified component
*
* @param string $component The name of the component, e.g. com_foobar
* @param boolean $force Force reload even if it's already parsed?
*
* @return void
*/
public function parseComponent($component, $force = false)
{
if (!$force && isset(self::$configurations[$component]))
{
return;
}
if (F0FPlatform::getInstance()->isCli())
{
$order = array('cli', 'backend');
}
elseif (F0FPlatform::getInstance()->isBackend())
{
$order = array('backend');
}
else
{
$order = array('frontend');
}
$order[] = 'common';
$order = array_reverse($order);
self::$configurations[$component] = array();
foreach ($order as $area)
{
$config = $this->parseComponentArea($component, $area);
self::$configurations[$component] = array_merge_recursive(self::$configurations[$component], $config);
}
}
/**
* Returns the value of a variable. Variables use a dot notation, e.g.
* view.config.whatever where the first part is the domain, the rest of the
* parts specify the path to the variable.
*
* @param string $variable The variable name
* @param mixed $default The default value, or null if not specified
*
* @return mixed The value of the variable
*/
public function get($variable, $default = null)
{
static $domains = null;
if (is_null($domains))
{
$domains = $this->getDomains();
}
list($component, $domain, $var) = explode('.', $variable, 3);
if (!isset(self::$configurations[$component]))
{
$this->parseComponent($component);
}
if (!in_array($domain, $domains))
{
return $default;
}
$class = 'F0FConfigDomain' . ucfirst($domain);
$o = new $class;
return $o->get(self::$configurations[$component], $var, $default);
}
/**
* Parses the configuration options of a specific component area
*
* @param string $component Which component's cionfiguration to parse
* @param string $area Which area to parse (frontend, backend, cli)
*
* @return array A hash array with the configuration data
*/
protected function parseComponentArea($component, $area)
{
// Initialise the return array
$ret = array();
// Get the folders of the component
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($component);
$filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem');
// Check that the path exists
$path = $componentPaths['admin'];
$path = $filesystem->pathCheck($path);
if (!$filesystem->folderExists($path))
{
return $ret;
}
// Read the filename if it exists
$filename = $path . '/fof.xml';
if (!$filesystem->fileExists($filename))
{
return $ret;
}
$data = file_get_contents($filename);
// Load the XML data in a SimpleXMLElement object
$xml = simplexml_load_string($data);
if (!($xml instanceof SimpleXMLElement))
{
return $ret;
}
// Get this area's data
$areaData = $xml->xpath('//' . $area);
if (empty($areaData))
{
return $ret;
}
$xml = array_shift($areaData);
// Parse individual configuration domains
$domains = $this->getDomains();
foreach ($domains as $dom)
{
$class = 'F0FConfigDomain' . ucfirst($dom);
if (class_exists($class, true))
{
$o = new $class;
$o->parseDomain($xml, $ret);
}
}
// Finally, return the result
return $ret;
}
/**
* Gets a list of the available configuration domain adapters
*
* @return array A list of the available domains
*/
protected function getDomains()
{
static $domains = array();
if (empty($domains))
{
$filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem');
$files = $filesystem->folderFiles(__DIR__ . '/domain', '.php');
if (!empty($files))
{
foreach ($files as $file)
{
$domain = basename($file, '.php');
if ($domain == 'interface')
{
continue;
}
$domain = preg_replace('/[^A-Za-z0-9]/', '', $domain);
$domains[] = $domain;
}
$domains = array_unique($domains);
}
}
return $domains;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,199 @@
<?php
/**
* @package FrameworkOnFramework
* @subpackage database
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*
* This file is adapted from the Joomla! Platform. It is used to iterate a database cursor returning F0FTable objects
* instead of plain stdClass objects
*/
// Protect from unauthorized access
defined('F0F_INCLUDED') or die;
/**
* Database connector class.
*
* @since 11.1
* @deprecated 13.3 (Platform) & 4.0 (CMS)
*/
abstract class F0FDatabase
{
/**
* Execute the SQL statement.
*
* @return mixed A database cursor resource on success, boolean false on failure.
*
* @since 11.1
* @throws RuntimeException
* @deprecated 13.1 (Platform) & 4.0 (CMS)
*/
public function query()
{
if (class_exists('JLog'))
{
JLog::add('F0FDatabase::query() is deprecated, use F0FDatabaseDriver::execute() instead.', JLog::WARNING, 'deprecated');
}
return $this->execute();
}
/**
* Get a list of available database connectors. The list will only be populated with connectors that both
* the class exists and the static test method returns true. This gives us the ability to have a multitude
* of connector classes that are self-aware as to whether or not they are able to be used on a given system.
*
* @return array An array of available database connectors.
*
* @since 11.1
* @deprecated 13.1 (Platform) & 4.0 (CMS)
*/
public static function getConnectors()
{
if (class_exists('JLog'))
{
JLog::add('F0FDatabase::getConnectors() is deprecated, use F0FDatabaseDriver::getConnectors() instead.', JLog::WARNING, 'deprecated');
}
return F0FDatabaseDriver::getConnectors();
}
/**
* Gets the error message from the database connection.
*
* @param boolean $escaped True to escape the message string for use in JavaScript.
*
* @return string The error message for the most recent query.
*
* @deprecated 13.3 (Platform) & 4.0 (CMS)
* @since 11.1
*/
public function getErrorMsg($escaped = false)
{
if (class_exists('JLog'))
{
JLog::add('F0FDatabase::getErrorMsg() is deprecated, use exception handling instead.', JLog::WARNING, 'deprecated');
}
if ($escaped)
{
return addslashes($this->errorMsg);
}
else
{
return $this->errorMsg;
}
}
/**
* Gets the error number from the database connection.
*
* @return integer The error number for the most recent query.
*
* @since 11.1
* @deprecated 13.3 (Platform) & 4.0 (CMS)
*/
public function getErrorNum()
{
if (class_exists('JLog'))
{
JLog::add('F0FDatabase::getErrorNum() is deprecated, use exception handling instead.', JLog::WARNING, 'deprecated');
}
return $this->errorNum;
}
/**
* Method to return a F0FDatabaseDriver instance based on the given options. There are three global options and then
* the rest are specific to the database driver. The 'driver' option defines which F0FDatabaseDriver class is
* used for the connection -- the default is 'mysqli'. The 'database' option determines which database is to
* be used for the connection. The 'select' option determines whether the connector should automatically select
* the chosen database.
*
* Instances are unique to the given options and new objects are only created when a unique options array is
* passed into the method. This ensures that we don't end up with unnecessary database connection resources.
*
* @param array $options Parameters to be passed to the database driver.
*
* @return F0FDatabaseDriver A database object.
*
* @since 11.1
* @deprecated 13.1 (Platform) & 4.0 (CMS)
*/
public static function getInstance($options = array())
{
if (class_exists('JLog'))
{
JLog::add('F0FDatabase::getInstance() is deprecated, use F0FDatabaseDriver::getInstance() instead.', JLog::WARNING, 'deprecated');
}
return F0FDatabaseDriver::getInstance($options);
}
/**
* Splits a string of multiple queries into an array of individual queries.
*
* @param string $query Input SQL string with which to split into individual queries.
*
* @return array The queries from the input string separated into an array.
*
* @since 11.1
* @deprecated 13.1 (Platform) & 4.0 (CMS)
*/
public static function splitSql($query)
{
if (class_exists('JLog'))
{
JLog::add('F0FDatabase::splitSql() is deprecated, use F0FDatabaseDriver::splitSql() instead.', JLog::WARNING, 'deprecated');
}
return F0FDatabaseDriver::splitSql($query);
}
/**
* Return the most recent error message for the database connector.
*
* @param boolean $showSQL True to display the SQL statement sent to the database as well as the error.
*
* @return string The error message for the most recent query.
*
* @since 11.1
* @deprecated 13.3 (Platform) & 4.0 (CMS)
*/
public function stderr($showSQL = false)
{
if (class_exists('JLog'))
{
JLog::add('F0FDatabase::stderr() is deprecated.', JLog::WARNING, 'deprecated');
}
if ($this->errorNum != 0)
{
return JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $this->errorNum, $this->errorMsg)
. ($showSQL ? "<br />SQL = <pre>$this->sql</pre>" : '');
}
else
{
return JText::_('JLIB_DATABASE_FUNCTION_NOERROR');
}
}
/**
* Test to see if the connector is available.
*
* @return boolean True on success, false otherwise.
*
* @since 11.1
* @deprecated 12.3 (Platform) & 4.0 (CMS) - Use F0FDatabaseDriver::isSupported() instead.
*/
public static function test()
{
if (class_exists('JLog'))
{
JLog::add('F0FDatabase::test() is deprecated. Use F0FDatabaseDriver::isSupported() instead.', JLog::WARNING, 'deprecated');
}
return static::isSupported();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,778 @@
<?php
/**
* @package FrameworkOnFramework
* @subpackage database
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*
* This file is adapted from the Joomla! Platform. It is used to iterate a database cursor returning F0FTable objects
* instead of plain stdClass objects
*/
// Protect from unauthorized access
defined('F0F_INCLUDED') or die;
/**
* This crazy three line bit is required to convince Joomla! to load JDatabaseInterface which is on the same file as the
* abstract JDatabaseDriver class for reasons that beat me. It makes no sense. Furthermore, jimport on Joomla! 3.4
* doesn't seem to actually load the file, merely registering the association in the autoloader. Hence the class_exists
* in here.
*/
jimport('joomla.database.driver');
jimport('joomla.database.driver.mysqli');
class_exists('JDatabaseDriver', true);
/**
* Joomla! pass-through database driver.
*/
class F0FDatabaseDriverJoomla extends F0FDatabase implements F0FDatabaseInterface
{
/** @var F0FDatabase The real database connection object */
private $dbo;
/**
* @var string The character(s) used to quote SQL statement names such as table names or field names,
* etc. The child classes should define this as necessary. If a single character string the
* same character is used for both sides of the quoted name, else the first character will be
* used for the opening quote and the second for the closing quote.
* @since 11.1
*/
protected $nameQuote = '';
/**
* Is this driver supported
*
* @since 11.2
*/
public static function isSupported()
{
return true;
}
/**
* Database object constructor
*
* @param array $options List of options used to configure the connection
*/
public function __construct($options = array())
{
// Get best matching Akeeba Backup driver instance
$this->dbo = JFactory::getDbo();
$reflection = new ReflectionClass($this->dbo);
try
{
$refProp = $reflection->getProperty('nameQuote');
$refProp->setAccessible(true);
$this->nameQuote = $refProp->getValue($this->dbo);
}
catch (Exception $e)
{
$this->nameQuote = '`';
}
}
public function close()
{
if (method_exists($this->dbo, 'close'))
{
$this->dbo->close();
}
elseif (method_exists($this->dbo, 'disconnect'))
{
$this->dbo->disconnect();
}
}
public function disconnect()
{
$this->close();
}
public function open()
{
if (method_exists($this->dbo, 'open'))
{
$this->dbo->open();
}
elseif (method_exists($this->dbo, 'connect'))
{
$this->dbo->connect();
}
}
public function connect()
{
$this->open();
}
public function connected()
{
if (method_exists($this->dbo, 'connected'))
{
return $this->dbo->connected();
}
return true;
}
public function escape($text, $extra = false)
{
return $this->dbo->escape($text, $extra);
}
public function execute()
{
if (method_exists($this->dbo, 'execute'))
{
return $this->dbo->execute();
}
return $this->dbo->query();
}
public function getAffectedRows()
{
if (method_exists($this->dbo, 'getAffectedRows'))
{
return $this->dbo->getAffectedRows();
}
return 0;
}
public function getCollation()
{
if (method_exists($this->dbo, 'getCollation'))
{
return $this->dbo->getCollation();
}
return 'utf8_general_ci';
}
public function getConnection()
{
if (method_exists($this->dbo, 'getConnection'))
{
return $this->dbo->getConnection();
}
return null;
}
public function getCount()
{
if (method_exists($this->dbo, 'getCount'))
{
return $this->dbo->getCount();
}
return 0;
}
public function getDateFormat()
{
if (method_exists($this->dbo, 'getDateFormat'))
{
return $this->dbo->getDateFormat();
}
return 'Y-m-d H:i:s';;
}
public function getMinimum()
{
if (method_exists($this->dbo, 'getMinimum'))
{
return $this->dbo->getMinimum();
}
return '5.0.40';
}
public function getNullDate()
{
if (method_exists($this->dbo, 'getNullDate'))
{
return $this->dbo->getNullDate();
}
return '0000-00-00 00:00:00';
}
public function getNumRows($cursor = null)
{
if (method_exists($this->dbo, 'getNumRows'))
{
return $this->dbo->getNumRows($cursor);
}
return 0;
}
public function getQuery($new = false)
{
if (method_exists($this->dbo, 'getQuery'))
{
return $this->dbo->getQuery($new);
}
return null;
}
public function getTableColumns($table, $typeOnly = true)
{
if (method_exists($this->dbo, 'getTableColumns'))
{
return $this->dbo->getTableColumns($table, $typeOnly);
}
$result = $this->dbo->getTableFields(array($table), $typeOnly);
return $result[$table];
}
public function getTableKeys($tables)
{
if (method_exists($this->dbo, 'getTableKeys'))
{
return $this->dbo->getTableKeys($tables);
}
return array();
}
public function getTableList()
{
if (method_exists($this->dbo, 'getTableList'))
{
return $this->dbo->getTableList();
}
return array();
}
public function getVersion()
{
if (method_exists($this->dbo, 'getVersion'))
{
return $this->dbo->getVersion();
}
return '5.0.40';
}
public function insertid()
{
if (method_exists($this->dbo, 'insertid'))
{
return $this->dbo->insertid();
}
return null;
}
public function insertObject($table, &$object, $key = null)
{
if (method_exists($this->dbo, 'insertObject'))
{
return $this->dbo->insertObject($table, $object, $key);
}
return null;
}
public function loadAssoc()
{
if (method_exists($this->dbo, 'loadAssoc'))
{
return $this->dbo->loadAssoc();
}
return null;
}
public function loadAssocList($key = null, $column = null)
{
if (method_exists($this->dbo, 'loadAssocList'))
{
return $this->dbo->loadAssocList($key, $column);
}
return null;
}
public function loadObject($class = 'stdClass')
{
if (method_exists($this->dbo, 'loadObject'))
{
return $this->dbo->loadObject($class);
}
return null;
}
public function loadObjectList($key = '', $class = 'stdClass')
{
if (method_exists($this->dbo, 'loadObjectList'))
{
return $this->dbo->loadObjectList($key, $class);
}
return null;
}
public function loadResult()
{
if (method_exists($this->dbo, 'loadResult'))
{
return $this->dbo->loadResult();
}
return null;
}
public function loadRow()
{
if (method_exists($this->dbo, 'loadRow'))
{
return $this->dbo->loadRow();
}
return null;
}
public function loadRowList($key = null)
{
if (method_exists($this->dbo, 'loadRowList'))
{
return $this->dbo->loadRowList($key);
}
return null;
}
public function lockTable($tableName)
{
if (method_exists($this->dbo, 'lockTable'))
{
return $this->dbo->lockTable($this);
}
return $this;
}
public function quote($text, $escape = true)
{
if (method_exists($this->dbo, 'quote'))
{
return $this->dbo->quote($text, $escape);
}
return $text;
}
public function select($database)
{
if (method_exists($this->dbo, 'select'))
{
return $this->dbo->select($database);
}
return false;
}
public function setQuery($query, $offset = 0, $limit = 0)
{
if (method_exists($this->dbo, 'setQuery'))
{
return $this->dbo->setQuery($query, $offset, $limit);
}
return false;
}
public function transactionCommit($toSavepoint = false)
{
if (method_exists($this->dbo, 'transactionCommit'))
{
$this->dbo->transactionCommit($toSavepoint);
}
}
public function transactionRollback($toSavepoint = false)
{
if (method_exists($this->dbo, 'transactionRollback'))
{
$this->dbo->transactionRollback($toSavepoint);
}
}
public function transactionStart($asSavepoint = false)
{
if (method_exists($this->dbo, 'transactionStart'))
{
$this->dbo->transactionStart($asSavepoint);
}
}
public function unlockTables()
{
if (method_exists($this->dbo, 'unlockTables'))
{
return $this->dbo->unlockTables();
}
return $this;
}
public function updateObject($table, &$object, $key, $nulls = false)
{
if (method_exists($this->dbo, 'updateObject'))
{
return $this->dbo->updateObject($table, $object, $key, $nulls);
}
return false;
}
public function getLog()
{
if (method_exists($this->dbo, 'getLog'))
{
return $this->dbo->getLog();
}
return array();
}
public function dropTable($table, $ifExists = true)
{
if (method_exists($this->dbo, 'dropTable'))
{
return $this->dbo->dropTable($table, $ifExists);
}
return $this;
}
public function getTableCreate($tables)
{
if (method_exists($this->dbo, 'getTableCreate'))
{
return $this->dbo->getTableCreate($tables);
}
return array();
}
public function renameTable($oldTable, $newTable, $backup = null, $prefix = null)
{
if (method_exists($this->dbo, 'renameTable'))
{
return $this->dbo->renameTable($oldTable, $newTable, $backup, $prefix);
}
return $this;
}
public function setUtf()
{
if (method_exists($this->dbo, 'setUtf'))
{
return $this->dbo->setUtf();
}
return false;
}
protected function freeResult($cursor = null)
{
return false;
}
/**
* Method to get an array of values from the <var>$offset</var> field in each row of the result set from
* the database query.
*
* @param integer $offset The row offset to use to build the result array.
*
* @return mixed The return value or null if the query failed.
*
* @since 11.1
* @throws RuntimeException
*/
public function loadColumn($offset = 0)
{
if (method_exists($this->dbo, 'loadColumn'))
{
return $this->dbo->loadColumn($offset);
}
return $this->dbo->loadResultArray($offset);
}
/**
* Wrap an SQL statement identifier name such as column, table or database names in quotes to prevent injection
* risks and reserved word conflicts.
*
* @param mixed $name The identifier name to wrap in quotes, or an array of identifier names to wrap in quotes.
* Each type supports dot-notation name.
* @param mixed $as The AS query part associated to $name. It can be string or array, in latter case it has to be
* same length of $name; if is null there will not be any AS part for string or array element.
*
* @return mixed The quote wrapped name, same type of $name.
*
* @since 11.1
*/
public function quoteName($name, $as = null)
{
if (is_string($name))
{
$quotedName = $this->quoteNameStr(explode('.', $name));
$quotedAs = '';
if (!is_null($as))
{
settype($as, 'array');
$quotedAs .= ' AS ' . $this->quoteNameStr($as);
}
return $quotedName . $quotedAs;
}
else
{
$fin = array();
if (is_null($as))
{
foreach ($name as $str)
{
$fin[] = $this->quoteName($str);
}
}
elseif (is_array($name) && (count($name) == count($as)))
{
$count = count($name);
for ($i = 0; $i < $count; $i++)
{
$fin[] = $this->quoteName($name[$i], $as[$i]);
}
}
return $fin;
}
}
/**
* Quote strings coming from quoteName call.
*
* @param array $strArr Array of strings coming from quoteName dot-explosion.
*
* @return string Dot-imploded string of quoted parts.
*
* @since 11.3
*/
protected function quoteNameStr($strArr)
{
$parts = array();
$q = $this->nameQuote;
foreach ($strArr as $part)
{
if (is_null($part))
{
continue;
}
if (strlen($q) == 1)
{
$parts[] = $q . $part . $q;
}
else
{
$parts[] = $q{0} . $part . $q{1};
}
}
return implode('.', $parts);
}
/**
* Gets the error message from the database connection.
*
* @param boolean $escaped True to escape the message string for use in JavaScript.
*
* @return string The error message for the most recent query.
*
* @since 11.1
*/
public function getErrorMsg($escaped = false)
{
if (method_exists($this->dbo, 'getErrorMsg'))
{
$errorMessage = $this->dbo->getErrorMsg();
}
else
{
$errorMessage = $this->errorMsg;
}
if ($escaped)
{
return addslashes($errorMessage);
}
return $errorMessage;
}
/**
* Gets the error number from the database connection.
*
* @return integer The error number for the most recent query.
*
* @since 11.1
* @deprecated 13.3 (Platform) & 4.0 (CMS)
*/
public function getErrorNum()
{
if (method_exists($this->dbo, 'getErrorNum'))
{
$errorNum = $this->dbo->getErrorNum();
}
else
{
$errorNum = $this->getErrorNum;
}
return $errorNum;
}
/**
* Return the most recent error message for the database connector.
*
* @param boolean $showSQL True to display the SQL statement sent to the database as well as the error.
*
* @return string The error message for the most recent query.
*/
public function stderr($showSQL = false)
{
if (method_exists($this->dbo, 'stderr'))
{
return $this->dbo->stderr($showSQL);
}
return parent::stderr($showSQL);
}
/**
* Magic method to proxy all calls to the loaded database driver object
*/
public function __call($name, array $arguments)
{
if (is_null($this->dbo))
{
throw new Exception('F0F database driver is not loaded');
}
if (method_exists($this->dbo, $name) || in_array($name, array('q', 'nq', 'qn', 'query')))
{
switch ($name)
{
case 'execute':
$name = 'query';
break;
case 'q':
$name = 'quote';
break;
case 'qn':
case 'nq':
switch (count($arguments))
{
case 0 :
$result = $this->quoteName();
break;
case 1 :
$result = $this->quoteName($arguments[0]);
break;
case 2:
default:
$result = $this->quoteName($arguments[0], $arguments[1]);
break;
}
return $result;
break;
}
switch (count($arguments))
{
case 0 :
$result = $this->dbo->$name();
break;
case 1 :
$result = $this->dbo->$name($arguments[0]);
break;
case 2:
$result = $this->dbo->$name($arguments[0], $arguments[1]);
break;
case 3:
$result = $this->dbo->$name($arguments[0], $arguments[1], $arguments[2]);
break;
case 4:
$result = $this->dbo->$name($arguments[0], $arguments[1], $arguments[2], $arguments[3]);
break;
case 5:
$result = $this->dbo->$name($arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4]);
break;
default:
// Resort to using call_user_func_array for many segments
$result = call_user_func_array(array($this->dbo, $name), $arguments);
}
if (class_exists('JDatabase') && is_object($result) && ($result instanceof JDatabase))
{
return $this;
}
return $result;
}
else
{
throw new \Exception('Method ' . $name . ' not found in F0FDatabase');
}
}
public function __get($name)
{
if (isset($this->dbo->$name) || property_exists($this->dbo, $name))
{
return $this->dbo->$name;
}
else
{
$this->dbo->$name = null;
user_error('Database driver does not support property ' . $name);
}
}
public function __set($name, $value)
{
if (isset($this->dbo->name) || property_exists($this->dbo, $name))
{
$this->dbo->$name = $value;
}
else
{
$this->dbo->$name = null;
user_error('Database driver not support property ' . $name);
}
}
}

View File

@ -0,0 +1,577 @@
<?php
/**
* @package FrameworkOnFramework
* @subpackage database
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*
* This file is adapted from the Joomla! Platform. It is used to iterate a database cursor returning F0FTable objects
* instead of plain stdClass objects
*/
// Protect from unauthorized access
defined('F0F_INCLUDED') or die;
/**
* MySQL database driver
*
* @see http://dev.mysql.com/doc/
* @since 12.1
* @deprecated Will be removed when the minimum supported PHP version no longer includes the deprecated PHP `mysql` extension
*/
class F0FDatabaseDriverMysql extends F0FDatabaseDriverMysqli
{
/**
* The name of the database driver.
*
* @var string
* @since 12.1
*/
public $name = 'mysql';
/**
* Constructor.
*
* @param array $options Array of database options with keys: host, user, password, database, select.
*
* @since 12.1
*/
public function __construct($options)
{
// PHP's `mysql` extension is not present in PHP 7, block instantiation in this environment
if (PHP_MAJOR_VERSION >= 7)
{
throw new RuntimeException(
'This driver is unsupported in PHP 7, please use the MySQLi or PDO MySQL driver instead.'
);
}
// Get some basic values from the options.
$options['host'] = (isset($options['host'])) ? $options['host'] : 'localhost';
$options['user'] = (isset($options['user'])) ? $options['user'] : 'root';
$options['password'] = (isset($options['password'])) ? $options['password'] : '';
$options['database'] = (isset($options['database'])) ? $options['database'] : '';
$options['select'] = (isset($options['select'])) ? (bool) $options['select'] : true;
// Finalize initialisation.
parent::__construct($options);
}
/**
* Destructor.
*
* @since 12.1
*/
public function __destruct()
{
$this->disconnect();
}
/**
* Connects to the database if needed.
*
* @return void Returns void if the database connected successfully.
*
* @since 12.1
* @throws RuntimeException
*/
public function connect()
{
if ($this->connection)
{
return;
}
// Make sure the MySQL extension for PHP is installed and enabled.
if (!self::isSupported())
{
throw new RuntimeException('Could not connect to MySQL.');
}
// Attempt to connect to the server.
if (!($this->connection = @ mysql_connect($this->options['host'], $this->options['user'], $this->options['password'], true)))
{
throw new RuntimeException('Could not connect to MySQL.');
}
// Set sql_mode to non_strict mode
mysql_query("SET @@SESSION.sql_mode = '';", $this->connection);
// If auto-select is enabled select the given database.
if ($this->options['select'] && !empty($this->options['database']))
{
$this->select($this->options['database']);
}
// Pre-populate the UTF-8 Multibyte compatibility flag based on server version
$this->utf8mb4 = $this->serverClaimsUtf8mb4Support();
// Set the character set (needed for MySQL 4.1.2+).
$this->utf = $this->setUtf();
// Turn MySQL profiling ON in debug mode:
if ($this->debug && $this->hasProfiling())
{
mysql_query("SET profiling = 1;", $this->connection);
}
}
/**
* Disconnects the database.
*
* @return void
*
* @since 12.1
*/
public function disconnect()
{
// Close the connection.
if (is_resource($this->connection))
{
foreach ($this->disconnectHandlers as $h)
{
call_user_func_array($h, array( &$this));
}
mysql_close($this->connection);
}
$this->connection = null;
}
/**
* Method to escape a string for usage in an SQL statement.
*
* @param string $text The string to be escaped.
* @param boolean $extra Optional parameter to provide extra escaping.
*
* @return string The escaped string.
*
* @since 12.1
*/
public function escape($text, $extra = false)
{
$this->connect();
$result = mysql_real_escape_string($text, $this->getConnection());
if ($extra)
{
$result = addcslashes($result, '%_');
}
return $result;
}
/**
* Test to see if the MySQL connector is available.
*
* @return boolean True on success, false otherwise.
*
* @since 12.1
*/
public static function isSupported()
{
return (function_exists('mysql_connect'));
}
/**
* Determines if the connection to the server is active.
*
* @return boolean True if connected to the database engine.
*
* @since 12.1
*/
public function connected()
{
if (is_resource($this->connection))
{
return @mysql_ping($this->connection);
}
return false;
}
/**
* Get the number of affected rows by the last INSERT, UPDATE, REPLACE or DELETE for the previous executed SQL statement.
*
* @return integer The number of affected rows.
*
* @since 12.1
*/
public function getAffectedRows()
{
$this->connect();
return mysql_affected_rows($this->connection);
}
/**
* Get the number of returned rows for the previous executed SQL statement.
* This command is only valid for statements like SELECT or SHOW that return an actual result set.
* To retrieve the number of rows affected by a INSERT, UPDATE, REPLACE or DELETE query, use getAffectedRows().
*
* @param resource $cursor An optional database cursor resource to extract the row count from.
*
* @return integer The number of returned rows.
*
* @since 12.1
*/
public function getNumRows($cursor = null)
{
$this->connect();
return mysql_num_rows($cursor ? $cursor : $this->cursor);
}
/**
* Get the version of the database connector.
*
* @return string The database connector version.
*
* @since 12.1
*/
public function getVersion()
{
$this->connect();
return mysql_get_server_info($this->connection);
}
/**
* Method to get the auto-incremented value from the last INSERT statement.
*
* @return integer The value of the auto-increment field from the last inserted row.
*
* @since 12.1
*/
public function insertid()
{
$this->connect();
return mysql_insert_id($this->connection);
}
/**
* Execute the SQL statement.
*
* @return mixed A database cursor resource on success, boolean false on failure.
*
* @since 12.1
* @throws RuntimeException
*/
public function execute()
{
$this->connect();
if (!is_resource($this->connection))
{
if (class_exists('JLog'))
{
JLog::add(JText::sprintf('JLIB_DATABASE_QUERY_FAILED', $this->errorNum, $this->errorMsg), JLog::ERROR, 'database');
}
throw new RuntimeException($this->errorMsg, $this->errorNum);
}
// Take a local copy so that we don't modify the original query and cause issues later
$query = $this->replacePrefix((string) $this->sql);
if (!($this->sql instanceof F0FDatabaseQuery) && ($this->limit > 0 || $this->offset > 0))
{
$query .= ' LIMIT ' . $this->offset . ', ' . $this->limit;
}
// Increment the query counter.
$this->count++;
// Reset the error values.
$this->errorNum = 0;
$this->errorMsg = '';
// If debugging is enabled then let's log the query.
if ($this->debug)
{
// Add the query to the object queue.
$this->log[] = $query;
if (class_exists('JLog'))
{
JLog::add($query, JLog::DEBUG, 'databasequery');
}
$this->timings[] = microtime(true);
}
// Execute the query. Error suppression is used here to prevent warnings/notices that the connection has been lost.
$this->cursor = @mysql_query($query, $this->connection);
if ($this->debug)
{
$this->timings[] = microtime(true);
if (defined('DEBUG_BACKTRACE_IGNORE_ARGS'))
{
$this->callStacks[] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
}
else
{
$this->callStacks[] = debug_backtrace();
}
}
// If an error occurred handle it.
if (!$this->cursor)
{
// Get the error number and message before we execute any more queries.
$this->errorNum = $this->getErrorNumber();
$this->errorMsg = $this->getErrorMessage($query);
// Check if the server was disconnected.
if (!$this->connected())
{
try
{
// Attempt to reconnect.
$this->connection = null;
$this->connect();
}
// If connect fails, ignore that exception and throw the normal exception.
catch (RuntimeException $e)
{
// Get the error number and message.
$this->errorNum = $this->getErrorNumber();
$this->errorMsg = $this->getErrorMessage($query);
// Throw the normal query exception.
if (class_exists('JLog'))
{
JLog::add(JText::sprintf('JLIB_DATABASE_QUERY_FAILED', $this->errorNum, $this->errorMsg), JLog::ERROR, 'database-error');
}
throw new RuntimeException($this->errorMsg, $this->errorNum, $e);
}
// Since we were able to reconnect, run the query again.
return $this->execute();
}
// The server was not disconnected.
else
{
// Throw the normal query exception.
if (class_exists('JLog'))
{
JLog::add(JText::sprintf('JLIB_DATABASE_QUERY_FAILED', $this->errorNum, $this->errorMsg), JLog::ERROR, 'database-error');
}
throw new RuntimeException($this->errorMsg, $this->errorNum);
}
}
return $this->cursor;
}
/**
* Select a database for use.
*
* @param string $database The name of the database to select for use.
*
* @return boolean True if the database was successfully selected.
*
* @since 12.1
* @throws RuntimeException
*/
public function select($database)
{
$this->connect();
if (!$database)
{
return false;
}
if (!mysql_select_db($database, $this->connection))
{
throw new RuntimeException('Could not connect to database');
}
return true;
}
/**
* Set the connection to use UTF-8 character encoding.
*
* @return boolean True on success.
*
* @since 12.1
*/
public function setUtf()
{
// If UTF is not supported return false immediately
if (!$this->utf)
{
return false;
}
// Make sure we're connected to the server
$this->connect();
// Which charset should I use, plain utf8 or multibyte utf8mb4?
$charset = $this->utf8mb4 ? 'utf8mb4' : 'utf8';
$result = @mysql_set_charset($charset, $this->connection);
/**
* If I could not set the utf8mb4 charset then the server doesn't support utf8mb4 despite claiming otherwise.
* This happens on old MySQL server versions (less than 5.5.3) using the mysqlnd PHP driver. Since mysqlnd
* masks the server version and reports only its own we can not be sure if the server actually does support
* UTF-8 Multibyte (i.e. it's MySQL 5.5.3 or later). Since the utf8mb4 charset is undefined in this case we
* catch the error and determine that utf8mb4 is not supported!
*/
if (!$result && $this->utf8mb4)
{
$this->utf8mb4 = false;
$result = @mysql_set_charset('utf8', $this->connection);
}
return $result;
}
/**
* Method to fetch a row from the result set cursor as an array.
*
* @param mixed $cursor The optional result set cursor from which to fetch the row.
*
* @return mixed Either the next row from the result set or false if there are no more rows.
*
* @since 12.1
*/
protected function fetchArray($cursor = null)
{
return mysql_fetch_row($cursor ? $cursor : $this->cursor);
}
/**
* Method to fetch a row from the result set cursor as an associative array.
*
* @param mixed $cursor The optional result set cursor from which to fetch the row.
*
* @return mixed Either the next row from the result set or false if there are no more rows.
*
* @since 12.1
*/
protected function fetchAssoc($cursor = null)
{
return mysql_fetch_assoc($cursor ? $cursor : $this->cursor);
}
/**
* Method to fetch a row from the result set cursor as an object.
*
* @param mixed $cursor The optional result set cursor from which to fetch the row.
* @param string $class The class name to use for the returned row object.
*
* @return mixed Either the next row from the result set or false if there are no more rows.
*
* @since 12.1
*/
protected function fetchObject($cursor = null, $class = 'stdClass')
{
return mysql_fetch_object($cursor ? $cursor : $this->cursor, $class);
}
/**
* Method to free up the memory used for the result set.
*
* @param mixed $cursor The optional result set cursor from which to fetch the row.
*
* @return void
*
* @since 12.1
*/
protected function freeResult($cursor = null)
{
mysql_free_result($cursor ? $cursor : $this->cursor);
}
/**
* Internal function to check if profiling is available
*
* @return boolean
*
* @since 3.1.3
*/
private function hasProfiling()
{
try
{
$res = mysql_query("SHOW VARIABLES LIKE 'have_profiling'", $this->connection);
$row = mysql_fetch_assoc($res);
return isset($row);
}
catch (Exception $e)
{
return false;
}
}
/**
* Does the database server claim to have support for UTF-8 Multibyte (utf8mb4) collation?
*
* libmysql supports utf8mb4 since 5.5.3 (same version as the MySQL server). mysqlnd supports utf8mb4 since 5.0.9.
*
* @return boolean
*
* @since CMS 3.5.0
*/
private function serverClaimsUtf8mb4Support()
{
$client_version = mysql_get_client_info();
if (strpos($client_version, 'mysqlnd') !== false)
{
$client_version = preg_replace('/^\D+([\d.]+).*/', '$1', $client_version);
return version_compare($client_version, '5.0.9', '>=');
}
else
{
return version_compare($client_version, '5.5.3', '>=');
}
}
/**
* Return the actual SQL Error number
*
* @return integer The SQL Error number
*
* @since 3.4.6
*/
protected function getErrorNumber()
{
return (int) mysql_errno($this->connection);
}
/**
* Return the actual SQL Error message
*
* @param string $query The SQL Query that fails
*
* @return string The SQL Error message
*
* @since 3.4.6
*/
protected function getErrorMessage($query)
{
$errorMessage = (string) mysql_error($this->connection);
// Replace the Databaseprefix with `#__` if we are not in Debug
if (!$this->debug)
{
$errorMessage = str_replace($this->tablePrefix, '#__', $errorMessage);
$query = str_replace($this->tablePrefix, '#__', $query);
}
return $errorMessage . ' SQL=' . $query;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,712 @@
<?php
/**
* @package FrameworkOnFramework
* @subpackage database
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*
* This file is adapted from the Joomla! Platform. It is used to iterate a database cursor returning F0FTable objects
* instead of plain stdClass objects
*/
// Protect from unauthorized access
defined('F0F_INCLUDED') or die;
/**
* Oracle database driver
*
* @see http://php.net/pdo
* @since 12.1
*/
class F0FDatabaseDriverOracle extends F0FDatabaseDriverPdo
{
/**
* The name of the database driver.
*
* @var string
* @since 12.1
*/
public $name = 'oracle';
/**
* The type of the database server family supported by this driver.
*
* @var string
* @since CMS 3.5.0
*/
public $serverType = 'oracle';
/**
* The character(s) used to quote SQL statement names such as table names or field names,
* etc. The child classes should define this as necessary. If a single character string the
* same character is used for both sides of the quoted name, else the first character will be
* used for the opening quote and the second for the closing quote.
*
* @var string
* @since 12.1
*/
protected $nameQuote = '"';
/**
* Returns the current dateformat
*
* @var string
* @since 12.1
*/
protected $dateformat;
/**
* Returns the current character set
*
* @var string
* @since 12.1
*/
protected $charset;
/**
* Constructor.
*
* @param array $options List of options used to configure the connection
*
* @since 12.1
*/
public function __construct($options)
{
$options['driver'] = 'oci';
$options['charset'] = (isset($options['charset'])) ? $options['charset'] : 'AL32UTF8';
$options['dateformat'] = (isset($options['dateformat'])) ? $options['dateformat'] : 'RRRR-MM-DD HH24:MI:SS';
$this->charset = $options['charset'];
$this->dateformat = $options['dateformat'];
// Finalize initialisation
parent::__construct($options);
}
/**
* Destructor.
*
* @since 12.1
*/
public function __destruct()
{
$this->freeResult();
unset($this->connection);
}
/**
* Connects to the database if needed.
*
* @return void Returns void if the database connected successfully.
*
* @since 12.1
* @throws RuntimeException
*/
public function connect()
{
if ($this->connection)
{
return;
}
parent::connect();
if (isset($this->options['schema']))
{
$this->setQuery('ALTER SESSION SET CURRENT_SCHEMA = ' . $this->quoteName($this->options['schema']))->execute();
}
$this->setDateFormat($this->dateformat);
}
/**
* Disconnects the database.
*
* @return void
*
* @since 12.1
*/
public function disconnect()
{
// Close the connection.
$this->freeResult();
unset($this->connection);
}
/**
* Drops a table from the database.
*
* Note: The IF EXISTS flag is unused in the Oracle driver.
*
* @param string $tableName The name of the database table to drop.
* @param boolean $ifExists Optionally specify that the table must exist before it is dropped.
*
* @return F0FDatabaseDriverOracle Returns this object to support chaining.
*
* @since 12.1
*/
public function dropTable($tableName, $ifExists = true)
{
$this->connect();
$query = $this->getQuery(true)
->setQuery('DROP TABLE :tableName');
$query->bind(':tableName', $tableName);
$this->setQuery($query);
$this->execute();
return $this;
}
/**
* Method to get the database collation in use by sampling a text field of a table in the database.
*
* @return mixed The collation in use by the database or boolean false if not supported.
*
* @since 12.1
*/
public function getCollation()
{
return $this->charset;
}
/**
* Method to get the database connection collation, as reported by the driver. If the connector doesn't support
* reporting this value please return an empty string.
*
* @return string
*/
public function getConnectionCollation()
{
return $this->charset;
}
/**
* Get a query to run and verify the database is operational.
*
* @return string The query to check the health of the DB.
*
* @since 12.2
*/
public function getConnectedQuery()
{
return 'SELECT 1 FROM dual';
}
/**
* Returns the current date format
* This method should be useful in the case that
* somebody actually wants to use a different
* date format and needs to check what the current
* one is to see if it needs to be changed.
*
* @return string The current date format
*
* @since 12.1
*/
public function getDateFormat()
{
return $this->dateformat;
}
/**
* Shows the table CREATE statement that creates the given tables.
*
* Note: You must have the correct privileges before this method
* will return usable results!
*
* @param mixed $tables A table name or a list of table names.
*
* @return array A list of the create SQL for the tables.
*
* @since 12.1
* @throws RuntimeException
*/
public function getTableCreate($tables)
{
$this->connect();
$result = array();
$query = $this->getQuery(true)
->select('dbms_metadata.get_ddl(:type, :tableName)')
->from('dual')
->bind(':type', 'TABLE');
// Sanitize input to an array and iterate over the list.
settype($tables, 'array');
foreach ($tables as $table)
{
$query->bind(':tableName', $table);
$this->setQuery($query);
$statement = (string) $this->loadResult();
$result[$table] = $statement;
}
return $result;
}
/**
* Retrieves field information about a given table.
*
* @param string $table The name of the database table.
* @param boolean $typeOnly True to only return field types.
*
* @return array An array of fields for the database table.
*
* @since 12.1
* @throws RuntimeException
*/
public function getTableColumns($table, $typeOnly = true)
{
$this->connect();
$columns = array();
$query = $this->getQuery(true);
$fieldCasing = $this->getOption(PDO::ATTR_CASE);
$this->setOption(PDO::ATTR_CASE, PDO::CASE_UPPER);
$table = strtoupper($table);
$query->select('*');
$query->from('ALL_TAB_COLUMNS');
$query->where('table_name = :tableName');
$prefixedTable = str_replace('#__', strtoupper($this->tablePrefix), $table);
$query->bind(':tableName', $prefixedTable);
$this->setQuery($query);
$fields = $this->loadObjectList();
if ($typeOnly)
{
foreach ($fields as $field)
{
$columns[$field->COLUMN_NAME] = $field->DATA_TYPE;
}
}
else
{
foreach ($fields as $field)
{
$columns[$field->COLUMN_NAME] = $field;
$columns[$field->COLUMN_NAME]->Default = null;
}
}
$this->setOption(PDO::ATTR_CASE, $fieldCasing);
return $columns;
}
/**
* Get the details list of keys for a table.
*
* @param string $table The name of the table.
*
* @return array An array of the column specification for the table.
*
* @since 12.1
* @throws RuntimeException
*/
public function getTableKeys($table)
{
$this->connect();
$query = $this->getQuery(true);
$fieldCasing = $this->getOption(PDO::ATTR_CASE);
$this->setOption(PDO::ATTR_CASE, PDO::CASE_UPPER);
$table = strtoupper($table);
$query->select('*')
->from('ALL_CONSTRAINTS')
->where('table_name = :tableName')
->bind(':tableName', $table);
$this->setQuery($query);
$keys = $this->loadObjectList();
$this->setOption(PDO::ATTR_CASE, $fieldCasing);
return $keys;
}
/**
* Method to get an array of all tables in the database (schema).
*
* @param string $databaseName The database (schema) name
* @param boolean $includeDatabaseName Whether to include the schema name in the results
*
* @return array An array of all the tables in the database.
*
* @since 12.1
* @throws RuntimeException
*/
public function getTableList($databaseName = null, $includeDatabaseName = false)
{
$this->connect();
$query = $this->getQuery(true);
if ($includeDatabaseName)
{
$query->select('owner, table_name');
}
else
{
$query->select('table_name');
}
$query->from('all_tables');
if ($databaseName)
{
$query->where('owner = :database')
->bind(':database', $databaseName);
}
$query->order('table_name');
$this->setQuery($query);
if ($includeDatabaseName)
{
$tables = $this->loadAssocList();
}
else
{
$tables = $this->loadColumn();
}
return $tables;
}
/**
* Get the version of the database connector.
*
* @return string The database connector version.
*
* @since 12.1
*/
public function getVersion()
{
$this->connect();
$this->setQuery("select value from nls_database_parameters where parameter = 'NLS_RDBMS_VERSION'");
return $this->loadResult();
}
/**
* Select a database for use.
*
* @param string $database The name of the database to select for use.
*
* @return boolean True if the database was successfully selected.
*
* @since 12.1
* @throws RuntimeException
*/
public function select($database)
{
$this->connect();
return true;
}
/**
* Sets the Oracle Date Format for the session
* Default date format for Oracle is = DD-MON-RR
* The default date format for this driver is:
* 'RRRR-MM-DD HH24:MI:SS' since it is the format
* that matches the MySQL one used within most Joomla
* tables.
*
* @param string $dateFormat Oracle Date Format String
*
* @return boolean
*
* @since 12.1
*/
public function setDateFormat($dateFormat = 'DD-MON-RR')
{
$this->connect();
$this->setQuery("ALTER SESSION SET NLS_DATE_FORMAT = '$dateFormat'");
if (!$this->execute())
{
return false;
}
$this->setQuery("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = '$dateFormat'");
if (!$this->execute())
{
return false;
}
$this->dateformat = $dateFormat;
return true;
}
/**
* Set the connection to use UTF-8 character encoding.
*
* Returns false automatically for the Oracle driver since
* you can only set the character set when the connection
* is created.
*
* @return boolean True on success.
*
* @since 12.1
*/
public function setUtf()
{
return false;
}
/**
* Locks a table in the database.
*
* @param string $table The name of the table to unlock.
*
* @return F0FDatabaseDriverOracle Returns this object to support chaining.
*
* @since 12.1
* @throws RuntimeException
*/
public function lockTable($table)
{
$this->setQuery('LOCK TABLE ' . $this->quoteName($table) . ' IN EXCLUSIVE MODE')->execute();
return $this;
}
/**
* Renames a table in the database.
*
* @param string $oldTable The name of the table to be renamed
* @param string $newTable The new name for the table.
* @param string $backup Not used by Oracle.
* @param string $prefix Not used by Oracle.
*
* @return F0FDatabaseDriverOracle Returns this object to support chaining.
*
* @since 12.1
* @throws RuntimeException
*/
public function renameTable($oldTable, $newTable, $backup = null, $prefix = null)
{
$this->setQuery('RENAME ' . $oldTable . ' TO ' . $newTable)->execute();
return $this;
}
/**
* Unlocks tables in the database.
*
* @return F0FDatabaseDriverOracle Returns this object to support chaining.
*
* @since 12.1
* @throws RuntimeException
*/
public function unlockTables()
{
$this->setQuery('COMMIT')->execute();
return $this;
}
/**
* Test to see if the PDO ODBC connector is available.
*
* @return boolean True on success, false otherwise.
*
* @since 12.1
*/
public static function isSupported()
{
return class_exists('PDO') && in_array('oci', PDO::getAvailableDrivers());
}
/**
* This function replaces a string identifier <var>$prefix</var> with the string held is the
* <var>tablePrefix</var> class variable.
*
* @param string $query The SQL statement to prepare.
* @param string $prefix The common table prefix.
*
* @return string The processed SQL statement.
*
* @since 11.1
*/
public function replacePrefix($query, $prefix = '#__')
{
$startPos = 0;
$quoteChar = "'";
$literal = '';
$query = trim($query);
$n = strlen($query);
while ($startPos < $n)
{
$ip = strpos($query, $prefix, $startPos);
if ($ip === false)
{
break;
}
$j = strpos($query, "'", $startPos);
if ($j === false)
{
$j = $n;
}
$literal .= str_replace($prefix, $this->tablePrefix, substr($query, $startPos, $j - $startPos));
$startPos = $j;
$j = $startPos + 1;
if ($j >= $n)
{
break;
}
// Quote comes first, find end of quote
while (true)
{
$k = strpos($query, $quoteChar, $j);
$escaped = false;
if ($k === false)
{
break;
}
$l = $k - 1;
while ($l >= 0 && $query{$l} == '\\')
{
$l--;
$escaped = !$escaped;
}
if ($escaped)
{
$j = $k + 1;
continue;
}
break;
}
if ($k === false)
{
// Error in the query - no end quote; ignore it
break;
}
$literal .= substr($query, $startPos, $k - $startPos + 1);
$startPos = $k + 1;
}
if ($startPos < $n)
{
$literal .= substr($query, $startPos, $n - $startPos);
}
return $literal;
}
/**
* Method to commit a transaction.
*
* @param boolean $toSavepoint If true, commit to the last savepoint.
*
* @return void
*
* @since 12.3
* @throws RuntimeException
*/
public function transactionCommit($toSavepoint = false)
{
$this->connect();
if (!$toSavepoint || $this->transactionDepth <= 1)
{
parent::transactionCommit($toSavepoint);
}
else
{
$this->transactionDepth--;
}
}
/**
* Method to roll back a transaction.
*
* @param boolean $toSavepoint If true, rollback to the last savepoint.
*
* @return void
*
* @since 12.3
* @throws RuntimeException
*/
public function transactionRollback($toSavepoint = false)
{
$this->connect();
if (!$toSavepoint || $this->transactionDepth <= 1)
{
parent::transactionRollback($toSavepoint);
}
else
{
$savepoint = 'SP_' . ($this->transactionDepth - 1);
$this->setQuery('ROLLBACK TO SAVEPOINT ' . $this->quoteName($savepoint));
if ($this->execute())
{
$this->transactionDepth--;
}
}
}
/**
* Method to initialize a transaction.
*
* @param boolean $asSavepoint If true and a transaction is already active, a savepoint will be created.
*
* @return void
*
* @since 12.3
* @throws RuntimeException
*/
public function transactionStart($asSavepoint = false)
{
$this->connect();
if (!$asSavepoint || !$this->transactionDepth)
{
return parent::transactionStart($asSavepoint);
}
$savepoint = 'SP_' . $this->transactionDepth;
$this->setQuery('SAVEPOINT ' . $this->quoteName($savepoint));
if ($this->execute())
{
$this->transactionDepth++;
}
}
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More