I want to apply this DB::transaction code to other controllers.
How can I use it globally?
public function store(EmployeeRequest $request)
{
$data = $request->validated();
$employees = Arr::except($data, ['salaries', 'designations']);
$salaries = $data['salaries'];
$designations = $data['designations'];
DB::transaction(function () use ($employees, $salaries, $designations) {
$emp = Employee::create($employees);
$emp->salaries()->create($salaries);
$emp->designations()->create($designations);
return JsonResponseHandler::successResponse(new EmployeeResource($emp->load(['salaries', 'designations'])));
});
}
Related
There's a way to passing parameters from controller to phtml view using PageFactory class?
Controller code:
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\View\Result\Page;
use Magento\Framework\View\Result\PageFactory;
use MyModule\Services\Service\CurlService;
class Index extends Action implements HttpGetActionInterface
{
protected $resultPageFactory;
protected $curlService;
public function __construct(
Context $context,
PageFactory $resultPageFactory,
CurlService $curlService
) {
parent::__construct($context);
$this->resultPageFactory = $resultPageFactory;
$this->curlService = $curlService;
}
public function execute()
{
if(isset($_GET['action']) && $_GET['action'] == true)
{
$response = json_decode($this->curlService->response());
switch($response->status)
{
case 'ok': $msgReturn = 'Successfull'; break;
default: $msgReturn = 'Error'; break;
}
}
$resultPage = $this->resultPageFactory->create();
$resultPage->setActiveMenu(static::MENU_ID);
$resultPage->getConfig()->getTitle()->prepend(__('Page Title'));
return $resultPage;
}
I need passing $msgReturn using PageFactory to the corresponding view
To add data to your phtml block, simply enter this example in the controller where you set your data.
use Magento\Framework\View\Result\PageFactory;
$page = $this->pageFactory->create();
$block = $page->getLayout()->getBlock('block_alias');
$block->setData('name_var', $data);
And then in the phtml file
$data = $block->getData('name_var');
My custom Elemental Extension
renders a GroupedDropdownField to select a Video from a Video - Dataobject.
This works well when
inline_editable is set to false.
When i try to set inline_editable to true, the GroupedDropdownField is not rendered.
How can i display the GroupedDropdownField when inline_editing is true?
<?php
use DNADesign\Elemental\Models\BaseElement;
use SilverStripe\Forms\GroupedDropdownField;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\FieldList;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\View\HTML;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\Backtrace;
class VideoElement extends BaseElement
{
private static $singular_name = 'Videoelement';
private static $plural_name = 'Videoelements';
private static $description = 'add a Video';
private static $icon = 'fa fa-video-camera outline mt-1';
private static $table_name = 'VideoElementBlock';
private static $inline_editable = false;
private static $has_one = [
'Video' => VideoObject::class
];
private static $owns = [
'Video',
];
public function getCMSFields()
{
$fields = parent::getCMSFields();
$categories = VideoCatObject::get();
$subcategoryArray = [];
foreach ($categories as $category) {
$subcategoryArray[$category->Title] = $category->Videos()->map('ID', 'Title')->toArray();
}
$fields->addFieldToTab('Root.Main', GroupedDropdownField::create(
'VideoID',
'Video',
$subcategoryArray
));
return $fields;
}
public function getSummary()
{
if ($this->Video() && $this->Video()->exists()) {
return $this->getSummaryThumbnail() . $this->Video()->Title;
}
return '';
}
public function getSummaryThumbnail()
{
$data = [];
if ($this->Video() && $this->Video()->exists()) {
$data['Image'] = $this->Video()->AutoThumbnail()->ScaleWidth(36)->CropHeight(36);
}
return $this->customise($data)->renderWith('VideoElementThumbnail');
}
public function fieldLabels($includerelations = true)
{
$labels = parent::fieldLabels($includerelations);
$labels['EmbeddedObject'] = _t(__CLASS__ . '.EmbeddedObjectLabel', 'Content from oEmbed URL');
return $labels;
}
protected function provideBlockSchema()
{
$blockSchema = parent::provideBlockSchema();
if ($this->Video() && $this->Video()->exists()) {
$blockSchema['fileURL'] = $this->Video()->AutoThumbnail()->getURL();
$blockSchema['fileTitle'] = $this->Video()->getTitle();
}
return $blockSchema;
}
public function getType()
{
return 'Video';
}
}
At the time of writing, in the current Silverstripe CMS Recipe version (4.7.0), GroupedDropdownField does not have a React implementation, which is required for the Elemental inline editor to support rendering it.
Unfortunately, for the time being you'll need to use a different field that has a React implementation, or write this yourself.
I want to set up a Controller following this guide:
https://webkul.com/blog/create-modules-admin-controllers-without-creating-tab-prestashop/
So in my custom module I do this:
....
public function install() {
return (parent::install()
&& $this->registerHook('header')
&& $this->registerHook('footer')
&& $this->installTab()
);
}
public function installTab() {
$tab = new Tab();
$tab->active = 1;
$tab->class_name = 'abandonedCartsAdminModuleController';
$tab->name = "test";
//If you don't want to create a tab for your admin controller then Pass id_parent value as -1.
$tab->id_parent = -1;
$tab->module = $this->name;
return $tab->add();
}
This is the Controller: abandonedCartsAdminModuleController.php
<?php
class abandonedCartsAdminModuleController extends AdminModuleController {
public function __construct() {
parent::__construct();
$this->context = Context::getContext();
}
public function init() {
$this->retrieve();
}
public function retrieve() {
...
}
}
What happens when I try to install my module is I have the PrestaShopException: "Property Tab->name is empty
at line 887 in file classes/ObjectModel.php"
$tab->name must be an array, one name by language.
$tab->name = array();
foreach (Language::getLanguages(true) as $lang) {
$tab->name[$lang['id_lang']] = 'test';
}
I want to restrict my users to edit/delete only the comments which they added. I found an example on youtube by a guy named intergral30 and followed his instruction. And now my admin account has the possibility to edit/delete everything, but my user has no access to his own comment.
Here's the code:
Resource
class Application_Model_CommentResource implements Zend_Acl_Resource_Interface{
public $ownerId = null;
public $resourceId = 'comment';
public function getResourceId() {
return $this->resourceId;
}
}
Role
class Application_Model_UserRole implements Zend_Acl_Role_Interface{
public $role = 'guest';
public $id = null;
public function __construct(){
$auth = Zend_Auth::getInstance();
$identity = $auth->getStorage()->read();
$this->id = $identity->id;
$this->role = $identity->role;
}
public function getRoleId(){
return $this->role;
}
}
Assertion
class Application_Model_CommentAssertion implements Zend_Acl_Assert_Interface
{
public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $user=null,
Zend_Acl_Resource_Interface $comment=null, $privilege=null){
// if role is admin, he can always edit a comment
if ($user->getRoleId() == 'admin') {
return true;
}
if ($user->id != null && $comment->ownerId == $user->id){
return true;
} else {
return false;
}
}
}
In my ACL I have a function named setDynemicPermissions, which is called in an access check plugin's preDispatch method.
public function setDynamicPermissions() {
$this->addResource('comment');
$this->addResource('post');
$this->allow('user', 'comment', 'modify', new Application_Model_CommentAssertion());
$this->allow('admin', 'post', 'modify', new Application_Model_PostAssertion());
}
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$this->_acl->setDynamicPermissions();
}
And I'm calling the ACL-s isAllowed method from my comment model where I return a list of comment objects.
public function getComments($id){
//loading comments from the DB
$userRole = new Application_Model_UserRole();
$commentResource = new Application_Model_CommentResource();
$comments = array();
foreach ($res as $comment) {
$commentResource->ownerId = $comment[userId];
$commentObj = new Application_Model_Comment();
$commentObj->setId($comment[id]);
//setting the data
$commentObj->setLink('');
if (Zend_Registry::get('acl')->isAllowed($userRole->getRoleId(), $commentResource->getResourceId(), 'modify')) {
$commentObj->setLink('Edit'.'Delete');
}
$comments[$comment[id]] = $commentObj;
}
}
Can anyone tell me what have I done wrong?
Or what should I use if I want to give my admins the right to start a post and other users the right to comment on them. Each user should have the chance to edit or delete his own comment and an admin should have all rights.
You seem to be using the dynamic assertions in a wrong manner, as you are still passing the roleId to isAllowed().
What these dynamic assertions really do, is take a complete object and work with it. Zend will determine which rule has to be used by calling getResourceId() and getRoleId() on your objects.
So all you have to do is pass your objects instead of the strings to isAllowed():
public function getComments($id){
//loading comments from the DB
$userRole = new Application_Model_UserRole();
$commentResource = new Application_Model_CommentResource();
$comments = array();
foreach ($res as $comment) {
$commentResource->ownerId = $comment[userId];
$commentObj = new Application_Model_Comment();
$commentObj->setId($comment[id]);
//setting the data
$commentObj->setLink('');
// This line includes the changes
if (Zend_Registry::get('acl')->isAllowed($userRole, $commentResource, 'modify')) {
$commentObj->setLink('Edit'.'Delete');
}
$comments[$comment[id]] = $commentObj;
}
}
But in can be done better
You would not have to implement a total new Application_Model_CommentResource, but instead you can use your actual Application_Model_Comment like this:
// we are using your normal Comment class here
class Application_Model_Comment implements Zend_Acl_Resource_Interface {
public $resourceId = 'comment';
public function getResourceId() {
return $this->resourceId;
}
// all other methods you have implemented
// I think there is something like this among them
public function getOwnerId() {
return $this->ownerId;
}
}
Assertion would then use this object and retrieve the owner to compare it with the actually logged in person:
class Application_Model_CommentAssertion implements Zend_Acl_Assert_Interface {
public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $user=null,
Zend_Acl_Resource_Interface $comment=null, $privilege=null){
// if role is admin, he can always edit a comment
if ($user->getRoleId() == 'admin') {
return true;
}
// using the method now instead of ->ownerId, but this totally depends
// on how one can get the owner in Application_Model_Comment
if ($user->id != null && $comment->getOwnerId() == $user->id){
return true;
} else {
return false;
}
}
And the usage is like this:
public function getComments($id) {
//loading comments from the DB
$userRole = new Application_Model_UserRole();
$comments = array();
foreach ($res as $comment) {
$commentObj = new Application_Model_Comment();
$commentObj->setId($comment[id]);
//setting the data
$commentObj->setLink('');
// no $commentResource anymore, just pure $comment
if (Zend_Registry::get('acl')->isAllowed($userRole, $comment, 'modify')) {
$commentObj->setLink('Edit'.'Delete');
}
$comments[$comment[id]] = $commentObj;
}
}
I created a parent CRUD class for several controllers and when I render the script it isn't recognizing the paginator variable I set within the listAction(). The code is from my parent class. For instance, I extend Admin_UserController to create Webapp_Controller_Crud.
class Webapp_Controller_Crud extends Zend_Controller_Action
{
public function init()
{
$actionController = get_class($this);
$actionController = str_replace('Admin_',null,$actionController);
$actionController = str_replace('Controller',null,$actionController);
$this->_actionClassName = $actionController;
$actionController = 'Model_' . $this->_actionClassName;
$this->_actionModel = new $actionController();
}
/**
* #return Zend_Paginator
*/
public function getPaginator()
{
$model = $this->getActionModel();
$adapter = new Zend_Paginator_Adapter_DbSelect($model->select());
$paginator = new Zend_Paginator($adapter);
$paginator->setItemCountPerPage(10);
$page = $this->_request->getParam('page', 1);
$paginator->setCurrentPageNumber($page);
return $paginator;
}
public function listAction()
{
$this->view->paginator = $this->getPaginator();
}
}
You use
$this->getView()->paginator = $this->getPaginator();
Which should be
$this->view->paginator = $this->getPaginator();