$i = 0;
$suggestion = 'page';
$suggestions = array();
while ($arg = arg($i++)) {
$arg = str_replace(array("/", "\\", "\0"), '', $arg);
$suggestions[] = $suggestion . '-' . $arg;
if (!is_numeric($arg)) {
$suggestion .= '-' . $arg;
}
}
i am a newbie of drupal,i can't follow the above code well, hope someone can explain it to me.i know the first line is assign the 0 to $i,then assign 'page' to an array. and i know arg is an array in drupal.
for example, now the url is example.com/node/1. how to use this url to use the above code.
It looks like its purpose is to generate ID strings (probably for a CSS class) depending on paths and excludes numeric components of the path out of the generated ID.
For example, 'my/123/article' produces the ID "page-my-article".
It seems this comes from a function (because the loop reads parameters using arg()) and that it expects Drupal paths such as "node/123/edit".
So the function would be called something like that:
mystery_function("my/123/article", "even/better/article");
Variables:
$i is the variable that stores the loop index
$suggestion is a String that store the generated ID. It is initialized to "page" because the ID is meant to have the syntax "page-SOMETHING".
$arg comes from the while loop: it reads the parameters passed to the mystery function one by one
$suggestions is an array that contains the generated IDs, one per argument passed to the mystery function.
In the loop:
The "$arg = str_replace..." line removes unwanted characters like "\" (however that line could definitely be improved).
The "$suggestions[] = ..." line adds the ID to the array of results.
The "if (!is_numeric($arg)..." line excludes numbers from the generated ID (e.g. "my/123/article" is probably supposed to produce "my-article")
The "$suggestion .= ..." line appends the value of "$arg" to the value of "$suggestion" and stores it in "$suggestion"
But honestly, I wouldn't advise to use that code: I doubt it works as intended given $suggestion isn't reinitialized at each loop so the value of the first path will get attached to the second, and to the third, and so on, and I doubt that is intentional.
Most likely this code is located in a theme's template.php in the preprocess_page hook. If that is the case, it's used to create template suggestions based on an argument supplied like the node id, to make it possible to create a page template per node.
What this code does, is that it loops though all the arguments in the drupal url, This could be user/3, node/3, taxonomy/term/3 or any custom url.
It first does some cleanup in the argument, to make sure that no weird symbols is added. This is not needed for most urls, but is probably there as a safety to avoid needing to have to create weird template names in some cases. This is done with str_replace
Next it adds the a suggestion to the list, based on the arg.
If the arg isn't numeric it adds that to the suggestion so it will be used in the next loop.
The idea is that you with the above urls will get added some template suggestions that look like this:
page
page-user
page-user-3
And
page
page-taxonomy
page-taxonomy-term
page-taxonomy-term-3
In this list drupal will use the last one possible, so if page-user-3.tpl.php exists, that will be used as page template for user/3, if not page-user.tpl.php will be used and so on.
This can be desired if you want to create customize page templates for the users page, or the nodes page while being able to create customized page templates for specific users.
This is not, however, a strategy I would want to employ. If you do this, you will end of with lots of different versions of a page template, and it will end up creating the maintenance nightmare that CMS systems was supposed to eliminate. If you truly need this many different page templates, you should instead look at context or panels, and put some logic into this instead.
Related
I am faced with a piece of code that does not make a lot of sense to me. I am working on a website using PHP and Smarty template, but there is one line of code regarding arrays that i do not understand how it works.
$SLang = &SLanguage::getInstance();
$q="SELECT * FROM texte where text_lang='{$SLang->lang}' ORDER BY text_id";
$texte = _sqlFetchQuery($q);
foreach($texte as $text)
{
$texteList[$text['text_alias']]['text'] = $text['text_text'];
if($text["text_category"]==3){
$philosophyList[] = $text["text_text"];
$philosophyListSeo[] = $text["text_alias"];
}
}
The output of "var_dump" on $philosophyList gets out only the "text_text" column from the database, and i do now understand the structure of how it gets there. Can someone care to explain? How does this particular line of code works? $texteList[$text['text_alias']]['text'] = $text['text_text'];
It's called a jagged array.
It's shorthand for this:
$texteList[$text['text_alias']] = array('text'=>$text['text_text']);
So it's creating a named array using whatever text is $text['text_alias'] brings out, and assigning as it's value an array with a named "text" element.
But this is irrelevant to $philosophyList[]. To understand how $philosophyList[] is working, you need to understand how foreach works; basically it takes each item in an array (in this case $texte) and assigns the value of that array item to a variable (in this case $text). This is just an easier way to do a for loop. They could just have easily done:
$philosophyList[] = $texte[$i]["text_text"];
I am trying to restrict content within a Wordpress template file and am using a plugin called Paid Memberships Pro to do so.
The code below restricts content to members with 'levels' of 1 or 2.
if(pmPro_hasMembershipLevel(array(1,2))){
restricted content goes here
}
The problem comes when I try to use a variable to provide the levels. These levels are held in a custom field group 'restrictions' with field name 'pmpro_id'. I access these levels within the template using...
foreach($restrictions as $restriction){
$temp=get_field('pmpro_id', $restriction->ID );
$temp_array[]=$temp;
}
$levels=implode(',', $temp_array);
If I then pass $levels to pmPro_hasMembershipLevel, this works fine if there is only one level but fails if there are 2 or more. I believe this is because the variable type is then a string rather than integer? I had previously tried to pass the $temp_array directly though I felt this wouldn't work and was correct.
I realise this is probably PHP 101. I have searched but don't really know what I'm looking for to be honest! I am not a developer and this is the last thing holding me back from finishing this project so ANY help anyone could provide would be brilliant. Thanks in advance.
You don't need to implode $temp_array if pmPro_hasMembershipLevel accepts array as its argument. When you implode an array you get string as a return value — that's not what you want here. If you think that the issue might be with the type of values, then you can try to cast them to integers, like this $temp_array[]= (int) $temp;
I'm using PHP and ToroPHP for routing.
Unknown number of child pages
It works fine, but in my case I can add pages with childs and parents, where a parent can have an unknown number of have childpages.
In ToroPHP it might look like this:
// My Path: http://www.test.com/product/house/room/table/leg/color/
Toro::serve(array(
"/" => "Home",
"/:string/:string/:string/:string/:string/:string/" => "Page"
));
class Page {
function get($slug, $slug2, $slug3, $slug4, $slug5, $slug6) {
echo "First slug: $slug";
}
}
Problem
I can figure out what the maximum depth can be and then loop and append
out a string containing the "/:string" parameters but it don't look
that nice.
The get-function in the Page-class takes an unknown number of in
parameters. I can calculate the max depth from outside the function, but I need the function to know how many values to take.
Question
Is there an alternative way the the problem 1? Some regular expression maybe?
How can I make a function take an unkown number of in parameters?
Maybe I try to solve this the wrong way and the first two questions are not relevant? Correct me if that is.
In order for your action to receive all parameters, you need to capture them in your regex. You capture a value in regular expressions using parentheses. :string is just an alias for ([a-zA-Z]+). You could apply a wildcard after the first segment, like this:
"/product/(.*?)" => "Page"
However, this means that you need to parse the URL by yourself in your action, which is not very clean either.
If you want to make this particular case more clean, an option would be to use str_repeat:
Toro::serve(array(
"/" => "Home",
"/" . str_repeat(":string/", 6) => "Page"
));
ToroPHP is a very simple library, it should not be that hard to fork it and bend it to your will. Ideally, how would you like to define routes like this? Maybe a route like /:string*6?
You can always pass more or fewer parameters than defined to a PHP function. Use func_get_args to get all passed parameters and func_num_args to get the number of passed parameters.
In response to question 2, can you possibly format the GET parameters into an array and then pass in arrays rather than individual values?
Maybe like:
$allSlugs = array($slug, $slug2, $slug3, $slug4, $slug5, $slug6);
// Pass $allSlugs into your instance of Page::get($allSlugs);
class Page {
function get($getValues) {
echo isset($getValues[0]) ? "First slug: ".$getValues[0] : '';
}
}
I have a node reference field which I can output using echo render( $content['field_link'] );
This is fine for one situation in the node but I also need to output just the path of that node. I can output it using echo $node->field_link['und'][0]['node']->uri['path'] but I don't want to hard code the 'und' and '0' array keys in. There is presumably a way to do it with render().
If someone could point me in the right direction that'd be great, thanks.
Ben
You can't do it with render but you don't need to hard code the language code, you can get it from the global variables:
global $language;
echo $node->field_link[$language->language][0]['node']->uri['path']
You won't be able to get around using the 0 key though, all fields are stored with the potential to be multiple so you will always need to 'pick' which element you want to get.
If the cardinality of your field is 1, you can always assume that the element you're looking is for is at field_link[$language->language][0]. If not you'd need to run through each element in the und array and decide which one to display.
EDIT
You can also use the LANGUAGE_NONE constant (which will generally return 'und', but either way wil be the correct language code for the default content).
The PHP function eval() appears to be a rather interesting function. Can someone explain why it works in this given situaton, on line: 14
function Parse($inFrontEnd)
{
// Now create an array holding translation tokens with some from above
// Load translation table into buffer
$tableLines = file(Utilities::GetRelativePath(TTABLE_DIR).TTABLE); // Array of lines from TTable.cfg
// Explode by whitespace
foreach($tableLines as $aLine)
{
$lineParts = EXPLODE(' ', $aLine);
$word = "/".$lineParts[0]."/";
$definition = $lineParts[1];
// Add key (word) => value (definition) to array
// Eval() to return value of the const
Main::$translateChars[$word] = eval("return $definition;");
}
// Read data from template file
$parseArray = file($inFrontEnd); // Load FrontEnd source code into array ready for parse
/* Perform the translation of template by the translation table defined data */
$parseArray = preg_replace(array_keys(Main::$translateChars), array_values(Main::$translateChars), $parseArray);
return $parseArray;
}
So what I'm doing here is reading in a template from a template directory. The templatename.php file comprises of text tokens written constant-like, which are then translated by regular expressions replacing the tokens with the data the constants with their names hold, thus returning a fully validated page of a webpage, which is printed for the user to view. This allows pages to be very dynamic by allowing the reuse of these tokens over many webpages (templates).
My question is: I had trouble for a while with the line that uses eval(). What I'm trying to do there is fill an array with each key being the name of the constant read in from, what I've named, the translation table (TTable.cfg), which holds the name of each token and the constant associated with it:
TITLE TITLE
CSS_INCLUDE CSS_INCLUDE
SHOW_ALL_POSTS SHOW_ALL_POSTS
...
So with the protocol [TOKEN] [CONSTANT][CR][LF]
The keys within the array would be created fine, but the values would return null or break my code when I had the key be associated with: constant($definition);
It complained it couldn't find the constants being declared. However, when I use eval as is on this line, each key associated with: eval("return $definition;");
it works as I want it - the values as their corresponding constant's data.
I do apologise for the length of this post. I couldn't find any other example for my question other than the case I found it in.
The value of the variable $definition is replaced into the string definition "return $definition;", as you're using double quotes. Hence, what is passed to eval is essential something like this: "return FOO;", where FOO is the value of the variable $definition.
Now, that code is evaluated using eval(), and the result is returned as the result of the evaluation, which is the value of the constant FOO (different in each iteration).
Using the constant in this case makes more sense: It is faster, potentially securer, and more readable.
if ( defined( $definition ) ) {
$constval = constant( $definition );
}
else {
$constval = $definition;
}
This will also give you some insight of why it works when using eval() and not just constant(); PHP replaces unknown constants with their respective names, thus eval works in your case. However, any other way would raise warnings and be a bad practice, as it doesn't make clear what's going on to the reader.
Remember, eval is evil, so don't use it, when you can avoid it. Here you could just use constant instead.
The tiniest of oversights. I forgot to clean $definition after I exploded it from each line of the translation table. So a simple trim() has solved the problem.
constant($definition);
Now works.
Crazy :D