3xw/cakephp-utils

There is no license information available for the latest version (4.1.23) of this package.

CakePHP utils plugins

Installs: 1 282

Dependents: 4

Suggesters: 0

Security: 0

Stars: 1

Watchers: 4

Forks: 0

Open Issues: 1

Type:cakephp-plugin


README

This plugin is full of handly stuff

Installation

You can install this plugin into your CakePHP application using composer.

The recommended way to install composer packages is:

composer require 3xw/cakephp-utils

In src/Application.php

use Cake\Http\BaseApplication;
...

class Application extends BaseApplication {

	...

  public function bootstrap()
  {
    parent::bootstrap();
    this->addPlugin('Trois/Utils', ['routes' => true]);
  }
	..
}

ORM

Behaviors

  • Sluggable Behavior
  • Translate Behavior

Rules

  • IsUniqueTranslationRule

Associations

MinMaxAssocationTrait

namespace App\Model\Table
use Trois\Utils\ORM\Traits\MinMaxAssocationTrait;

class SubscriptionsTable extends Table
{
	use MinMaxAssocationTrait;

	public function initialize(array $config)
	{
		...

		// custom Association
    	$this->belongsToMinMax('MinPeriodes', [
      'type' => 'MIN',
      'field' => 'date',
      'className' => 'Periodes',
      'foreignKey' => 'subscription_id',
      'targetForeignKey' => 'periode_id',
      'joinTable' => 'subscriptions_periodes',
      'joinType' => 'LEFT'
			'joinAlias' => 'SP', // extra stuff: define yourself join alias
      'joinExtraConditions' => ['SP.was_present' => true] // extra stuff: add conditions on join clause
    ]);
	}
}

// OR
namespace App\Model\Table
use Trois\Utils\ORM\Traits\MinMaxAssocationTrait;

class LessonsTable extends Table
{
	use MinMaxAssocationTrait;

	public function initialize(array $config)
	{
		...

		// custom Association
    	$this->hasOneMinMax('MinPeriode', [
      'type' => 'MIN',
      'field' => 'date',
      'className' => 'Periodes',
      'foreignKey' => 'lesson_id',
      'joinType' => 'LEFT'
    ]);
	}
}

Shell

  • MissingTranslations
  • Token

MissingTranslations

tu_miss_i18n $model, ...$locales

Token

ut_token username

View

  • LngSwitchCell

Security

GUARD Component

This component allows you to check constructed request object and clean it if needed...

in your src/Controller/AppController.php add following:

public function initialize()
{
    parent::initialize();

    ...

    // Auth
    $this->loadComponent('Auth', [...]);

    // Guard
    $this->loadComponent('Trois/Utils.Guard',[
      'autoload_configs' => [
        'Guard.requestBody' => 'guard_request_body'
      ]
    ]);

    ...
}

in config/guard_request_body.php

	<?php
	use Cake\Http\ServerRequest;

	return [
	  'Guard.requestBody' => [
	    [
	      'role' => '*',
	      'prefix' => 'Book',
	      'controller' => ['Users','Subscriptions'],
	      'action' => ['register','registerAndBook'],
	      'method' => ['POST','PUT'],
	      'rule' => function($user, $role, ServerRequest $request)
	      {
	        // magic here... manipulate request here
	      }
	    ],
	]];

CORS Middleware

in your src/Application.php add following:

use Trois\Utils\Middleware\CorsMiddleware;
...
public function middleware($middlewareQueue)
{
	$middlewareQueue
	->add(new CorsMiddleware::class)

	/* -- OR  -- */
	->add(new CorsMiddleware([

		// thoses are default options
	    'all' => [
	      'Access-Control-Allow-Origin' => '*',
	      'Access-Control-Allow-Credentials' => 'true',
	      'Access-Control-Expose-Headers' => 'X-Token',
	      'Access-Control-Max-Age' => '86400'
	    ],
	    'options' => [
	      'methods' => 'GET, POST, OPTIONS, PUT, DELETE'
	    ]

  	]))

	...
}

Auth tools

Config example:

config/bootsrap.php

Configure::load('auth', 'default');

src/Controller/Appcontroller.php

$this->loadComponent('Auth', Configure::read('Auth.V2'));

config/auth.php

<?php
use Cake\Core\Configure;

return [
  'Auth.V2' => [

    'loginAction' => false,
    'unauthorizedRedirect' => false,
    'checkAuthIn' => 'Controller.initialize' ,

    // Authenticate
    'authenticate' => [

      // map role
      'all' => ['finder' => 'Auth'],

      // Legacy X-API-TOKEN header token
      'Trois/Utils.LegacyToken' => [
        'key' => Configure::read('Legacy.key'),
        'salt' => Configure::read('Legacy.salt')
      ],

      // with Bearer JWT token
      'Trois\Utils\Auth\JwtBearerAuthenticate' => [
        'duration' => 3600
      ],

      // Basic username + pass
      'Trois\Utils\Auth\BasicToJwtBearerAuthenticate' => [
        'fields' => ['username' => 'username'],
        'passwordHasher' => 'Trois\Utils\Auth\LegacyPasswordHasher',
      ],
    ],

    // Cache Storage Engine
    'storage' => [
      'className' => 'Trois\Utils\Auth\Storage\CacheStorage',
      'cache' => 'token'
    ],

    // Authorize
    'authorize' => [
      'CakeDC/Auth.SimpleRbac' => [
        'autoload_config' => 'permissions',
      ],
    ],
  ]
];

Two factor Auth

set up Auth:

  'Trois\Utils\Auth\TwoFactorAuthenticate' => [
    'userModel' => 'ExtranetUsers',
    'passwordHasher' => 'App\Auth\NoHasher',
    'fields' => [
      'username' => 'CLIENT_ID',
      'password' => 'Password'
    ],
    'transmitter' => [
      'class' => '\Trois\Utils\Auth\TwoFactor\EmailCodeTransmitter', // any child of Trois\Utils\Auth\TwoFactor\AbstractCodeTransmitter
      'config' => [
        'messages' => [
          'success' => 'Un email avec un code vous a été envoyé',
          'error' => 'L\'application n\'a pas pu vous envoyer de mail. Veuillez essayer à nouveau.'
        ],
        'email' => [
          'field' => 'Email',
          'profile' => 'default',
          'from' => ['info@xxx' => 'Site xxx'],
          'subject' => 'Votre code personnel',
          'emailFormat' => 'both',
          'template' => 'Trois/Utils.default',
          'layout' => 'default',
        ]
      ]
    ],
    'verifyAction' => [
      'prefix' => 'extranet',
      'controller' => 'ExtranetUsers',
      'action' => 'verify',
      'plugin' => false
    ],
  ],

Cache

cache settings

in config folder create a cache.php file with as exemple:

<?php
return [
	'Trois.cache.settings' => [
		'default' => 'default', // default cache config to use if not set in rules...
	],
	'Trois.cache.rules' => [

		// cache request
		[
		  'cache' => 'html', // default: 'default', can be a fct($request)
		  'skip' => false, // default: false, can be a fct($request)
		  'clear' => false, // default: false, can be a fct($request)
		  'compress' => true, // default: false, can be a fct($request)
		  //'key' => 'whatEver',// default is fct($request) => return $request->here()
		  'method' => ['GET'],
		  'code' => '200', // must be set or '*' !!!!!
		  'prefix' => '*',
		  'plugin' => '*',
		  'controller' => '*',
		  'action' => '*',
		  'extension' => '*'
		],

		// clear request
		[
		  'cache' => 'html', // default: 'default'
		  'skip' => false, // default: false
		  'clear' => true, // default: false,
		  'key' => '*', // * => Cache::clear(false, cache) (Will clear all keys), 'whatEver' => Cache::delete('whatEver', cache), null => Cache::delete($request->here(), cache)
		  'method' => ['POST','PUT','DELETE'],
		  'code' => ['200','201','202'],
		  'prefix' => '*',
		  'plugin' => '*',
		  'controller' => ['Users','Pages'],
		  'action' => '*',
		  'extension' => '*'
		],
  	]
];

Cache as your last middleware

in your src/Application.php file add the middleware as last chain block. This will create or delete view renders as cache ( html/json /etc...)

<?php
namespace App;
...
use Trois\Utils\Middleware\ResponseCacheMiddleware;

class Application extends BaseApplication
{
    public function middleware($middleware)
    {
        $middleware
			...
            // Apply Response caching
            ->add(ResponseCacheMiddleware::class);

        return $middleware;
    }
}

Retrieve cache via ActionCacheComponent

in your AppController load the component AFTER Auth!!

$this->loadComponent('Awallef/Cache.ActionCache');

Retrieve cache via Nginx

First install nginx redis extension. Then set your cache config to store in redis. You can use my plugin...

composer require awallef/cakephp-redis

Configure the engine in app.php like follow:

'Cache' => [
	...
	'redis' => [
		'className' => 'Trois/Utils.Redis',
		'prefix' => 'hello.com:',
		'duration' => '+24 hours',
		'serialize' => true
	],
	...
]

Configure cache.php like follow:

return [
		'Trois.cache.settings' => [
			'default' => 'redis', // default cache config to use if not set in rules...
		],
	'Trois.cache.rules' => [

		// cache request
		[
			'skip' => false, // default: false, can be a fct($request)
			'clear' => false, // default: false, can be a fct($request)
			'compress' => true, // default: false, can be a fct($request)
			//'key' => 'whatEver',// default is fct($request) => return $request->here()
			'method' => ['GET'],
			'code' => '200', // must be set or '*' !!!!!
			'prefix' => '*',
			'plugin' => '*',
			'controller' => '*',
			'action' => '*',
			'extension' => '*'
		],

		// clear request
		[
	      'clear' => true,
	      'key' => '*',
	      'method' => ['POST','PUT','DELETE'],
		  'code' => ['200','201','202','302'], // 302 is often triggered by cakephp in case of success crud operation...
		  'prefix' => '*',
		  'plugin' => '*',
		  'controller' => '*',
		  'action' => '*',
		  'extension' => '*'
		],
	]
];

Configure Nginx too:

map $http_accept $hello_com_response_header {
	default   "text/html; charset=UTF-8";
	"~*json"  "application/json; charset=UTF-8";
}
server {
	listen 443;
	server_name hello.com;

	ssl on;
	...

	# redis key
	set $redis_key  "hello.com:$request_uri";
	if ($args) {
		set $redis_key  "hello.com:$request_uri?$args";
	}

	location / {
		redis_pass 127.0.0.1:6379;
		error_page 404 405 502 504 = @fallback;
		more_set_headers "Content-Type: $hello_com_response_header";
	}

	#default cake handling
	location @fallback {
		try_files $uri $uri/ /index.php?$args;
	}

	location ~ \.php$ {
		try_files $uri =404;
		include /etc/nginx/fastcgi_params;
		fastcgi_intercept_errors on;
		fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
		fastcgi_index   index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	}

}

Redis caching

This plugin provides a very little bit different redis engine based on cakephp's RedisEngine. differences are:

  • Engine config comes with a bool 'serialize' option ( default is true )
  • Read and wirte fct use config 'serialize' option
  • Keys are stored/read/deleted in order to uses : and :* redis skills!

Configure the engine in app.php like follow:

'Cache' => [
    ...
    'redis' => [
      'className' => 'Trois/Utils.Redis',
      'prefix' => 'www.your-site.com:',
      'duration' => '+24 hours',
      'serialize' => true
    ],
    ...
]