mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 03:18:26 +00:00
- Cake didn't work without mod_rewrite, fixed (/index.php, /libs/router.php).
- Controller accepts $params as a constructor parameter (for Larry). - DBO::prepare() returned an array even when a string was passed to it, fixed. - Flay and Folder tests fixed, DBO_Factory test disabled (no database config by default, so do database access to test). - git-svn-id: https://svn.cakephp.org/repo/trunk/cake@238 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
parent
443a702376
commit
3f10d747b7
16 changed files with 180 additions and 107 deletions
44
index.php
44
index.php
|
@ -40,10 +40,48 @@ define ('ROOT', dirname(__FILE__).DS);
|
||||||
* We need to redefine some constants and variables, so that Cake knows it is
|
* We need to redefine some constants and variables, so that Cake knows it is
|
||||||
* working without mod_rewrite.
|
* working without mod_rewrite.
|
||||||
*/
|
*/
|
||||||
define ('BASE_URL', $_SERVER['SCRIPT_NAME']);
|
define ('BASE_URL', $_SERVER['SCRIPT_NAME'].'?url=');
|
||||||
|
|
||||||
$_GET['url'] = ltrim($_SERVER['PATH_INFO'],'/');
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As mod_rewrite (or .htaccess files) is not working, we need to take care
|
||||||
|
* of what would normally be rewrited, i.e. the static files in /public
|
||||||
|
*/
|
||||||
|
if (empty($_GET['url']) || ($_GET['url'] == '/'))
|
||||||
|
{
|
||||||
require (ROOT.'public/index.php');
|
require (ROOT.'public/index.php');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$elements = explode('/index.php?url=', $_SERVER['REQUEST_URI']);
|
||||||
|
$base = $elements[0].'/public';
|
||||||
|
$path = $elements[1];
|
||||||
|
|
||||||
|
$filename = ROOT.'public'.str_replace('/', DS, $path);
|
||||||
|
$url = $base.$path;
|
||||||
|
|
||||||
|
if (file_exists($filename))
|
||||||
|
{
|
||||||
|
if (preg_match('/^.*\.([a-z]+)$/i', $filename, $ext))
|
||||||
|
{
|
||||||
|
switch ($ext[1])
|
||||||
|
{
|
||||||
|
case 'jpg':
|
||||||
|
case 'jpeg':
|
||||||
|
header('Content-type: image/jpeg');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'css':
|
||||||
|
header('Content-type: text/css');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print (file_get_contents($filename));
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
require (ROOT.'public/index.php');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
|
@ -102,8 +102,9 @@ class Controller extends Template {
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function __construct () {
|
function __construct ($params=null)
|
||||||
global $DB;
|
{
|
||||||
|
$this->params = $params;
|
||||||
|
|
||||||
$r = null;
|
$r = null;
|
||||||
if (!preg_match('/(.*)Controller/i', get_class($this), $r))
|
if (!preg_match('/(.*)Controller/i', get_class($this), $r))
|
||||||
|
@ -113,28 +114,32 @@ class Controller extends Template {
|
||||||
$this->viewpath = Inflector::underscore($r[1]);
|
$this->viewpath = Inflector::underscore($r[1]);
|
||||||
|
|
||||||
$model_class = Inflector::singularize($this->name);
|
$model_class = Inflector::singularize($this->name);
|
||||||
if (($this->uses === false) && class_exists($model_class)) {
|
|
||||||
if (!$DB)
|
|
||||||
die("Controller::__construct() : ".$this->name." controller needs database access, exiting.");
|
|
||||||
|
|
||||||
|
if (class_exists($model_class) && $this->db && ($this->uses === false))
|
||||||
|
{
|
||||||
$this->$model_class = new $model_class ();
|
$this->$model_class = new $model_class ();
|
||||||
}
|
}
|
||||||
elseif ($this->uses) {
|
elseif ($this->uses)
|
||||||
|
{
|
||||||
if (!$DB)
|
if (!$DB)
|
||||||
die("Controller::__construct() : ".$this->name." controller needs database access, exiting.");
|
die("Controller::__construct() : ".$this->name." controller needs database access, exiting.");
|
||||||
|
|
||||||
$uses = is_array($this->uses)? $this->uses: array($this->uses);
|
$uses = is_array($this->uses)? $this->uses: array($this->uses);
|
||||||
|
|
||||||
foreach ($uses as $model_name) {
|
foreach ($uses as $model_name)
|
||||||
|
{
|
||||||
$model_class = ucfirst(strtolower($model_name));
|
$model_class = ucfirst(strtolower($model_name));
|
||||||
|
|
||||||
if (class_exists($model_class)) {
|
if (class_exists($model_class))
|
||||||
|
{
|
||||||
$this->$model_name = new $model_class (false);
|
$this->$model_name = new $model_class (false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
die("Controller::__construct() : ".ucfirst($this->name)." requires missing model {$model_class}, exiting.");
|
die("Controller::__construct() : ".ucfirst($this->name)." requires missing model {$model_class}, exiting.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
25
libs/dbo.php
25
libs/dbo.php
|
@ -276,16 +276,22 @@ class DBO extends Object {
|
||||||
* @param mixed $data A value or an array of values to prepare.
|
* @param mixed $data A value or an array of values to prepare.
|
||||||
* @return mixed Prepared value or array of values.
|
* @return mixed Prepared value or array of values.
|
||||||
*/
|
*/
|
||||||
function prepare ($data) {
|
function prepare ($data)
|
||||||
if (!is_array($data))
|
{
|
||||||
$data = array($data);
|
if (is_string($data))
|
||||||
|
{
|
||||||
|
return $this->prepareValue($data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$out = null;
|
$out = null;
|
||||||
foreach ($data as $key=>$item) {
|
foreach ($data as $key=>$item)
|
||||||
|
{
|
||||||
$out[$key] = $this->prepareValue($item);
|
$out[$key] = $this->prepareValue($item);
|
||||||
}
|
}
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes given SQL statement.
|
* Executes given SQL statement.
|
||||||
|
@ -326,8 +332,8 @@ class DBO extends Object {
|
||||||
* @param resource $res
|
* @param resource $res
|
||||||
* @return array A single row of results
|
* @return array A single row of results
|
||||||
*/
|
*/
|
||||||
function farr ($res=false) {
|
function farr ($res=false, $assoc=false) {
|
||||||
return $this->fetchRow($res? $res: $this->_result);
|
return $this->fetchRow($res? $res: $this->_result, $assoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -350,7 +356,10 @@ class DBO extends Object {
|
||||||
function all ($sql) {
|
function all ($sql) {
|
||||||
if($this->query($sql)) {
|
if($this->query($sql)) {
|
||||||
$out=array();
|
$out=array();
|
||||||
while($item = $this->farr()) $out[] = $item;
|
while ($item = $this->farr(null, true))
|
||||||
|
{
|
||||||
|
$out[] = $item;
|
||||||
|
}
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -95,8 +95,8 @@ class DBO_MySQL extends DBO {
|
||||||
* @param unknown_type $res Resultset
|
* @param unknown_type $res Resultset
|
||||||
* @return array The fetched row as an array
|
* @return array The fetched row as an array
|
||||||
*/
|
*/
|
||||||
function fetchRow ($res) {
|
function fetchRow ($res, $assoc=false) {
|
||||||
return mysql_fetch_array($res);
|
return mysql_fetch_array($res, $assoc? MYSQL_ASSOC: MYSQL_BOTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,20 +3,14 @@
|
||||||
// + $Id$
|
// + $Id$
|
||||||
// +------------------------------------------------------------------+ //
|
// +------------------------------------------------------------------+ //
|
||||||
// + Cake <https://developers.nextco.com/cake/> + //
|
// + Cake <https://developers.nextco.com/cake/> + //
|
||||||
// + Copyright: (c) 2005 Cake Authors/Developers + //
|
// + Copyright: (c) 2005, Cake Authors/Developers + //
|
||||||
// + + //
|
|
||||||
// + Author(s): Michal Tatarynowicz aka Pies <tatarynowicz@gmail.com> + //
|
// + Author(s): Michal Tatarynowicz aka Pies <tatarynowicz@gmail.com> + //
|
||||||
// + Larry E. Masters aka PhpNut <nut@phpnut.com> + //
|
// + Larry E. Masters aka PhpNut <nut@phpnut.com> + //
|
||||||
// + Kamil Dzielinski aka Brego <brego.dk@gmail.com> + //
|
// + Kamil Dzielinski aka Brego <brego.dk@gmail.com> + //
|
||||||
// + + //
|
|
||||||
// +------------------------------------------------------------------+ //
|
// +------------------------------------------------------------------+ //
|
||||||
// + Licensed under The MIT License + //
|
// + Licensed under The MIT License + //
|
||||||
// + Redistributions of files must retain the above copyright notice. + //
|
// + Redistributions of files must retain the above copyright notice. + //
|
||||||
// + You may not use this file except in compliance with the License. + //
|
// + See: http://www.opensource.org/licenses/mit-license.php + //
|
||||||
// + + //
|
|
||||||
// + You may obtain a copy of the License at: + //
|
|
||||||
// + License page: http://www.opensource.org/licenses/mit-license.php + //
|
|
||||||
// +------------------------------------------------------------------+ //
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -100,13 +100,17 @@ class Dispatcher extends Object {
|
||||||
/**
|
/**
|
||||||
* If _no_action_is set, check if the default action, index() exists. If it doesn't, die.
|
* If _no_action_is set, check if the default action, index() exists. If it doesn't, die.
|
||||||
*/
|
*/
|
||||||
if (empty($params['action']) && in_array('index', $ctrl_methods))
|
if (empty($params['action']))
|
||||||
|
{
|
||||||
|
if (in_array('index', $ctrl_methods))
|
||||||
{
|
{
|
||||||
$params['action'] = 'index';
|
$params['action'] = 'index';
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
$this->errorNoAction($url);
|
$this->errorNoAction($url);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the specified action really exists.
|
* Check if the specified action really exists.
|
||||||
|
@ -116,7 +120,8 @@ class Dispatcher extends Object {
|
||||||
$this->errorUnknownAction($url, $ctrl_class, $params['action']);
|
$this->errorUnknownAction($url, $ctrl_class, $params['action']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$controller->params = $params;
|
$controller = new $ctrl_class ($params);
|
||||||
|
$controller->base = $this->base;
|
||||||
$controller->action = $params['action'];
|
$controller->action = $params['action'];
|
||||||
$controller->data = empty($params['data'])? null: $params['data'];
|
$controller->data = empty($params['data'])? null: $params['data'];
|
||||||
$controller->passed_args = empty($params['pass'])? null: $params['pass'];
|
$controller->passed_args = empty($params['pass'])? null: $params['pass'];
|
||||||
|
@ -142,7 +147,7 @@ class Dispatcher extends Object {
|
||||||
// load routes config
|
// load routes config
|
||||||
$Route = new Router();
|
$Route = new Router();
|
||||||
require CONFIGS.'routes.php';
|
require CONFIGS.'routes.php';
|
||||||
$params = $Route->parse ('/'.$from_url);
|
$params = $Route->parse ($from_url);
|
||||||
|
|
||||||
// add submitted form data
|
// add submitted form data
|
||||||
$params['form'] = $_POST;
|
$params['form'] = $_POST;
|
||||||
|
|
|
@ -47,7 +47,6 @@ if (version_compare(phpversion(), '5.0') < 0) {
|
||||||
* @package PHP_Compat
|
* @package PHP_Compat
|
||||||
* @link http://php.net/function.file_get_contents
|
* @link http://php.net/function.file_get_contents
|
||||||
* @author Aidan Lister <aidan@php.net>
|
* @author Aidan Lister <aidan@php.net>
|
||||||
* @version $Revision$
|
|
||||||
* @internal resource_context is not supported
|
* @internal resource_context is not supported
|
||||||
* @since PHP 5
|
* @since PHP 5
|
||||||
* @require PHP 4.0.0 (user_error)
|
* @require PHP 4.0.0 (user_error)
|
||||||
|
|
|
@ -518,8 +518,6 @@ class Model extends Object {
|
||||||
else
|
else
|
||||||
$f = array('*');
|
$f = array('*');
|
||||||
|
|
||||||
$conditions = $this->db->prepare($conditions);
|
|
||||||
|
|
||||||
$joins = $whers = array();
|
$joins = $whers = array();
|
||||||
|
|
||||||
foreach ($this->_oneToMany as $rule) {
|
foreach ($this->_oneToMany as $rule) {
|
||||||
|
|
|
@ -36,7 +36,13 @@ class NeatArray {
|
||||||
* @access public
|
* @access public
|
||||||
* @uses NeatArray::value
|
* @uses NeatArray::value
|
||||||
*/
|
*/
|
||||||
function findIn ($fieldName, $value) {
|
function findIn ($fieldName, $value)
|
||||||
|
{
|
||||||
|
if (!is_array($this->value))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$out = false;
|
$out = false;
|
||||||
foreach ($this->value as $k=>$v) {
|
foreach ($this->value as $k=>$v) {
|
||||||
if (isset($v[$fieldName]) && ($v[$fieldName] == $value)) {
|
if (isset($v[$fieldName]) && ($v[$fieldName] == $value)) {
|
||||||
|
|
|
@ -111,11 +111,20 @@ class Router extends Object {
|
||||||
* @param string $url URL to be parsed
|
* @param string $url URL to be parsed
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
function parse ($url) {
|
function parse ($url)
|
||||||
|
{
|
||||||
|
// An URL should start with a '/', mod_rewrite doesn't respect that, but no-mod_rewrite version does.
|
||||||
|
// Here's the fix.
|
||||||
|
if ($url && ('/' != $url[0]))
|
||||||
|
{
|
||||||
|
$url = '/'.$url;
|
||||||
|
}
|
||||||
|
|
||||||
$out = array();
|
$out = array();
|
||||||
$r = null;
|
$r = null;
|
||||||
|
|
||||||
$default_route = array(
|
$default_route = array
|
||||||
|
(
|
||||||
'/:controller/:action/* (default)',
|
'/:controller/:action/* (default)',
|
||||||
"#^(?:\/(?:([a-z0-9_\-]+)(?:\/([a-z0-9_\-]+)(?:\/(.*))?)?))[\/]*$#",
|
"#^(?:\/(?:([a-z0-9_\-]+)(?:\/([a-z0-9_\-]+)(?:\/(.*))?)?))[\/]*$#",
|
||||||
array('controller', 'action'),
|
array('controller', 'action'),
|
||||||
|
@ -124,10 +133,12 @@ class Router extends Object {
|
||||||
|
|
||||||
$this->routes[] = $default_route;
|
$this->routes[] = $default_route;
|
||||||
|
|
||||||
foreach ($this->routes as $route) {
|
foreach ($this->routes as $route)
|
||||||
|
{
|
||||||
list($route, $regexp, $names, $defaults) = $route;
|
list($route, $regexp, $names, $defaults) = $route;
|
||||||
|
|
||||||
if (preg_match($regexp, $url, $r)) {
|
if (preg_match($regexp, $url, $r))
|
||||||
|
{
|
||||||
// $this->log($url.' matched '.$regexp, 'note');
|
// $this->log($url.' matched '.$regexp, 'note');
|
||||||
// remove the first element, which is the url
|
// remove the first element, which is the url
|
||||||
array_shift($r);
|
array_shift($r);
|
||||||
|
@ -138,8 +149,10 @@ class Router extends Object {
|
||||||
|
|
||||||
$ii = 0;
|
$ii = 0;
|
||||||
|
|
||||||
if (is_array($defaults)) {
|
if (is_array($defaults))
|
||||||
foreach ($defaults as $name=>$value) {
|
{
|
||||||
|
foreach ($defaults as $name=>$value)
|
||||||
|
{
|
||||||
if (preg_match('#[a-z_\-]#i', $name))
|
if (preg_match('#[a-z_\-]#i', $name))
|
||||||
$out[$name] = $value;
|
$out[$name] = $value;
|
||||||
else
|
else
|
||||||
|
@ -149,11 +162,13 @@ class Router extends Object {
|
||||||
|
|
||||||
foreach ($r as $found) {
|
foreach ($r as $found) {
|
||||||
// if $found is a named url element (i.e. ':action')
|
// if $found is a named url element (i.e. ':action')
|
||||||
if (isset($names[$ii])) {
|
if (isset($names[$ii]))
|
||||||
|
{
|
||||||
$out[$names[$ii]] = $found;
|
$out[$names[$ii]] = $found;
|
||||||
}
|
}
|
||||||
// unnamed elements go in as 'pass'
|
// unnamed elements go in as 'pass'
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
$pass = new NeatArray(explode('/', $found));
|
$pass = new NeatArray(explode('/', $found));
|
||||||
$pass->cleanup();
|
$pass->cleanup();
|
||||||
$out['pass'] = $pass->value;
|
$out['pass'] = $pass->value;
|
||||||
|
@ -163,7 +178,6 @@ class Router extends Object {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,10 @@ session_start();
|
||||||
/**
|
/**
|
||||||
* Get Cake's root directory
|
* Get Cake's root directory
|
||||||
*/
|
*/
|
||||||
|
if (!defined('DS'))
|
||||||
define ('DS', DIRECTORY_SEPARATOR);
|
define ('DS', DIRECTORY_SEPARATOR);
|
||||||
|
|
||||||
|
if (!defined('ROOT'))
|
||||||
define ('ROOT', dirname(dirname(__FILE__)).DS);
|
define ('ROOT', dirname(dirname(__FILE__)).DS);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -181,8 +181,8 @@ class ControllerTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSelectTag () {
|
function testSelectTag () {
|
||||||
$result = $this->abc->selectTag('tofu', array('m'=>'male', 'f'=>'female'), array('class'=>'Outer'), array('class'=>'Inner', 'id'=>'FooID'));
|
$result = $this->abc->selectTag('tofu', array('m'=>'male', 'f'=>'female'), 'f', array('class'=>'Outer'), array('class'=>'Inner', 'id'=>'FooID'));
|
||||||
$expected = '<select name="data[tofu]" class="Outer">'."\n".'<option value="" class="Inner" id="FooID"></option>'."\n".'<option value="m" class="Inner" id="FooID">male</option>'."\n".'<option value="f" class="Inner" id="FooID">female</option>'."\n".'</select>';
|
$expected = '<select name="data[tofu]" class="Outer">'."\n".'<option value="" class="Inner" id="FooID"></option>'."\n".'<option value="m" class="Inner" id="FooID">male</option>'."\n".'<option value="f" class="Inner" id="FooID" selected="selected">female</option>'."\n".'</select>';
|
||||||
$this->assertEquals($result, $expected);
|
$this->assertEquals($result, $expected);
|
||||||
|
|
||||||
$result = $this->abc->selectTag('tofu', array());
|
$result = $this->abc->selectTag('tofu', array());
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
uses ('test', 'dbo_factory');
|
uses ('test', 'dbo_factory');
|
||||||
|
config ('database');
|
||||||
|
|
||||||
class DboFactoryTest extends TestCase {
|
class DboFactoryTest extends TestCase {
|
||||||
var $abc;
|
var $abc;
|
||||||
|
@ -25,9 +26,10 @@ class DboFactoryTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function testMake () {
|
function testMake ()
|
||||||
if (class_exists(DATABASE_CONFIG)) {
|
{
|
||||||
|
if (class_exists(DATABASE_CONFIG))
|
||||||
|
{
|
||||||
$output = $this->abc->make('test');
|
$output = $this->abc->make('test');
|
||||||
$this->assertTrue(is_object($output));
|
$this->assertTrue(is_object($output));
|
||||||
|
|
|
@ -29,7 +29,7 @@ class FlayTest extends TestCase {
|
||||||
$tests_to_html = array(
|
$tests_to_html = array(
|
||||||
array(
|
array(
|
||||||
'text'=>"",
|
'text'=>"",
|
||||||
'html'=>""
|
'html'=>false
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'text'=>"This is a text.",
|
'text'=>"This is a text.",
|
||||||
|
@ -69,7 +69,7 @@ class FlayTest extends TestCase {
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'text'=>"Now auto-link an url such as http://sputnik.pl or www.robocik-malowany.com/dupa[4] - or any other.",
|
'text'=>"Now auto-link an url such as http://sputnik.pl or www.robocik-malowany.com/dupa[4] - or any other.",
|
||||||
'html'=>"<p>Now auto-link an url such as <a href=\"http://sputnik.pl\">http://sputnik.pl</a> or <a href=\"www.robocik-malowany.com/dupa[4]\">www.robocik-malowany.com/dupa[4]</a> – or any other.</p>\n"
|
'html'=>"<p>Now auto-link an url such as <a href=\"http://sputnik.pl\">http://sputnik.pl</a> or <a href=\"http://www.robocik-malowany.com/dupa[4]\">www.robocik-malowany.com/dupa[4]</a> – or any other.</p>\n"
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'text'=>"===This be centered===",
|
'text'=>"===This be centered===",
|
||||||
|
|
|
@ -27,7 +27,7 @@ class FolderTest extends TestCase {
|
||||||
|
|
||||||
function testLs () {
|
function testLs () {
|
||||||
$result = $this->abc->ls();
|
$result = $this->abc->ls();
|
||||||
$expected = array(array('css', 'files', 'img'),array('.htaccess', '500.html', 'index.php', 'index_no_mod_rewrite.php'));
|
$expected = array(array('.svn', 'css', 'files', 'img', 'js'),array('.htaccess', '500.html', 'index.php'));
|
||||||
$this->assertEquals($result, $expected);
|
$this->assertEquals($result, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue