PHP RecursiveIteratorIterator empty when passed a RecursiveRegexIterator - php

A snapshot of Explorer class can be see below -
class Explorer
{
//....
public function getIterator()
{
//$iterator = new FileSearchIterator($this->baseDir, $this->pattern, $this->buildFlag());
if ($this->iterator) {
return $this->iterator;
}
$iterator = new RecursiveDirectoryIterator($this->baseDir, $this->buildFlag());
if ($this->ignoreVcsFiles) {
$this->ignore = array_merge($this->ignore, static::$vcsFiles);
}
if (!empty($this->ignore)) {
$iterator = new ExcludeFilter($iterator, $this->ignore);
}
if ($this->searchFor === static::SEARCH_FILES) {
$iterator = new FilenameRegexFilter($iterator, $this->pattern);
} else {
$iterator = new DirectoryRegexFilter($iterator, $this->pattern);
}
$this->iterator = new RecursiveIteratorIterator($iterator);
return $this->iterator;
}
//......
}
In Tests the given directory contains a single php file. But when filtering for only ****.php*** files using new FilenameRegexFilter(...) and then passing it through RecursiveIteratorIterator results in an empty RecursiveIteratorIterator instance.
You can see the rest of the filter classes (used above) below -
class ExcludeFilter extends \RecursiveFilterIterator
{
protected $iterator;
protected $ignore = [];
/**
* #inheritDoc
*/
public function __construct(\RecursiveIterator $iterator, array $ignore)
{
$this->iterator = $iterator;
$this->ignore = $ignore;
parent::__construct($iterator);
}
public function accept()
{
return !in_array($this->current()->getFilename(), $this->ignore, true);
}
public function getChildren()
{
$children = parent::getChildren();
$children->ignore = $this->ignore;
return $children;
}
}
class FilenameRegexFilter extends RecursiveRegexFilter
{
/**
* #inheritdoc
*/
public function accept()
{
return ($this->current()->isFile() && preg_match($this->regex, $this->current()->getFilename()));
}
/**
* #return \RecursiveRegexIterator
*/
public function getChildren()
{
$children = parent::getChildren();
$children->regex = $this->regex;
return $children;
}
}
abstract class RecursiveRegexFilter extends \RecursiveRegexIterator
{
protected $regex;
protected $iterator;
/**
* RegexFilter constructor.
* #param \RecursiveIterator $iterator
* #param string $regex
*/
public function __construct(\RecursiveIterator $iterator, $regex)
{
$this->iterator = $iterator;
$this->regex = $this->toRegex($regex);
parent::__construct($iterator, $this->regex);
}
/**
* #return \RecursiveRegexIterator
*/
public function getChildren()
{
$children = new static($this->iterator->getChildren(), $this->regex);
return $children;
}
/**
* #param $pattern
* #param array $options
* #return string
*/
public function toRegex($pattern, $options = [])
{
$pattern = str_replace(array('\*', '\?'), array('.*','.'), preg_quote($pattern));
$pattern = '/^' . $pattern . '$/';
if (!empty($options)) {
$pattern .= implode('', $options);
}
return $pattern;
}
}
class DirectoryRegexFilter extends RecursiveRegexFilter
{
public function accept()
{
return ($this->current()->isDir() || preg_match($this->regex, $this->current()->getFilename()));
}
}
I don't get where I'm going wrong. Can someone please point me in the right direction.
EDIT: To simplify my Question largely is how do I use RecursiveDirectoryIterator with RecursiveFilterIterator

Related

Looking for a design pattern to process or batch process

I have the following structure. Until this point each element could be processed one by one.
interface ProcessingStrategyInterface
{
public function process(Element $object): string;
}
class SomeListener
{
/**
* #var array<string, ProcessingStrategyInterface>
*/
protected array $processers;
public function __invoke(DocumentContent $event)
{
/**
* #var array<string, list<Element>> $elements
*/
$elementGroups = $event->getDynamicElements();
foreach ($elementGroups as $type => $elements) {
$processer = $this->processers[$type];
foreach ($elements as $element) {
$result = $processer->process($element);
}
}
// [...]
}
}
Now I have to add a new type of processer which takes the whole list<Element>, and processes them as one, then gives back a string result. For this a new interface could be defined.
interface BatchProcessingStrategyInterface
{
/**
* #param list<Element> $elements
*/
public function batchProcess(array $elements): string;
}
This solution I feel a little bit off:
class SomeListener
{
/**
* #var array<string, ProcessingStrategyInterface|BatchProcessingStrategyInterface>
*/
protected array $processers;
public function __invoke(DocumentContent $event)
{
/**
* #var array<string, list<Element>> $elements
*/
$elementGroups = $event->getDynamicElements();
foreach ($elementGroups as $type => $elements) {
$processer = $this->processers[$type];
if ($processer instanceof BatchProcessingStrategyInterface) {
$result = $processer->batchProcess($elements);
} else {
foreach ($elements as $element) {
$result = $processer->process($element);
}
}
}
// [...]
}
}
I'm wondering if there is a way to solve this in a 100% type-strict way? What I want to achieve is to have single types everywhere by calling them the following way:
class SomeListener
{
/**
* #var array<string, ProcessingStrategyInterface>
*/
protected array $processers;
public function __invoke(DocumentContent $event)
{
/**
* #var array<string, list<Element>> $elements
*/
$elementGroups = $event->getDynamicElements();
foreach ($elementGroups as $type => $elements) {
$processer = $this->processers[$type];
$result = $processer->process($elements);
}
// [...]
}
}
I just came up with a solution with which I can keep to code type-hinted. Basically I just moved the logic a level up into the processor.
interface ProcessingStrategyInterface
{
/**
* #param list<Element> $elements
*/
public function process(array $elements): string;
}
class ProcesserA implements ProcessingStrategyInterface
{
public function process(array $elements): string
{
foreach ($elements as $element) {
$this->processElement($element);
}
}
protected function processElement(Element $element): string
{
// logic
}
}
class BatchProcesserA implements ProcessingStrategyInterface
{
public function process(array $elements): string
{
foreach ($elements as $element) {
$this->processElement($element);
}
}
}
I am not sure, but if I were you, I would make smth like this:
interface ProcessingStrategyInterface {
/**
* #param Element $elements
*/
public function process( Element $elements ): string;
}
interface BatchProcessingStrategyInterface
{
/**
* #param list<Element> $elements
*/
public function process(array $elements): string;
}
class ProcesserA implements ProcessingStrategyInterface {
public function process( Element $element ): string {
// logic
}
}
class BatchProcesserA implements BatchProcessingStrategyInterface {
private ProcessingStrategyInterface $strategy;
public function process( array $elements ): string {
foreach ( $elements as $element ) {
$this->strategy->processElement( $element );
}
}
}

Function and variables issue

I have a problem.. When I execute this code:
public function korisnici(){
$modelk = new Korisnici();
$upit = $modelk::find()->asArray()->orderBy('id DESC')->all();
$items = [];
foreach ($upit as $key => $value) {
foreach ($value as $kljuc => $vrijednost){
$items[] = [$kljuc => $vrijednost];
}
}
return $items;
}
private static $users = $this->korisnici();
It gives me this error: syntax error, unexpected '$this' (T_VARIABLE)..
Can someone help me, how can I call this function?
Here's my whole class:
class User extends \yii\base\Object implements \yii\web\IdentityInterface
{
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;
public $arr;
public function korisnici(){
$modelk = new Korisnici();
$upit = $modelk::find()->asArray()->orderBy('id DESC')->all();
$items = [];
foreach ($upit as $key => $value) {
foreach ($value as $kljuc => $vrijednost){
$items[] = [$kljuc => $vrijednost];
}
}
return $items;
}
public $users = $this->korisnici();
/**
* #inheritdoc
*/
public static function findIdentity($id)
{
return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
foreach (self::$users as $user) {
if ($user['accessToken'] === $token) {
return new static($user);
}
}
return null;
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username)
{
foreach (self::$users as $user) {
if (strcasecmp($user['username'], $username) === 0) {
return new static($user);
}
}
return null;
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->id;
}
/**
* #inheritdoc
*/
public function getAuthKey()
{
return $this->authKey;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return $this->password === $password;
}
}
I'm trying to change this default model from Yii Framework so I can login using database...
Looks like you have copied it from a class. The following will work like a regular function. Still not sure where you get $modelk = new Korisnici(); from
function korisnici(){
$modelk = new Korisnici();
$upit = $modelk::find()->asArray()->orderBy('id DESC')->all();
$items = [];
foreach ($upit as $key => $value) {
foreach ($value as $kljuc => $vrijednost){
$items[] = [$kljuc => $vrijednost];
}
}
return $items;
}
print_r(korisnici());
EDIT: After looking at your whole class:
You need to use the __construct method.
public function __construct()
{
$this->users = $this->korisnici();
}

Update a record through model in zend framework

I am having a model and would need to update the record. every time $count ($count = $post->save()) is being NULL. how is it possible to know whether this record saved or not. if saved, i want to display the following message 'Post updated' and if not the other message 'Post cannot update'.
This is always going to the else port. how can i know model updated correctly or not?
$post = new Application_Model_Post($form->getValues());
$post->setId($id);
$count = $post->save();
//var_dump($count); exit;
if ($count > 0) {
$this->_helper->flashMessenger->addMessage('Post updated');
} else {
$this->_helper->flashMessenger->addMessage('Post cannot update');
}
Application_Model_Post code is as below,
class Application_Model_Post
{
/**
* #var int
*/
protected $_id;
/**
* #var string
*/
protected $_title;
/**
* #var string
*/
protected $_body;
/**
* #var string
*/
protected $_created;
/**
* #var string
*/
protected $_updated;
/**
* #var Application_Model_PostMapper
*/
protected $_mapper;
/**
* Class Constructor.
*
* #param array $options
* #return void
*/
public function __construct(array $options = null)
{
if (is_array($options)) {
$this->setOptions($options);
}
}
public function setOptions(array $options)
{
$methods = get_class_methods($this);
foreach ($options as $key=> $value) {
$method = 'set'.ucfirst($key);
if (in_array($method, $methods)) {
$this->$method($value);
}
}
return $this;
}
public function setId($id)
{
$this->_id = $id;
return $this;
}
public function getId()
{
return $this->_id;
}
public function setTitle($title)
{
$this->_title = (string) $title;
return $this;
}
public function getTitle()
{
return $this->_title;
}
public function setBody($body)
{
$this->_body = $body;
return $this;
}
public function getBody()
{
return $this->_body;
}
public function setCreated($ts)
{
$this->_created = $ts;
return $this;
}
public function getCreated()
{
return $this->_created;
}
/**
* Set data mapper.
*
* #param mixed $mapper
* #return Application_Model_Post
*/
public function setMapper($mapper)
{
$this->_mapper = $mapper;
return $this;
}
/**
* Get data mapper.
*
* Lazy loads Application_Model_PostMapper instance if no mapper
* registered.
*
* #return Application_Model_PostMapper
*/
public function getMapper()
{
if (null === $this->_mapper) {
$this->setMapper(new Application_Model_PostMapper());
}
return $this->_mapper;
}
/**
* Save the current post.
*
* #return void
*/
public function save()
{
$this->getMapper()->save($this);
}
public function getPost($id)
{
return $this->getMapper()->getPost($id);
}
/**
* Update the current post.
*
* #return void
*/
public function update($data, $where)
{
$this->getMapper()->update($data, $where);
}
/**
* Find a post.
*
* Resets entry state if matching id found.
*
* #param int $id
* #return Application_Model_Post
*/
public function find($id)
{
$this->getMapper()->find($id, $this);
return $this;
}
/**
* Fetch all posts.
*
* #return array
*/
public function fetchAll()
{
return $this->getMapper()->fetchAll();
}
}
getMapper refers to the class Application_Model_PostMapper.
class Application_Model_PostMapper
{
public function save(Application_Model_Post $post)
{
$data = array(
'title'=>$post->getTitle(),
'body'=>$post->getBody(),
'created'=>$post->getCreated()
);
if (null === ($id = $post->getId())) {
unset($data['id']);
$data['created'] = date('Y-m-d H:i:s');
$post->setId($this->getDbTable()->insert($data));
} else {
$this->getDbTable()->update($data, array('id = ?'=>$id));
}
}
public function getDbTable()
{
if (null === $this->_dbTable) {
$this->setDbTable('Application_Model_DbTable_Post');
}
return $this->_dbTable;
}
}
Class of Application_Model_DbTable_Post
class Application_Model_DbTable_Post extends Zend_Db_Table_Abstract
{
protected $_name = 'posts';
}
Let me know if anything is incorrect. i am a newbie to zend and did thsi while referring the zend site. http://framework.zend.com/manual/1.12/en/learning.quickstart.create-model.html
you can extend your script like this. zend dbtable triggers the Zend_Db_Exception on any error during any insert or update.
class Application_Model_PostMapper
{
public function save(Application_Model_Post $post)
{
$data = array(
'title'=>$post->getTitle(),
'body'=>$post->getBody(),
'created'=>$post->getCreated()
);
try {
if (null === ($id = $post->getId())) {
unset($data['id']);
$data['created'] = date('Y-m-d H:i:s');
$post->setId($this->getDbTable()->insert($data));
} else {
$this->getDbTable()->update($data, array('id = ?'=>$id));
}
} catch (Zend_Db_Exception $e) {
// error thrown by dbtable class
return $e->getMessage();
}
// no error
return true;
}
}
now you can check like this
$post = new Application_Model_Post($form->getValues());
$post->setId($id);
$isSaved = $post->save();
if ($isSaved === true) {
$this->_helper->flashMessenger->addMessage('Post updated');
} else {
// error
// $isSaved holds the error message
$this->_helper->flashMessenger->addMessage('Post cannot update');
}

PHP RecursiveIterator traversing

I have a structure representing a form and I want to iterate it using RecursiveIterator.
The problem is this only returns the top-level questions. What am I doing wrong?
Whole form:
class Form implements RecursiveIterator{
private $id;
private $caption;
private $other_text;
private $questions = array();
private $current;
private function __construct(DibiRow $row){
$this->id = $row->id;
$this->caption = $row->caption;
$this->other_text = $row->other_text;
$this->loadQuestions();
}
private function loadQuestions(){
$questions = dibi::query('SELECT * FROM cyp_questions WHERE form_id = %i AND parent_id IS NULL', $this->id);
while($question = $questions->fetch()) $this->questions[] = new Question($question->question_id, $question->type, $question->caption, $question->other_text, $question->triggers_unique == 1);
}
/**
* #throws InvalidArgumentException
* #param $id
* #return Form
*/
public static function loadById($id){
$form = dibi::query('SELECT * FROM cyp_forms WHERE id = %i', $id)->fetch();
if($form === false) throw new InvalidArgumentException('Form with id '.$id.' was not found.');
return new Form($form);
}
/**
* #throws FormFieldException
* #return bool
*/
public function validate($postfields){
}
public function getQuestions(){
return $this->questions;
}
public function getChildren(){
return $this->questions[$this->current];
}
public function hasChildren(){
return count($this->questions) > 0;
}
public function current(){
return $this->questions[$this->current];
}
public function key(){
return $this->current;
}
public function next(){
$this->current++;
}
public function rewind(){
$this->current = 0;
}
public function valid(){
return isset($this->questions[$this->current]);
}
}
Question:
class Question implements RecursiveIterator{
private $id;
private $type;
private $answers = array();
private $subquestions = array();
private $other_text;
private $triggers_unique;
private $caption;
private $current = 0;
public function __construct($id, $type, $caption, $other_text = null, $triggers_unique = false){
$this->id = $id;
$this->type = $type;
$this->caption = $caption;
$this->other_text = $other_text;
$this->triggers_unique = $triggers_unique;
$this->setSubQuestions();
}
private function setSubQuestions(){
$questions = dibi::query('SELECT * FROM cyp_questions WHERE parent_id = %i', $this->id);
while($question = $questions->fetch()) $this->subquestions[] = new Question($question->question_id, $question->type, $question->caption, $question->other_text, $question->triggers_unique == 1);
}
public function getOtherText(){
return $this->other_text;
}
public function getCaption(){
return $this->caption;
}
public function addAnswer($answer){
$this->answers[] = $answer;
}
public function getChildren(){
return $this->subquestions[$this->current];
}
public function hasChildren(){
return count($this->subquestions) > 0;
}
public function current(){
return $this->subquestions[$this->current];
}
public function key(){
return $this->id;
}
public function next(){
++$this->current;
}
public function rewind(){
$this->current = 0;
}
public function valid(){
return isset($this->subquestions[$this->current]);
}
public function getAnswers(){
return $this->answers;
}
}
Iteration:
$form = Form::loadById(1);
foreach($form as $question){
echo $question->getCaption().'<br />';
}
To iterate over a RecursiveIterator, you have to wrap it into a RecursiveIteratorIterator.
See some examples at
Introduction to Spl
SplWiki
The default iteration mode is only to list leaves. If you also want the containing nodes to appear in the iteration, pass RecursiveIteratorIterator::SELF_FIRST as the second argument to the constructor of the RecursiveIteratorIterator
Well, as you can see here
public RecursiveIterator RecursiveIterator::getChildren ( void )
Returns an iterator for the current iterator entry.
the method should return an object implementing the iterator. Your method return a simple array.
My guess would be to return something like:
public function getChildren(){
return new Question($this->subquestions);
}
This is because you're using a RECURSIVE iterator so it's expected to have each node of the tree of the same type (an iterator)

Fatal error: Declaration of registerContainerConfiguration must be compatible with that of Kernel::registerContainerConfiguration

Do anyone know why this occurs?
as far I can get, the child class method is declared in the same way as parent's.
Thanks!
here is my kernel code:
<?php
require_once __DIR__.'/../src/autoload.php';
use Symfony\Framework\Kernel;
use Symfony\Components\DependencyInjection\Loader\YamlFileLoader as ContainerLoader;
use Symfony\Components\Routing\Loader\YamlFileLoader as RoutingLoader;
use Symfony\Framework\KernelBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\ZendBundle\ZendBundle;
use Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle;
use Symfony\Bundle\DoctrineBundle\DoctrineBundle;
use Symfony\Bundle\DoctrineMigrationsBundle\DoctrineMigrationsBundle;
use Symfony\Bundle\DoctrineMongoDBBundle\DoctrineMongoDBBundle;
use Symfony\Bundle\PropelBundle\PropelBundle;
use Symfony\Bundle\TwigBundle\TwigBundle;
use Application\UfaraBundle\UfaraBundle;
class UfaraKernel extends Kernel {
public function registerRootDir() {
return __DIR__;
}
public function registerBundles() {
$bundles = array(
new KernelBundle(),
new FrameworkBundle(),
new ZendBundle(),
new SwiftmailerBundle(),
new DoctrineBundle(),
//new DoctrineMigrationsBundle(),
//new DoctrineMongoDBBundle(),
//new PropelBundle(),
//new TwigBundle(),
new UfaraBundle(),
);
if ($this->isDebug()) {
}
return $bundles;
}
public function registerBundleDirs() {
$bundles = array(
'Application' => __DIR__.'/../src/Application',
'Bundle' => __DIR__.'/../src/Bundle',
'Symfony\\Framework' => __DIR__.'/../src/vendor/symfony/src/Symfony/Framework',
'Symfony\\Bundle' => __DIR__.'/../src/vendor/symfony/src/Symfony/Bundle',
);
return $bundles;
}
public function registerContainerConfiguration(LoaderInterface $loader) {
return $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
}
public function registerRoutes() {
$loader = new RoutingLoader($this->getBundleDirs());
return $loader->load(__DIR__.'/config/routing.yml');
}
}
here is the parent class code:
<?php
namespace Symfony\Framework;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\Resource\FileResource;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Loader\DelegatingLoader;
use Symfony\Component\DependencyInjection\Loader\LoaderResolver;
use Symfony\Component\DependencyInjection\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Framework\ClassCollectionLoader;
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier#symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* The Kernel is the heart of the Symfony system. It manages an environment
* that can host bundles.
*
* #author Fabien Potencier <fabien.potencier#symfony-project.org>
*/
abstract class Kernel implements HttpKernelInterface, \Serializable
{
protected $bundles;
protected $bundleDirs;
protected $container;
protected $rootDir;
protected $environment;
protected $debug;
protected $booted;
protected $name;
protected $startTime;
protected $request;
const VERSION = '2.0.0-DEV';
/**
* Constructor.
*
* #param string $environment The environment
* #param Boolean $debug Whether to enable debugging or not
*/
public function __construct($environment, $debug)
{
$this->environment = $environment;
$this->debug = (Boolean) $debug;
$this->booted = false;
$this->rootDir = realpath($this->registerRootDir());
$this->name = basename($this->rootDir);
if ($this->debug) {
ini_set('display_errors', 1);
error_reporting(-1);
$this->startTime = microtime(true);
} else {
ini_set('display_errors', 0);
}
}
public function __clone()
{
if ($this->debug) {
$this->startTime = microtime(true);
}
$this->booted = false;
$this->container = null;
$this->request = null;
}
abstract public function registerRootDir();
abstract public function registerBundles();
abstract public function registerBundleDirs();
abstract public function registerContainerConfiguration(LoaderInterface $loader);
/**
* Checks whether the current kernel has been booted or not.
*
* #return boolean $booted
*/
public function isBooted()
{
return $this->booted;
}
/**
* Boots the current kernel.
*
* This method boots the bundles, which MUST set
* the DI container.
*
* #throws \LogicException When the Kernel is already booted
*/
public function boot()
{
if (true === $this->booted) {
throw new \LogicException('The kernel is already booted.');
}
if (!$this->isDebug()) {
require_once __DIR__.'/bootstrap.php';
}
$this->bundles = $this->registerBundles();
$this->bundleDirs = $this->registerBundleDirs();
$this->container = $this->initializeContainer();
// load core classes
ClassCollectionLoader::load(
$this->container->getParameter('kernel.compiled_classes'),
$this->container->getParameter('kernel.cache_dir'),
'classes',
$this->container->getParameter('kernel.debug'),
true
);
foreach ($this->bundles as $bundle) {
$bundle->setContainer($this->container);
$bundle->boot();
}
$this->booted = true;
}
/**
* Shutdowns the kernel.
*
* This method is mainly useful when doing functional testing.
*/
public function shutdown()
{
$this->booted = false;
foreach ($this->bundles as $bundle) {
$bundle->shutdown();
$bundle->setContainer(null);
}
$this->container = null;
}
/**
* Reboots the kernel.
*
* This method is mainly useful when doing functional testing.
*
* It is a shortcut for the call to shutdown() and boot().
*/
public function reboot()
{
$this->shutdown();
$this->boot();
}
/**
* Gets the Request instance associated with the master request.
*
* #return Request A Request instance
*/
public function getRequest()
{
return $this->request;
}
/**
* Handles a request to convert it to a response by calling the HttpKernel service.
*
* #param Request $request A Request instance
* #param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
* #param Boolean $raw Whether to catch exceptions or not
*
* #return Response $response A Response instance
*/
public function handle(Request $request = null, $type = HttpKernelInterface::MASTER_REQUEST, $raw = false)
{
if (false === $this->booted) {
$this->boot();
}
if (null === $request) {
$request = $this->container->get('request');
} else {
$this->container->set('request', $request);
}
if (HttpKernelInterface::MASTER_REQUEST === $type) {
$this->request = $request;
}
$response = $this->container->getHttpKernelService()->handle($request, $type, $raw);
$this->container->set('request', $this->request);
return $response;
}
/**
* Gets the directories where bundles can be stored.
*
* #return array An array of directories where bundles can be stored
*/
public function getBundleDirs()
{
return $this->bundleDirs;
}
/**
* Gets the registered bundle names.
*
* #return array An array of registered bundle names
*/
public function getBundles()
{
return $this->bundles;
}
/**
* Checks if a given class name belongs to an active bundle.
*
* #param string $class A class name
*
* #return Boolean true if the class belongs to an active bundle, false otherwise
*/
public function isClassInActiveBundle($class)
{
foreach ($this->bundles as $bundle) {
$bundleClass = get_class($bundle);
if (0 === strpos($class, substr($bundleClass, 0, strrpos($bundleClass, '\\')))) {
return true;
}
}
return false;
}
/**
* Returns the Bundle name for a given class.
*
* #param string $class A class name
*
* #return string The Bundle name or null if the class does not belongs to a bundle
*/
public function getBundleForClass($class)
{
$namespace = substr($class, 0, strrpos($class, '\\'));
foreach (array_keys($this->getBundleDirs()) as $prefix) {
if (0 === $pos = strpos($namespace, $prefix)) {
return substr($namespace, strlen($prefix) + 1, strpos($class, 'Bundle\\') + 7);
}
}
}
public function getName()
{
return $this->name;
}
public function getSafeName()
{
return preg_replace('/[^a-zA-Z0-9_]+/', '', $this->name);
}
public function getEnvironment()
{
return $this->environment;
}
public function isDebug()
{
return $this->debug;
}
public function getRootDir()
{
return $this->rootDir;
}
public function getContainer()
{
return $this->container;
}
public function getStartTime()
{
return $this->debug ? $this->startTime : -INF;
}
public function getCacheDir()
{
return $this->rootDir.'/cache/'.$this->environment;
}
public function getLogDir()
{
return $this->rootDir.'/logs';
}
protected function initializeContainer()
{
$class = $this->getSafeName().ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
$location = $this->getCacheDir().'/'.$class;
$reload = $this->debug ? $this->needsReload($class, $location) : false;
if ($reload || !file_exists($location.'.php')) {
$this->buildContainer($class, $location.'.php');
}
require_once $location.'.php';
$container = new $class();
$container->set('kernel', $this);
return $container;
}
public function getKernelParameters()
{
$bundles = array();
foreach ($this->bundles as $bundle) {
$bundles[] = get_class($bundle);
}
return array_merge(
array(
'kernel.root_dir' => $this->rootDir,
'kernel.environment' => $this->environment,
'kernel.debug' => $this->debug,
'kernel.name' => $this->name,
'kernel.cache_dir' => $this->getCacheDir(),
'kernel.logs_dir' => $this->getLogDir(),
'kernel.bundle_dirs' => $this->bundleDirs,
'kernel.bundles' => $bundles,
'kernel.charset' => 'UTF-8',
'kernel.compiled_classes' => array(),
),
$this->getEnvParameters()
);
}
protected function getEnvParameters()
{
$parameters = array();
foreach ($_SERVER as $key => $value) {
if ('SYMFONY__' === substr($key, 0, 9)) {
$parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
}
}
return $parameters;
}
protected function needsReload($class, $location)
{
if (!file_exists($location.'.meta') || !file_exists($location.'.php')) {
return true;
}
$meta = unserialize(file_get_contents($location.'.meta'));
$time = filemtime($location.'.php');
foreach ($meta as $resource) {
if (!$resource->isUptodate($time)) {
return true;
}
}
return false;
}
protected function buildContainer($class, $file)
{
$parameterBag = new ParameterBag($this->getKernelParameters());
$container = new ContainerBuilder($parameterBag);
foreach ($this->bundles as $bundle) {
$bundle->registerExtensions($container);
if ($this->debug) {
$container->addObjectResource($bundle);
}
}
if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
$container->merge($cont);
}
$container->freeze();
foreach (array('cache', 'logs') as $name) {
$dir = $container->getParameter(sprintf('kernel.%s_dir', $name));
if (!is_dir($dir)) {
if (false === #mkdir($dir, 0777, true)) {
die(sprintf('Unable to create the %s directory (%s)', $name, dirname($dir)));
}
} elseif (!is_writable($dir)) {
die(sprintf('Unable to write in the %s directory (%s)', $name, $dir));
}
}
// cache the container
$dumper = new PhpDumper($container);
$content = $dumper->dump(array('class' => $class));
if (!$this->debug) {
$content = self::stripComments($content);
}
$this->writeCacheFile($file, $content);
if ($this->debug) {
$container->addObjectResource($this);
// save the resources
$this->writeCacheFile($this->getCacheDir().'/'.$class.'.meta', serialize($container->getResources()));
}
}
protected function getContainerLoader(ContainerInterface $container)
{
$resolver = new LoaderResolver(array(
new XmlFileLoader($container, $this->getBundleDirs()),
new YamlFileLoader($container, $this->getBundleDirs()),
new IniFileLoader($container, $this->getBundleDirs()),
new PhpFileLoader($container, $this->getBundleDirs()),
new ClosureLoader($container),
));
return new DelegatingLoader($resolver);
}
/**
* Removes comments from a PHP source string.
*
* We don't use the PHP php_strip_whitespace() function
* as we want the content to be readable and well-formatted.
*
* #param string $source A PHP string
*
* #return string The PHP string with the comments removed
*/
static public function stripComments($source)
{
if (!function_exists('token_get_all')) {
return $source;
}
$output = '';
foreach (token_get_all($source) as $token) {
if (is_string($token)) {
$output .= $token;
} elseif (!in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
$output .= $token[1];
}
}
// replace multiple new lines with a single newline
$output = preg_replace(array('/\s+$/Sm', '/\n+/S'), "\n", $output);
// reformat {} "a la python"
$output = preg_replace(array('/\n\s*\{/', '/\n\s*\}/'), array(' {', ' }'), $output);
return $output;
}
protected function writeCacheFile($file, $content)
{
$tmpFile = tempnam(dirname($file), basename($file));
if (false !== #file_put_contents($tmpFile, $content) && #rename($tmpFile, $file)) {
chmod($file, 0644);
return;
}
throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
}
public function serialize()
{
return serialize(array($this->environment, $this->debug));
}
public function unserialize($data)
{
list($environment, $debug) = unserialize($data);
$this->__construct($environment, $debug);
}
}
Your answer lies in the imported namespaces. In the Kernel's file, there's this use clause:
use Symfony\Component\DependencyInjection\Loader\LoaderInterface;
So that ties LoaderInterface to the fully namespaced class Symfony\Component\DependencyInjection\Loader\LoaderInterface.
Basically making the signature:
public function registerContainerConfiguration(Symfony\Component\DependencyInjection\Loader\LoaderInterface $loader);
In your class, you don't import that namespace. So PHP by default assumes the class is in your namespace (since none of the imported namespaces have that interface name).
So your signature is (since you don't declare a namespace):
public function registerContainerConfiguration(\LoaderInterface $loader);
So to get them to match, simply add the use line to the top of your file:
use Symfony\Component\DependencyInjection\Loader\LoaderInterface;

Categories