I am currently developing an advertising module for a custom CMS, and using template tags to allow customers to add adverts into their pages through a WSYWIG page content editor.
Eg. {=advert_1}
On the frontend, this will be found through a regex and then be converted into a function, which will look to a database to select and display an advert
Template_tags.php
while ($advertRow = $advertResult->fetch_assoc()) {
$advertGroupID = $advertRow['grpID'];
$advert = "advert_";
${$advert . $advertGroupID} = showAdvert($advertGroupID);
}
This means {=advert_1} will be converted to showAdvert(1)
The problem I am having is that the showAdvert function will be run for all adverts regardless of whether or not it appears on the page, which then adds to the "views", even though the advert may not be displayed.
What I want is to just define the function without executing it, so when it appears in the page content, only then will the function will be executed.
Use a function expression to create a closure.
${$advert . $advertGroupID} = function() use($advertGroupID) {
showAdvert($advertGroupID);
};
To call the function, you need to put parentheses after it:
$name = 'advert_1';
echo $$name();
To use it with preg_replace_callback
preg_replace_callback("/\{=([^\{]{1,100}?)\}/", function($match) {
return $match[1]();
}, $pageContent);
Related
I want to access and use a variable passed in the URL within a WordPress page (not a template file, but the page itself).
Here's what I'm trying to accomplish. I want to create a single page that will display different WP content by using text passed in the URL in shortcodes and elsewhere on the page. So, if the URL was specified as:
www.greenneedham.org/blog/topicpage/?topic=solar
I will be able to use the passed text ('solar') in shortcodes and other places in the page, like this:
[documents category_name="solar" numberposts="-1" orderby="title" order="ASC"]
Ideally, I'd like to be able to create a variable or field that I can simply use within the page text. I just don't know how to accomplish that.
Here's what I've considered/tried:
1) There are plugins that access the passed variables (e.g. URL params), but that would seem to require nested shortcodes:
[documents category_name="[urlparam param="topic" default="home-energy-savings"/]" numberposts="-1" orderby="title" order="ASC"]
That doesn't work, and I'm not aware of any way to accomplish that.
Added: The Shortcode API documentation at http://codex.wordpress.org/Shortcode_API#Square_Brackets explains that the shortcode parser cannot handle square brackets within an attribute. Unfortunately, that's exactly what I'm trying to do.
If that won't work, The question is now - Is there some way within the page content of presenting a shortcode string that has been modified based on a query variable?
EndAdded
2) Using a filter to add the variable allows me to access the variable within a page template (e.g. page.php), but I want to use the value within the page itself.
3) Plugins to allow PHP snippets within a page or post. This seems to be generally discouraged. It's also complex, and the page itself (which may be used by non-coders) would get hard to use.
Any help or guidance would be much appreciated. Thanks!
add_shortcode('cat', 'get_name');
function get_name() {
return '[category_name='.$_GET['topic'].' numberposts="-1" orderby="title" order="ASC"]';
}
or echo do_shortcode('[category_name='.$_GET['topic'].' numberposts="-1" orderby="title" order="ASC"]'); // instead of return.
Should work as snippet function. then use it as [cat] shortcode
In addition, remember to sanitize your $_GET variable. Here's an example in the context of a simple shortcode to display a query variable within the page text, with reference to where I took the sanitizing code from:
//[query_string label="" class="" var=""] shortcode
function query_string_shortcode( $atts, $content = null ) {
//Create an array of default values for attributes. These don't have to be blank. If specified as attributes in the shortcode, those values will be used instead.
$a = shortcode_atts( array(
'label' => '',
'class' => '',
'var' => '',
), $atts );
//Create variables from atts/defaults
$label = $a['label'];
$class = $a['class'];
/*
* 1. Check if the variable is set
* 2. If so, sanitize the input for security (https://wordpress.stackexchange.com/questions/351292/sanitize-get-query-var-url-parameters)
* 3. Set the variable
*/
$var = ( isset( $_GET[$a['var']] ) ) ? sanitize_text_field( $_GET[$a['var']] ) : '';
if(!empty($label)) {
$label = "<b>$label</b>";
}
if(!empty($var)) {
$html = '<span class="pt-query ' . $class . '">' . $label . $var . '</span>';
return $html;
}
return;
}
add_shortcode( 'query_string', 'query_string_shortcode' );
Hello community WordPress forum.
I have a need to write the posts the output of a function, but all to getting to do is to display real-time and run this script / function in all posts, with I do to write the posts the output of a function instead of display it in posts?
because what 's happening is that the script is running on all posts, and each refresh / access the pages, a new script number is generated! I would like the generator create a different number for each post, but write to output them, and not display a number to each new access.
// Declare the function
function gen_num()
{
// DETERMINE THE CHARACTER THAT CONTAIN THE PASSWORD
$caracteres = "012345678910111213141516171819";
// Shuffles THE CHARACTER AND HANDLE ONLY THE FIRST 10
$mistura = substr(str_shuffle($caracteres),0,10);
// DISPLAYS THE OUTCOME
print $mistura;
}
// Add custom post content, inject function in content.
function add_post_content($content) {
gen_num();
return $content;
}
add_filter('the_content', 'add_post_content');
see in herculestest.tk, browse the pages, make f5 to refresh.
Thank you very much.
==========================================
another attempt:
I created a custom field from ACF plugin named: numeration:
function gen_num()
{
global $post;
$mistura = get_post_meta( $post->ID, 'numeration', true );
if ( '' == $mistura ) {
//DETERMINE THE CHARACTER THAT CONTAIN THE PASSWORD
$caracteres = "012345678910111213141516171819";
// Shuffles THE CHARACTER AND HANDLE ONLY THE FIRST 10
$mistura = substr(str_shuffle($caracteres),0,10);
update_post_meta( $post->ID, 'numeration', $mistura );
}
//DISPLAYS THE OUTCOME
print $mistura;
}
// Add custom post content, inject function in content.
function add_post_content($content) {
gen_num();
return $content;
}
add_filter('the_content', 'add_post_content');
this solution to not change the number each new access, now writing these data permanently in the database ?? because're not recording! if I change my theme, all the numbers in all the posts disappear, and if I make any errors in functions, php, these add up numbers, because they depend on the function running at him display the values, and worst of all, to fix the functions.php, the script will return to run and therefore, will be a re-run, which means that it will generate new numbers on all posts !! and this can not happen, should I ever have the same values!
The Post ID is unique in WordPress, is that number adequate for your needs?
Otherwise you'd need to generate a unique ID when the post is published and save it in a custom field. (Instead of your gener_numb function look into uniqid: http://php.net/manual/en/function.uniqid.php.)
hi i've got a gallery page. this gallery page has a gallery image object with an has_many relation.
private static $has_many = array(
'GalleryImages' => 'GalleryObject'
);
my gallery object has an image upload field. I want to set the upload folder to the title of the gallery page
i tried this with no result
$visual->setFolderName('Galerie/'.$this->Gallery()->Title);
and this (what i would prefer)
public function getGalleryTitle() {
$galleryTitle = $this->Gallery()->Title->First();
$uploadFolder = str_replace(' ', '-', $this->$galleryTitle);
return $uploadFolder;
}
$visual->setFolderName('Galerie/'.$this->$uploadFolder);
the second returns and error (undefined variable uploadFolder ?!) and my upload folder is now set to "Galerie/DataList"
can someone tell me how to convert the output of $uploadFolder so that i get back the title?
EDIT:
GalleryHolder: http://www.sspaste.com/paste/show/5267dea3579a6
GalleryPage: http://www.sspaste.com/paste/show/5267dee4c9752
GalleryObject: http://www.sspaste.com/paste/show/5267df0af1a65
you where almost there..
Here is your edited getGalleryTitle() function.
It is basically checking if the GalleryObject has a parent Gallery via $this->GalleryID. Since it is a has_one relation the column will be named GalleryID.
Then we get the Gallery object with $this->Gallery() and get it's title with $gallery->Title.
I've also replaced your str_replace with SilverStripe's URLSegmentFilter class. Which will removed spaces and other special characters non welcome in URL, a better solution.
public function getGalleryTitle()
{
if ( $this->GalleryID )
{
$gallery = $this->Gallery();
$filter = new URLSegmentFilter();
return $filter->filter( $gallery->Title );
}
else{
return 'default';
}
}
Then in the getCMSFields() function, when creating your UploadField we just call the getGalleryTitle() function that returns the string for the folder name.
$visual = new UploadField('Visual', _t('Dict.IMAGE', 'Image'));
$visual->setFolderName('Galerie/'.$this->getGalleryTitle());
A few notes..
$this references the current Object instance, so you can't use $this->$galleryTitle to access a variable you just created in your function, $galleryTitle by itself is enough.
You were calling $this->$uploadFolder in setFolderName, this doesn't work for the same reason, and also, using $uploadFolder by itself wouldn't work since this variable was created in the scope of another function. So we just call the function we defined on our Object with $this->getGalleryTitle() since it returns the value we want.
This should work fine, but keep in mind that if the Title of the Gallery changes at some point, the folder name will change too. So you might end up with images uploaded in many different folders for the same gallery... I personally wouldn't advise it, unless you implement some kind of "Title locking system" or some way to keep the "correct" or first "valid/acceptable" Gallery title in a separate object property that can't be edited and use this in the folder name.
I usually only use the ID in those case ($gallery->ID), as this will not change.
edit
Another version of getGalleryTitle() that should work even if the GalleryObject isn't saved yet.
public function getGalleryTitle()
{
$parentID = Session::get('CMSMain')['currentPage'];
if ( $parentID )
{
$gallery = Page::get()->byID( $parentID );
$filter = new URLSegmentFilter();
return $filter->filter( $gallery->Title );
}
else{
return 'default';
}
}
First, I check to see whether we're on the CMSSettingsPage or in a ModelAdmin page (Should you be using them). You want to get all the information about which class the controller is managing as it's data record. (If you have firebug, FB($this) in getCMSFields() on the related DataObject (DO) will show you the page managed under DataRecord)
Controller::curr()->currentPage() will get you the current page the DO is being managed on, and ->URLSegment will get the page url name, though you could use Title or MenuTitle also.
Here is an example which will set up a folder underneath assets/Headers to save images in. Running this on the HomePage (ie URL Segment 'home') will create and save objects into the folder /assets/Headers/home.
if (Controller::curr()->class == 'CMSSettingsController' || Controller::curr() instanceof Modeladmin) {
$uploadField->setFolderName('Headers');
}
else
{
$uploadField->setFolderName('Headers/' . Controller::curr()->currentPage()->URLSegment);
}
So this is the problem I am running into. If I have a comment object, I want to create a renderable array that is using the display settings of that comment. As of now this is what I have:
$commentNew = comment_load($var);
$reply[] = field_view_value('comment', $commentNew, 'comment_body', $commentNew->comment_body['und'][0]);
Which works fine because I dont have any specific settings setup for the body. But I also have image fields and video embed fields that I need to have rendered the way they are setup in the system. How would I go about doing that?
Drupal core does it with the comment_view() function:
$comment = comment_load($var);
$node = node_load($comment->nid);
$view_mode = 'full'; // Or whatever view mode is appropriate
$build = comment_view($comment, $node, $view_mode);
If you need to change a particular field from the default, use hook_comment_view():
function MYMODULE_comment_view($comment, $view_mode, $langcode) {
$comment->content['body'] = array('#markup' => 'something');
}
or just edit the $build array received from comment_view() as you need to if implementing the hook won't work for your use case.
Is this facebook link populated fully from the DB? Or, is it a physical file with PHP in it? Just, how is this page called?
http://www.facebook.com/profile.php?id=49300915&sk=photos
They probably do something like:
if(isset($_GET['id'], $_GET['sk'])) {
mysql_query("SELECT info, photos FROM users WHERE id = '$id'");
}
I'm trying to ask, how do they include this page? Is it like Drupal / any CMS where the PHP and page is stored in the DB, or is it a physical file on the server? If the latter, what's the best way to get the file (case insensitive URL)?
I would have a class with a single method, which reads 'sk' and runs another method, depending on what it's value is.
One method would be 'photos' which would read 'id' and fetch a photo from the database. It would then run another method, displayPage, which will display a page from that data.
The displayPage method takes a "template" filename and an array of variables to provide to the template. It sets up a smarty object, provides the variables, and instructs it to display the template.
Inside the template, I'd include another template for the global header that's on every page in the site, then i'd have the html page content, using smarty to insert dynamic values, then include a global footer.
Note that i've simplified this system a lot. A real page like that would take me a week to write all the code, since a big website does a lot of stuff just to display a simple page (for example: find out if the logged in user actually has access to the page... i don't have access to the example one you gave).
<?php
// profile.php
class ProfileController
{
public function run()
{
if ($_GET['sk'] == 'photos')
return $this->photosPage();
}
protected function photosPage()
{
$id = (int)$_GET['id'];
$result = mysql_query("select * from photo where id = $id");
$photo = mysql_fetch_object($photo);
$this->displayPage('view-photo.tpl', array('photo' => $photo);
}
protected function displayPage($templateFile, $templateVariables)
{
$smarty = new Smarty();
foreach ($templateVariables as $variableName => $variableValue) {
$smarty->assign($variableName, $variableValue);
}
$smarty->display($templateFile);
}
}
$conntroller = new ProfileController();
$controller->run();
And the smarty code:
<!-- view-photo.tpl -->
{include file='head.tpl'}
<h1>View Photo {$photo->name|escape}</h1>
<img src="{$photo->src|escape}" width="{$photo->width|escape} height="{$photo->height|escape}>
{include file='foot.tpl'}