Launching a custom view from a custom model. Zend_possible? - zend-framework

You have to promise not to giggle, but my situation is following:
Instead of using partials and helpers and other similar tools that we use already, we want to use a custom view outside all frames and borders of the actual application. Basically, we need at this point to load clean HTML into a variable upon a certain reaction a model. That is monkeys business and can be done by virtually anyone without using a keyboard.
The problem is that the HTML pages that we want to create are supposed to be quite extensive and are a trainwreck to debug/maintain/expand due to the inate "return $arrlglllgll;" approach. To make a smooth and humane script, we would very much love to use the .phtml style with clean html mixed up with php injections without actually rendering it.
Is that possible and how?
I am currently struggling with
$mailView = new Zend_View();
$mailView->setScriptPath('/Templates');
echo($mailView->render('test.php'));
die;
Where test.php is a file I have been trying to reach with any means and corelations imaginable, but ultimately failed every time due to
exception 'Zend_View_Exception' with message 'script 'test.php' not found in path (\library\Extras\Controller\Action\Helpers\)' in \library\Zend\View\Abstract.php:875
Stack trace: blablabla
Loading a custom view from a controller is butt-easy, just provide the relative path and you're set, but it seems that I cannot find anything if I shoot from within a library. Any advice?

In case anybody wonders, this is a lot easier than I ever thought it to be...
// Set the view
$layout = new Zend_Layout();
$view = $layout->getView();
// Send inherited custom parameters
$view->params = $params;
You can thus use the $view as a real view and load any $view->helper as you please.
To save rendered view, type...
$savingParameter = $view->render('controller/subfolder/' . $page . '.phtml');
TADAA

Related

FuelPHP - Building a page in blocks

What is the best way to build a page in FuelPHP so that each of the blocks of the page are built on their own as modules and then the output HTML is put together in a layout.
The best i have found thus far is the HMVC with something like the below.
$block1= Request::forge('mycontroller/block1')->execute();
$block2= Request::forge('mycontroller/block2')->execute();
$data['block1'] =$block1;
$data['block2'] = $block2;
//assign the view to browser output
return View::forge('home/index', $data);
However loading up the whole framework for the calls seems rather inefficient (and possibly slow as a result) . Is there a better way to do this?
If you're using modules (instead of calling a different action in the same controller like you seem to do here), requests are absolutely the way to go. And since requests use the routing table, you can control which controller/action is called by manipulating your routes.
Setting up a new request isn't very complex, the additional delay is a few milliseconds tops.
For completeness, the way to perform an HMVC request:
try
{
$result = \Request::forge('your/uri/here')->execute()->response()->body;
}
catch (\HttpNotFoundException $e)
{
// the requested URI could not be found
}
Instead to use Request::forge('mycontroller/block1')->execute(); you can use View::forge('mycontroller/block1').
The view must be proccess the blocks, not the request. Other advantage is pas vars to block.... i've not tested completely, but it seems more fast to render.

CQ5.5: getting Style of a target page

I've been working on this for sometime now, and I keep running into a wall. I think I'm close, but I figured someone out here in the land of SO might have some deeper insight if not a better way of doing what I'm trying to do.
Basically lets look at this scenario. I have a logo w/ some text that can be set from a few different places. If we look at the setup here is what it looks like.
Hiearchy:
Homepage [has designPath]
- Child Microsite Page [has designPath]
- Logo Component
Logic Flow (in logo component):
if properties.get("logoText") {
use this
} else if currentStyle.get("logoTextFromStyle") {
use this
} else if parentStyle.get("logoTextFromGlobal") {
use this
} else {
be blank
}
My query is with how to get the "parentStyle" of this page. Looking at the docs here: http://dev.day.com/docs/en/cq/5-5/javadoc/com/day/cq/wcm/api/designer/Style.html
I've been able to come up with the fact that I can get a Style object from the "designer" object made available via defineObjects. This is defined with the other utility objects like "pageManager, resourceUtil, resource, currentPage, etc".
With that being said this doesn't seem to work.
//assuming we have getting homePage earlier and it is a valid cq Page resource
Resource homePageResource.slingRequest.getResourceResolver().getResource(homePage.getPath());
Style homePageStyle = designer.getStyle(homePageResource);
at this point homePageStyle is null. To do some more testing I i tried passing currentPage.getPath() instead of homePage.getPath(). I assumed this would give me the currentPage resource and would in end yield the currentStyle object. This also resulted in a null Style object. From this I think I can safely conclude I'm passing the incorrect resource type.
I attempted to load the the cq:designPath into the resource hoping to get a Designer resourceType but to no avail.
I am curious if anyone has run into this problem before. I apologize if I've gone into too much detail, but I wanted to lay out the "why" to my question as well, just in case there was a better way overall of accomplishing this.
I've figured out how to return the style. Here is the rundown of what I did.
//get your page object
Page targetPage = pageManager.getPage("/path/to/target");
//get the Design object of the target page
Design homePageDesign = designer.getDesign(homePage);
//extract the style from the design using the design path
Style homePageStyle = homePageDesign.getStyle(homePageDesign.getPath());
it's very interesting the definition of "getStyle" is a little different from the designer.getStyle vs a Design.getStyle. designer.getStyle asks for a resource whereas Design.getStyle will take the path to a Design "cell" and return the appropriate Style.
I did some testing and it looks like it does work with inherited Styles/Designs. So if my cq:designPath is set at level 1 and I look up a page on at level 2 they will return the Design/Style at the cq:designPath set at level 1.
I hope this helps someone else down the way.
I tried this approach but was not getting the Styles in the Style object.
When we do this:
Design homePageDesign = designer.getDesign(homePage);
In this Design object we get the path till the project node i.e etc/design/myproject
After this if we try to extract the Style from the design path we do not get it.
However I implemented it in a different way.
In the design object, we also get the complete JSON of designs for(etc/design/myproject).
Get the sling:resourceType of the target page and get the value after last index of "/".
Check if this JSON contains the last value. If it contains, you can get your styles, i.e. image, etc.

Access images or doc outside public folder in zend framework

I developing an application in zend framework. I want to store certain secure images and pdf documents outside public folder like /project/data/uploads or /projects/application/data/uploads.
I am not able to access the images/pdf documents other than public folder.
Can someone suggest a way to do it.
thank you
You have to have a separate action that knows how to fetch and deliver all that stuff. Something like this:
public function viewpdfAction()
{
$id = (int) $this->_getParam('id', 0);
// You implement some function - either here in your controller
// or someplace else - to get the pdf name from the passed id.
// Alternatively, you can pass the name itself. Up to you, of course.
// The key is that the request somehow identifies the file requested.
$pdfName = $this->_mapPdfIdToName($id);
// The path to the real pdf
$pdfFile = '/project/data/uploads/pdf/' . $pdfName;
// Disable rendering
$this->_helper->viewRenderer->setNoRender(true);
// Send the right mime headers for the content type
$this->getResponse()
->setBody('')
->setHeader('Cache-control', 'public') // needed for IE, I have read
->setHeader('Content-type', 'application/pdf')
->setHeader('Content-Disposition', sprintf('attachment; filename="%s"', $pdfName));
// Send the content
readfile($pdfFile);
}
Of course, some of this can be pushed down into service classes to keep the controller as thin as possible. Everyone has different tastes in this regard.
I confess that this code not completely tested, mostly trying to give the basic idea. If I have made a total bonehead error in here, please let me know.
Hope it helps!

Running a premade bulletin board through my Front Controller in Zend

I tried to ask this once, but I think that my former question was too unclear for you guys to answer, so I'll try again
I'm making a website using the Zend Framework, and am trying to include the premade messageboard Phorum. So far, I've made it work by not running it through my bootstrap using my .htaccess file. What I'd like to do i'd like to do is to be able to run it through my bootstrap so that I can use my previously created Layouts and Classes that I can only run through Zend.
For example, I have a premade sign in system that works through Zend_Auth. I have the person's data saved in Zend_Session. I load the user's profile through a controller. I have a service layer for the model that connects to my database on behalf of the user. There are several other dependencies that, as far as I can tell, I need the bootstrap for.
Phorum is basically just a large set of PHP scripts that are dependent on GET parameters. My original idea had been to use a controller to render the scripts. An example of what that URI would look like is this: My-Site.com/messageboard/list.php?1,3 with messageboard being the messageboardController. While this works for loading list, it can't capture the GET parameters, which Phorum is dependent on. Due to the complex nature of Phorum, it would be nearly impossible for me to be able to go in and make it something like My-Site.com/messageboard/list/1/3 or anything along those lines. The URI has to be the former, as it is built in to Phorum.
I have tried using frames. I got to keep my log in panel up top, and had the body of the page be a frame, but it was unbookmarkable, and the back button made everything outrageously difficult. I also couldn't get the frame to talk to the parent page in Zend well, so frames aren't an option.
Does anyone have a way that I can do this? What I need, in essence, is to take the script (ex. list.php?1,3) and place whatever it would render, after having used the 1,3 parameters, into a div in the "body" div of my layout. As far as I can tell, render doesn't seem to be able to capture the GET parameters. Does anyone know of a way I can do this.
Any ideas would be immeasurably appreciated. Thank you for your help!
This isn't a trivial thing to process, however, it is possible to write a custom route, along with some controller magic to handle this sort of thing and include the proper php file:
First of all - Your route should probably be (in ZF1.9 application.ini conventions)
resources.router.routes.phorum.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.phorum.route = "messageboard(?:/(.*))?"
resources.router.routes.phorum.defaults.controller = "phorum"
resources.router.routes.phorum.defaults.action = "wrapper"
resources.router.routes.phorum.defaults.module = "default"
resources.router.routes.phorum.defaults.page = "index.php"
resources.router.routes.phorum.map.1 = "page"
Now all requests to messageboard/whatever.php should be routed to PhorumController::wrapperAction() and have 'whatever.php' in $this->getRequest()->getParam('page')
Then it should become a simple matter of redirecting your "wrapper" action to include the proper php file from phorum. I have added some code from a similar controller I have (although mine didn't include php files - it was meant solely for serving a directory of content)
public function wrapperAction() {
$phorumPath = APPLICATION_PATH."../ext/phorum/";
$file = realpath($phorumPath . $this->getRequest()->getParam('page');
if (!$file || !is_file($file)) throw new Exception("File not found");
// disable default viewRenderer - layout should still render at this point
$this->_helper->viewRenderer->setNoRender(true);
// determine extension to determine mime-type
preg_match("#\.([^.]+)$#", $filename, $matches);
switch (strtolower($matches[1]))
{
case "php":
// patch the request over to phorum
include($file);
return; // exit from the rest of the handler, which deals specifically
// with other types of files
case "js":
$this->getResponse()->setHeader('Content-Type', 'text/javascript');
ini_set('html_errors', 0);
break;
case "css":
$this->getResponse()->setHeader('Content-Type', 'text/css');
ini_set('html_errors', 0);
break;
case "html":
$this->getResponse()->setHeader('Content-Type', 'text/html');
break;
// you get the idea... add any others like gif/etc that may be needed
default:
$this->getResponse()->setHeader('Content-Type', 'text/plain');
ini_set('html_errors', 0);
break;
}
// Disable Layout
$this->_helper->layout->disableLayout();
// Sending 304 cache headers if the file hasn't changed can be a bandwidth saver
$mtime = filemtime($fn);
if ($modsince = $this->getRequest()->getServer('HTTP_IF_MODIFIED_SINCE'))
{
$modsince = new Zend_Date($modsince);
$modsince = $modsince->getTimestamp();
if ($mtime <= $modsince) {
$this->getResponse()->setHttpResponseCode(304);
return;
}
}
$this->getResponse()->setHeader('Last-Modified', gmdate("D, d M Y H:i:s",$mtime). " GMT");
readfile($fn);
}
Please - Make sure to test this code for people trying to craft requests with .., etc in the page.

Dynamically setting view directory

I am making a customer portal application using ZF. And the portal needs to work for different company brands. So I need to use all of the same backend code/controllers/etc, but dynamically change the view directory based off of the hostname.
Right now my view directory structure looks something like this:
/application/views/scripts/brand1/
/application/views/scripts/brand1/index/index.phtml
/application/views/scripts/brand1/error/error.phtml
/application/views/scripts/brand2/
/application/views/scripts/brand2/index/index.phtml
/application/views/scripts/brand2/error/error.phtml
/application/views/scripts/brand3/
/application/views/scripts/brand3/index/index.phtml
/application/views/scripts/brand3/error/error.phtml
and so on.
I am using the addScriptPath() function in bootstrap.php like so
protected function _initView()
{
$view = new Zend_View();
$view->doctype('XHTML1_STRICT');
$view->env = APPLICATION_ENV;
$view->addScriptPath(APPLICATION_PATH . '/views/scripts/brand1');
$view->addHelperPath(APPLICATION_PATH . '/views/helpers');
...
}
However when this is run, it is looking for all views using /views/scripts/brand1/(action).phtml instead of looking for views using the correct scheme /view/scripts/brand1/(controller)/(action).phtml
tl;dr is it possible to dynamically choose the view directory and have it work like the default /views/scripts/(controller)/(action).phtml behavior?
I knew I would find the answer after I posted here. In case anyone else encounters the same problem, the solution was using:
$view->setBasePath(APPLICATION_PATH . '/views/brand1');
And then modifying the directory structure to:
/application/views/brand1/scripts/...