missbach/snooper-components

1.5.0 2020-09-03 05:28 UTC

This package is not auto-updated.

Last update: 2024-06-06 00:06:44 UTC


README

Setup project

Install

To install via composer, add the following line to your composer.json in your project root path:

{
    ...
    require: {
    ...
    "snooper/components": "1.*"
    }
    ...
}

Execute composer:

composer update

You should see something similar:

Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
Package operations: 1 install, 0 updates, 0 removals
  - Installing snooper/components (1.0.0): Loading from ...

After the process finished, you can start using it:

Snooper::instance()->....

Implement

Create a provider

Now you need to implement a listener for the event. Every provider can listen to several events. Let´s start.

<?php
namespace App\Providers;

use Snooper\Components\Provider\Provider;
use Snooper\Components\EventTrigger;
use Snooper\Components\Provider\ProviderCallDefinition;

class TestProvider extends Provider
{
    public function isActive()
    {
        return true;
    }

    public function getEvents()
    {
        return [
            'some.event'=>ProviderCallDefinition::create('someEvent')
        ];
    }

    public function someEvent(EventTrigger $e)
    {
    }
}

Ok, what about to fill the provider action with life?

<?php
namespace App\Providers;

...
use Snooper\Components\Response\Builder;

class TestProvider extends Provider
{
    ...
    public function someEvent(EventTrigger $e)
    {
        $helloWorld = $e->getParameters()->get('some_variable');
        
        return Builder::createStandardResponse(
            Builder::createDeliver('head'),
            'console.log',
            Builder::createParameter($helloWorld,false)
        );
    }
}

Add to your bootstrap process:

Snooper::instance()->getConfig()->setDebugMode(true);

Snooper::instance()->addProvider(new TestProvider());

Snooper::instance()->raiseEvent('some.event',['some_variable'=>'hello world']);

echo Snooper::instance()->outputSection('head');

Hint: Feel free to inject any service you like through the constructor because it isn´t used by the process.

Config

The config is a raw php array:

protected $rawParameters = [
        'first_section' => 'head',
        'last_section' => 'footer',
        'sections' => [
            'head','body','footer'
        ],
        'json_response_key' => 'snooper_data',
        'xhr_send_mode'=>self::XHR_SEND_METHOD_BOTH,
        self::DEBUG => [
            'nested_level' => 25,
            'url_param' => 'snooper_debug',
            'session_param' => 'snooper_debug',
            'debug_environments' => [
                'dev'
            ]
        ],
        'log' => [
            'excludeClass' => [
                'Doctrine\ORM\PersistentCollection'
            ]
        ],
        'ignoredRoutes' => [
            '/\/admin$/'
        ]
    ];

The Config-class knows a method "mergeConfig". Feel free to overwrite it to your own needs.

Run

Go to your page, reload it and open the developer tools of your browser and have a look on the javascript console. You should see something similar like this:

...
hello world
...
------------ SNOOPER EVENTS BEGINS ------------
Event some.event fired.
Object { ..... }
Calls "console.log" with:
hello world
------------- SNOOPER EVENTS ENDS -------------

Hint: The output between "SNOOPER EVENTS BEGINS" and "SNOOPER EVENTS ENDS" are only debugging prints.

Congratulations! Now your first event is sent from server to the frontend to do something with it.

What works

Provider

There are several methods to use in the provider base class which you can overwrite. For custom output of html or javascript tags use getHeadSection, e.g. to include an external script:

<?php
...
class TestProvider extends Provider
{
    ...
    public function getHeadSection()
    {
        return '<script type="text/javascript" async="" src="http://www.google-analytics.com/analytics.js"></script>';
    }
    ...
}

The name of the called method depends on the section, which you want to use. The pattern is "get###Section", e.g. for "footer" use getFooterSection.

<!DOCTYPE html>
<html>
    <head>
        <?php echo Snooper::instance()->outputSection('head');?>
    </head>
    <body>
        ...
        Content goes here!
        ...
    </body>
</html>

It ends up with:

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" async="" src="http://www.google-analytics.com/analytics.js"></script>
    </head>
    <body>
        ...
        Content goes here!
        ...
    </body>
</html>

Hint: The output does not depend on the events and are always printed. But keep in mind that the provider has to be active (see method isActive()).

Next there are 2 events that are always called on each registrated provider, no matter if the fired event is listed or needed in this provider, exactly like the output prints. They are called "preRaiseEvent" and "postRaiseEvent" and the methods gets the EventTrigger as parameter, too. Remember the tracking example and add the two methods:

<?php
...
class TestProvider extends Provider
{
    ...
    public function preRaiseEvent(EventTrigger $e)
    {
    }

    public function postRaiseEvent(EventTrigger $e)
    {
    }
    ...
}

Ok, let´s have a look at the order of functions wich are called:

- Event "some.event" are called.
- Get the first provider.
- Is it Active? (have a look on isActive())
- Yes.
- Call preRaiseEvent.
- Is there a listener for the event "some.event"?
- Yes.
- Ok, call it. (in our case it´s the method someEvent())
- Call postRaiseEvent.
- Is there another provider?
- No. Finish the process.

Note: Each of the methods that are given an EventTrigger object can return several things: Nothing, a single Response or an array of Responses. Responses can be a StandardResponse or an InteractionResponse.

The setting of the available events can be extended like this:

<?php
...
class TestProvider extends Provider
{
    ...
    public function getEvents()
    {
        return [
            'some.event'=>ProviderCallDefinition::create(
                'someEvent',
                ['testkey'=>'testvalue'],
                ProviderCallDefinition::PRIORIZATION_STANDARD
                )
        ];
    }

    public function someEvent(EventTrigger $e, $additional)
    {
        //$addtional => ['testkey'=>'testvalue']
        ...
    }
}

The second parameter can be whatever you want to inject it into the method. The third defines the priorization of the called methods in each provider if there are more than one providers, which listening to the same event.

EventTrigger

Below you find a list of methods wich are included in the object :

stopPropagation() : cancels any subsequent processing
isPropagationStopped(): checks for cancellation
getParameters() : returns a Bag(Snooper\Components\Utility\Bag), filled with sended parameters
getEventName() : returns the currently raised event (in our case "some.event")
getContext() : returns the context
setContext() : set the context, can be whatever you want

StandardResponse

The constructor takes exactly 3 parameters. The first parameter is mandatory:

<php
...
Builder::createStandardResponse(Builder::createDeliver('head'));

This defines the rendered section.

<php
Builder::createDeliver('head',Deliver::PRE_SECTION)

It's possible to move the output on before the static method getHeadSection.

Hint: Keep in mind that if the tracking informations are delivered and executed after an javascript ajax call not being ordered this way. Rather, they are executed in the order they were registered. The static methods getHeadSection or getBodySection are ignored, too.

The second parameter is mandatory, too. It defines of which javascript method will be called.

<php
...
Builder::createStandardResponse(Builder::createDeliver('head'),'console.log');

This would produce this javascript code...

console.log();

...and the log would look like this:

...

...
------------ SNOOPER EVENTS BEGINS ------------
Event some.event fired.
Object { .... }
Calls console.log without parameters.
------------- SNOOPER EVENTS ENDS -------------

The third parameter define given informations send to the called javascript method:

<php
...
Builder::createStandardResponse(
    Builder::createDeliver('head'),
    'console.log',
    Builder::createParameter(['test'=>'some information'],false));

In javascript...

console.log({"test":"some information"});

...and the log:

...
Object { test: "some information" }
...
------------ SNOOPER EVENTS BEGINS ------------
Event some.event fired.
Object { ... }
Calls console.log with:
Object { test: "some information" }
------------- SNOOPER EVENTS ENDS -------------

Let´s have a closer look to "Builder::createParameter". The second parameter makes it possible to execute the second parameters on frontend and use the result of it. Take a look on this example:

<php
...
Builder::createParameter('{id:document.location.href}', false);

This would results in something like this:

...
{href:document.location.href}
...
------------ SNOOPER EVENTS BEGINS ------------
Event some.event fired.
Calls console.log with:
{href:document.location.href}
------------- SNOOPER EVENTS ENDS -------------

Hm, ok, this is not what we want. Let´s make a little change in the code and change the false to true:

<php
...
Builder::createParameter('{id:document.location.href}', true);

Now we try again:

...
Object { href: "http://?????.de/" }
...
------------ SNOOPER EVENTS BEGINS ------------
Event some.event fired.
...
  Eval executed: {href:document.location.href}
Object { href: "http://?????.de/" }
------------- SNOOPER EVENTS ENDS -------------

Yeah! This allows objects to be enriched with data available only in the frontend.

If you have to send more than one paramter to your javascript function you can easily do this:

<php
...
Builder::createParameter('param1', true, 'param2', true [,....]), 

Hint: You have always to specify parameter pairs. Otherwise the script will raise an exception.

InteractionResponse

The constructor takes 4 parameters. Example:

<?php
Builder::createInteractionResponse(
    Builder::createInteractionFreeSelector('.test',Interaction::ON_CLICK),
    'console.log',
    Builder::createParameter('hello world'),
    Builder::createInteractionOptionDelay(5000),Builder::createInteractionOptionSendFrontendTarget(SendFrontendTarget::SEND_FE_TARGET_LAST
);

The first paramter defines which element which what kind of event should listen:

<?php
Builder::createInteractionFreeSelector('.test',Interaction::ON_CLICK); // selector: ".test"

Builder::createInteractionSnooperTarget('test',Interaction::ON_CLICK); // selector: "data-snooper-event='test'"

The second and third parameter works exactly like been descriped before in StandardResponse.

The last parameter is a list of interaction options which can be called in any order. "Builder::createInteractionOptionDelay(5000)" delays the javascript by the given time in ms. "Builder::createInteractionOptionSendFrontendTarget(SendFrontendTarget::SEND_FE_TARGET_LAST" adds to the javascript method the sended source-element.

VariableSet

The constructor takes 3 parameters. Example:

<?php
Builder::createVariableSet(
    Builder::createDeliver('head'),
    'test',
    Builder::createParameter('hello world')    
);

In this example the variable "test" in window scope will set to the value "hello world".

Raw

The constructor takes 2 parameters. Example:

<?php
Builder::createRaw(
    Builder::createDeliver('head'),
    'alert("test")'    
);