Is there a way to tell Smarty not to print an expression? - php

I'd like to use Smarty in conjuction with the Zend Framework, especially some of it's View Helpers.
Now i got to the point, where i implemented a Zend_View that uses Smarty to display templates. I can assign values as usual. So far so good.
Now I would really like to use Zend View Helpers in Smarty. I asssigned the Zend_View object as "this" and tried this in the template:
{$this->layout()->setLayout('default')}
As this will print the return value of the setLayout() method (which is a Zend_Layout), there is an error:
Catchable fatal error: Object of class Zend_Layout could not be converted to string in /path/to/templates_c/089c3d67082722c7cabc028fa92a077f8d8b4af5.file.default.tpl.cache.php on line 27
This is clear to me, so I went into Smarty's core to fix this:
The generated code did look like this:
<?php
echo $_smarty_tpl->tpl_vars['this']
->value->layout()
->setLayout('default');
?>
And now it reads:
<?php
$hack = $_smarty_tpl->tpl_vars['this']
->value
->layout()
->setLayout('default');
if( is_string($hack) ||
( is_object($hack) && method_exists($hack, '__toString') ) )
echo $hack;
?>
Now this is probably the worst fix i can think of, for several reasons (Smarty compatibility loss, performance). Sadly, it's the only one. Is there a way to stop Smarty from trying to print the output of the expression? Also, i want the syntax to stay as intuitive as possible, and i don't want to write Smarty functions for all the Helpers, because I want to use this code with a third-party application (Pimcore) that might add new helpers.
Thanks in advance for any suggestions!

Some suggestions (only ideas, nothing so good):
Create a __toString() in Zend_Layout who returns null or empty string (big/ugly/worse workaround).
Create a variable modifier/filter who return null or empty string, so your call will be something like {$this->layout()->setLayout('default')|noreturn} (you can use it with other things too and noreturn can be called with an friendly name like definition or define to indicate the purpose of the instruction, but a workaround too)
Using the assign to build a expression who set all this thing to another var (workaround too).
Maybe this can give you some good ideas =)

Related

unrequire a file once it's been required in PHP

Suppose I do
require('lol.php');
whereby lol.php contains the following function declaration
function lolfunc(){
}
is it possible to "unrequire" lol.php such that I can then require another file
require('lol2.php');
whereby lol2.php contains a function with the same name previously declared in lol.php:
function lolfunc(){
echo "this is lol2 biyotch";
}
and have lolfunc() be the one declared in lol2.php? eg if I call lolfunc() it'll echo "this is lol2 biyotch"??
My answer: don't do that.
Try to work with the original author to include the functions you need into a patched version of the old code and then use that patched version everywhere.
If you can't do that, find out how big a job it would actually be to update all the code to new version. Start with white-box analysis: see what's changed in terms of interfaces, data structures et al. Then examine the calling code to see whether the caller cares about any of the things that have changed.
If you can't even do that, use namespacing or some other form of wrapping so that you can include both libs. However, make sure any initialisaton or setup is done on both libs!
What you should do, is to include the required (sets) of files based on conditional clauses, instead of trying to "unrequire".
So:
if($flag_use_oldver)
{
include("oldver.php");
}
else
{
include("newver.php");
}
If you want a more sophisticated solution, of course you could try to have a wrapper class hierarchy that will extend/override as required, but I think that is a bit over-engineering for a pretty straightforward problem statement.

Problems using a Wiki to HTML script (FFNN) as Helper in CodeIgniter

I've found this script for converting wiki syntax to HTML in php and i've tried to integrate it into Codeigniter. it seems really easy to use. However, it's not working, and instead producing around 8 of these errors:
Message: Use of undefined constant LS_NONE - assumed 'LS_NONE'
I think this is because Codeigniter helpers are not a class but rather functions, and this bit of code is a class, or does this issue lie with something else? I've also tried to use it as a model without success.
It also seems horribly outdated (2007). Could somebody suggest a really simple alternative or maybe give an idea of how to convert this to a simple function if that is possible? It's a very short piece of code. I'm not sure how these constants work in relationship to a function versus a class.
I've given the Text_Wiki from Pear ago, but the use and complexity well exceeds both my requirements and knowledge :)
//Any help would be greatly appreciated
Loaded using:
$row = $query->row();
$content=$row->course_content;
$this->load->helper('wiki');
$content=explode("\n", $content);
$output = WikiTextToHTML::convertWikiTextToHTML($content);
$html=array_merge($output);
$data['contents'][]= $html;
$this->load->view('default/a',$data);
It looks like the script is actually a class. put it in the libraries folder and load it with $this->load->library(). That will allow it to properly initialize and define the constants that it uses.
something like:
$this->load->library('wikitexttohtml');
$this->wikitexttohtml->convertWikiTextToHTML($wiki_text);

Zend Framework partialLoop with associative array of models

I'm making a web application in Zend Framework. I've reached the stage of cleaning up. As things often go, I have a couple of messy view scripts that have become utterly unreadable (tons of (v)sprintf's and loops).
There's one view that's an absolute nightmare... (no/inaccurate comments, shorthand... all things considered to be mortal sins). Just an example:
$rows[$c] .= '<div>'.sprintf('<select id="%s" name="%1$s">',$t.'['.$ref->getCode().']').str_replace('>'.$ref->getCValue().'<',' selected="selected">'.$ref->getCValue().'<','<option>'.implode('</option><option>',$this->vals['P']).'</option>').'</select></div>';
In this particular case, I have an array of models that looks like this:
$arr = array('FOO'=> $Mylib_Model_Person,'BAR'=> $Mylib_Model_Person2);//1~50 mdls
I would like to use a partial loop, but there's a problem:
$this->partialLoop('controller/_myPartial.phtml',array('model'=>$arr));
//in the partial loop:
Zend_Debug::dump($this->m);
I see all my models correctly, but their keys have all been turned into properties.
$this->FOO->someMethod();//works fine
Bur I want it to be:
<span><?php echo $key; ?></span><span><?php echo $model->someMethod(); ?></span>
I've also tried using $this->partialLoop()->setObjectKey('Mylib_Model_Person');, but that didn't seem to make any difference, other then confuse me.
The only solutions I see is either array_map, but that would defeat the point (I'm trying to end up with a clean view script); or rewrite a part of my service layer, to return the data ready structured, and keep the array_map there.
I can't help thinking that what I want to do, essentially use a partialLoop as an array_map callback, is possible. If it isn't, is there an alternative? Any thoughts?
I've tried get_object_properties($this), and iterate through the object properties, to no avail, the loop simply doesn't get executed(?!)
As it turns out $this->partialLoop()->setObjectKey('Mylib_Model_Person'); should have been $this->partialLoop()->setObjectKey('model');. If I do change this, and start the partial loop by dumping $this->model, I see my model. However:
echo $this->model->someMethod(); //throws error: method on non-object
Zend_Debug::dump(get_class_methods($this->model));//shows all methods, including someMethod()
And to add insult to injury, tears and confusion. The model implements the toArray-thing, so I tried:
echo $this->model['someData'];//Error: cannot use object of type Mylib_Model_Person as array!!
So, it's not an object when I try to use methods, it's an object when trying to access data as an array, and when using the magic getter method ($this->model->some_Data) it doesn't do anything. No errors, but no output either. The view is rendered as is.
I'm thinking I ran into a bug. I'll rapport it. Consider this:
$methods = get_class_methods($this->model);
while($m = array_shift($methods))
{
if (substr($m,0,3) === 'get')
{
Zend_Debug::dump($m);//e.g getName
Zend_Debug::dump($this->model->{$m}());//'Foobar'
$m = 'someMethod';//copy-paste, so typo's aren't to blame
Zend_Debug::dump($this->model->{$m}());//'the data I was after'
}
}
So that works, but the, if I try:
$this->model->{'someMethod'}();//Error again
//or even:
$m = 'someMethod';
echo $this->model->{$m}();//Error...
That can't be right
I found out what the problem was. Our development server used to be set up better in terms of error reporting:
I assumed E_ALL | E_STRICT, but I had a look only to find it changed to a cruddy E_COMPILE_ERROR | E_ERROR | E_CORE_ERROR. Seeing as some values in the array can be false rather then an object, at some point in the partialLoop script, a notice should have been raised - with the correct ini settings, of course.
That was the cause of the unexpected behaviour; that, and a silly bug or two.

JS Lexer to detect function calls

In order to localize strings used within my javascript, I want scan all my js files for such strings.
I am using a t() function to request string translations as follows:
t("Hello world");
or with dynamic portions:
t("Hello #user", {"#user": "d_inevitable"});
I want to detect all calls to the t() function and thus gather the strings contained in the first argument in a php "build" script, but skipping the following:
function foo(t) {
t("This is not the real t, do not localize this!");
}
function bar() {
var t = function(){}; //not the real t either...
}
function zoo() {
function t() {
//This also isn't the real t() function.
}
}
t("Translate this string, because this is the real t() in its global scope");
So the simple rule here is that the t function being invokes must be in global scope in order for the first argument to qualify as a translation string.
As a rule, dynamic runtime data as first argument is not allowed. The first argument to t() must always be a "constant" literal string.
I think php codesniffer will help me do it, however all the documentation I could find on it is about enforcing code standard (or detecting violations of it). I need lower level access to its js lexer.
My question is:
Would the php codesniffer's js lexer be able to help me solve my problem?
If so how do I access that lexer?
Are there any other php libs that could help me find the calls to t()?
Please do not suggest stand-alone regular expressions as they cannot possibly solve my problem in full.
Thank you in advance.
What you are describing is basically a coding standard. Certainly, ensuring strings are localised correctly is part of many project standards. So I think PHPCS is the right tool for you, but you will need to write a custom sniff for it because nothing exists to do exactly what you are after.
The best thing to do is probably clone the PHPCS Git repo from Github and then create a new directory under CodeSniffer/Standards to contain your custom sniff. Let's say you call it MyStandard. Make sure you create a Sniffs directory under it and then a subdirectory to house your new sniff. Take a look at the other standards in there to see how they work. You'll also find it easier to copy an existing ruleset.xml file from another standard and just change the cotent to suit you. if you don't want to include any other sniffs from anywhere (you just want to run this one check over your code) then you can just specify a name and description and leave the rest blank.
There is a basic tutorial that covers that.
Inside your sniff, you'll obviously want it to check JS files only, so make sure you specify that in the supportedTokenizers member var (also in the docs). This will ensure PHP and CSS files are always ignored.
When you get down to the actual checking, you'll have full low-level access to the parsed and tokenised content of your file. There are a lot of helper functions to check things like if the code inside other scopes, or to help you move backwards and forwards through the stack looking for bits of code you need.
TIP: run PHPCS using the -v option to see the token output on your file. It should help you see the structure more easily.
If you want to really do things properly, you can even create a nice unit test for your sniff to make sure it keeps running over time.
After all this, you'd check your code like this:
phpcs --standard=MyStandard /path/to/code
And you can use a lot of integrations that exist for PHPCS inside code editors.
You might decide to add a new more sniffs to the standard to check other things, which you can then do easily using your ruleset.xml file or by writing more custom sniff classes.
I hope that helps a bit. If you do decide to write your own sniff and need help, just let me know.

Loading View Page In Library In Codeigniter

In my codeigniter i created a library in library folder.I want to load view pages in that library.How can i do this?
This is my code:
$this->load->view('view_page');
But when iam using this code i get an error:
A PHP Error was encountered
Severity: Notice
Message: Undefined property: CI_theme_lib::$load
Filename: libraries/theme_lib.php
Line Number: 9
What is the problem in mycode?
In Line number 9 in library the code is :
$this->load->view('view_page');
To do what you're trying to do you need to get an instance of CI, and use that.
e.g.
$CI =& get_instance();
Within your library functions you could then use this variable to load the view:
$CI->load->view('view_page');
I would question though why you want to call a view, in the form that you have done, within a library. I suspect that you would be better to get the view call to return data (setting the 3rd parameter 'true') and then have your library return the display data to the controller.... Your approach seems messy, but then I have no idea what your library is trying to do.....
I have came across your question for different reason, I seem to have problem passing variables to views instead. Let me explain before I tell you answer to your problem.
Imagine you have an Emailer library to send emails rather than sorting that out in controller.
Emailer than within itself builds email string using views. My problem is that when I make my call from controller something like Emailer::send_mail($data,$template) it passes the variables correctly but when I do it from another library the view fails to register the variables. LOL
So yes Stéphane Bourzeix you do sometimes want to use output from view in a different way than just returning to client browser.
The solution is here.
https://www.codeigniter.com/userguide2/general/views.html
the last section of that page has something like
$string = $this->load->view('myfile', '', true);
but something like
$string = $this->load->view('myfile', $view_data, true);
should work too
in case of doing this from other places than controllers you will need to:
$this->ci = & get_instance();
$string = $this->ci->load->view("myfile",$view_data,true);
it seems like the last argument in the list (true) is the one that tells it not to render to browser but instead just create string with template content
I know it's a bit too late but hope it still helps to some. Good luck with your code.
tomhre
You simply DON'T load pages (aka Views) in a Library.
I don't see any need for doing this.

Categories