GoAOP framework, can't get simple Aspect to work - goaop

I have been trying to play with the GoAOP library for awhile and have never successfully been able to get it to work. I have gone through the documentation several times and copied examples but haven't even been able to get them to work. All I am trying to achieve right now is a simple aspect.
I have several files as below:
app/ApplicationAspectKernel.php
<?php
require './aspect/MonitorAspect.php';
use Go\Core\AspectKernel;
use Go\Core\AspectContainer;
/**
* Application Aspect Kernel
*/
class ApplicationAspectKernel extends AspectKernel
{
/**
* Configure an AspectContainer with advisors, aspects and pointcuts
*
* #param AspectContainer $container
*
* #return void
*/
protected function configureAop(AspectContainer $container)
{
$container->registerAspect(new Aspect\MonitorAspect());
}
}
init.php
<?php
require './vendor/autoload.php';
require_once './ApplicationAspectKernel.php';
// Initialize an application aspect container
$applicationAspectKernel = ApplicationAspectKernel::getInstance();
$applicationAspectKernel->init(array(
'debug' => true, // Use 'false' for production mode
// Cache directory
'cacheDir' => __DIR__ . '/cache/', // Adjust this path if needed
// Include paths restricts the directories where aspects should be applied, or empty for all source files
'includePaths' => array(__DIR__ . '/app/')
));
require_once './app/Example.php';
$e = new Example();
$e->test1();
$e->test2('parameter');
aspect/MonitorAspect.php
<?php
namespace Aspect;
use Go\Aop\Aspect;
use Go\Aop\Intercept\FieldAccess;
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\After;
use Go\Lang\Annotation\Before;
use Go\Lang\Annotation\Around;
use Go\Lang\Annotation\Pointcut;
/**
* Monitor aspect
*/
class MonitorAspect implements Aspect
{
/**
* Method that will be called before real method
*
* #param MethodInvocation $invocation Invocation
* #Before("execution(public Example->*(*))")
*/
public function beforeMethodExecution(MethodInvocation $invocation)
{
$obj = $invocation->getThis();
echo 'Calling Before Interceptor for method: ',
is_object($obj) ? get_class($obj) : $obj,
$invocation->getMethod()->isStatic() ? '::' : '->',
$invocation->getMethod()->getName(),
'()',
' with arguments: ',
json_encode($invocation->getArguments()),
"<br>\n";
}
}
app/Example.php
<?php
class Example {
public function test1() {
print 'test1' . PHP_EOL;
}
public function test2($param) {
print $param . PHP_EOL;
}
}
When I run php init.php it does run but just prints without the output from MonitorAspect. I don't know if I'm defining the pointcut wrong in the #Before (I've tried several variations) or if I just have a fundamental misunderstanding of how this code is suppose to work.
Any help to point me in the right direction would be greatly appreciated.

GoAOP framework was designed to work with autoloader this means that it can handle only classes that were loaded indirectly via composer autoloader.
When you manually include you class via require_once './app/Example.php'; class is loaded by PHP immediately and could not be transformed by AOP, so nothing happens, because class is already present in the PHP's memory.
In order to make AOP working you should delegate class loading to the Composer and use PSR-0/PSR-4 standard for your classes. In this case, AOP will hook autoloading process and will perform transformation when needed.
See my answer about how AOP works in plain PHP that doesn't require any PECL-extentions for additional details about internals of the framework. This information should be useful for you.

Related

How do I pass data to a component in Laravel Livewire?

class Counter extends Component
{
public $counter = 0;
public $name;
public function mount($name)
{
$this->name = $name;
}
public function render()
{
return view('livewire.counter');
}
}
I'm trying to pass the name variable as parameter to the livewire component call like so #livewire('counter', ['name' => $name]) but receiving "Undefined variable $name" error. I have been following the livewire docs too, still same error. what could possibly be wrong? Thank you.
If $name is not defined, then it is not a property available in the blade file where you are including Livewire. Since we don't know anything about your blade file or controllers, I can't give you a direct answer. However, you should check if $name is set anywhere and if so, if it's available in your blade view. This error is not related to Livewire. If you've simply copied the docs without checking the variables, you might as well set it right away:
#livewire('counter', ['name' => 'Gilles'])

I am trying to alter route in my custon module. But it is already overridden in one of the contrib module

I tried to altered route it didn't work in my custom module. it is taking the altered path from contributed module. then i tried to extend the routesubscriber.php from extended module but its still didn't work.
I have cleared cache, rebuild routes, and tried to adjust weight for my custom module giving it highest weight. But still didn't work.
If anyone call help with this issue, it will be great help.
this is MyAppsRouteSubscriber.php
<?php
namespace Drupal\MyApps\Routing;
use Drupal\MyApps\Entity\ListBuilder\DeveloperAppListBuilder;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
use Drupal\apigee_kickstart_enhancement\Routing\RouteSubscriber;
/**
* Custom MyAppsRouteSubscriber for MyApps.
*/
class MyAppsRouteSubscriber extends RouteSubscriber
{
protected function alterRoutes(RouteCollection $collection)
{
// Override the controller for the Apigee Kickstart Enhancement.
/** #var \Drupal\Core\Entity\EntityTypeInterface $app_entity_type */
foreach (\Drupal::service('apigee_kickstart.enhancer')->getAppEntityTypes() as $entity_type_id => $app_entity_type) {
if ($route = $collection->get("entity.$entity_type_id.collection_by_" . str_replace('_app', '', $entity_type_id))) {
if ($entity_type_id == 'team_app') {
$route->setDefault('_controller', TeamAppListBuilder::class . '::render');
} else {
$route->setDefault('_controller', DeveloperAppListBuilder::class . '::render');
}
}
}
}
}
and i have DeveloperAppListBuilder.php
<?php
namespace Drupal\MyApps\Entity\ListBuilder;
use Drupal\apigee_edge\Entity\DeveloperAppRouteProvider;
use Drupal\apigee_edge\Entity\ListBuilder\DeveloperAppListBuilderForDeveloper;
/**
* Renders the Apps list as a list of entity views instead of a table.
*/
class DeveloperAppListBuilder extends DeveloperAppListBuilderForDeveloper
{
/**
* {#inheritdoc}
*/
public function render()
{
//code here
}
}
First make sure your module is following the details outlined in Naming and placing your Drupal 8 module - Name your module:
It must contain only lower-case letters and underscores.
The namespace in your details indicates it is using upper camel case instead of snake cases.
Also ensure your route subscriber has a relevant my_app.services.yml services YAML file and tag it with event_subscriber or it won't be registered:
services:
my_app.route_subscriber:
class: Drupal\my_app\Routing\MyAppsRouteSubscriber
tags:
- { name: event_subscriber }
Make sure your module is enabled or it won't be working either. Debug through it to see where it still fails.

Drupal 8 - How can I override a content's template in a custom module?

After looking at a bunch of modules I am still confused as to how I can take a content piece I've created (a Server), make my own custom module (servers) and do some logic so I can pass that on to a servers-template.
servers.info.yml
name: Servers Module
description: Creates a Servers Module
package: Servers
type: module
core: 8.x
servers.module
<?php
function servers_theme(){
$theme['server_page'] = [
'variables' =>['name' => NULL],
'template' => 'server',
];
return $theme;
}
And I am not sure if this is correct, but my servers.routing.yml
servers.server: #Pretty sure this part doesn't matter
path: '/node/{server}' #I'd like to have /server/{server/ but my content's url is /node/xx
defaults:
_title: 'Servers'
_controller: '\Drupal\servers\Controller\Servers::getServersImplementation'
entity_type: 'server' #Not sure if this is correct
requirements:
_permission: 'access content' #Do I need this?
Controller
#located in servers/src/controller/Servers.php
namespace Drupal\Servers\Controller;
use Drupal\Core\Controller\ControllerBase;
/**
* Controller for js_example pages.
*
* #ingroup js_example
*/
class Servers extends ControllerBase {
/**
* Accordion page implementation.
*
* We're allowing a twig template to define our content in this case,
* which isn't normally how things work, but it's easier to demonstrate
* the JavaScript this way.
*
* #return array
* A renderable array.
*/
public function getServersImplementation($name)
{
return[
'#theme'=>'server_page',
'#name'=>$name,
];
}
}
Absolutely nothing shows up when I've enabled the module. I know it's enabled because I can change the routing path to a node id /node/93 and that node will give me a page not found error, when without the routing I can get the content.
No errors are present in the error.log, or recent log messages. I am quite confused with this in D8, but once I can get this concept I know I will be able to understand all I need to complete my modules.
Thanks in advance.

How to mock a CakePHP behavior for unit testing

I've just started with unit testing in CakePHP (yay!) and ran into the following challenge. Hope somebody can help me :-)
Situation
My model uses a Behavior to send changes to an API after saving it locally. I would like to fake all calls made to the API during the test (those will be tested seperately) to save load on the API server, and more important, not actually save the changes :-)
I'm using CakePHP 2.4.1.
What I've tried
Read the docs. The manual shows how to do this for Components and Helpers but not for Behaviors.
Google. What I've found:
A Google Group post which says it simply "isn't possible". I don't take no for an answer.
An article explaining how to mock an object. Comes pretty close.
The code from the article reads:
$provider = $this->getMock('OurProvider', array('getInfo'));
$provider->expects($this->any())
->method('getInfo')
->will($this->returnValue('200'));
It might be the wrong direction, but I think that might be a good start.
What I want
Effectively: A snippet of code to demo how to mock a behavior in a CakePHP Model for unit testing purposes.
Maybe this question will result in an addition of the CakePHP manual too as an added bonus, since I feel it's missing in there.
Thanks in advance for the effort!
Update (2013-11-07)
I've found this related question, which should answer this question (partly). No need to mock up the API, instead I can create a Behavior test that the model will use.
I'm trying to figure out what that BehaviorTest should look like.
Use the class registry
As with many classes, behaviors are added to the class registry using the class name as the key, and for subsequent requests for the same object loaded from the classregistry. Therefore, the way to mock a behavior is simply to put it in the class registry before using it.
Full Example:
<?php
App::uses('AppModel', 'Model');
class Example extends AppModel {
}
class TestBehavior extends ModelBehavior {
public function foo() {
throw new \Exception('Real method called');
}
}
class BehaviorExampleTest extends CakeTestCase {
/**
* testNormalBehavior
*
* #expectedException Exception
* #expectedExceptionMessage Real method called
* #return void
*/
public function testNormalBehavior() {
$model = ClassRegistry::init('Example');
$model->Behaviors->attach('Test');
$this->assertInstanceOf('TestBehavior', $model->Behaviors->Test);
$this->assertSame('TestBehavior', get_class($model->Behaviors->Test));
$this->assertSame(['foo' => ['Test', 'foo']], $model->Behaviors->methods());
$model->foo();
}
public function testMockedBehavior() {
$mockedBehavior = $this->getMock('TestBehavior', ['foo', 'bar']);
ClassRegistry::addObject('TestBehavior', $mockedBehavior);
$model = ClassRegistry::init('Example');
$model->Behaviors->attach('Test');
$this->assertInstanceOf('TestBehavior', $model->Behaviors->Test);
$this->assertNotSame('TestBehavior', get_class($model->Behaviors->Test));
$expected = [
'foo' => ['Test', 'foo'],
'bar' => ['Test', 'bar'],
'expects' => ['Test', 'expects'], // noise, due to being a mock
'staticExpects' => ['Test', 'staticExpects'], // noise, due to being a mock
];
$this->assertSame($expected, $model->Behaviors->methods());
$model->foo(); // no exception thrown
$mockedBehavior
->expects($this->once())
->method('bar')
->will($this->returnValue('something special'));
$return = $model->bar();
$this->assertSame('something special', $return);
}
}

PHPUnit with Selenium2 - share session not working

I'm doing some tests with PHPUnit and Selenium and i would like all of them to run in the same browser window.
I've tried starting the Selenium Server with
java -jar c:\php\selenium-server-standalone-2.33.0.jar -browserSessionReuse
but with no visible change.
I've also tried with shareSession() in the setup
public function setUp()
{
$this->setHost('localhost');
$this->setPort(4444);
$this->setBrowser('firefox');
$this->shareSession(true);
$this->setBrowserUrl('http://localhost/project');
}
but the only change is that it opens a window for every test, and not really sharing the session. I'm out of ideas at this point.
My tests look like this:
public function testHasLoginForm()
{
$this->url('');
$email = $this->byName('email');
$password = $this->byName('password');
$this->assertEquals('', $email->value());
$this->assertEquals('', $password->value());
}
Here's the elegant solution. To share browser sessions in Selenium2TestCase, you must set sessionStrategy => 'shared' in your initial browser setup:
public static $browsers = array(
array(
'...
'browserName' => 'iexplorer',
'sessionStrategy' => 'shared',
...
)
);
The alternative (default) is 'isolated'.
You do not need to use the flag -browserSessionReuse
In your case The set up function running before every test and starting new instance.
This is what i did to prevent this to happen (Its little bit ugly but work for me both in Windows and Ubuntu):
I created helper class with static ver: $first and initialized it.
helper.php:
<?php
class helper
{
public static $first;
}
helper::$first = 0;
?>
Edit main test file setUp() function(and add require_once to helper.php):
require_once "helper.php";
class mySeleniumTest extends PHPUnit_Extensions_SeleniumTestCase
{
public function setUp()
{
$this->setHost('localhost');
$this->setPort(4444);
if (helper::$first == 0 )
{
$this->shareSession(TRUE);
$this->setBrowser('firefox');
$this->setBrowserUrl('http://localhost/project');
helper::$first = 1 ;
}
}
....
setHost and setPort outside the if because the values restarted after each test(For me...) and need to set up every time (if the selenium server is not localhost:4444)
Just found an (much) faster way to proceed : If you perform several test in one function, all test are performed in the same window. The setback is that the tests and reporting won't be nicely presented by tests, but the speed is way up!
In the same function for each test just use:
$this->url('...');
Or
$this->back();