<?php /** * Piwik - free/libre analytics platform * * @link http://piwik.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ namespace Piwik\Tracker; use Piwik\Tracker\Visit\VisitProperties; /** * Base class for all tracker RequestProcessors. RequestProcessors handle and respond to tracking * requests. * * ## Concept: Request Metadata * * RequestProcessors take a Tracker\Request object and based on its information, set request metadata. * * Request metadata is information about the current tracking request, for example, whether * the request is for an existing visit or new visit, or whether the current visitor is a known * visitor, etc. It is used to control tracking behavior. * * Request metadata is shared between RequestProcessors, so RequestProcessors can tweak each others * behavior, and thus, the behavior of the Tracker. Request metadata can be set and get using the * {@link Request::setMetadata()} and {@link Request::getMetadata()} * methods. * * Each RequestProcessor lists the request metadata it computes and exposes in its class * documentation. * * ## The Tracking Process * * When Piwik handles a single tracking request, it gathers all available RequestProcessors and * invokes their methods in sequence. * * The first method called is {@link self::manipulateRequest()}. By default this is a no-op, but * RequestProcessors can use it to manipulate tracker requests before they are processed. * * The second method called is {@link self::processRequestParams()}. RequestProcessors should use * this method to compute request metadata and set visit properties using the tracking request. * An example includes the ActionRequestProcessor, which uses this method to determine the action * being tracked. * * The third method called is {@link self::afterRequestProcessed()}. RequestProcessors should * use this method to either compute request metadata/visit properties using other plugins' * request metadata, OR override other plugins' request metadata to tweak tracker behavior. * An example of the former can be seen in the GoalsRequestProcessor which uses the action * detected by the ActionsRequestProcessor to see if there are any action-matching goal * conversions. An example of the latter can be seen in the PingRequestProcessor, which on * ping requests, aborts conversion recording and new visit recording. * * After these methods are called, either {@link self::onNewVisit()} or {@link self::onExistingVisit()} * is called. Generally, plugins should favor defining Dimension classes instead of using these methods, * however sometimes it is not possible (as is the case with the CustomVariables plugin). * * Finally, the {@link self::recordLogs()} method is called. In this method, RequestProcessors * should use the request metadata that was set (and maybe overridden) to insert whatever log data * they want. * * ## Extending The Piwik Tracker * * Plugins that want to change the tracking process in order to track new data or change how * existing data is tracked can create RequestProcessors to accomplish. * * _Note: If you only want to add tracked data to visits, actions or conversions, you should create * a {@link Dimension} class._ * * To create a new RequestProcessor, create a new class that derives from this one, and implement the * methods you need. Then put this class inside the `Tracker` directory of your plugin. * * Final note: RequestProcessors are shared between tracking requests, and so, should ideally be * stateless. They are stored in DI, so they can contain references to other objects in DI, but * they shouldn't contain data that might change between tracking requests. */ abstract class RequestProcessor { /** * This is the first method called when processing a tracker request. * * Derived classes can use this method to manipulate a tracker request before the request * is handled. Plugins could change the URL, add custom variables, etc. * * @param Request $request */ public function manipulateRequest(Request $request) { // empty } /** * This is the second method called when processing a tracker request. * * Derived classes should use this method to set request metadata based on the tracking * request alone. They should not try to access request metadata from other plugins, * since they may not be set yet. * * When this method is called, `$visitProperties->visitorInfo` will be empty. * * @param VisitProperties $visitProperties * @param Request $request * @return bool If `true` the tracking request will be aborted. */ public function processRequestParams(VisitProperties $visitProperties, Request $request) { return false; } /** * This is the third method called when processing a tracker request. * * Derived classes should use this method to set request metadata that needs request metadata * from other plugins, or to override request metadata from other plugins to change * tracking behavior. * * When this method is called, you can assume all available request metadata from all plugins * will be initialized (but not at their final value). Also, `$visitProperties->visitorInfo` * will contain the values of the visitor's last known visit (if any). * * @param VisitProperties $visitProperties * @param Request $request * @return bool If `true` the tracking request will be aborted. */ public function afterRequestProcessed(VisitProperties $visitProperties, Request $request) { return false; } /** * This method is called before recording a new visit. You can set/change visit information here * to change what gets inserted into `log_visit`. * * Only implement this method if you cannot use a Dimension for the same thing. * * @param VisitProperties $visitProperties * @param Request $request */ public function onNewVisit(VisitProperties $visitProperties, Request $request) { // empty } /** * This method is called before updating an existing visit. You can set/change visit information * here to change what gets recorded in `log_visit`. * * Only implement this method if you cannot use a Dimension for the same thing. * * @param array &$valuesToUpdate * @param VisitProperties $visitProperties * @param Request $request */ public function onExistingVisit(&$valuesToUpdate, VisitProperties $visitProperties, Request $request) { // empty } /** * This method is called last. Derived classes should use this method to insert log data. They * should also only read request metadata, and not set it. * * When this method is called, you can assume all request metadata have their final values. Also, * `$visitProperties->visitorInfo` will contain the properties of the visitor's current visit (in * other words, the values in the array were persisted to the DB before this method was called). * * @param VisitProperties $visitProperties * @param Request $request */ public function recordLogs(VisitProperties $visitProperties, Request $request) { // empty } }