I'm building a site with Drupal and I have a small problem. I'm rendering a form using hook_menu. The form renders fine and all is good. I am then adding some more markup to the page using hook_page_alter(). Hook_page_alter looks like this:
function renderer_page_alter(&$page) {
if(drupal_is_front_page()) {
$q = db_query('SELECT name, mname, number_of_instances FROM {event_type} ORDER BY number_of_instances DESC');
foreach($q as $event) {
$options['name'][] = $event->name;
$options['mname'][] = $event->mname;
}
$tri = array(
'#theme' => 'frontpage_canvas',
'#options' => $options
);
return $page['content']['triangles'] = $tri;
}
}
So in my local MAMP install, the content is displayed with the results from hook_page_alter() first then followed by the form. However, in the remote install, the order is reversed (with the submit button for the form at the top of the page and the rest of the content beneath it). The only difference between the installs (that I can think of) is that the remote install is Drupal 7.8 and the local one is Drupal 7.9.
I would like to have the remote install in the same way as the local one. Has anyone come across an issue like this before?
The basic structure of the rendered HTML is like this:
<div class=content>
//all the form information is in here
</div>
<div class=rendered>
//all the output from hook_page_alter() is here
</div>
EDIT: The issue is that for some reason, block.tpl.php is adding two divs:
<div id="block-system-main" class="block block-system first last odd">
<div class="content">
//My form markup is in here
</div>
</div>
//The hook_page_alter markup is in here.
So, is there any way to force Drupal to add the hook_page_alter markup to the same div as the form is being rendered in? Because the way it's being rendered at the moment, the #weight property doesn't affect the positioning.
Thanks,
The display order in render arrays is set using the #weight attribute, elements with a higher #weight will be rendered after those with a lower value.
If you want to force the content added in hook_page_alter() to be rendered at the top of the content area declare it like this:
$tri = array(
'#theme' => 'frontpage_canvas',
'#options' => $options,
'#weight' => -1000
);
or at the bottom of the content area:
$tri = array(
'#theme' => 'frontpage_canvas',
'#options' => $options,
'#weight' => 1000
);
You can also adjust the #weight for other elements that already exist in the $page array passed in to the function, so you have total control over the display order.
Related
This is probably super simple but I just cant seem to figure it out.
How can I pass the current Wordpress page title into this code?
Below is a snippet from Formidable Forms WP plug-in which basically prints statistics from forms within my website.
In this case, the # of entries for a specific form (55jqi) and a specific field(50) are displayed on the pages, showing how many other people also submitted that form.
Im trying to skip needing to update each page (4,380 pages) with the stats output snippet.. and instead call the current page into the stats display code, to show stats for that particular page being viewed.. using an elementor custom post type template.
I need this:
echo FrmProStatisticsController::stats_shortcode(array('id' => '55jqi', 'type' => 'count', 50 => 'runtz'));
To work like this:
echo FrmProStatisticsController::stats_shortcode(array('id' => '55jqi', 'type' => 'count', 50 => 'single_post_title();'));
Replace the input area ‘Runts’ with the current page title, using
single_post_title()
Or similar.
Any help would be amazing!!
There is also a short code available which works the similarly.
[frm-stats id=55jqi type=count 50="Runtz"]
Formidable Forms Plugin shortcode and php page for reference: https://formidableforms.com/knowledgebase/add-field-totals-and-statistics/#kb-field-filters
You are using single_post_title function in a wrong way. By default, this function will echo the output but in the shortcode, you need to return the output.
This function accepts 2 param: 1: $prefix 2: $display
You need to pass $display as false, which will tell the function to return the value.
so you'll have to make a call like this `single_post_title( '', false )``
and your shortcode call will be like this:
echo FrmProStatisticsController::stats_shortcode(
array(
'id' => '55jqi',
'type' => 'count',
'50' => single_post_title( '', false ),
)
);
This is the original php code:
function lovethemes_pricing_shortcode($atts)
{extract(shortcode_atts(array(
"heading" => '',
"price" => '',
"link" => '',
"name" => '',
), $atts ) );
return '<div class="pricing animated bounceIn">
<section class="head">'.heading.'
<section class="content">
<ul><li class="price">'.$price.'</li>
<li>'.$name.'</li>
</ul></section> </div>';}
add_shortcode('pricing', 'lovethemes_pricing_shortcode');
This is what is written on my page in the backend:
[pricing heading="7 februari 2015"
price="Strak bekleden van een taart"
link="/agenda/workshops/strak-bekleden-van-een-fondant-taart"
name="Info"]
Resulting in this:
http://www.alexandra-van-zandbergen.be/wp-content/uploads/2015/08/Schermafbeelding-2015-08-08-om-13.23.38.png
And what I would like to have is this:
http://www.alexandra-van-zandbergen.be/wp-content/uploads/2015/08/Schermafbeelding-2015-08-08-om-13.22.47.png
I can read and write html and css but no php... Can anyone help me with this please? I've tried to add several codes and nothing is working.
I have to be able to change the image in the backend, I would like to be able to just choose an image from the Wordpress image gallery.
Thanks in advance!
Alexandra
I'm not very familiar with it either, and would need to try it to see if it works, so pls don't shoot me if it does not. However, this function makes use of the shortcode API.
The code tells to create a [pricing] shortcode, currently with 4 attributes. So, if all the rest works, then you most likely can simply add another one.
What I do not understand - and I'm not taking the time to look it up - is why all variables in your code start with $, but not the heading. I'll ignore that since it doesn't seem to be the problem.
Note:
It's best to add:
the image size to the HTML for performance. I'm assuming that you'll
use images of the same size. If you would want to set the image
size, you can create attributes for it too.
an alt text for SEO. Below I use the price attribute.
While I'm at it I would suggest to add a link to the image and title too. People sometimes click on it instead of on the info button. This would make it more user friendly.
So, it then would look like this:
function lovethemes_pricing_shortcode($atts) {
extract(shortcode_atts(array(
"heading" => '',
"price" => '',
"link" => '',
"name" => '',
"img" => '',
), $atts ) );
return '<div class="pricing animated bounceIn">
<section class="head">'.heading.'
<section class="content">
<ul><li class="price">'.$price.'</li>
<li><img src="'.$img.'" alt="'.$price.'" width="247" height="186" /></li>
<li>'.$name.'</li>
</ul></section></div>';
}
add_shortcode('pricing', 'lovethemes_pricing_shortcode');
and your shortcode would be:
[pricing heading="7 februari 2015"
price="Strak bekleden van een taart"
link="/agenda/workshops/strak-bekleden-van-een-fondant-taart"
img="/your/image/url.jpg"
name="Info"]
To make it a little more user friendly, you could also rename the attributes to something that corresponds to the content, f.ex. heading > date
I hope this helps!
I am trying to place a variable inside a PHP array which will work with a Wordpress plugin. Here is the code I have:
function custom_list( $lists ) {
$fil = "Dump";
$new_lists = array(
'ddl-list-block' => array(
'name' => __( 'Download Block', 'delightful-downloads' ),
'format' => "
<article class=\"ddl-list-block ddl-list-item\" id=\"ddl-%id%\">
<div class=\"download-wrap\" style=\"background-image: url('fi');\">
<div class=\"download-item\">
<div class=\"download-details\">
<h2>%title%</h2>
".$fil." /* VARIABLE SHOULD APPEAR HERE */
<div class=\"download-meta\">
<div class=\"download-meta-data\"></div>
Download
</div>
</div>
</div>
</div>
</article>
"
),
'ddl-list-plain' => array(
'name' => 'Flain List',
'format' => '<i class="fa fa-download"></i>%title% - %date%'
)
);
return $new_lists;
}
add_filter( 'dedo_get_lists', 'custom_list' );
I have tried using ., {, single quotes and double quotes, but I can not get the word "Dump" to display where it is supposed to. The reason I am trying to get it to show the word "Dump" is just to make sure that variables can be passed through into an array, because I am using another Wordpress plugin (Simple Fields) to manage extra fields in my post types and I want to pull out one particular aspect of the field (the URL of an uploaded image), so I will be inserting something like $my_field['url']. But none of the options I am aware of have even inserted a simple string into my array. Is there something I am missing?
I am posting this solely because it answers my problem. Not necessarily because it answers the question. I guess that's because of the plugin that I used which answers to that function.
The variable I was using called a featured image, but it could not be fed into the function. As a solution, I used their dedo_search_replace_wildcards filter and created another wildcard (I think I used %fi% or something like that), which gave me the outcome I wanted. Shame it didn't feed native $ variables into it.
I'm using CakePHP's SecurityComponent. And it's very essential as it saves forms from CSRF attacks. My project has total 10-12 forms and this is my first CakePHP project. After enabling SecurityComponent I was in a bit trouble but could get rid off after some careful minutes. This is the last form of my project and seems everything is correct to me but still the form is being black holed :(. Can anybody please tell me the problem? I don't want to disable CSRF checking or SecurityComponent. Here is my view code:
<?php
echo $this->Form->create('Record');
?>
<script type="text/javascript"> var me = new MetroExam(); </script>
<div class="exam_paper">
<div class="question_box" id="q_b">
<div class="q_n_a_header">
<div class="instructions">
<b>Instructions:</b><br>
<?=$inst['value_text']; ?>
</div>
<div id="timer">Please wait</div>
</div>
<div id="q_paper">
<img id="q" style="display: none;" src="/oes/<?=$exam['path'].'?ts='.time(); ?>">
<img id="loading_img" src="/oes/img/loading.gif">
</div>
</div>
<div class="ans_box" id="a_b">
<!-- information about answer paper. !important -->
<?php
$i = 0;
//these fields are essential for evaluating ans paper
echo $this->Form->hidden('submit', array('value' => 'true'));
echo $this->Form->hidden('start_time', array('value' => ''));
echo $this->Form->hidden('end_time', array('value' => ''));
echo $this->Form->hidden('duration', array('value' => ''));
echo $this->Form->hidden('valid', array('value' => ''));
echo $this->Form->hidden('passed', array('value' => ''));
//options for all radio
$options = array(
'1' => 'A',
'2' => 'B',
'3' => 'C',
'4' => 'D'
);
if($exam['choices'] == 5){
$options['5'] = 'None';
}
$questions = (int)$exam['questions']; // 40 <= $exam['questions'] <= 100
$i = 1;
while($questions--){
echo '<div class="'.(($i%2)==1?'each_answer_even':'each_answer_odd').'" id="ans-'.$i.'">';
echo '<div class="q_number">'.($i <= 9 ? '0'.$i : $i).'</div>';
$name = 'ans'.str_pad($i, 3, '0', STR_PAD_LEFT);
$attributes = array('empty' => false, 'legend' => false, 'onclick' => 'me.answer_click('.$i.')');
echo '<div class="mcq">'.$this->Form->radio($name, $options, $attributes).'</div>';
echo '</div>';
$i++;
}
echo $this->Form->end('Submit');
?>
</div>
</div>
This is basically a MCQ exam form. Where each group has 4 or 5 radio buttons and total 40 to 100 groups in a form. I'm using CakePHP 2.4. Thanks in advance.
As per the comments, the problem appears because you are changing the hidden values of the form. The way SecurityComponent works, is that it "locks" the name of the fields, so an evildoer can't add new fields or change the values once the form is sent. But it is even more strict with the hidden values, because it locks the field name and value. So by changing it with jQuery you're blackhole-ing your own form.
There's a nice little post where I learned this, take a look at it. The author there also explains two ways of bypassing this problem. One is to disable the security for hidden fields, so the hash calculated for the token doesn't include those values... which isn't really secure...
And another solution is to modify the FormHelper, and tell it to "lock" the hidden fields names but not the values. I don't remember what version of Cake the author uses for the example, but the code given there should be practicaly the same. So with that solution, you can tell the form to not be so strict with you with an option array.
Oh, and the other option given there (this is what I normally use) (I just read it now there... I thought I figure that on my own... oh well), is to just use normal input text fields for the ones you want hidden, and add a css style like display:none.
It's up to you what you think is best. I like the css option because is simpler, and really, if someone is going to mess with my css evily (with firebug or something like that), they might just as well do it with the values of hidden fields, it doesn't require any more effort. You should take all the extra steps and verifications when handling that form submission anyway. But like I said, up to you which do you think is best for your situation.
In addition to what was already posted, here's something else what might be causing the problem: in my case, a hidden input had it's name overwritten.
$this->Form->create('ExampleModel'):
$this->Form->input('foo_bar', array(
'type' => 'hidden',
'name' => 'foo_bar',
));
As a result, the final $this->request->data had the corresponding key $this->request->data['foo_bar']. It was not within the $this->request->data['ExampleModel'] array, and that's what the problem was.
To fix the issue, I had to remove the name key from the template, making the input belong to the model's data, and then just change the controller to accept that value.
Hope this helps someone else.
Update: this would also work on a form not attached to any model, e.g.:
$this->Form->create(false, array(
'url' => '/example',
)):
I am modifying an already contributed drupal module (Inline Ajax Search) to handle searching of a specific content type with some search filters (i.e. when searching for help documentation, you filter out your search results by selecting for which product and version of the product you want help with).
I have modified the module some what to handle all the search filters.
I also added in similar functionality from the standard core search module to handle the presenting of the search form and search results on the actual search page ( not the block form ).
The problem is that when i submit the form, i discovered that I'd lose all my post data on that submit because somewhere, and i don't know where, drupal is either redirecting me or something else is happening that is causing me to lose everything in the $_POST array.
here's the hook_menu() implementation:
<?php
function inline_ajax_search_menu() {
$items = array();
$items['search/inline_ajax_search'] = array(
'title' => t('Learning Center Search'),
'description' => t(''),
'page callback' => 'inline_ajax_search_view',
'access arguments' => array('search with inline_ajax_search'),
'type' => MENU_LOCAL_TASK,
'file' => 'inline_ajax_search.pages.inc',
);
}
?>
the page callback is defined as such (very similar to the core search module's search_view function):
<?php
function inline_ajax_search_view() {
drupal_add_css(drupal_get_path('module', 'inline_ajax_search') . '/css/inline_ajax_search.css', 'module', 'all', FALSE );
if (isset($_POST['form_id'])) {
$keys = $_POST['keys'];
// Only perform search if there is non-whitespace search term:
$results = '';
if(trim($keys)) {
require_once( drupal_get_path( 'module', 'inline_ajax_search' ) . '/includes/inline_ajax_search.inc' );
// Collect the search results:
$results = _inline_ajax_search($keys, inline_ajax_search_get_filters(), "page" );
if ($results) {
$results = theme('box', t('Search results'), $results);
}
else {
$results = theme('box', t('Your search yielded no results'), inline_ajax_search_help('inline_ajax_search#noresults', drupal_help_arg()));
}
}
// Construct the search form.
$output = drupal_get_form('inline_ajax_search_search_form', inline_ajax_search_build_filters( variable_get( 'inline_ajax_search_filters', array() ) ) );
$output .= $results;
return $output;
}
return drupal_get_form('inline_ajax_search_search_form', inline_ajax_search_build_filters( variable_get( 'inline_ajax_search_filters', array() ) ) );
}
?>
from my understanding, things should work like this: A user goes to www.mysite.com/search/inline_ajax_search and drupal will process the path given in my url and provide me with a page that holds the themed form for my search module. When i submit the form, whose action is the same url (www.mysite.com/search/inline_ajax_search), then we go thru the same function calls, but we now have data in the $_POST array and one of them is indeed $_POST['form_id'] which is the name of the form "inline_ajax_search_search_form". so we should be able to enter into that if block and put out the search results.
but that's not what happens...somewhere from when i submit the form and get my results and theme it all up, i get redirected some how and lose all my post data.
if anybody can help me, it'd make me so happy lol.
drupal_get_form actually wipes out the $_POST array and so that's why I lose all my post data.
according to this: http://drupal.org/node/748830 $_POST should really be ignored when doing things in drupal. It's better to find a way around using it. One way is the way described in the link, making ur form data persist using the $_SESSION array. I'm sure there are various other and better ways to do this, but yeah, drupal_get_form was the culprit here...