I try to create a block for the main page based on list action sonata admin is possible?
example
dashboard:
blocks:
- { type: mea.task.block, position: center, roles: [ ROLE_WORKER ] }
Here is block render
class TaskListAdminBlock extends AbstractAdminBlockService
{
/**
* {#inheritdoc}
*/
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
$controller = 'Mea\TaskBundle\Sonata\Controller\TaskCrudController::listAction';
$path = [
'_controller' => $controller,
];
$subRequest = $this->requestStack->getMasterRequest()->duplicate($query, null, $path);
return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}
}
TaskCrudController is sonata admin controller for task
this throw error
There is no `_sonata_admin` defined for the controller `Mea\TaskBundle\Sonata\Controller\TaskCrudController` and the current route ``
Is possible to fix this code or archive this in another way?
Ok I found beautifully solution
This renders in ajax made admin list
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
$controller = 'Mea\TaskBundle\Sonata\Controller\TaskCrudController::listAction';
$path = array(
'_controller' => $controller
);
$query = [
'filter'=>[
'_per_page'=>4,
],
];
$subRequest = $this->requestStack->getMasterRequest()->duplicate($query, null, $path);
$subRequest->headers->set('X-Requested-With','XMLHttpRequest');
$subRequest->request->set('_sonata_admin','mea.task.task.admin');
$response = $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
return $response;
}
Not fully work fine - ajax mode switch actions to select.
Related
I am working on a website using the Slim framework. I am trying to make a link that takes the user to a specific place on the home page.
This is the normal link:
Home
First I tried to write an absolute link like:
Anchor
But this doesn't work and results in https://example.com/#anchor
This doesn't work either:
Home
How can I get the link to work and take me to the specified anchor?
The path_for twig extension can't handle anchors:
Home
UPD:
class DecoratedTwigExtension
{
private TwigExtension $twigExtension;
public function __construct(TwigExtension $twigExtension)
{
$this->twigExtension = $twigExtension;
}
public function __call($name, $arguments)
{
if (is_callable([$this->twigExtension, $name])) {
return $this->twigExtension->$name(...$arguments);
}
$message = sprintf('There is no callable method %s::%s', get_class($this->twigExtension), $name);
throw new \BadMethodCallException($message);
}
public function pathFor($name, $data = [], $queryParams = [], $appName = 'default', $anchor = '')
{
$path = $this->twigExtension->pathFor($name, $data, $queryParams);
// some manipulations with $path
if ($anchor !== '') {
}
return $path;
}
}
// Register Twig View helper
$container['view'] = function ($c) {
$view = new \Slim\Views\Twig('path/to/templates', [
'cache' => 'path/to/cache'
]);
// Instantiate and add Slim specific extension
$router = $c->get('router');
$uri = \Slim\Http\Uri::createFromEnvironment(new \Slim\Http\Environment($_SERVER));
// ======= the main lines =======
$twigExtension = new \Slim\Views\TwigExtension($router, $uri);
$view->addExtension(new \App\Namespace\DecoratedTwigExtension($twigExtension));
return $view;
};
I'm creating a site that needs an oauth authorization through microsoft. In yii/authclient there's only live client and it is not working anymore.
I tried to write my own but something goes wrong. As far as I understood my AuthAction doesn't see clientId and returns 404 exception without text. Here's my code of the auth client.
What I get
AuthAction class method run (it's default)
class Office365OAuth extends OAuth2
{
public $authUrl = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize';
public $tokenUrl = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
public $apiBaseUrl = 'https://login.microsoftonline.com/common/oauth2/v1.0';
public $scope = null;
public function init()
{
parent::init();
if ($this->scope === null)
{
$this->scope = 'https://graph.microsoft.com/User.Read';
}
}
/**
* Overrides default function to fix malformed url
*/
public function getReturnUrl()
{
return $this->returnUrl;
}
protected function defaultName()
{
return 'office365';
}
protected function defaultTitle()
{
return 'Office365';
}
/**
* For popup mode
*/
protected function defaultViewOptions()
{
return [
'popupWidth' => 800,
'popupHeight' => 500,
];
}
/**
* Gets new auth token to replace expired one.
*/
protected function initUserAttributes()
{
return $this->api('me', 'GET');
}
}
So, how can I authenticate through MS graph?
The yii\authclient package requires using the returnUrl having a request param authclient=live, e.g. https://example.com/site/auth?authclient=live
However, Azure prohibits request params in the returnUrl. Therefore, to make yii\authclient works with Azure, i.e., the returnUrl as https://example.com/site/auth/live. You need to prettify the url with request param as follows:
In config/main.php
'components' => [
'urlManager' => [
'class' => 'yii\web\UrlManager',
'enablePrettyUrl' => true,
'rules' => [
'site/auth/<authclient>' => 'site/auth'
]
]
]
In controllers/SiteController.php,
public function actions()
{
return [
'auth' => [
'class' => 'yii\authclient\AuthAction',
'successCallback' => [$this, 'onAuthSuccess']
]
];
}
...
public function onAuthSuccess($client) {
// get user data from client
$userAttributes = $client->getUserAttributes();
// DO YOUR THING
}
I'm migrating from zend framework 1 to 3 , and I have a function that returns twig template but I don't know what should I use to render view twig template on zf3
How to:
use class of viewer
set my template path
set array to render it in template
return template
code:
protected function convertItemList($aItemList)
{
$aSet = [];
//$config['template_paths'] = [APPLICATION_PATH . '/../library/Core/Backend/SRO/Views/'];
//$oView = new Core_Twig_View($config);
if (!$aItemList) {
return [];
}
foreach ($aItemList as $iKey => $aCurItem) {
$aSpecialInfo = [];
$aInfo = $aCurItem;
$aInfo['info'] = $this->getItemInfo($aCurItem);
$aInfo['blues'] = $this->getBluesStats($aCurItem, $aSpecialInfo);
$aInfo['whitestats'] = $this->getWhiteStats($aCurItem, $aSpecialInfo);
//$oView->assign('aItem', $aInfo);
$i = isset($aCurItem['Slot']) ? $aCurItem['Slot'] : $aCurItem['ID64'];
if ($aCurItem['MaxStack'] > 1) {
$aSet[$i]['amount'] = $aCurItem['Data'];
}
$aSet[$i]['TypeID2'] = $aInfo['TypeID2'];
$aSet[$i]['OptLevel'] = $aInfo['OptLevel'];
$aSet[$i]['RefItemID'] = !isset($aCurItem['RefItemID']) ? 0 : $aCurItem['RefItemID'];
$aSet[$i]['special'] = isset($aInfo['info']['sox']) && $aInfo['info']['sox'] ? true : false;
$aSet[$i]['ItemID'] = $aCurItem['ID64'];
$aSet[$i]['ItemName'] = $aInfo['info']['WebName'];
$aSet[$i]['imgpath'] = $this->getItemIcon($aCurItem['AssocFileIcon128']);
//$aSet[$i]['data'] = $oView->render('itemData.twig');
}
return $aSet;
}
I use this module https://github.com/OxCom/zf3-twig.
You can install it by github instructions and add this parameter to zf3 configuration array:
'service_manager' => array(
'factories' => array(
...
'TwigStrategy' => \ZendTwig\Service\TwigStrategyFactory::class,
...
),
)
1) After this you can use Twig in some action of some controller by this code:
function someAction(){
...
$viewModel = new ZendTwig\View\TwigModel(['foo'=>'bar']);
return $viewModel;
}
2) To set other template:
function someAction(){
$viewModel = new ZendTwig\View\TwigModel(['foo'=>'bar']);
$viewModel->setTemplate('application/controller/name'); //set path here
return $viewModel;
}
3) You can to set array variables by TwigModel "__construct" parameter:
function someAction(){
$viewModel = new ZendTwig\View\TwigModel($someVariablesArray);
$viewModel->setTemplate('application/controller/name'); //set path here
return $viewModel;
}
4) If you need to return html code, you need to do something:
Add in services config one more param:
'service_manager' => array(
'factories' => array(
...
'TwigStrategy' => \ZendTwig\Service\TwigStrategyFactory::class,
'TwigRenderer' => \ZendTwig\Service\TwigRendererFactory::class,
...
),
)
Add TwigRenderer service in your controller factory:
class YourControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new YourController($twigRenderer);
}
}
and get twigRenderer in your Controller:
private $twigRenderer;
public function __construct($twigRenderer)
{
$this->twigRenderer = $twigRenderer;
}
After this get html:
function someAction(){
$viewModel = new ZendTwig\View\TwigModel(['foo'=>'bar']);
$viewModel->setTemplate('mails/order/order_in_process');
$html = $this->twigRenderer->render($viewModel);
return $html;
}
Sorry for my english!
I've added an ACL to my website but when I test the result of my role variable in the SecurityPlugin.php file I get the result twice.
Why does Phalcon show the var_dump of $role twice? I'm fairly new to this framework and my initial thought was it might me due to routing in Phalcon?
Phalcon version: 3.0.3
\app\plugins\SecurityPlugin.php
use Phalcon\Acl;
use Phalcon\Acl\Role;
use Phalcon\Acl\Adapter\Memory as AclList;
use Phalcon\Acl\Resource;
use Phalcon\Events\Event;
use Phalcon\Mvc\User\Plugin;
use Phalcon\Mvc\Dispatcher;
class SecurityPlugin extends Plugin
{
/**
* Returns an existing or new access control list
*
* #returns AclList
*/
public function getAcl()
{
if (!isset($this->persistent->acl)) {
$acl = new AclList();
$acl->setDefaultAction(Acl::DENY);
// Register roles
$roles = [
'admins' => new Role(
'admins',
'Website administrators'
),
'users' => new Role(
'users',
'Member privileges, granted after sign in.'
),
'guests' => new Role(
'guests',
'Anyone browsing the site who is not signed in is considered to be a "Guest".'
)
];
foreach ($roles as $role) {
$acl->addRole($role);
}
//Private area resources
$privateResources = array(
'account' => array('*')
);
$privateResourcesAdmin = array(
'admin' => array('*')
);
//Public area resources
$publicResources = array(
'index' => array('*'),
'register' => array('*'),
'errors' => array('show401', 'show404', 'show500'),
'register' => array('*'),
'login' => array('*'),
'logout' => array('*')
);
foreach ($privateResources as $resource => $actions) {
$acl->addResource(new Resource($resource), $actions);
}
foreach ($privateResourcesAdmin as $resource => $actions) {
$acl->addResource(new Resource($resource), $actions);
}
foreach ($publicResources as $resource => $actions) {
$acl->addResource(new Resource($resource), $actions);
}
//Grant access to public areas to users, admins and guests
foreach ($roles as $role) {
foreach ($publicResources as $resource => $actions) {
foreach ($actions as $action){
$acl->allow($role->getName(), $resource, $action);
}
}
}
//Grant access to private area to role Users
foreach ($privateResources as $resource => $actions) {
foreach ($actions as $action){
$acl->allow('users', $resource, $action);
}
}
foreach ($privateResourcesAdmin as $resource => $actions) {
foreach ($actions as $action){
$acl->allow('admins', $resource, $action);
}
}
//The acl is stored in session, APC would be useful here too
$this->persistent->acl = $acl;
}
return $this->persistent->acl;
}
/**
* This action is executed before execute any action in the application
*
* #param Event $event
* #param Dispatcher $dispatcher
* #return bool
*/
public function beforeExecuteRoute(Event $event, Dispatcher $dispatcher){
$auth = $this->session->get('auth');
if (!$auth){
$role = 'guests';
} else {
if ($this->session->has("account_type")) {
$type = $this->session->get("account_type");
if($type == 99){
$role = 'admins';
} else {
$role = 'users';
}
}
}
var_dump($role);
$controller = $dispatcher->getControllerName();
$action = $dispatcher->getActionName();
$acl = $this->getAcl();
if (!$acl->isResource($controller)) {
$dispatcher->forward([
'controller' => 'errors',
'action' => 'show404'
]);
return false;
}
$allowed = $acl->isAllowed($role, $controller, $action);
if (!$allowed) {
$dispatcher->forward(array(
'controller' => 'errors',
'action' => 'show401'
));
$this->session->destroy();
return false;
}
}
}
\public\index.php
<?php
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Dispatcher; //Used for ACL list and authorization routing
use Phalcon\Events\Manager as EventsManager; //Used for ACL List
use Phalcon\Mvc\Router; //Used for routing logout page
error_reporting(E_ALL);
define('BASE_PATH', dirname(__DIR__));
define('APP_PATH', BASE_PATH . '/app');
try {
/**
* The FactoryDefault Dependency Injector automatically registers
* the services that provide a full stack framework.
*/
$di = new FactoryDefault();
/**
* Read services
*/
include APP_PATH . "/config/services.php";
/**
* Get config service for use in inline setup below
*/
$config = $di->getConfig();
/**
* Include Autoloader
*/
include APP_PATH . '/config/loader.php';
//This makes sure the routes are correctly handled for authorized/unauthorized in people
/**
* MVC dispatcher
*/
$di->set("dispatcher", function () use ($di) {
// Create an events manager
$eventsManager = $di->getShared('eventsManager');
/**
*Check if the user is allowed to access certain action using the SecurityPlugin
*Listen for events produced in the dispatcher using the Security plugin
*/
$eventsManager->attach(
"dispatch:beforeExecuteRoute",
new SecurityPlugin()
);
// Handle exceptions and not-found exceptions using NotFoundPlugin
$eventsManager->attach(
"dispatch:beforeException",
new NotFoundPlugin()
);
$dispatcher = new Dispatcher();
// Assign the events manager to the dispatcher
$dispatcher->setEventsManager($eventsManager);
return $dispatcher;
}
);
/**
* Handle and deploy the application
*/
$application = new \Phalcon\Mvc\Application($di);
echo $application->handle()->getContent();
} catch (\Exception $e) {
echo $e->getMessage() . '<br>';
echo '<pre>' . $e->getTraceAsString() . '</pre>';
}
Because you are doing forward - so this means there is other action executed again and beforeExecuteRoute fired again - that's why 2 times var_dump
I'm still trying to add a recaptcha to my website, I want try the recaptcha from Google but I can't use it properly. Checked or not, my email is still sent.
I tried to understand the code of How to validate Google reCaptcha v2 using phalcon/volt forms?.
But i don't understand where are my problems and more over how can you create an element like
$recaptcha = new Check('recaptcha');
My controller implementation :
<?php
/**
* ContactController
*
* Allows to contact the staff using a contact form
*/
class ContactController extends ControllerBase
{
public function initialize()
{
$this->tag->setTitle('Contact');
parent::initialize();
}
public function indexAction()
{
$this->view->form = new ContactForm;
}
/**
* Saves the contact information in the database
*/
public function sendAction()
{
if ($this->request->isPost() != true) {
return $this->forward('contact/index');
}
$form = new ContactForm;
$contact = new Contact();
// Validate the form
$data = $this->request->getPost();
if (!$form->isValid($data, $contact)) {
foreach ($form->getMessages() as $message) {
$this->flash->error($message);
}
return $this->forward('contact/index');
}
if ($contact->save() == false) {
foreach ($contact->getMessages() as $message) {
$this->flash->error($message);
}
return $this->forward('contact/index');
}
$this->flash->success('Merci, nous vous contacterons très rapidement');
return $this->forward('index/index');
}
}
In my view i added :
<div class="g-recaptcha" data-sitekey="mypublickey0123456789"></div>
{{ form.messages('recaptcha') }}
But my problem is after : i create a new validator for the recaptcha like in How to validate Google reCaptcha v2 using phalcon/volt forms? :
use \Phalcon\Validation\Validator;
use \Phalcon\Validation\ValidatorInterface;
use \Phalcon\Validation\Message;
class RecaptchaValidator extends Validator implements ValidatorInterface
{
public function validate(\Phalcon\Validation $validation, $attribute)
{
if (!$this->isValid($validation)) {
$message = $this->getOption('message');
if ($message) {
$validation->appendMessage(new Message($message, $attribute, 'Recaptcha'));
}
return false;
}
return true;
}
public function isValid($validation)
{
try {
$value = $validation->getValue('g-recaptcha-response');
$ip = $validation->request->getClientAddress();
$url = $config->'https://www.google.com/recaptcha/api/siteverify'
$data = ['secret' => $config->mysecretkey123456789
'response' => $value,
'remoteip' => $ip,
];
// Prepare POST request
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
],
];
// Make POST request and evaluate the response
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return json_decode($result)->success;
}
catch (Exception $e) {
return null;
}
}
}
So i don't know if tjis code is correct anyway, i have a problem too after that : how to create an object "recaptcha" in my form add
$recaptcha = new ?????('recaptcha');
$recaptcha->addValidator(new RecaptchaValidator([
'message' => 'Please confirm that you are human'
]));
$this->add($recaptcha);
PS: I apologize because i'm a noob here and my mother tongue is not english, so if you don't understand me or want give me some advices to create a proper question, don't hesitate ^^
I've made a custom form element for recaptcha. Used it for many projects so far.
The form element class:
class Recaptcha extends \Phalcon\Forms\Element
{
public function render($attributes = null)
{
$html = '<script src="https://www.google.com/recaptcha/api.js?hl=en"></script>';
$html.= '<div class="g-recaptcha" data-sitekey="YOUR_PUBLIC_KEY"></div>';
return $html;
}
}
The recaptcha validator class:
use Phalcon\Validation\Validator;
use Phalcon\Validation\ValidatorInterface;
use Phalcon\Validation\Message;
class RecaptchaValidator extends Validator implements ValidatorInterface
{
public function validate(\Phalcon\Validation $validation, $attribute)
{
$value = $validation->getValue('g-recaptcha-response');
$ip = $validation->request->getClientAddress();
if (!$this->verify($value, $ip)) {
$validation->appendMessage(new Message($this->getOption('message'), $attribute, 'Recaptcha'));
return false;
}
return true;
}
protected function verify($value, $ip)
{
$params = [
'secret' => 'YOUR_PRIVATE_KEY',
'response' => $value,
'remoteip' => $ip
];
$response = json_decode(file_get_contents('https://www.google.com/recaptcha/api/siteverify?' . http_build_query($params)));
return (bool)$response->success;
}
}
Using in your form class:
$recaptcha = new Recaptcha($name);
$recaptcha->addValidator(new RecaptchaValidator([
'message' => 'YOUR_RECAPTCHA_ERROR_MESSAGE'
]));
Note 1: You were almost there, you just missed to create custom form element (the first and last code piece from my example);
Note 2: Also there is a library in Github: https://github.com/fizzka/phalcon-recaptcha I have not used it, but few peeps at phalcon forum recommended it.