common object zend framework for Zend_Filter_StripTags which can be used throughout the application? - zend-framework

I'm trying to create a function in bootstrap to intitiate object for Zend_Filter_StripTags, so that I can use its object throughout the application.
protected function _initHtmlFilter() {
$allowedTags = array('p','b','br','strong'); // Allowed tags
$allowedAttributes = array('href'); // Allowed attributes
$stripTags = new Zend_Filter_StripTags($allowedTags,$allowedAttributes);
}
but I'm unable to use this object($stripTags) in any controller.

I would create an Controller Action Helper for this:
class My_Controller_Action_Helper_StripTags extends
Zend_Controller_Action_Helper_Abstract
{
/**
* StripTags
*
* #param string $input String to strip tags from
*
* #return string String without tags
*/
public function stripTags($input)
{
$allowedTags = array('p','b','br','strong'); // Allowed tags
$allowedAttributes = array('href'); // Allowed attributes
$stripTags = new Zend_Filter_StripTags($allowedTags,$allowedAttributes);
// return input without tags
return $stripTags->filter($input);
}
}
// example in indexAction
$noTags = $this->_helper->stripTags('<h2>TEST</h2>');
You have to add the path to your helpers in your application.ini:
resources.frontController.actionhelperpaths.My_Controller_Action_Helper_ = "My/Controller/Action/Helper"

You can use zend registry for this:
protected function _initHtmlFilter() {
$allowedTags = array('p','b','br','strong'); // Allowed tags
$allowedAttributes = array('href'); // Allowed attributes
$stripTags = new Zend_Filter_StripTags($allowedTags,$allowedAttributes);
Zend_Registry::set('zend_strip_tags', $stripTags);
}
and can access it any where like :
Zend_Registry::get('zend_strip_tags');

Related

What is the best way to update an Entity whitout form, FosRest

I'm currently build an API with FosRestBundle. I search how can i make a reusable and optimize service for update my entities.
For now, in my controller i get two entites with paramConverter :
/**
* #Rest\Put("/enseignes/{enseigne_id}",
* requirements={"id" = "\d+"})
*#ParamConverter("enseigne", options={"id":"enseigne_id"})
*#ParamConverter("enseigneUpdate",
* converter="fos_rest.request_body")
*
* #Rest\View()
*/
public function updateEnseigneAction(Enseigne $enseigne,Enseigne $enseigneUpdate, ConstraintViolationList $violations)
{
if (count($violations)){
return $this->view($violations,Response::HTTP_BAD_REQUEST);
}
$mapData = $this->get('app.mapdata');
$mapData->mapDataOnEntity($enseigneUpdate,$enseigne);
$em = $this->getDoctrine()->getManager();
$em->flush();
return $enseigne;
}
So, one entity currently in my bdd with id parameter (and check if the id exist ), and another one who is validate with the converter of fosRest. GOOD
My service look like :
class MapData {
private $propertyMetadata;
private $serializer;
function __construct(MetadataFactory $metadataFactory,Serializer $serializer)
{
$this->propertyMetadata = $metadataFactory;
$this->serializer = $serializer;
}
public function mapDataOnEntity($entityUpdate, $targetEntity)
{
if (get_class($entityUpdate) != get_class($targetEntity)){
throw new BadRequestHttpException('Entity doesnt match');
}
$this->fillProperties($targetEntity,$entityUpdate );
}
/**
*
* #param object $targetEntity
* #param object $entityUpdate
*/
protected function fillProperties($targetEntity, $entityUpdate)
{
$propertyAccessor = new PropertyAccessor();
$reflectorTargetEntity = new \ReflectionClass($entityUpdate);
// dump($classAnnotaions);die();
// Recupere les propriétés de targetEntity
$properties = $reflectorTargetEntity->getProperties();
// dump($properties);die();
foreach ($properties as $property){
if ($property->getName() != 'id'){
$newValue = $propertyAccessor->getValue($entityUpdate,$property->getName());
$propertyAccessor->setValue($targetEntity,$property->getName(),$newValue);
}
}
}
}
First :
In the properties of my class i have the properties of relation with other entities and i don't want it !
Second:
How i can use this code for manage the PATCH too ? And what do you think about this solution ?

Redirect inside a service class?

I've created my own service class and I have a function inside it, handleRedirect() that's supposed to perform some minimal logical check before choosing to which route to redirect.
class LoginService
{
private $CartTable;
private $SessionCustomer;
private $Customer;
public function __construct(Container $SessionCustomer, CartTable $CartTable, Customer $Customer)
{
$this->SessionCustomer = $SessionCustomer;
$this->CartTable = $CartTable;
$this->Customer = $Customer;
$this->prepareSession();
$this->setCartOwner();
$this->handleRedirect();
}
public function prepareSession()
{
// Store user's first name
$this->SessionCustomer->offsetSet('first_name', $this->Customer->first_name);
// Store user id
$this->SessionCustomer->offsetSet('customer_id', $this->Customer->customer_id);
}
public function handleRedirect()
{
// If redirected to log in, or if previous page visited before logging in is cart page:
// Redirect to shipping_info
// Else
// Redirect to /
}
public function setCartOwner()
{
// GET USER ID FROM SESSION
$customer_id = $this->SessionCustomer->offsetGet('customer_id');
// GET CART ID FROM SESSION
$cart_id = $this->SessionCustomer->offsetGet('cart_id');
// UPDATE
$this->CartTable->updateCartCustomerId($customer_id, $cart_id);
}
}
This service is invoked in the controller after a successful login or registration. I'm not sure what's the best way to access redirect()->toRoute(); from here (or if I should do it here).
Also if you have other comments on how my code is structured please feel free to leave them.
Using plugins within your services is a bad idea as they require a controller to be set. When a service is created and you inject a plugin it has no idea of the controller instance so it will result in an error exception. If you want to redirect the user you might just edit the response object as the redirect plugin does.
Notice that I stripped the code to keep the example clear and simple.
class LoginServiceFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new LoginService($container->get('Application')->getMvcEvent());
}
}
class LoginService
{
/**
* #var \Zend\Mvc\MvcEvent
*/
private $event;
/**
* RedirectService constructor.
* #param \Zend\Mvc\MvcEvent $event
*/
public function __construct(\Zend\Mvc\MvcEvent $event)
{
$this->event = $event;
}
/**
* #return Response|\Zend\Stdlib\ResponseInterface
*/
public function handleRedirect()
{
// conditions check
if (true) {
$url = $this->event->getRouter()->assemble([], ['name' => 'home']);
} else {
$url = $this->event->getRouter()->assemble([], ['name' => 'cart/shipping-info']);
}
/** #var \Zend\Http\Response $response */
$response = $this->event->getResponse();
$response->getHeaders()->addHeaderLine('Location', $url);
$response->setStatusCode(302);
return $response;
}
}
Now from within your controller you can do the following:
return $loginService->handleRedirect();

get settings in validator - typo3

I have an extension with backend configuration options.I need to validate a phone number in AddAction and UpdateAction.I can configure the phone number format in backend (say us phone number/indian phone number etc).How can i get the settings in validator?
I have a custom validator to validate phone numbers.Here is my code
<?php
namespace vendor\Validation\Validator;
class UsphonenumberValidator extends \TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator
{
protected $supportedOptions = array(
'pattern' => '/^([\(]{1}[0-9]{3}[\)]{1}[ ]{1}[0-9]{3}[\-]{1}[0-9]{4})$/'
);
public function isValid($property) {
$settings = $this->settings['phone'];
$pattern = $this->supportedOptions['pattern'];
$match = preg_match($pattern, $property);
if ($match >= 1) {
return TRUE;
} else {
$this->addError('Phone number you are entered is not valid.', 1451318887);
return FALSE;
}
}
}
$settings returns null
In cases where the extbase configuration of your extension isn't implemented by default you should retrieve it yourself by using the \TYPO3\CMS\Extbase\Configuration\ConfigurationManager.
Here is an example how you can obtain the settings of your extension:
<?php
namespace MyVendor\MyExtName\Something;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Extbase\Object\ObjectManager;
class Something {
/**
* #var string
*/
static protected $extensionName = 'MyExtName';
/**
* #var null|array
*/
protected $settings = NULL;
/**
* Gets the Settings
*
* #return array
*/
public function getSettings() {
if (is_null($this->settings)) {
$this->settings = [];
/* #var $objectManager \TYPO3\CMS\Extbase\Object\ObjectManager */
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/* #var $configurationManager \TYPO3\CMS\Extbase\Configuration\ConfigurationManager */
$configurationManager = $objectManager->get(ConfigurationManager::class);
$this->settings = $configurationManager->getConfiguration(
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
self::$extensionName
);
}
return $this->settings;
}
}
I recommend that you implement such functionality in general. So you could retrieve any configuration of any extension as a Service inside your extension or something similar to this.
Good luck!

In extbase, how to access item by another value than uid

In a custom extbase extension, I need to call a show action, passing it another value than uid (this is a continuation of Use other than primary key as RealURL id_field).
As the value "other than uid" is not resolved, it results in the exception http://wiki.typo3.org/Exception/CMS/1297759968
EDIT: here's the current working (but ugly) Controller code:
/**
* ItemController
*/
class ItemController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
/**
* itemRepository
*
* #var \STUBR\Weiterbildung\Domain\Repository\ItemRepository
* #inject
*/
protected $itemRepository = NULL;
/**
* action list
*
* #return void
*/
public function listAction(\STUBR\Weiterbildung\Domain\Model\Item $item=null) {
if (!empty(\TYPO3\CMS\Core\Utility\GeneralUtility::_GET('tx_weiterbildung_pi1'))){
$this->forward('show');
}
$items = $this->itemRepository->findAll();
$this->view->assign('items', $items);
}
/**
* action show
*
* #param \STUBR\Weiterbildung\Domain\Model\Item $item
* #return void
*/
public function showAction(\STUBR\Weiterbildung\Domain\Model\Item $item=null) {
$tx_weiterbildung_pi1_get = \TYPO3\CMS\Core\Utility\GeneralUtility::_GET('tx_weiterbildung_pi1');
if (!empty($tx_weiterbildung_pi1_get)){
$dfid = intval($tx_weiterbildung_pi1_get['durchfuehrungId']);
}
$items = $this->itemRepository->findByDurchfuehrungId($dfid);
// helpful:
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($item);
$this->view->assign('item', $items[0]);
}
}
PS here are the 5 lines that could be used in the Repository if the magical method wouldn't work:
//public function findByDurchfuehrungId($dfid) {
// $query = $this->createQuery();
// $query->matching($query->equals('durchfuehrungId', $dfid));
// return $query->execute();
//}
Yes, when you're using actions with model binding in param it will always look for object by field defined as ID - in our case it's always uid, but remember, that you do not need to bind model automatically, as you can retrive it yourself.
Most probably you remember, that some time ago I advised to use <f:link.page additionalParams="{originalUid:myObj.originalUid}"Click here</f:link.page> instead of <f:link.action...>
In that case your show action would look like this:
public function showAction() {
$item = $this->itemRepository->findByOriginalUid(intval(GeneralUtility::_GET('originalUid')));
$this->view->assign('item', $item);
}
Where findByOriginalUid should work magically without declaration, but even if it doesn't it's just matter of 5 lines in the repo ;)
Other sample
According to the code you pasted I'd use it rather like this, in this case listAction gets a role of dispatcher for whole plugin:
public function listAction() {
// access get param in array
$tx_weiterbildung_pi1_get = \TYPO3\CMS\Core\Utility\GeneralUtility::_GET('tx_weiterbildung_pi1');
$dfId = intval($tx_weiterbildung_pi1_get['durchfuehrungId']);
if ($dfId > 0) { // tx_weiterbildung_pi1 exists and is positive, that means you want to go to showAction
$item = $this->itemRepository->findByDurchfuehrungId($dfId);
if (!is_null($item)) { // Forward to showAction with found $item
$this->forward('show', null, null, array('item' => $item));
}else { // Or redirect to the view URL after excluding single item ID from GET params
$this->redirectToUri($this->uriBuilder->setArgumentsToBeExcludedFromQueryString(array('tx_weiterbildung_pi1'))->build());
}
}
// No `tx_weiterbildung_pi1` param, so it should be displayed as a listAction
$items = $this->itemRepository->findAll();
$this->view->assign('items', $items);
}
/**
* #param \STUBR\Weiterbildung\Domain\Model\Item $item
*/
public function showAction(\STUBR\Weiterbildung\Domain\Model\Item $item = null) {
$this->view->assign('item', $item);
}
Your finder should also getFirst() object if possible:
public function findByDurchfuehrungId($DfId) {
$query = $this->createQuery();
$query->matching($query->equals('durchfuehrungId', $DfId));
return $query->execute()->getFirst();
}

Zend framework data mappers + paginator

I mostly use zend_db_table with a paginator, the problem is that it will return zend_db_rows instead the domain objects from my datamapper.
Let's say :
class Content_Model_ArticleMapper {
/*
* #param Zend_Db_Select $select
* #return Zend_Paginator
*/
public function getPaginator($select = null){}
}
I can hack it by overriding _loadAndReturnRow method in a custom rowset
However this is pretty ugly as I don't have a Zend_Db_Row anymore when I query the table.
And loose the methods too like save which I don't want to replicate on the domain object.
:
class Content_Model_DbTable_Rowset_Articles extends Zend_Db_Table_Rowset {
protected function _loadAndReturnRow($position)
{
if (!isset($this->_data[$position])) {
require_once 'Zend/Db/Table/Rowset/Exception.php';
throw new Zend_Db_Table_Rowset_Exception("Data for provided position does not exist");
}
// do we already have a row object for this position?
if (empty($this->_rows[$position])) {
$this->_rows[$position] = new Content_Model_Article($this->_data[$position]);
}
// return the row object
return $this->_rows[$position];
}
}
So my question how do you do this nicely ? :) Do you write custom Paginator adapters?
You can set a rowClass in your DbTable like
DbTable
class Content_Model_DbTable_Article extends Zend_Db_Table_Abstract {
protected $_name = 'article';
public function init() {
$this->setRowClass('Content_Model_Article');
}
}
Domain Model
class Content_Model_Article extends Zend_Db_Table_Row {
//for example
public function getAuthorFullName() {
return $this->author_firstname . ' ' . $this->author_lastname;
}
}
Now rows in your rowset are instances of Content_Model_Article and you can use the Zend_Paginator_Adapter_Iterator.
Using Paginator
$articleTable = new Content_Model_DbTable_Article();
$articleRowset = $articleTable->fetchAll();
$paginator = new Zend_Paginator(Zend_Paginator_Adapter_Iterator($articleRowset));
//now you can loop through the paginator
foreach($paginator as $article) {
echo $article->getAuthorFullName();
}