Fake IP on Codeception functional tests - yii2

I´m using Yii2 and Codeception to run tests.
When i run a functional test, the $SERVER['REMOTE_ADDR'] is not defined. How can i mockup the ip to use in those tests.
I have tried $SERVER['REMOTE_ADDR'] = '127.0.0.1', but it does not work.

Yesterday I faced with such problem, and I have found the solution! So, my solution related to Yii2 framework, but I think that you will be able to modify it for your environment.
Extend your codeception module (Yii2 for me):
<?php
namespace codeception;
use Codeception\Module\Yii2;
class CustomModule extends Yii2
{
protected function recreateClient()
{
parent::recreateClient();
if ($ip = ($this->config['ip'] ?? null)) {
$this->client->setServerParameter('REMOTE_ADDR', $ip);
}
}
}
Go to codeception.yaml config and set your ip:
actor: MyTester
modules:
enabled:
- \Helper\E2eCommon
- Asserts
- Mockery
# here
- \codeception\CustomModule:
configFile: 'codeception/_config/config.php'
- REST:
# here
depends: \codeception\CustomModule
part: Json
config:
# and here!
\codeception\CustomModule:
ip: 192.168.1.1 # ip mock here!
extensions:
enabled:
- \ResetYiiContainerExtension
that's all! enjoy :)

Create your functional Helper class under tests/_support (if it doesn't exist):
class FunctionalHelper extends \Codeception\Module {
public function _before(\Codeception\TestInterface $test)
{
$this->getModule('Yii2')->client->defaultServerVars = array_merge(
$this->getModule('Yii2')->client->defaultServerVars,
['REMOTE_ADDR' => '127.0.0.1']
);
}
}

For versions of codecept >=2.4 and <4.0 try to use something similar to:
class Helper extends \Codeception\Module
{
/**
* {#inheritdoc}
*/
public function _before(\Codeception\TestInterface $test)
{
$this->getModule('Yii2')->client->setServerParameter('REMOTE_ADDR', '127.0.0.1');
}
}
and don't forget to enable it in a *.suite.yml file:
modules:
enabled:
- \tests\Helper\Helper

Find 2 files (if project built on yii2-app-basic template - remove from path dir common/):
common/config/codeception-local.php
environments/dev/common/config/codeception-local.php
Add inside of array:
[
...
'on beforeAction' => static function () {
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
},
...
]

Related

I can't use Autoloader from Symfony2 in Symfony 1.4 for load this namespaced classes

I want to use this php library with namespaced classes in my Symfony 1.4 project: https://github.com/donquixote/cellbrush.
I'm not quite familiar with the namespaces concept. So when i fisrt try the to use the main class of this library, according to its docs, i just did:
$table = \Donquixote\Cellbrush\Table\Table::create();
And i got this fatal error:
Fatal error: Class 'Donquixote\Cellbrush\Table\Table' not found in D:\SF_ROOT_DIR\apps\frontend\modules\home\actions\actions.class.php
So i searched for a solution, and supposedly there is one: stackoverflow sol 1, stackoverflow sol 1 eg, but when i try to implement it i still get the above error.
My case:
Directories and files of interest:
D:\SF_ROOT_DIR\lib\autoload\sfClassLoader.class.php
D:\SF_ROOT_DIR\lib\vendor\ClassLoader (contains:
https://github.com/symfony/ClassLoader/tree/2.6)
D:\SF_ROOT_DIR\lib\vendor\cellbrush-1.0 (contains:
https://github.com/donquixote/cellbrush.)
Code:
SF_ROOT_DIR/config/ProjectConfiguration.class.php
require_once dirname(__FILE__).'/../lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php';
require_once dirname(__FILE__) . '/../lib/autoload/sfClassLoader.class.php';
use Symfony\Component\ClassLoader\UniversalClassLoader;
use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
sfCoreAutoload::register();
class ProjectConfiguration extends sfProjectConfiguration
{
public function setup()
{
$this->namespacesClassLoader();
$this->enableAllPluginsExcept('sfPropelPlugin');
}
public function namespacesClassLoader() {
if (extension_loaded('apc')) {
$loader = new ApcUniversalClassLoader('S2A');
} else {
$loader = new UniversalClassLoader();
}
$loader->registerNamespaces(array(
'Donquixote' => __DIR__ . '/../lib/vendor/cellbrush-1.0/src/Table'));
$loader->register();
}
}
actions.class.php
$table = \Donquixote\Cellbrush\Table\Table::create();
Thanks.
Use composer and its autoloading.
Execute:
composer require donquixote/cellbrush
Now the library is installed in vendor directory and autoloader is generated, you just need to include it. Add this line to the top of config/ProjectConfiguration.class.php:
require_once dirname(__FILE__).'/../vendor/autoload.php';

Upgrading Laravel 4.2 to 5.0, getting [ReflectionException] Class App\Http\Controllers\PagesController does not exist

I was updating my project from laravel 4.2 to laravel 5.0. But, after I am facing this error and have been trying to solve it for the past 4 hours.
I didn't face any error like this on the 4.2 version. I have tried composer dump-autoload with no effect.
As stated in the guide to update, I have shifted all the controllers as it is, and made the namespace property in app/Providers/RouteServiceProvider.php to null. So, I guess all my controllers are in global namespace, so don't need to add the path anywhere.
Here is my composer.json:
"autoload": {
"classmap": [
"app/console/commands",
"app/Http/Controllers",
"app/models",
"database/migrations",
"database/seeds",
"tests/TestCase.php"
],
Pages Controller :
<?php
class PagesController extends BaseController {
protected $layout = 'layouts.loggedout';
public function getIndex() {
$categories = Category::all();
$messages = Message::groupBy('receiver_id')
->select(['receiver_id', DB::raw("COUNT('receiver_id') AS total")])
->orderBy('total', 'DESC'.....
And, here is BaseController.
<?php
class BaseController extends Controller {
//Setup the layout used by the controller.
protected function setupLayout(){
if(!is_null($this->layout)) {
$this->layout = View::make($this->layout);
}
}
}
In routes.php, I am calling controller as follows :
Route::get('/', array('as' => 'pages.index', 'uses' => 'PagesController#getIndex'));
Anyone please help. I have been scratching my head over it for the past few hours.
Routes are loaded in the app/Providers/RouteServiceProvider.php file. If you look in there, you’ll see this block of code:
$router->group(['namespace' => $this->namespace], function($router)
{
require app_path('Http/routes.php');
});
This prepends a namespace to any routes, which by default is App\Http\Controllers, hence your error message.
You have two options:
Add the proper namespace to the top of your controllers.
Load routes outside of the group, so a namespace isn’t automatically prepended.
I would go with option #1, because it’s going to save you headaches in the long run.

Accessing config.yml variables in Bolt extensions

I've set up a clean extension and am trying to pull in info from the extension's config.yml file. Config.yml is placed inside the extension folder (at the same level as Extension.php).
At the moment I'm just testing to see if I can retrieve the config. Here's the whole Extension.php:
<?php
namespace Bolt\Extension\andyjessop\vimeo;
use Bolt\Events\CronEvent;
use Bolt\Events\CronEvents;
use Bolt\Application;
use Bolt\BaseExtension;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class Extension extends BaseExtension
{
public function initialize() {
$this->app->get('api/update_video_content', array($this, 'updateVideoContent'))
->bind('updateVideoContent');
}
public function getName()
{
return "vimeo";
}
public function updateVideoContent()
{
$config = $this->config['user_id'];
$response = $this->app->json($config);
return $response;
}
}
And in the config.yml:
access_token: xxxxxxxx
user_id: xxxx
api_base_url: https://api.vimeo.com/
But it returns an empty object. What am I doing wrong here?
Is your config called Config.yml.dist or config.yml.dist - note the capital C, it should be all lowercase? Other than that, after installation of your extension the config.yml.dist will be copied to app/config/extensions/{extensionname}.config.yml and the values in there will be used.

Namespaced helper won't load in Laravel 4

I have a controller that calls a helper class in my app/helpers directory and then that helpers calls another class within it's namespace, but it can't find that class.
So here is my controller:
<?php
namespace App\Controllers\Dash;
use \App\Models\SalesFlyer;
use \App\Helpers\MyPdf;
class FlyerBuilderController extends BaseController {
public function getPdf($flyerId = null) {
$flyer = new SalesFlyer();
$flyerData = $flyer->getSalesFlyerName($flyerId);
$flyerPath = public_path().'/assets/media/flyers/'.Session::get('userid').'/'.$flyerData->name.'-'.$flyerId.'.html';
return MyPdf::downloadPdf($flyerPath, $flyerData->name);
}
}
It catches MyPdf class perfectly fine. Here is MyPdf class:
<?php
namespace App\Helpers;
class MyPdf {
public static function downloadPdf($filePath, $filename) {
$client = new PdfCrowd("anthonythomas", "1ebd0d6e3ec1dfa83a6c5f3dd32906f0");
// other code here
}
}
The PdfCrowd class is within App\Helpers namespace like so:
<?php
namespace App\Helpers;
//
// Pdfcrowd API client.
//
class PdfCrowd { }
Class 'App\Helpers\PdfCrowd' not found
Here is my start/global.php file:
<?php
ClassLoader::addDirectories(array(
app_path().'/commands',
app_path().'/controllers',
app_path().'/controllers/dash',
app_path().'/controllers/dash/product',
app_path().'/models/Product',
app_path().'/models',
app_path().'/database/seeds',
app_path().'/helpers',
));
Then here is my composer:
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/controllers/dash",
"app/controllers/dash/product",
"app/models",
"app/models/Product",
"app/helpers",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
]
}
Any idea why I'm getting that error?..
Everything looks fine but you also have to remember to
composer dump-autoload
Every time you create a new class. Also, check the file
vendor/composer/autoload_classmap.php
You must see your Helper class there.
But if you use PSR-4, you can use the same namespace and you won't have execute composer dump-autoload again:
"autoload": {
"psr-4": {
"App\\Helpers\\": "app/helpers"
}
},
Just remember to remove "app/helpers", from the classmap.
Ok for a shared hosting provider... EVERYTIME you add a new namespace and update composer even with psr-4 it seems, you have to replace the vendor directory with the current one on your local machine for it to actually go through! This saved me so much hours of time after I realized I had to replace the vendor directory everytime a composer dump-autoload was issued locally.

Is there a way to specify Doctrine2 Entitymanager implementation class in Symfony2?

I'm currently working with Symfony2 and Doctrine2, but I must override the Doctrine2 EntityManager and add it some "undelete" features (ACLs inside).
So I'm wondering : is there a way to override the EntityManager class and specify Doctrine2 in Symfony2 to use it as implementation of the EntityManager?
Thank you for any help!
After Doctrine 2.4 (Doctrine 2.4 release) you need to use decorator for this. Do not extend EntityManager directly.
First you need to implement you own entity manager decorator that extends Doctrine\ORM\Decorator\EntityManagerDecorator (like #Dana)
But you can't just change doctrine.orm.entity_manager.class to your new decorator because EntityManagerDecorator requires EntityManagerInterface in it's constructor:
public function __construct(EntityManagerInterface $wrapped)
You can't just pass doctrine.orm.entity_manager as a parameter here because it will be a recursion.
And don't do like this:
return new self(\Doctrine\ORM\EntityManager::create(
What you need is to configure your decorator in services like a decorator:
yourcompany_entity_manager:
public: false
class: YourCompany\ORM\EntityManagerDecorator
decorates: doctrine.orm.default_entity_manager
arguments: ["#yourcompany_entity_manager.inner"]
Now you'll have your decorator as a default entity manager for Doctrine. #yourcompany_entity_manager.inner is actually a link to doctrine.orm.default_entity_manager that will be passed to yourcompany_entity_manager constructor.
Symfony docs for configuring decorators: link
Btw this command is very useful to debug your services:
app/console container:debug | grep entity_manager
Yes, it's possible with two steps:
1 - Override the doctrine.orm.entity_manager.class parameter to point to your custom entity manager (which should extend Doctrine\ORM\EntityManager.)
2 - Your custom entity manager must override the create method so that it returns an instance of your class. See my example below, and note the last line regarding MyEntityManager:
public static function create($conn, Configuration $config, EventManager $eventManager = null) {
if (!$config->getMetadataDriverImpl()) {
throw ORMException::missingMappingDriverImpl();
}
if (is_array($conn)) {
$conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, ($eventManager ? : new EventManager()));
} else if ($conn instanceof Connection) {
if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
throw ORMException::mismatchedEventManager();
}
} else {
throw new \InvalidArgumentException("Invalid argument: " . $conn);
}
// This is where you return an instance of your custom class!
return new MyEntityManager($conn, $config, $conn->getEventManager());
}
You'll also need to use the following in your class:
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\ORMException;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Connection;
To be honest, I'm surprised that the 2nd step is required at all, I would think this should be possible to accomplish using only the service container.
At least in Doctrine/ORM 2.4, the doc string of the EntityManager class explicitly discourages inheriting from Doctrine\ORM\EntityManager, instead they suggest inheriting from Doctrine\ORM\Decorator\EntityManagerDecorator:
/**
* The EntityManager is the central access point to ORM functionality.
* ...
* You should never attempt to inherit from the EntityManager: Inheritance
* is not a valid extension point for the EntityManager. Instead you
* should take a look at the {#see \Doctrine\ORM\Decorator\EntityManagerDecorator}
* and wrap your entity manager in a decorator.
* ...
*/
/* final */class EntityManager implements EntityManagerInterface
{
...
So, extend EntityManagerDecorator and make whatever changes you need. You will need to implement the create() factory method, but you don't need to copy EntityManager's implementation now:
use Doctrine\ORM\Decorator\EntityManagerDecorator;
use Doctrine\Common\EventManager;
use Doctrine\ORM\Configuration;
class MyEntityManager extends EntityManagerDecorator
{
/**
* {#inheritDoc}
*/
public function persist($entity)
{
// do something interesting
parent::persist($entity);
}
public function create($conn, Configuration $config, EventManager $eventManager = null)
{
return new self(\Doctrine\ORM\EntityManager::create($conn, $config, $eventManager));
}
}
Then override the doctrine.orm.entity_manager.class parameter to point to your custom entity manager class.
The docs don't cover everything, in many cases you just have to read the code.
I found the process of extending the entity manager extremely counterintuitive,
despite a decent grasp of concepts including dependency injection, service locator, code generation, caching and the decorator pattern.
Hopefully this concise example will paint a clear picture for you (this expands on the answer by #user2563451)
Symfony Version (Mon Aug 20 13:05:58 CEST 2018)
$ composer info | grep -E -e symfony/framework -e 'doctrine/(common|orm|dbal)'
doctrine/common v2.9.0 Common Library for Doctrine projects
doctrine/dbal v2.8.0 Database Abstraction Layer
doctrine/orm v2.6.2 Object-Relational-Mapper for PHP
symfony/framework-bundle v4.1.3 Symfony FrameworkBundle
config/services.yaml
App\Doctrine\ORM\CustomEntityManager:
public: false # optional afaik
decorates: doctrine.orm.original_entity_manager
arguments: [ '#App\Doctrine\ORM\CustomEntityManager.inner' ]
config/packages/doctrine.yaml
doctrine:
orm:
auto_generate_proxy_classes: '%kernel.debug%'
default_entity_manager: original
entity_managers:
original:
connection: from_env
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: false
mappings:
TimeTracking:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/php/Model'
prefix: TimeTracking\Model
alias: TimeTracking
mapping: true
#mapper_number_5:
# (...)
src/php/App/Doctrine/ORM/CustomEntityManager.php
<?php
namespace App\Doctrine\ORM;
use App\Doctrine\ORM\Proxy\SoggyProxyFactory;
use Doctrine\ORM\Decorator\EntityManagerDecorator;
use Doctrine\ORM\Proxy\ProxyFactory;
/**
* Writes custom proxy-class methods with support for the set-or-get-trait
* #property ProxyFactory soggyProxyFactory
*/
class CustomEntityManager extends EntityManagerDecorator
{
/// SUPER: __construct(EntityManagerInterface $wrapped) { $this->wrapped = $wrapped; }
private $soggyProxyFactory;
public function getProxyFactory() {
$config = $this->getConfiguration();
if (null === $this->soggyProxyFactory) {
$this->soggyProxyFactory = new SoggyProxyFactory(
$this,
$config->getProxyDir(),
$config->getProxyNamespace(),
$config->getAutoGenerateProxyClasses()
);
}
return $this->soggyProxyFactory;
}
}
references
http://symfony.com/doc/current/service_container/service_decoration.html
https://symfony.com/doc/current/doctrine/multiple_entity_managers.html