Yii returns exception.CHttpException.404 error - php

I have some problems with my Yii system. All modules are working fine in the system, but there is an error with the activity module. It returns the following error:
2013/10/22 10:21:17 [error] [exception.CHttpException.404] exception 'CHttpException' with message '"activity/default/list" isteği çözümlenemedi.' in /var/www/yii/framework/web/CWebApplication.php:286
Stack trace:
#0 /var/www/yii/framework/web/CWebApplication.php(141): CWebApplication->runController('activity/defaul...')
#1 /var/www/yii/framework/base/CApplication.php(180): CWebApplication->processRequest()
#2 /var/www/hello/index.php(13): CApplication->run()
#3 {main}
REQUEST_URI=/etkinlikler/liste
Here are my main and defaultController files for activity module.
main.php
<?php
date_default_timezone_set('Asia/Istanbul');
return array(
'basePath' => dirname(__FILE__) . DIRECTORY_SEPARATOR . '..',
'name' => 'Kendim Panel',
'language' => 'tr',
'preload' => array('log'),
'import' => array(
'application.models.*',
'application.modules.*',
'application.components.*',
'application.helpers.*'
),
'modules' => array(
'gii' => array(
'class' => 'system.gii.GiiModule',
'password' => '121212',
'ipFilters' => array('127.0.0.1, 192.168.1.27', '::1'),
),
'wlapi' => array(),
'panel' => array(),
'ileti' => array(),
'anket' => array(),
'hastag' => array(),
'category' => array(),
'product' => array(),
'menu' => array(),
'siparis' => array(),
'kisisel' => array(),
'istatistik' => array()
),
'components' => array(
'CString' => array('class'=>'CString'),
'myFunc' => array('class'=>'myFunc'),
'user' => array(
'allowAutoLogin' => true,
),
'db' => array(
'connectionString' => 'mysql:host=localhost;dbname=kendim_db',
'emulatePrepare' => true,
'username' => 'root',
'password' => 'root',
'charset' => 'utf8',
)
, 'urlManager' =>array(
'urlFormat' => 'path',
'showScriptName' => false,
'rules' => array(
'/' => 'panel/default',
'wl-api' => 'wlapi',
'etkinlikler' => 'activity',
'etkinlikler/ekle' => 'activity/default/create',
'etkinlikler/duzenle' => 'activity/default/update',
'etkinlikler/duzenle/id/<id:\d+>' => 'activity/default/update',
'etkinlikler/sil' => 'activity/default/delete',
'etkinlikler/sil/id/<id:\d+>' => 'activity/default/delete',
'etkinlikler/liste' => 'activity/default/list',
'kategoriler' => 'category',
'kategoriler/ekle' => 'category/default/create',
'kategoriler/duzenle' => 'cateogry/default/update',
'kategoriler/duzenle/id/<id:\d+>' => 'category/default/update',
'kategoriler/sil' => 'category/default/delete',
'kategoriler/sil/id/<id:\d+>' => 'category/default/delete',
'kategoriler/liste' => 'category/default/list',
'urunler' => 'product',
'urunler/ekle' => 'product/default/create',
'urunler/duzenle' => 'product/default/update',
'urunler/duzenle/id/<id:\d+>' => 'product/default/update',
'urunler/sil' => 'product/default/delete',
'urunler/sil/id/<id:\d+>' => 'product/default/delete',
'urunler/liste' => 'product/default/list',
),
),
'errorHandler' => array(
'errorAction' => 'panel/default/error',
),
'log' => array(
'class' => 'CLogRouter',
'routes' => array(
array(
'class' => 'CFileLogRoute',
'levels' => 'error, warning',
),
),
),
'image'=>array(
'class'=>'application.extensions.image.CImageComponent',
//GD or ImageMagick
'driver'=>'GD',
'params'=>array('directory'=>'/opt/local/bin',
'product'=>array(
'size'=>array(
'detail'=>array(
'width' => 418,
'height' => 314
),
'thumbnail'=>array(
'width' => 90,
'height' => 68
),
'org'=>array(
'width' => 800,
'height' => 600
),
),
),
),
),
),
);
?>
DefaultController.php
<?php
class DefaultController extends ActivityController
{
public $layout = 'activity';
private $actionStatus;
private $defaultDetailImageWidth;
private $defaultDetailImageHeight;
private $defaultListImageWidth;
private $defaultListImageHeight;
private $defaultOrgImageWidth;
private $defaultOrgImageHeight;
public function actionCreate()
{
$this->pageTitle = "Etkinlik Yönetimi > Etkinlik Ekleme";
$this->render("create", array('model'=>$newActivityModel, 'actionStatus'=>$this->actionStatus, 'categoryGridList'=>$categoryGridList));
}
public function actionList()
{
$this->pageTitle = "Etkinlik Yönetimi > Etkinlik Listeleme";
$this->render("list");
}
public function actionDelete()
{
$this->pageTitle = "Ürün Yönetimi > Ürün Silme";
$this->render("delete", array('actionStatus' => $this->actionStatus));
}
public function actionUpdate()
{
$this->pageTitle = "Ürün Yönetimi > Ürün Güncelleme";
$this->render("update", array('model'=>$product, 'actionStatus' => $this->actionStatus, 'categoryList' => $categoryList));
}
public function actionIndex()
{
$this->render("index");
}
public function actionError()
{
$this->render("error");
}
}
?>
ActivityController.php
<?php
/**
* Controller is the customized base controller class.
* All controller classes for this application should extend from this base class.
*/
class ActivityController extends CController {
/**
* #var string the default layout for the controller view. Defaults to '//layouts/column1',
* meaning using a single column layout. See 'protected/views/layouts/column1.php'.
*/
public $layout = '/layouts/column1';
/**
* #var array context menu items. This property will be assigned to {#link CMenu::items}.
*/
public $constants = array();
public $menu = array(
array('label'=>'Etkinlik Ekle', 'url'=>'/etkinlikler/ekle'),
array('label'=>'Etkinlik Liste', 'url'=>'/etkinlikler/liste'),
);
/**
* #var array the breadcrumbs of the current page. The value of this property will
* be assigned to {#link CBreadcrumbs::links}. Please refer to {#link CBreadcrumbs::links}
* for more details on how to specify this property.
*/
public $breadcrumbs = array();
}
I've set permissions for all files to 777 and I still get the same error.
Also I checked that system is not able to go to controllers. I get the error in main.php
What is the problem?

Ok I found the problem. I haven't defined the activity module in main.php After adding
'activity' => array();
the problem was solved.

Change
array('label'=>'Etkinlik Ekle', 'url'=>'/etkinlikler/ekle'),
array('label'=>'Etkinlik Liste', 'url'=>'/etkinlikler/liste'),
to
array('label' => 'Etkinlik Ekle', 'url' => array('activity/default/create')),
array('label' => 'Etkinlik Liste', 'url' => array('activity/default/list)),

Related

ZendFramework 2 - removing InputFilter causes misbehavior in custom filter

I have an registration form User\UserForm which contains a fieldset User\UserFieldset. In User\UserFieldset I put an field called "passwordVerify" which should be identical with another field in the fieldset called "password".
This works fine.
However, if an admin wants to modify an user account within the Admin\UserForm, which also contains the User\UserFieldset, the field "passwordVerify" in the fieldset User\UserFieldset should be removed. Therefore I call the following within the Admin\UserForm:
$this->get('user')->remove('passwordVerify');
$this->getInputFilter()->get('user')->remove('passwordVerify')
As expected, the form lacks the field "passwordVerify" now.
If I save the form after editing some stuff, my custom filter "PasswordFilter" cannot retrieve the bound object of the fieldset anymore ($this->getOption('object'); returns an User-object) - but all properties of the bound object are nulled. If I use the Admin\UserForm without removing "passwordVerify"-field and "passwordVerify"-inputfilter everything works fine and the bound object is passed to "PasswordFilter" with populated properties (in respect of values, inserted by the user in the Admin\UserForm). The line which breaks everything is $this->getInputFilter()->get('user')->remove('passwordVerify'). So this leads to my assumption, that by removing an inputfilter, the hydrated object gets somehow nulled / emptied. Below are my some excerpts of my code, if needed I can provide more information about factories, etc.
Admin\UserForm:
class UserForm extends Form
{
/**
* #var EntityManager
*/
protected $entityManager = null;
/**
* #var Translator
*/
protected $translator = null;
public function __construct(EntityManager $entityManager, Translator $translator)
{
$this->entityManager = $entityManager;
$this->translator = $translator;
parent::__construct("userForm");
$this->setHydrator(new DoctrineHydrator($entityManager));
}
public function init()
{
// Adding UserFieldset
$this->add(array(
'name' => 'user',
'type' => \User\Form\UserFieldset::class,
'options' => array(
'use_as_base_fieldset' => true,
),
));
$this->get('user')->remove('passwordVerify');
$this->getInputFilter()->get('user')->remove('passwordVerify');
$this->add(array(
'type' => 'Zend\Form\Element\Csrf',
'name' => 'csrf',
));
$this->add(array(
'type' => 'submit',
'name' => 'submit',
'options' => array(
'label' => $this->translator->translate('Btn.submit.user', 'Form')
),
));
}
}
User\UserFieldset:
class UserFieldset extends Fieldset implements InputFilterProviderInterface
{
/**
* #var EntityManager
*/
protected $entityManager = null;
/**
* #var Translator
*/
protected $translator = null;
public function __construct(EntityManager $entityManager, Translator $translator)
{
$this->entityManager = $entityManager;
$this->translator = $translator;
parent::__construct("userFieldset");
$this->setHydrator(new DoctrineHydrator($entityManager))->setObject(new User());
}
public function init()
{
$this->add(array(
'type' => 'text',
'name' => 'firstName',
'options' => array(
'label' => $this->translator->translate('label.firstName', 'Form'),
'label_attributes' => array(
'class' => 'col-sm-3',
),
'column-size' => 'sm-5',
),
'attributes' => array(
'id' => 'firstName',
),
));
/* ... */
$this->add(array(
'type' => 'text',
'name' => 'password',
'options' => array(
'label' => $this->translator->translate('label.password', 'Form'),
'label_attributes' => array(
'class' => 'col-sm-3',
),
'column-size' => 'sm-5',
),
'attributes' => array(
'id' => 'password',
),
));
$this->add(array(
'type' => 'password',
'name' => 'passwordVerify',
'options' => array(
'label_attributes' => array(
'class' => 'col-sm-3 control-label'
),
'label' => $this->translator->translate('label.verifyPassword', 'Form'),
'column-size' => 'sm-8',
),
'attributes' => array(
'class' => 'form-control',
'id' => 'password'),
));
/* ... */
// Adding AddressFieldset
$this->add(array(
'name' => 'address',
'type' => \User\Form\AddressFieldset::class,
));
/* ... */
$this->add(array(
'type' => 'datetime',
'name' => 'created',
'options' => array(
'label' => $this->translator->translate('label.created', 'Form'),
'format' => 'd.m.Y H:i',
'label_attributes' => array(
'class' => 'col-sm-3',
),
'column-size' => 'sm-5',
),
'attributes' => array(
'id' => 'created',
),
));
}
public function getInputFilterSpecification()
{
return array(
'firstName' => array(
'required' => true,
'filters' => array(
array('name' => 'StringTrim'),
array('name' => 'StripTags'),
),
'validators' => array(),
),
/* ... */
'password' => array(
'required' => true,
'filters' => array(
array('name' => 'StringTrim'),
array('name' => 'StripTags'),
[
'name' => PasswordFilter::class,
'options' => [
'object' => $this->getObject(),
'field' => 'password'
]
]
),
'validators' => array(),
),
'passwordVerify' => array(
'required' => true,
'filters' => [
[
'name' => PasswordFilter::class,
'options' => [
'object' => $this->getObject(),
'field' => 'password'
]
]
],
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'min' => 6
)
),
array(
'name' => 'Identical',
'options' => array(
'token' => 'password'
)
)
)
),
/* ... */
'created' => array(
'required' => false,
'filters' => array(
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'Date',
'options' => array('format' => 'd.m.Y H:i')
),
),
)
);
}
}
PasswordFilter:
class PasswordFilter extends AbstractFilter
{
/** #var EntityManager */
protected $entityManager;
/** #var PasswordInterface */
protected $passwordManager;
/**
* PasswordFilter constructor.
* #param EntityManager $entityManager
* #param PasswordInterface $passwordManager
* #param array $options
*/
public function __construct(EntityManager $entityManager, PasswordInterface $passwordManager, $options = [])
{
$this->entityManager = $entityManager;
$this->passwordManager = $passwordManager;
$this->options = $options;
}
public function filter($value)
{
$object = $this->getOption('object');
$field = $this->getOption('field');
$getter = 'get'.ucfirst($field);
if (!$object || !$field) {
throw new \Exception('Options "object" and "field" are required.');
}
if ($object->getId()) {
$dbObject = $this->entityManager->getRepository(get_class($object))->find($object->getId());
if ($value === $dbObject->{$getter}()) {
return $value;
}
}
// hash password here...
return $this->passwordManager->create($value);
}
private function getOption($option)
{
if (array_key_exists($option, $this->options)) {
return $this->options[$option];
}
return false;
}
}
Any clues? Do I call remove inputfilter of "passwordVerify" to early in the process of instantiation?
I also tested to remove the inputFilter and field after "$this->form->bind($user)" in my controller, which also works. Why it does not work then if I remove it in Admin\UserForm, which is in my opinion the cleaner way of managing the "passwordVerify"-stuff?
If you call $this->getInputFilter(), the InputProviderInterface::getInputSpecification method in your UserForm is being called.
If you did not attached the object already, it cannot retrieve it.
But I dont get why you would even need that. You are hashing the password if the value does not fit to the database value, but obviously the database value seems to be plain text as the input or why would you compare it?
IMHO you just should hash the password, no matter what the current value in your database is.
If you are using doctrine and the password wont change, it wont execute an UPDATE query anyway.

Secondary database connection with Doctrine 2 and ZF2

I am trying to add a extra connection to my doctrine configuration. my orm_default connection works perfectly fine, and now I'm trying to add a new module with its own Doctrine configuration (mostly learning purposes, buts its rather annoying that I can't get it to work).
The module is called Frontpage, and all relevant code is in this one, except for username/password details that resides in local.php...
My error is
Zend\ServiceManager\Exception\ServiceNotCreatedException
An exception was raised while creating "doctrine.entitymanager.orm_hosts"; no instance returned
Also further down the stacktrace (the last exception) which I think is relevant, but don't know how to fix...
Zend\Stdlib\Exception\BadMethodCallException
The option "hydration_cache" does not have a matching setHydrationCache setter method which must be defined
Here is my module config (relevant parts) file:
'doctrine' => [
'connection' => [
'orm_hosts' => [
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'params' => [
'host' => '127.0.0.1',
'port' => '3306',
'dbname' => 'hosts',
],
],
],
'entitymanager' => array(
'orm_hosts' => array(
'connection' => 'orm_hosts',
'configuration' => 'orm_hosts'
)
),
'configuration' => array(
'orm_hosts' => array(
'driver' => 'orm_hosts',
'generate_proxies' => true,
'proxy_dir' => 'data/DoctrineORMModule/Proxy',
'proxy_namespace' => 'DoctrineORMModule\Proxy',
'filters' => array(),
'metadata_cache' => 'array',
'query_cache' => 'array',
'result_cache' => 'array',
//'hydration_cache' => 'array',
)
),
'driver' => array(
'orm_hosts' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\DriverChain',
'drivers' => array(
'Common\Entity' => 'Hosts_Driver'
)
),
'Hosts_Driver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(
__DIR__ . '/../src/Common/Entity'
)
),
),
'eventmanager' => array(
'orm_hosts' => array()
),
'sql_logger_collector' => array(
'orm_hosts' => array(),
),
'entity_resolver' => array(
'orm_hosts' => array()
),
],
And my Module.php's getServiceConfig():
public function getServiceConfig()
{
return array(
'factories' => array(
'doctrine.connection.orm_hosts' => new Service\DBALConnectionFactory('orm_hosts'),
'doctrine.configuration.orm_hosts' => new Service\ConfigurationFactory('orm_hosts'),
'doctrine.entitymanager.orm_hosts' => new Service\EntityManagerFactory('orm_hosts'),
'doctrine.entity_resolver.orm_hosts' => new Service\EntityResolverFactory('orm_hosts'),
'doctrine.sql_logger_collector.orm_hosts' => new Service\SQLLoggerCollectorFactory('orm_hosts'),
'doctrine.driver.orm_hosts' => new \DoctrineModule\Service\DriverFactory('orm_hosts'),
'doctrine.eventmanager.orm_hosts' => new \DoctrineModule\Service\EventManagerFactory('orm_hosts'),
'DoctrineORMModule\Form\Annotation\AnnotationBuilder\orm_hosts' => function(\Zend\ServiceManager\ServiceLocatorInterface $sl) {
return new \DoctrineORMModule\Form\Annotation\AnnotationBuilder($sl->get('doctrine.entitymanager.orm_hosts'));
},
),
);
}
And here is my getEntityManager() in IndexController that fails
/**
* #return array|EntityManager|object
*/
public function getEntityManager() {
if (NULL === $this->em) {
/** #var \Doctrine\ORM\EntityManager $em */
$em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_hosts');
//$em = $this->getServiceLocator()->get('doctrine')->getManager("orm_hosts");
$this->em = $em;
}
return $this->em;
}
Any help will be gratly appreciated :)
Best regards
Richard
Okay, so I still don't know what is wrong with the above code, but if I remove
'Hydration_cache' => 'array'
In the doctrine configuration from my module config, it actually works! Still, if anyone want's to explain what happens, I would appreciate to know more :)

Multiple loggers

I'd like to create multiple loggers where different areas of my app will log to different files. For example, all the classes associated with getting the users data would log to a user.log, all functionality of making purchases going to a purchase.log. I am using the configuration array method for setting up the logger & appenders. In my index.php:
require_once('log4php/Logger.php');
require_once('classB.php');
require_once('classA.php');
Logger::configure(array(
'rootLogger' => array('appenders' => array('default')),
'classALogger' => array('appenders' => array('classAAppender')),
'appenders' => array(
'default' => array(
'class' => 'LoggerAppenderEcho',
'layout' => array(
'class' => 'LoggerLayoutSimple'
)
),'classAAppender' => array(
'class' => 'LoggerAppenderFile',
'additivity' => false,
'layout' => array(
'class' => 'LoggerLayoutSimple'
),
'params' => array(
'file' => 'log/classA.log',
'append' => true
)
)
),
));
$logger = Logger::getLogger("main");
$logger->info('message from index' . '<br>');
$classA = new ClassA();
$classA->test();
Class A is as follows:
class ClassA
{
public function test()
{
$logger = Logger::getLogger("classALogger");
$logger->error('from ClassA');
}
}
I am able to log to the default or root logger but am not able to log to, in this example, classALogger. Any suggestions?

ZF2 - Doctrine2 MongoDB ODM - "The class was not found in the chain configuration namespaces"

I've seen the same error posted often here and have read through and made changes based on the previous questions and answers, to no avail.
I have installed Doctrine's Mongo ODM with Zend Framework via Composer and completed the installation as described here
https://github.com/doctrine/DoctrineMongoODMModule
I have modified my /config/autoload/module.doctrine-mongo-odm.local.php file beyond the recommendations of the above documentation in an effort to fix my problem and based on answers to similar questions here, so that it now looks as follows
<?php
return array(
'doctrine' => array(
'connection' => array(
'odm_default' => array(
'server' => 'removed.mongolab.com',
'port' => '43957',
'user' => 'removed',
'password' => 'removed',
'dbname' => 'richard',
'options' => array()
),
),
'configuration' => array(
'odm_default' => array(
'metadata_cache' => 'array',
'driver' => 'odm_default',
'generate_proxies' => true,
'proxy_dir' => 'data/DoctrineMongoODMModule/Proxy',
'proxy_namespace' => 'DoctrineMongoODMModule\Proxy',
'generate_hydrators' => true,
'hydrator_dir' => 'data/DoctrineMongoODMModule/Hydrator',
'hydrator_namespace' => 'DoctrineMongoODMModule\Hydrator',
'default_db' => 'richard',
'filters' => array(),
'logger' => null
)
),
'odm_default' => array(
'drivers' => array(
'Application\Document' => 'odm_driver'
)
),
'odm_driver' => array(
'class' => 'Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(
'module/Application/src/Application/Document'
),
),
'documentmanager' => array(
'odm_default' => array(
'connection' => 'odm_default',
'configuration' => 'odm_default',
'eventmanager' => 'odm_default'
)
),
'eventmanager' => array(
'odm_default' => array(
'subscribers' => array()
)
),
),
);
I have a file /module/Application/src/Application/Document/User.php as follows
<?php
namespace Application\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations;
class User {
/** #ODM\Id */
private $id;
/** #ODM\Field(type="bin_data_timestamp") */
private $timestamp;
/** #ODM\Field(type="string") */
private $username;
/** #ODM\Field(type="bin_data_md5") */
private $password;
/** #ODM\Field(type="bin_data_uuid") */
private $salt;
/** #ODM\Field(type="string") */
private $realName;
/** #ODM\Field(type="string") */
private $email;
public function getId() {
return $this->id;
}
// ...
public function setId($id) {
$this->id = $id;
}
// ...
}
In my controller, I'm using the following code.
$dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');
$user = new User;
$user->setUsername("test");
$dm->persist($user);
$dm->flush();
However, I'm getting the infamous error
The class 'Application\Document\User' was not found in the chain configured namespaces
Any assistance would be greatly appreciated.
My configuration had become a bit confused, as it turns out. I was able to correct the issue with the following configuration code.
'driver' => array(
'odm_driver' => array(
'class' => 'Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver',
'paths' => array(__DIR__ . '/../../module/Application/src/Application/Document')
),
'odm_default' => array(
'drivers' => array(
'Application\Document' => 'odm_driver'
)
),
),
NB: The included code for Application\Document\User also produces errors, corrected with the following code.
namespace Application\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
/** #ODM\Document */
class User {
// ...
}

First optional routing segment acts as mandatory one for child routes

I have the following routing definition:
'admin_default' => array(
'type' => 'segment',
'options' => array(
'route' => '[/:lang]/administrator[/:module][/:action]',
'constraints' => array(
'lang' => '[a-zA-Z]{2}',
'module' => '[a-zA-Z0-9_-]*',
'action' => '[a-zA-Z0-9_-]*',
),
'defaults' => array(
'module' => 'Application',
'controller' => 'Admin',
'action' => 'index',
'lang' => 'ru'
),
),
'may_terminate' => true,
'child_routes' => array(
'wildcard' => array(
'type' => 'wildcard',
'may_terminate' => true,
'options' => array(
'key_value_delimiter' => '/',
'param_delimiter' => '/'
),
),
),
),
So, I can't get rid of segment [/:lang] in URL string
For example:
URL view helper $this->url('admin_default', array('module' => 'albums')) returns the following URL string:
/administrator/albums
while $this->url('admin_default/wildcard', array('module' => 'albums', 'action' => 'edit', 'id' => album_id_here)) returns:
/ru/administrator/albums/edit/id/album_id_here
How can I remove [/:lang] segment from URL string in second case?
so whats the matter with that "ru" ?
you have to extend the zend view helper URL to inject your current locale to the URL
look what i made for my current project :
<?php
namespace PatrickCore\View\Helper;
use Doctrine\ORM\EntityManager;
use Zend\View\Helper\Url;
class I18nUrl extends Url {
/**
* #var String
*/
protected $lang;
protected $router;
public function __construct($locale,$router) {
$arraylanguagemapping = array(
'en_US' => 'en',
'fa_IR' => 'fa'
);
$this->lang = $arraylanguagemapping[$locale];
$this->router = $router;
}
public function __invoke($name = null, array $params = array(), $options = array(), $reuseMatchedParams = false) {
$this->setRouter($this->router);
if (!array_key_exists('lang', $params)) {
$params['lang'] = $this->lang;
}
return parent::__invoke($name,$params,$options,$reuseMatchedParams);
}
}
?>

Categories