How to add custom extension for template in PHPixie? - php

I want to write my own extension for PHPixie to use it in templates like this:
<div class="title"><?=$formatStyle($person->id, $format_id)?></div>
My extension class (see sample in documentation) is:
\bundles\app\src\Template\Extensions\Extension\TYM.php
<?php
namespace Project\App\Template\Extensions\Extension;
class TYM implements \PHPixie\Template\Extensions\Extension
{
public function name()
{
return 'tym';
}
public function aliases()
{
return array();
}
public function methods()
{
return array(
'formatStyle' => 'format'
);
}
public function format($string, $formtat_id)
{
return 'asdf'; // TO DO
}
}
Where should i place this file in my bundle?

Just add your class to Project/Framework/Extensions.php to templateExtensions() method.
In my project it is now looking like this:
/**
* Extensions for the Template component
* #return array
*/
public function templateExtensions()
{
return array_merge(parent::templateExtensions(), array(
//add your Template Extensions here
new \Project\App\Template\Extensions\Extension\Base64()
));
}
I don't know full name for your class, so cannot provide full solution, only example :)

Related

Convert an array of objects into an array of DTOs

I am currently working on a HMS project (Hotel Management System). I am currently stucked in implementing a DTO based functionality in Symfony 5. The following from below is my HotelMapper.php file where I would like to build a method which transforms the Array of Hotels into an Array of DTOs so I can pass them in the Hotel Controller later on and for this I would like to use the objects from the dtoToHotel() function. I already created the DTO (setters & getters).
namespace App\Transformer;
use App\DTO\HotelDTO;
use App\Entity\HotelEntity;
class HotelMapper
{
public $hotel;
public function dtoToHotel(HotelDTO $hotelDTO, Hotel $hotel) : HotelEntity
{
$hotel->setId($hotelDTO->getId());
$hotel->setName($hotelDTO->getName());
$hotel->setLocation($hotelDTO->getLocation());
$hotel->setEmployees($hotelDTO->getEmployees());
$hotel->setAvailability($hotelDTO->getAvailability());
$hotel->setFacility($hotelDTO->getFacility());
$hotel->setPhoto($hotelDTO->getPhoto());
$hotel->setDescription($hotelDTO->getDescription());
$hotel->setEarnings($hotelDTO->getEarnings());
}
public function hotelToDto(HotelEntity $hotel)
{
return HotelDTO(
$hotel->getId(),
$hotel->getName(),
$hotel->getLocation(),
$hotel->getEmployees(),
$hotel->getAvailability(),
$hotel->getFacility(),
$hotel->getPhoto(),
$hotel->getDescription(),
$hotel->getEarnings()
);
}
public function transformHotelsArrayToDTO()
{
/* Code here */
}
}
The code from below is my HotelController where I would like to update the following line $hotels = $this->hotelRepository->findAll() inside the showAllHotels() function by passing the DTO in here. Any help is much appreciated!
class HotelController extends AbstractController
{
/**
* #var HotelRepository
*/
public $hotelRepository;
public function __construct(HotelRepository $hotelRepository)
{
$this->hotelRepository = $hotelRepository;
}
/**
* #Route (path="/", methods={"GET"})
*/
public function index(): Response
{
return $this->render('index/index.html.twig');
}
/**
* #Route (path="/hotel-management", methods={"GET"})
*/
// It does populate the table with the hotels from the DB
public function showAllHotels(): Response
{
$hotels = $this->hotelRepository->findAll();
return $this->render('hotel-management/hotel-management.html.twig', array('hotels' => $hotels));
}
}
Inject HotelMapper transformer to your controller and then pass findAll's result to this function:
public function transformHotelsArrayToDTO(array $items): array
{
if (empty($items) or is_null($items)) {
return [];
}
return array_map([$this, 'hotelToDto'], $items);
}

How to extend the class kartik\dynagrid\DynaGrid?

Installed the DynaGrid plugin and ran into the problem of expanding it. I created my own class DynaGridViewAdvanced, which is located on the path modules/appWidgets/widgets/grid and has namespace app\modules\appWidgets\widgets\grid.
The class code is as follows:
<?php
declare(strict_types=1);
namespace app\modules\appWidgets\widgets\grid;
use kartik\dynagrid\DynaGrid;
use Yii;
use yii\helpers\Url;
class DynaGridViewAdvanced extends DynaGrid {
/**
* #var bool активность функции перехода на просмотр при двойном клике
*/
public $transitionToView = false;
public function init() {
parent::init(); // TODO: Change the autogenerated stub
if ($this->transitionToView && empty($this->rowOptions)) {
$this->rowOptions = function($model, $key, $index, $grid) {
$viewLink = Url::toRoute(['/' . Yii::$app->controller->id . '/view']);
return ['ondblclick' => 'location.href="' . $viewLink . '?id="+(this.dataset.key);'];
};
}
}
public function run() {
parent::run(); // TODO: Change the autogenerated stub
}
}
Actually, the question is why the error is thrown out and how to fix it?
View not Found – yii\base\ViewNotFoundException
The view file does not exist: /var/www/urs/modules/appWidgets/widgets/grid/views/config.php
In DynaGrid itself there is a property _module, which stores in itself kartik\dynagrid\Module, in which there is a property configView. configView is used only in DynaGrid itself:
$dynagrid = $this->render(
$this->_module->configView,
[...]
)
As far as I understand the error, he is trying to find this configuration view file exactly with namespace.
See the full error page:

Create a global validate_date function in DateTimeHelper.php to use that function in all laravel.php controllers

I have separate validate_date functions in controller1.php, controller2.php, and controller3.php. I want to create a global function in DateTimeHelper.php to validate dates instead of creating a function in each controller for this functionality. I am using Laravel in the backend
Controller1:
private function validate_date($date)
{
$split_date = explode('/', $date);
if (count($split_date) == 3) {
return checkdate($split_date [0], $split_date [1], $split_date [2]);
}
return false;
}
Controller2 && controller 3:
private function validate_date($date)
{
if ($this->check_field($date) && $date !== 'Invalid date') {
return true;
}
return false;
}
My problem is that I am using different functions in different controllers, I need a global function to validate dates instead of creating a function in each controller for this functionality.
The following method will probably do what you're looking for:
Create a new file called DateTimeHelper.php inside a (new) Helpers folder. The final path will be app\Helpers\DateTimeHelper.php.
The content of DateTimeHelper.php will look like:
<?php
namespace App\Helpers;
class DateTimeHelper {
public function validate()
{
}
public function checkField()
{
}
}
Now edit the controllers where you want to use the class, add a procted property $dateTimeHelper and use Laravel's Automatic Injection like this:
<?php
namespace App\Http\Controllers;
use App\Helpers\DateTimeHelper;
class UserController extends Controller
{
protected $dateTimeHelper;
/**
* Create a new controller instance.
*
* #param DateTimeHelper $dateTimeHelper
* #return void
*/
public function __construct(DateTimeHelper $dateTimeHelper)
{
$this->dateTimeHelper = $dateTimeHelper;
}
public function show($date)
{
return $this->dateTimeHelper->validate($date);
}
}
Hopefully this should solve the problem, however, I'd recommend to look into Laravel validation.
How about a Service Class instead of helper function and put all possible date validation from the system into this Service Class?

What is the best prestashop-way to include tpl in AdminController?

I need interacts with a .tpl file in my adminController class, but when I try to do that, this error appears
Fatal error: Call to undefined method RiddlePageController::getCacheId() in /home/USER/public_html/prestashop/modules/RiddleModule/controllers/admin/RiddlePage.php on line 48
This is my admin controller code:
class RiddlePageController extends AdminController {
public function __construct()
{
$this->html = '';
$this->display = 'view';
$this->meta_title = $this->l('metatitle');
$this->module = "RiddleModule";
parent::__construct();
}
public function initContent()
{
$this->postProcess();
$this->show_toolbar = true;
$this->display = 'view';
$this->meta_title = $this->l('Modulo');
parent::initContent();
}
public function initToolBarTitle()
{
$this->toolbar_title = $this->l('Titulo');
}
public function initToolBar()
{
return true;
}
public function renderView() {
$this->context->smarty->assign(
array(
'img1' => "http://www.free-3dmodels.com/image/Flowers-3D-Model-3662994d.png",
'img2' => "http://www.all3dmodel.com/Images/39.jpg"
)
);
// in return have error "getCacheId"
return $this->display(__FILE__, 'content.tpl', $this->getCacheId());
// return "<b>This works fine!!</b>";
}
my tpl file have only {$img1} and {$img2} for testing.
Maybe I do all wrong, and this is not the best way to make in my own admin page.
Your error is because the AdminController class doesn't have the getCacheId method.
To answer to your question you have to made some little fix.
First (extends ModuleAdminController not AdminController):
class AdminRiddlePageController extends ModuleAdminController
{
}
Then if you want to view your custom tpl, place a view.tpl file in:
prestashop/modules/RiddleModule/views/templates/admin/riddlepage/helpers/view/
or
prestashop/modules/RiddleModule/views/templates/admin/riddle_page/helpers/view/ (I don't remember well if the underscore is necessary)
And your renderView method should be like this:
public function renderView()
{
/* Your code */
/* Use this snippet to assign vars to smarty */
$this->tpl_view_vars = array(
'myvar' => 1,
'secondvar' => true
)
return parent::renderView();
}
AdminController class has not an implementation of display method you use to render TPL.
You can use something like this after set module var:
$this->module->display(_PS_MODULE_DIR_.$this->module->name.DIRECTORY_SEPARATOR.$this->module->name.'.php', 'content.tpl')
Good luck.
As #TheDrot told us, the answer are in using $this->context->smarty->fetch(location), but not in renderList, but in the return statement of renderView is OK and prestashop get the tpl file and load correctly the smarty variables. Ex:
public function renderView(){
$this->context->smarty->assign(
array(
'img1' => "http://www.free-3dmodels.com/image/Flowers-3D-Model-3662994d.png",
'img2' => "http://www.all3dmodel.com/Images/39.jpg"
)
);
return $this->context->smarty->fetch(_PS_MODULE_DIR_ . "RiddleModule/controllers/front/prueba.tpl");
}
The file location isn't important to load the TPL file in this case

Symfony2 / FOSUserBundle: Change render variables in response without altering parent class

One of my classes currently extends the BaseController on the FOSUserBundle, and returns the parent action. However, due to project spec, I shouldn't have the need to edit the parent class. Is there a way of sending additional variables, for twig to render, through the child response?
Child Class:
class ChangePasswordController extends BaseController
{
public function changePasswordAction(Request $request)
{
$response = parent::changePasswordAction($request);
return $response; // and 'myVariable' => $myVariable
}
}
Parent Class:
class ChangePasswordController extends ContainerAware
{
/**
* Change user password
*/
public function changePasswordAction(Request $request)
{
//lots of code.....
return $this->container->get('templating')
->renderResponse(
'FOSUserBundle:ChangePassword:changePassword.html.'
.$this->container->getParameter('fos_user.template.engine'),
array(
'form' => $form->createView()
//and 'myVariable' => $myVariable
)
);
}
}
So to summarise, is there a way of passing something to the parent class, without changing the parent class... whilst rendering the twig view with an additional variable.
-- Update --
Essentially I want to render a form using the FOSUserBundle changePassword action, therefore this works fine:
return $this->container
->get('templating')
->renderResponse(
'FOSUserBundle:ChangePassword:changePassword.html.'.$this->container->getParameter('fos_user.template.engine'),
array('form' => $form->createView())
);
However, I want to pass more variables to the view, just like the 'form' is passed as shown above, without altering the FosUserBundle ChangePassword Controller. Therefore I have a class which inherits the that controller, adds some additional functionality and returns the parent change password action:
class ChangePassController extends ChangePasswordController
{
public function changePasswordAction(Request $request)
{
// more code......
$response = parent::changePasswordAction($request);
return $response;
}
}
But, like with most applications, I want to add more than just the form variable to a view template. So is there a way of passing an additional variable to the view, without altering the parent controller / action? Like (but not like) pushing 'myVariable' => $myVariable to the parent changePasswordAction return statement?
There is a section in FOSUserBundle documentation that describes exactly how to do that, and from Symfony2's Cookbook, How to use Bundle Inheritance to Override parts of a Bundle.
In summary, create a Bundle class to override FOSUserBundle in src:
// src/Acme/UserBundle/AcmeUserBundle.php
<?php
namespace Acme\UserBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class AcmeUserBundle extends Bundle
{
public function getParent()
{
return 'FOSUserBundle';
}
}
Then, override the ChangePasswordController class:
use FOS\UserBundle\Controller\ChangePasswordController as BaseController;
class ChangePasswordController extends BaseController
{
public function changePasswordAction(Request $request)
{
$response = parent::changePasswordAction($request);
return $response; // and 'myVariable' => $myVariable
}
}
--UPDATE--
Ok I think I misread you question. Anyway what renderResponse() of the templating service does is essentially:
$response->setContent($this->render($view, $parameters));
You can see the Class of the templating service by running app/console container:debug which is actually the TwigEngine class.
So you can just re-invoke renderResponse() and supply you own extra parameters. eg:
return $this->container->get('templating')->renderResponse(
'FOSUserBundle:ChangePassword:changePassword.html.'.$this->container->getParameter('fos_user.template.engine'),
array(
'form' => $form->createView(),
'myVariable' => $myVariable', // There you go
),
$response // The previous response that has been rendered by the parent class, by this is not necessary
);
Think bottom up.
You can access your data without passing it through action, using Twig Extension http://symfony.com/doc/current/cookbook/templating/twig_extension.html
twig.extension.user_profile:
class: 'MyBundle\UserProfileExtension'
arguments:
- '#doctrine.orm.entity_manager'
tags:
- { name: twig.extension }
Extension class
class UserProfileExtension extends \Twig_Extension
{
/**
* #var EntityManager
*/
private $entityManager;
/**
* #param UserProfileDataService $userProfileDataService
*/
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* #return array
*/
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('get_my_custom_var', array($this, 'getMyCustomVar')),
);
}
/**
* #return array
*/
public function getMyCustomVar()
{
$var = $this->entityManager->getRepository('MyCustomRepository')->findOneBy(['id' => 1]);
return $var;
}
/**
* Returns the name of the extension.
*
* #return string The extension name
*/
public function getName()
{
return 'user_profile_extension';
}
Template usage
{dump(get_my_custom_var())}
if I am understanding your question correctly you should be able to set additional variables on the response like this:
use FOS\UserBundle\Controller\ChangePasswordController as BaseController;
class ChangePasswordController extends BaseController
{
public function changePasswordAction(Request $request)
{
$response = parent::changePasswordAction($request);
$response['myVariable'] = $myVariable;
return $response;
}
}
Hope this helps!

Categories