How to use Aliasing Helpers in cakephp 3? - helper

I need to modify Html->link to check acl before generate a link. Then I use aliasing helper to do this. I have in appController
public $helpers = ['Tools' , 'Html' => ['className' => 'Mhtml']];
And in src/View/Helper/MhtmlHelper.php I have
<?php
namespace App\View\Helper;
use Cake\View\Helper;
use Cake\View\Helper\HtmlHelper;
class MhtmlHelper extends HtmlHelper {
public function acl() {
//return true if it is able to verify the user’s access, else false
}
public function link($title , $url=null , $options=[]) {
return $this->acl ? parent::link($title , $url , $options) : '';
}
}
But I run into this error
Strict (2048): Declaration of App\View\Helper\MhtmlHelper::link() should be compatible with Cake\View\Helper\HtmlHelper::link($title, $url = NULL, array $options = Array) [APP/View\Helper\MhtmlHelper.php, line 6]
What is wrong?

You need to declare the link function like this:
public function link($title , $url = null , array $options = []) {
return $this->acl ? parent::link($title , $url , $options) : '';
}

Related

Builder could not be converted to string

Need help, I want to sum one column in codeigniter4 but I get this error:
Error: object of class CodeIgniter\Database\MySQLi\Builder could not be converted to string
This is my model:
public function tot_crew_wni_arr() {
return $this->db->table('tbl_est_arr')->selectSum('crew_wni_arr');
}
at controller
$data = array(
'tot_crew_wni_arr' => $this->Model_home->tot_crew_wni_arr(),
);
return view('layout/v_wrapper', $data);
This is my view:
<h3><?= $tot_crew_wni_arr ?></h3>
Your model function should look something like this:
public function tot_crew_wni_arr() {
$db = \Config\Database::connect();
$builder = $db->table('tbl_est_arr');
return $builder->selectSum('crew_wni_arr')->get();
}

In EasyAdmin 3 configureActions method how do I get the current entity?

I wish to add an action to another to the index action with a predefined filter.
To build the filter I need the get current entity in the configureActions method.
public function configureActions(Actions $actions): Actions
{
parent::configureActions($actions);
$adminUrlGenerator = $this->get(AdminUrlGenerator::class);
$url = $adminUrlGenerator
->setController(SiteCrudController::class)
->setAction(Action::INDEX)
->set('filters', [
'agent' => [
'comparison' => '=',
'value' => 2194, // How to get current entity here??
]
])
->generateUrl()
;
$viewRelatesSites = Action::new('viewRelatedSites', 'Sites', 'fa fa-file-invoice')
->linkToUrl($url)
;
$actions->add(Action::DETAIL, $viewRelatesSites);
$actions->add(Action::EDIT, $viewRelatesSites);
return $actions;
}
}
How can I get the entity here?
To get the current entity the AdminContext is needed.
The best place to get this with the entity set is in a BeforeCrudActionEvent.
final class AgentCrudActionEventListen implements EventSubscriberInterface
{
private AdminUrlGenerator $adminUrlGenerator;
private AdminContextProvider $adminContextProvider;
public function __construct(AdminUrlGenerator $adminUrlGenerator, AdminContextProvider $adminContextProvider)
{
$this->adminUrlGenerator = $adminUrlGenerator;
$this->adminContextProvider = $adminContextProvider;
}
public static function getSubscribedEvents(): array
{
return [
BeforeCrudActionEvent::class => 'onBeforeCrudActionEvent',
];
}
public function onBeforeCrudActionEvent(BeforeCrudActionEvent $event): void
{
$crud = $event->getAdminContext()->getCrud();
if ($crud->getControllerFqcn() !== AgentCrudController::class) {
return;
}
$entity = $this->adminContextProvider->getContext()->getEntity();
if (!$entity) {
return;
}
$url = $this->adminUrlGenerator
->setController(SiteCrudController::class)
->setAction(Action::INDEX)
->set('filters', [
'agent' => [
'comparison' => '=',
'value' => $entity->getPrimaryKeyValue(),
]
])
->generateUrl()
;
$viewRelatedSites = Action::new('viewRelatedSites', 'Sites', 'fa fa-file-invoice')
->linkToUrl($url)
;
$actions = $crud->getActionsConfig();
$actions->appendAction(Action::DETAIL, $viewRelatedSites->getAsDto());
$actions->appendAction(Action::EDIT, $viewRelatedSites->getAsDto());
}
}
After a day looking for the current entity into my AbstractCrudController, I found this :
$currentEntity = $this->getContext()->getEntity()->getInstance();
Since EasyAdmin 3 events are discouraged per the docs:
Starting from EasyAdmin 3.0 everything is defined with PHP. That's why it's easier to customize backend behavior overloading PHP classes and methods and calling to your own services. However, the events still remain in case you want to use them.
public function configureActions(Actions $actions): Actions
{
// Create your action
$viewRelatedSites = Action::new('viewRelatedSites', 'Sites', 'fa fa-file-invoice');
//set the link using a string or a callable (function like its being used here)
$viewRelatedSites->linkToUrl(function($entity) {
$adminUrlGenerator = $this->get(AdminUrlGenerator::class);
$url = $adminUrlGenerator
->setController(SiteCrudController::class)
->setAction(Action::INDEX)
->set('filters', [
'agent' => [
'comparison' => '=',
'value' => $entity->getId()
]
])
->generateUrl();
return $url;
});
$actions->add(Crud::PAGE_INDEX, $viewRelatedSites);
return $actions;
}

Too few arguments to function App\Controllers\Parsys::__construct(), 0 passed in

First I code without use RequestInterface and runwell, but I when I applicate the RequestInterface from the docs here: https://codeigniter4.github.io/userguide/incoming/incomingrequest.html I got this error, What happen with my code?
<?php namespace App\Controllers;
use CodeIgniter\HTTP\RequestInterface;
class Parsys extends BaseController {
protected $request;
public function __construct(RequestInterface $request) {
$this->request = $request;
}
public function index() {
$data = [
'title' => "Parameter System",
];
return view("backend/parsys_frm", $data);
}
public function getList() {
$frm = $request->getGet('frm');
$q = $this->request->getGet('q');
$order_by = $this->request->getGet('order_by');
$page = $this->request->getGet('page');
$limit = $this->request->getGet('limit');
$limit = #$limit == 0 ? 10 : $limit;
$this->queryList($total, $current, $page, $limit, $q, [1 => 1]);
$data = $current->result_array();
header('Content-Type: application/json');
echo json_encode(compact(['total', 'page', 'limit', 'data', 'q']));
}
I use ubuntu 20.04, lampp PHP 7.4
Instead of using the __construct magic method use the built in init method.
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
}

Querying with the Query Builder

I'M USING SYMFONY 4.12 I'm trying to write queries to filter my jobs(I've job table ,départements one) I first try with experience but I'm stuck in
here is my offerController:
/**
* #Route("/offres", name="offres")
* #param Request $request
* #param PaginatorInterface $paginator
* #param FormFactoryInterface $formFactory
* #return Response
*/
public function offreSearch(Request $request, PaginatorInterface $paginator ,FormFactoryInterface $formFactory):Response
{
$datas =new OffreEmploi();
$formFilter=$formFactory->create(OfferFilterForm::class,$datas);
$offres = $this->repository->findSearch($datas);
$formFilter->handleRequest($request);
return $this->render('offre/index.html.twig', [
'controller_name' => 'OffreController',
'offres' => $offres,
'formulaire' =>$formFilter->createView(),
]);
}
and this is my query in the offerRepository:
public function findSearch(OffreEmploi $data):?array
{
$query = $this->createQueryBuilder('o');
if ($data->getExperience() !== null) {
$query
->where('o.experience > :experience')
->setParameter('experience', $data->getExperience());
}
return $query->getQuery()->getResult();
}
when it come to enter any number IT gives the same thing it shows all the jobs stored in the database,I don't know where the problem is.
THE RESULT
Try with this solution:
public function findSearch(OffreEmploi $data):?array
{
$query = $this->createQueryBuilder('o');
if (!empty($data->getExperience())
// ...
}
return $query->getQuery()->getResult();
}
If it doesn't work , try to dump $data->getExperience() to see its value
public function findSearch(OffreEmploi $data):?array
{
$query = $this->createQueryBuilder('o');
dd($data->getExperience()) ;
}
EDIT
So try to do like this but be sure you send the form with GET method not POST:
public function offreSearch(Request $request, PaginatorInterface $paginator)
{
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(OfferFilterForm::class);
$form->handleRequest($request);
$data = $request->query->all();
$qb = $em->getRepository(OffreEmploi::class)->findSearch($data);
$offres = $paginator->paginate($qb, $request->query->get('page', 1), 20);
return $this->render('offre/index.html.twig', array(
'formulaire' =>$form->createView(),
'offres' => $offres,
));
}
In the formType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('experience', IntegerType::class);
//.....
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => null,
'csrf_protection' => false,
));
}
public function getBlockPrefix()
{
return null;
}
and in the Repository:
public function findSearch($data)
{
$query = $this->createQueryBuilder('o');
if (!empty($data['experience'])) {
$query
->where('o.experience > :experience')
->setParameter('experience', $data['experience']);
}
return $query->getQuery()->getResult();
}
I think I found the answer but I just create another class witch contain all the form's field and that's it I don't know how it works because I didn't change significant things for that thinks for your help.

Overwrite backend template in bolt.cms

I am trying to overwrite a template file located in vendor/bolt/bolt/app/view/twig/editcontent/fields/_block.twig (I want to replace the "block selection" dropdown). Regarding to #1173, #1269, #5588, #3768 and #5102 this is not supported by default so I have to write a extension for this. So I tried this:
BackendBlockSelectionExtension:
namespace Bundle\Site;
use Bolt\Filesystem\Adapter\Local;
use Bolt\Filesystem\Filesystem;
use Silex\Application;
use Bolt\Extension\SimpleExtension;
class BackendBlockSelectionExtension extends SimpleExtension
{
public function getServiceProviders()
{
return [
$this,
new BackendBlockSelectionProvider(),
];
}
}
BackendBlockSelectionProvider:
namespace Bundle\Site;
use Bolt\Filesystem\Adapter\Local;
use Bolt\Filesystem\Filesystem;
use Silex\Application;
use Silex\ServiceProviderInterface;
class BackendBlockSelectionProvider implements ServiceProviderInterface
{
public function register(Application $app)
{
$side = $app['config']->getWhichEnd();
if ($side == 'backend') {
$path = __DIR__ . '/App/templates/Backend';
$filesystem = $app['filesystem'];
$filesystem->mountFilesystem('bolt', new Filesystem(new Local($path)));
$app['twig.loader.bolt_filesystem'] = $app->share(
$app->extend(
'twig.loader.bolt_filesystem',
function ($filesystem, $app) {
$path = __DIR__ . 'src/App/templates/Backend/';
$filesystem->prependPath($path, 'bolt');
return $filesystem;
}
)
);
}
}
public function boot(Application $app)
{
}
}
This seems to do the job, but I got an error I don't understand at all: The "bolt://app/theme_defaults" directory does not exist.
So my final question is: Does anyone have some example code how to overwrite/modify vendor/bolt/bolt/app/view/twig/editcontent/fields/_block.twig without touching the vendor folder?
This should be much simplier than this.
In your extension class overwrite protected function registerTwigPaths() function like this:
protected function registerTwigPaths()
{
if ($this->getEnd() == 'backend') {
return [
'view' => ['position' => 'prepend', 'namespace' => 'bolt']
];
}
return [];
}
private function getEnd()
{
$backendPrefix = $this->container['config']->get('general/branding/path');
$end = $this->container['config']->getWhichEnd();
switch ($end) {
case 'backend':
return 'backend';
case 'async':
// we have async request
// if the request begin with "/admin" (general/branding/path)
// it has been made on backend else somewhere else
$url = '/' . ltrim($_SERVER['REQUEST_URI'], $this->container['paths']['root']);
$adminUrl = '/' . trim($backendPrefix, '/');
if (strpos($url, $adminUrl) === 0) {
return 'backend';
}
default:
return $end;
}
}
Now you can crete a view directory in your extensions directory in which you can define templates in structure like in Bolt's default. I would start with copy and overwrite.

Resources