Here is a screenshot:
I want to catch a specific page template and show meta box according the specific page template. I have tried to with it:
$pageTemplate = get_post_meta($post->ID, '_wp_page_template', true);
but is not working.
Add the following code to functions.php:
add_filter('template_include', 'var_template_include', 1000);
function var_template_include($t) {
$GLOBALS['current_theme_template'] = basename($t);
return $t;
}
function get_current_template() {
if (isset($GLOBALS['current_theme_template'])) {
return $GLOBALS['current_theme_template'];
} else {
return false;
}
}
You'll then be able to do the following:
$pageTemplate = get_current_template();
Related
Hello I have been trying to create a woocommerce booking by code, I have managed to create a booking and add it to the user's cart. The problem is that I cannot set the booking's price. I have tried multiple solutions such as these:
add_filter('woocommerce_add_cart_item', 'tsc_booking_woocommerce_add_cart_item', 99, 1);
function tsc_booking_woocommerce_add_cart_item($cart_item)
{
try {
session_start();
if (!empty($cart_item['booking']) && isset($cart_item['booking']
['_cost']) && '' !== $cart_item['booking']['_cost']) {
$cart_item['data']->set_price(100);
$cart_item['custom_price'] = 100;
}
return $cart_item;
} catch (Exception $e) {
throw $e;
}
}
add_filter('woocommerce_get_cart_item_from_session', 'tsc_booking_woocommerce_get_cart_item_from_session', 99, 3);
function tsc_booking_woocommerce_get_cart_item_from_session($woo_data, $values, $key)
{
if (!isset($woo_data['custom_price']) || empty($woo_data['custom_price'])) {
return $woo_data;
}
$woo_data['data']->set_price($woo_data['custom_price']);
return $woo_data;
}
add_filter('woocommerce_bookings_calculated_booking_cost', 'tsc_booking_woocommerce_bookings_calculated_booking_cost', 99, 3);
function tsc_booking_woocommerce_bookings_calculated_booking_cost($booking_cost, $booking, $posted)
{
try {
return 100;
} catch (Exception $e) {
throw $e;
}
}
But they don't seem to work.
The documented solution would be to use the "woocommerce_before_calculate_totals" hook but it is not working.
I have debugged the code and all the function are being invoked and no there does not seem to be any errors.
add_action('woocommerce_before_calculate_totals', 'tsc_booking_woocommerce_before_calculate_totals', 1000, 1);
function tsc_booking_woocommerce_before_calculate_totals($cart)
{
if (is_admin() && !defined('DOING_AJAX'))
return;
if (did_action('woocommerce_before_calculate_totals') >= 2)
return;
foreach ($cart->get_cart() as $cart_item) {
$cart_item['data']->set_price(100);
}
}
I am pretty sure this worked for a normal WC_Product is there something else to do for a Booking product?
Thanks,
I got it...
Just in case anyone gets an headache like the one I just got.
The reason the price was reset to 0 in the cart was because of another plugin "Woocommerce Membership". The product had a discount price of 100€ for members and because I was using a testing price of 100€... the two would add up to 0. I guess the membership plugin has a lower priority when setting the product price.
I am trying to pre select a value within a select field in my contact from on the contact page from another page by passing a query string ?request=call-back. I am using Ninja Forms and the values that I have in my select field are: email-us, call-back
I have tried the following:
add_filter( 'ninja_forms_render_default_value', 'my_ninja_forms_pre_populate', 10, 3 );
function my_ninja_forms_pre_populate( $default_value, $field_type, $field_settings ){
if( 'request' == $field_settings[ 'key' ] ){
$default_value = $_GET['request'];
}
return $default_value;
}
I would like the select field to have call-back already selected.
I didnt need to use the filter that I was attempting. I changed the key value under administration within the ninja form builder and I made sure that none of the values were pre selected.
This drove me mad... but finally I've got a solution:
// register custom get parameter (to use it with get_query_var() for safety reasons)
function add_get_val() {
global $wp;
$wp->add_query_var('request');
}
add_action('init', 'add_get_val');
add_filter('ninja_forms_localize_field_listselect', function ($field) {
if (get_query_var('request')) {
$request = get_query_var('request');
$optionExists = FALSE;
// check if field exists
foreach ($field['settings']['options'] as $option) {
if ($option['value'] === $request) {
$optionExists = TRUE;
break;
}
}
if ($optionExists) {
foreach ($field['settings']['options'] as $key => $option) {
// deselect all fields
$field['settings']['options'][$key]['selected'] = 0;
// select parameter
if ($option['value'] === $request) {
$field['settings']['options'][$key]['selected'] = 1;
}
}
}
}
return $field;
});
I want to programmatically alter a page title in Drupal 8 so that it will be hard-coded in the theme file.
I'm attempting to use a hook function to preprocess_page_title, but it seems to not understand what page to change the title on.
Here's what I have so far:
function test_preprocess_page_title(&$variables) {
if (arg(0) == 'node/12') {
$variables['title'] = 'New Title';
}
}
I figured the only way to make this change on one specific page is to set the node argument. Has any one figured out a way to override page title on Drupal?
In your template.theme file add the preprocessor and then override page-title.html.twig in your template folder by printing the variable, like below:
function theme_preprocess_page_title(&$variables) {
$node = \Drupal::request()->attributes->get('node');
$nid = $node->id();
if($nid == '14') {
$variables['subtitle'] = 'Subheading';
}
}
then {{ subtitle }}
Here's the method to preprocess your page :
function yourthemename_preprocess_page(&$variables) {
$node = \Drupal::routeMatch()->getParameter('node');
if ($node) {
$variables['title'] = $node->getTitle();
}
}
and in your template page.html.twig
{{title}}
There are a couple of solutions to change the page title
On template
/**
* Implements hook_preprocess_HOOK().
*/
function MYMODULE_preprocess_page_title(&$variables) {
if ($YOUR_LOGIC == TRUE) {
$variables['title'] = 'New Title';
}
}
On the node view page
/**
* Implements hook_ENTITY_TYPE_view_alter().
*/
function mymodule_user_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
if ($YOUR_LOGIC == TRUE) {
$build['#title'] = $entity->get('field_display_name')->getString();
}
}
for a sample if you want to change user title
function mymodule_user_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
if ($entity->getEntityTypeId() == 'user') {
$build['#title'] = $entity->get('field_first_name')->getString();
}
}
On Controller or hook_form_alter
if ($YOUR_LOGIC == TRUE) {
$request = \Drupal::request();
if ($route = $request->attributes->get(\Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_OBJECT)) {
$route->setDefault('_title', 'New Title');
}
}
The Page Title is a block in Drupal 8. If you can find the plugin_id of the page title block (which is likely to be page_title_block), then you can override the title directly, with no need to change an existing twig template, using a block preprocessor. Your code may be similar to the following:
function vhs_preprocess_block(&$variables) {
// This example restricts based on the actual URL; you can replace this with any other logic you wish.
$request = \Drupal::request();
$uri = $request->getRequestUri();
if (
isset($variables['elements']['#base_plugin_id']) &&
$variables['elements']['#base_plugin_id'] == 'page_title_block' &&
isset($variables['content']['#title']['#markup']) &&
strpos($uri, '/url-to-match') === 0 // replace with logic that finds the correct page to override
) {
$variables['content']['#title']['#markup'] = 'My Custom Title';
}
}
The example above uses the Drupal request object to grab and compare the actual URL. The initial question asked to match based on the node path; you could get that with something like:
$current_path = \Drupal::service('path.current')->getPath();
Then, in place of the strpos condition above, you could use:
$current_path == 'node/12'
i have changed the page_title block for user/uid to a different custom account field name like this :
function hook_preprocess_block(&$variables) {
$path = \Drupal::request()->getpathInfo();
$arg = explode('/', $path);
if (isset($arg[2]) && $arg[2] == 'user' && isset($arg[3])) {
if (isset($variables['elements']['content']['#type']) && $variables['elements']['content']['#type'] == 'page_title') {
$account = \Drupal\user\Entity\User::load($arg[3]);
if(isset($account) && isset($account->field_mycustomfield->value)){
$variables['content']['#title']['#markup']=$account->field_mycustomfield->value;
}
}
}
}
I would like to add a select field in admin/post-new.php.
This select field will be populated with JSON data (from a GET URL).
^ This point is solved. In your function.php:
function acf_load_colors_field_choices($field) {
$field['choices'] = [];
$choices = json_decode(file_get_contents('http://127.0.0.1/json/colors'), true);
if (is_array($choices)) {
foreach ($choices as $choice) {
$field['choices'][$choice] = $choice;
}
}
return $field;
}
add_filter('acf/load_field/name=colors', 'acf_load_colors_field_choices');
Once the page is ready to be published, I would like to catch POST data to send them to another URL.
How to catch those data?
In functions.php, to catch POST data:
function on_save_post_articles($post_id) {
var_dump($post_id);
var_dump($_POST);
exit;
}
add_action('save_post', 'on_save_post_articles');
Solved!
I'm searching for a way to create a custom action button which allows me to make a new DataObject with pre-filled content from another DataObject. As a simple example: When I have an email and click the "answer"-button in my email-client, I get a new window with pre-filled content from the email before. I need exactly this functionality for my button. This button should appear next to each DataObject in the GridField.
So I know how to make a button and add it to my GridField (--> https://docs.silverstripe.org/en/3.2/developer_guides/forms/how_tos/create_a_gridfield_actionprovider/) and I know how to go to a new DataObject:
Controller::curr()->redirect($gridField->Link('item/new'));
I also found out that there is a duplicate function for DataObjects:
public function duplicate($doWrite = true) {
$className = $this->class;
$clone = new $className( $this->toMap(), false, $this->model );
$clone->ID = 0;
$clone->invokeWithExtensions('onBeforeDuplicate', $this, $doWrite);
if($doWrite) {
$clone->write();
$this->duplicateManyManyRelations($this, $clone);
}
$clone->invokeWithExtensions('onAfterDuplicate', $this, $doWrite);
return $clone;
}
Perhaps it's easier than I think but at the moment I just don't get how to rewrite this to get what I need. Can somebody give me a hint?
That's for sure not the cleanest solution but I think it should do the trick.
At first let's create the custom gridfield action. Here we will save all accessible records in a session and add a query string to the url so that we'll know which object we want to "clone"
public function getColumnContent($gridField, $record, $columnName) {
if(!$record->canEdit()) return;
$field = GridField_FormAction::create(
$gridField,
'clone'.$record->ID,
'Clone',
'clone',
array('RecordID' => $record->ID)
);
$values = Session::get('ClonedData');
$data = $record->data()->toMap();
if($arr = $values) {
$arr[$record->ID] = $data;
} else {
$arr = array(
$record->ID => $data
);
}
Session::set('ClonedData', $arr);
return $field->Field();
}
public function getActions($gridField) {
return array('clone');
}
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
if($actionName == 'clone') {
$id = $arguments['RecordID'];
Controller::curr()->redirect($gridField->Link("item/new/?cloneID=$id"));
}
}
after adding this new component to our gridfield,
$gridField->getConfig()->addComponent(new GridFieldCustomAction());
we'll need to bring the data into the new form. To do so, add this code directly above "return $fields" on your getCMSFields function so it will be executed every time we'll open this kind of object.
$values = Session::get('ClonedData');
if($values) {
Session::clear('ClonedData');
$json = json_encode($values);
$fields->push(LiteralField::create('ClonedData', "<div id='cloned-data' style='display:none;'>$json</div>"));
}
At the end we need to bring the content back into the fields. We'll do that with a little bit of javascript so at first you need to create a new script.js file and include it in the ss backend (or just use an existing one).
(function($) {
$('#cloned-data').entwine({
onmatch: function() {
var data = JSON.parse($(this).text()),
id = getParameterByName('cloneID');
if(id && data) {
var obj = data[id];
if(obj) {
$.each(obj, function(i, val) {
$('[name=' + i + ']').val(val);
});
}
}
}
});
// http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript#answer-901144
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
})(jQuery);
And that's it ... quite tricky. Hope it will solve your problem.