Resolve view helper location from within the controller or form - model-view-controller

I have a few view helpers that add JavaScript files when they're needed (for instance, so that only forms use CKEditor and such). My directory structure (simplified to include only the relevant files) is this:
application
--forms
--Project
AddIssue.php
--modules
--default
--views
--helpers
JQueryUI.php
Wysiwyg.php
--project
--controllers
ProjectController.php
--views
--scripts
--project
version.phtml
issueadd.phtml
What I want to do:
include CKEditor in the view project/project/issueadd
include jQuery UI in project/project/version
When I'm inside the view script, calling <?php $this->jQueryUI(); ?> works like a charm, even though the helper is in the default module's helpers directory. However, the same is not true for the controller and the form.
In the controller ProjectController.php, versionAction(), I tried to call:
$this->view->jQueryUI();
and the effect was an exception:
Message: Plugin by name 'JQueryUI' was not found in the registry; used paths: Project_View_Helper_: C:/xampp/htdocs/bugraid/application/modules/project/views\helpers/ Zend_View_Helper_: Zend/View/Helper/
Similarly, in the AddIssue.php form, I tried this:
$this->getView()->wysiwyg();
and there was an exception again:
Message: Plugin by name 'Wysiwyg' was not found in the registry; used paths: Project_View_Helper_: C:/xampp/htdocs/bugraid/application/modules/project/views\helpers/ Zend_View_Helper_: Zend/View/Helper/
Obviously, both would work if my view helpers were in the helper directories of the modules/controllers they're being called from, but since they're used across many modules, I'd like to have them in the default module's view helpers directory.
So, my questions are:
How do I access those view helpers from within the controller and the form?
Is there a simpler way to get around this (apart from simply including all javascript files in the layout)? Like creating a plugin or an action helper? (I haven't done these things before, so I really don't know, I'm only starting my adventure with ZF).

Regarding Q1 (based on the comments). You should be able to access the helpers in a usual way. However since it does not work, I think there is a problem with the way you bootstrap your view resource and/or the way how you perform concrete registration of the helpers or how you add helper path to it. I paste an example of adding helper path in Bootsrap.php:
<?php
#file: APPLICATION_PATH/Bootstrapt.php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
public function _initViewHelperPath() {
$this->bootstrap('view');
$view = $this->getResource('view');
$view->addHelperPath(
APPLICATION_PATH . '/modules/default/views/helpers',
'My_View_Helper' // <- this should be your helper class prefix.
);
}
}
?>
This off course should normally work for modular setup of ZF.
Regarding Q2:
You can use headScript view helper to manage what scripts do you load in the head tag of your layout. Using this helper you can do it from your actions.
For example. If in a layout.php you have:
<head>
<?php echo $this->headScript(); ?>
</head>
then in, e.g. indexAction you can append some JS file as follows:
$this->view->headScript()->appendFile($this->view->baseUrl('/js/someJS.js'));

As much as I hate answering my own questions, there's one more solution I came up with, based on what Marcin has suggested in his answer. It can also be done in application.ini:
resources.view[] =
resources.view.helperPath.My_View_Helper = APPLICATION_PATH "/modules/default/views/helpers"
The caveat is that the lines need to appear in this order. Should it be reversed, anything before resources.view[] = will be ignored.

I'd rather get rid of your JQueryUI.php and would use ZendX. Something like that:
In controller:
ZendX_JQuery::enableView ($this->view);
$this->view->jQuery ()->enable ()->setRenderMode (ZendX_JQuery::RENDER_ALL);
In layout:
<?php echo $this->jQuery () ?>

Related

How can I render a twig template in a custom controller in Silex?

I'm playing with Silex microframework to build a very simple app.
The Silex documentation briefly illustrates how to keep your code organised using controller as class and I've also found this useful article talking about the same practice:
https://igor.io/2012/11/09/scaling-silex.html
but still can't solve my problem
The issue:
in my app.php I'm using
$app->get('/{artist}', 'MyNamespace\\MyController::getAlbum');
This is working. MyController is a class correctly loaded through composer using psr-4.
At the moment the return method of getAlbum($artist) is return $player;
What I'd like to do instead, is returning a twig view from getAlbum, something like:
return $app['twig']->render('player.twig', $player);
To do so, what I've tried to do in my custom class/controller is:
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
[...]
public function getAlbum(Request $request, Application $app, $artist)
but this is generating the following error when I try to access the routed pages:
ReflectionException in ControllerResolver.php line 43:
Class MyNamespace\Request does not exist
Whic made me think that there's a namespace conflict between myNamespace and the Silex namespaces?!
What am I doing wrong?
Is this the right way to make $app visible in my custom controller in order to use return $app['twig']... ?
Thank you in advance!
EDIT
After several other tries still didn't get to the point (replies still welcome!) but I've found a workaround solution that could be useful to anyone will incur in a similar issue. Directly in my app.php I added this
$app->get('/{artist}', function (Silex\Application $app, $artist) use ($app)
{
$object = new MyNamespace\MyController();
$player = $object->getAlbum($artist);
return $app['twig']->render('player.twig',
array(
//passing my custom method return to twig
'player' => $player,));
});
then in my player.twig I added:
{{player | raw}}
And this basically means that I still need an anonymous function to get use of my custom method which is a working solution I'm not really happy with because:
I'm using 2 functions for 1 purpose.
The return value of getAlbum is dependent from the use of "raw" in twig.
SOLVED
The workflow described works fine. It was a distraction error: I've placed the namespace of my custom class after use Symfony\Component\HttpFoundation\Request;
namespace declaration in PHP needs always to be at the top of the file, Silex wasn't able to injects $app and $request for this reason.

Magento email template: Block template inheritance broken

Problem
When I try to add a block into my transactional email template in the following manner:
{{block type='core/template' area='frontend' template='invent/baskettimer/email_items.phtml' record=$record}}
I get the following error, and nothing is rendered.
CRIT (2): Not valid template file:frontend/base/default/template/invent/baskettimer/email_items.phtml
Troubleshooting
Normally this warning points to a typo which is breaking the inheritance but I have quadruple checked and this should work.
I then copied the file into the base and did a test, it rendered correctly.
Create a custom block and set the template, same error is displayed.
Theory
To me it seems template inheritance is broken / not implemented for emails, so it is always looking in base, I cannot put my templates there so I am not sure how to call them.
Possible workarounds
Render the block to html then send it to as a variable to render, problem with this is I am sending the emails from Model level and am having a hard time pre rendering the block, even with a helper.
Render the data using a method, don't really want to do this as it is message / against MVC.
Any help is much appreciated.
Bounty update
So I have traced down the problem, it is probably an easy solution now.
The problem is that I am calling it from a cronjob does not have the correct store view, it is fairly easy to replicate similar situation by using a shell script, then changing the _appCode to null.
<?php
require_once 'abstract.php';
class Mage_Shell_Shell extends Mage_Shell_Abstract
{
protected $_appCode = ''; // works - remove to not work
/**
* Run script
*
*/
public function run()
{
Mage::getModel('invent_baskettimer/email')->sendJob();
}
}
$shell = new Mage_Shell_Shell();
$shell->run();
So basically the question has become:
How do I call a block->toHtml() regardless of store view?
There is not way of setting a cronjob to be like that. Lucky magento lets you emulate your store views, see the following to emulate the default store.
public function cronjob()
{
$iDefaultStoreId = Mage::app()
->getWebsite()
->getDefaultGroup()
->getDefaultStoreId();
$appEmulation = Mage::getSingleton('core/app_emulation');
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($iDefaultStoreId);
.. do your stuff here ..
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
}
For more info see: http://inchoo.net/ecommerce/magento/emulate-store-in-magento/

Laravel: How to find the right blade master template?

To extend a blade template you have to write
#extends('folder.template_name')
This works for standard installation.
I've created a module for the backend and now I can't use my module template because Laravel catches the first record and that is the standard view folder.
My structure looks like this:
app
-- modules
-- modules\backend
-- modules\backend\views
-- modules\backend\views\layouts\master.blade.php
-- views
-- views\layouts\master.blade.php
So when I'm in the backend and try to display my template:
// app\modules\backend\views\page\index.blade.php
#extends('layouts.master')
Laravel renders the app\views\layouts\master.blade.php instead of
app\modules\backend\views\layouts\master.blade.php
I've tried many names inside that #extends e.g.
#extends('app\modules\backend\views\layouts\master')
#extends('app.modules.backend.views.layouts.master')
#extends(base_path(). '\app\modules\backend\views\\' . 'layouts.master')
Nothing works.
While using a package or autoloaded module, referring to it's resources is done using the double colon notation. In your case, to access the module's master template you need to use
#extends('backend::layouts.master')
These conventions are described in the docs, for further info please refer to
Laravel 4 package conventions
Make sure /app/config/view.php has a path entry for where those views are located.
I.E.
'paths' => array(__DIR__.'/../views'),
To
'paths' => array(
__DIR__.'/../views',
__DIR__.'/../modules/backend/views'
),
or whatever represents your actual path.
From here you might want to look into doing the view folder loading via another mechanism if your views are in dynamically generated folders. Maybe a module::boot event that adds the module path to the view paths array? Just an idea.

Codeigniter extend helper but want to call old helper

I am developing an Application in Bonfire.
They have extended the form helper.
Is there a way to call the original form helper from Codigniter without removing the extended one from Bonfire?
"Helpers" are just files with PHP functions in them. They aren't actually "extended", Codeigniter loads it's default helpers after loading yours, and checks if you "overwrote" a function like so:
if ( ! function_exists('form_open'))
{
function form_open() {/* default code */}
}
So unfortunately, no - there's no way to call the original function if you already declared your own.
HOWEVER: It appears that Bonfire does the exact same thing, checking with function_exists, so if you want to - you should be able to load your own form helper before it, but you still cannot simply load the original one without hacking Bonfire and removing the functions (which could have terrible side effects).
Faced the same prob, user742736's comment is the only answer that solved the prob.
Explained in detail, may be this can help some one
You can create your own helper function with out the divs surrounding the drop down here
bonfire/application/helpers/MY_form_helper.php
make a copy of the function form_dropdown, name it like form_dropdown_plain
modify the last few lines of the function to output with out divs
call form_dropdown_plain instead of form_dropdown

How do you create relative links in CodeIgniter?

Example I have the following code in Controller:
class Main extends CI_Controller {
public function index()
{
$this->load->view('main_view');
}
public function create ()
{
$this->load->view('create_view');
}
}
If I want to create a relative link to create, how do I accomplish that? The following link in view doesn't always work. What is apporpiate way to create relative links in CodeIngiter?
Create
Create
or simply:
<?= anchor('/main/create', 'Create'); ?>
Make sure you have loaded the URL Helper.
You don't have to do anything special or load any helpers, just keep in mind that paths will be relative to the url and not the filesystem or controller.
Assuming your installation is in the root directory of your domain, let's say your current URL is http://localhost/class/method/var:
Will work from anywhere
Will go to http://localhost/class/method/var/create
Will go to http://localhost/class/method/create
Relative paths are not your friend in Codeigniter, you are better off sticking with full urls (typically using the helper functions like base_url() and site_url()), or to use the forward slash (relative from root). People have mentioned using the <base> html tag, but I don't personally recommend it. You are going to have some very wacky urls if you use ../../relative paths when you get deeper into the url segments. Example:
If you are here:
http://localhost/controller/method/var1/var2/var3
A link might look like this:
Probably not what you want, but it's an option you may choose. I recommend using one of the other two.
Just to point another alternative, if you dont like the idea of writing a php fragment in each href, and if the other approaches don't satisfy you. You can use put a common <BASE > tag in your html header (for example that points to the root of your application), and then remember that every relative url in your pages will be with respect with that url.

Resources