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

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));
}
}