How to use Ajax pager in Drupal7 - ajax

I want to use ajax_pager in my block.
I've installed Libraries API and Ajax Pager API (as it described on the AP API page). But it's still not working.
When I use 'pager' instead of 'ajax_pager' it works.
What I'm doing wrong?
<?php
function latest_news_block_info() {
$blocks['latest_news_block'] = array(
// info: The name of the block.
'info' => t('Latest News'),
);
return $blocks;
}
function latest_news_block_view($delta = '') {
// The $delta parameter tells us which block is being requested.
switch ($delta) {
case 'latest_news_block':
// Create your block content here
$block['subject'] = t('Last news');
$query = new EntityFieldQuery();
//change news by the name of your content type
$entities = $query->entityCondition('entity_type', 'node')
->pager(5, 0)
->entityCondition('bundle', 'news')
->propertyOrderBy("created", "DESC")
->execute();
$content = "";
foreach($entities['node'] as $obj) {
$node = node_load($obj->nid);
$content .= "<img src='" .file_create_url($node->field_image['und'][0]['uri']) . "' width='200px' height='200px'>" . l($node->title, "node/" . $node->nid) . truncate_utf8($node->body['und'][0]['value'], 200, true, true) . '<br><hr>';
$block['content'] = $content;
}
break;
}
$pager = theme('ajax_pager', array('parameters' => array('selector' => 'block-system-main')));
$block['content'] .= $pager;
return $block;
}

Related

Woocommerce how to ajaxify add to cart button for variable products using custom html radio buttons instead of dropdown menu - no plugin

I'm trying to put all of the pieces of this puzzle together. I've been reading all of the questions and answers on this subject for the past 3 days. So the general blueprint that i'm following is as follows:
On single product page, first checking whether the type of product is "simple" or "variable".
If product is "variable" then i'm using woocommerce_variable_add_to_cart(); function to output the proper html.
Then trying to generate new and custom html (i.e "radio buttons") using the defualt html (i.e "dropdown menu") and woocommerce hooks.
Then trying to give functionality to the new and custom html (i.e "radio buttons") using javascript.
Then hiding the default dropdown menu using css.
Then trying to send an ajax request to the wordpress.
Then trying to process that ajax request on the backend and add the product to the cart.
Here is my code for each section:
Checking whether the type of product is "variable" on the single product page:
global $post;
$product = wc_get_product($post->ID);
$product_type = $product->get_type();
If the product type is "variable" then output the proper html:
if($product_type == 'variable'):
woocommerce_variable_add_to_cart();
endif;
Generating new and custom html (radio buttons) using php and woocommerce hooks:
add_filter('woocommerce_dropdown_variation_attribute_options_html', 'my_theme_variation_radio_buttons', 20, 2);
function my_theme_variation_radio_buttons($html, $args)
{
$args = wp_parse_args(apply_filters('woocommerce_dropdown_variation_attribute_options_args', $args), array(
'options' => false,
'attribute' => false,
'product' => false,
'selected' => false,
'name' => '',
'id' => '',
'class' => '',
'show_option_none' => __('Choose an option', 'woocommerce'),
));
if (false === $args['selected'] && $args['attribute'] && $args['product'] instanceof WC_Product) {
$selected_key = 'attribute_' . sanitize_title($args['attribute']);
$args['selected'] = isset($_REQUEST[$selected_key]) ? wc_clean(wp_unslash($_REQUEST[$selected_key])) : $args['product']->get_variation_default_attribute($args['attribute']);
}
$options = $args['options'];
$product = $args['product'];
$attribute = $args['attribute'];
$name = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title($attribute);
$id = $args['id'] ? $args['id'] : sanitize_title($attribute);
$class = $args['class'];
$show_option_none = (bool)$args['show_option_none'];
$show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __('Choose an option', 'woocommerce');
if (empty($options) && !empty($product) && !empty($attribute)) {
$attributes = $product->get_variation_attributes();
$options = $attributes[$attribute];
}
$radios = '<div class="variation-radios">';
if (!empty($options)) {
if ($product && taxonomy_exists($attribute)) {
$terms = wc_get_product_terms($product->get_id(), $attribute, array(
'fields' => 'all',
));
foreach ($terms as $term) {
if (in_array($term->slug, $options, true)) {
$id = $name . '-' . $term->slug;
$radios .= '<input type="radio" data-checked="no" id="' . esc_attr($id) . '" name="' . esc_attr($name) . '" value="' . esc_attr($term->slug) . '" ' . checked(sanitize_title($args['selected']), $term->slug, false) . '><label for="' . esc_attr($id) . '">' . esc_html(apply_filters('woocommerce_variation_option_name', $term->name)) . '</label>';
}
}
} else {
foreach ($options as $option) {
$id = $name . '-' . $option;
$checked = sanitize_title($args['selected']) === $args['selected'] ? checked($args['selected'], sanitize_title($option), false) : checked($args['selected'], $option, false);
$radios .= '<input type="radio" id="' . esc_attr($id) . '" name="' . esc_attr($name) . '" value="' . esc_attr($option) . '" id="' . sanitize_title($option) . '" ' . $checked . '><label for="' . esc_attr($id) . '">' . esc_html(apply_filters('woocommerce_variation_option_name', $option)) . '</label>';
}
}
}
$radios .= '</div>';
return $html . $radios;
}
add_filter('woocommerce_variation_is_active', 'my_theme_variation_check', 10, 2);
function my_theme_variation_check($active, $variation)
{
if (!$variation->is_in_stock() && !$variation->backorders_allowed()) {
return false;
}
return $active;
}
Giving functionality to "radio buttons" using javascript:
jQuery(document).ready($ => {
$(document).on('change', '.variation-radio input', function () {
$('.variation-radio input:checked').each(function (index, element) {
var radioElement = $(element);
var radioName = radioElement.attr('name');
var radioValue = radioElement.attr('value');
$('select[name="' + radioName + '"]').val(radioValue).trigger('change');
});
});
$(document).on('woocommerce_update_variation_values', function () {
$('.variation-radio input').each(function (index, element) {
var radioElement = $(element);
var radioName = radioElement.attr('name');
var radioValue = radioElement.attr('value');
radioElement.removeAttr('disabled');
if ($('select[name="' + radioName + '"] option[value="' + radioValue + '"]').is(':disabled')) {
radioElement.prop('disabled', true);
}
});
});
$("a.reset_variations").click(function () {
$('input:radio[name="attribute_size"]').prop('checked', false); $(this).css('display', 'none');
});
})
Hiding the default dropdown menu using css:
table.variations select{
display: none;
}
Sending an ajax request to the wordpress:
jQuery(document).ready($ => {
$("button.single_add_to_cart_button").on('click', function (e) {
e.preventDefault();
var myBtn = $(this),
$form = myBtn.closest('form.variations_form'),
product_qty = $form.find('input[name=quantity]').val() || 1,
product_id = $form.find('input[name=product_id]').val(),
variation_id = $form.find('input[name=variation_id]').val() || 0,
variation = {},
keys = [],
values = [];
// Looping through the attributes names and save them as the keys array
$('table tr td.label label').each(function (index, element) {
let radioElement = $(element);
keys[index] = radioElement.text();
});
// Looping through the attributes values and save them as the values array
$('.variation-radios input:checked').each(function (index, element) {
let radioElement = $(element);
values[index] = radioElement.val();
});
// Looping through the variation object and save keys and values in that object
$.each(keys, function (index, element) {
variation[element] = values[index]
})
console.log(variation);
var data = {
action: 'woocommerce_add_variation_to_cart',
product_id: product_id,
quantity: product_qty,
variation_id: variation_id,
var: variation
};
$(document.body).trigger('adding_to_cart', [myBtn, data]);
$.ajax({
type: 'post',
url: wc_add_to_cart_params.ajax_url,
data: data,
beforeSend: function (response) {
myBtn.removeClass('added').addClass('loading');
},
complete: function (response) {
myBtn.addClass('added').removeClass('loading');
},
success: function (response) {
console.log(response);
if (response.error && response.product_url) {
window.location = response.product_url;
return;
} else {
$(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, myBtn]);
}
},
});
return false;
});
})
Processing the ajax request on the backend and add the product to the cart:
add_action('wp_ajax_nopriv_woocommerce_add_variation_to_cart', 'my_theme_testing_add_to_cart_variable');
add_action('wp_ajax_woocommerce_add_variation_to_cart', 'my_theme_testing_add_to_cart_variable');
function my_theme_testing_add_to_cart_variable()
{
if (isset($_POST['product_id']) && $_POST['product_id'] > 0) {
$product_id = apply_filters('woocommerce_add_to_cart_product_id', absint($_POST['product_id']));
$quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount($_POST['quantity']);
$variation_id = isset($_POST['variation_id']) ? absint($_POST['variation_id']) : '';
$attributes = explode(',', $_POST['var']);
$variation = array();
foreach ($attributes as $values) {
$values = explode(':', $values);
$variation['attributes_' . $values[0]] = $values[1];
}
$passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity);
if ($passed_validation && WC()->cart->add_to_cart($product_id, $quantity, $variation_id, $variation)) {
do_action('woocommerce_ajax_added_to_cart', $product_id);
if (get_option('woocommerce_cart_redirect_after_add') == 'yes') {
wc_add_to_cart_message($product_id);
}
WC_AJAX::get_refreshed_fragments();
} else {
$data = array(
'error' => true,
'product_url' => apply_filters('woocommerce_cart_redirect_after_error', get_permalink($product_id), $product_id)
);
wp_send_json($data);
}
die();
}
}
PROBLEM
Everything works until step 7 with no error but when i run the whole thing, the single product page refreshes and variable product doesn't get added to the cart. And the wordpress error says "{your attribute field} is a required field"!
I think the bug could be somewhere in the ajax call when i'm trying to send variation object to the backend.
Although, i get the data absolutely fine on the backend but it doesn't add it to the cart.
Things that i've tried to debug it
I've tried to send the data in the ajax call as an array but didn't work either.
I also tried to explode the variation data using both = and : but none has worked!
Hooof! It's been a long week so far :\ full of debugging, headaches and frustrations. Now when i try to run the whole shebang, i can't get it to work and i've been reading all of the Qs and As on SO but can't find the bug! I think i've been overthinking it for a couple of days and also there are lots of pieces to it.
So i think i need some extra pairs of eyes to hopefully detect the bug.
Thank you, i appreciate any insight(s)!
In addition, huge shout out to these fellows whom i've learned a lot from:
LoicTheAztec for this great answer and this and this and many more.
cfx for this great answer
Anthony Grist for this answer
helgatheviking for this answer
AND OTHERS
EDIT
The code works fine, bug wasn't in the code, it was in the data that i was provided with. I'll leave the code here just in case somebody needs it in the future.
Short ansewer
The code works fine, i'll leave it here just in case somebody needs it in the future. Bug wasn't in the code, it was in the data that i was provided with.
Detailed Explanation
The code works fine. The data that i was provided with was manipulated for some reasons by my client so that each variable product wasn't a real variable product but at the same time the labels were typed in as variable products (yea i know it's confusing and not a standard practice), that's why whenever i tried to add them to cart, it would give the error saying {your-attribute} is a required field.
So we deleted each product data and add it back as a real and true variable product, then the code worked without us changing anything in it.
Take-away
So remember, whenever developing your app, there are always two sides to this coin! One side is your code and the other side is the data you're working on.
So, always always always, make sure the data you're working with is the way/format it's supposed to be. Also if you can't find any bug in your code, remember to check/debug the other side which is the data.
If you don't check the data first or at any debugging stage, then it'll be hard to track down the issue down the road!
This bug created a long delay in the project (about 2 weeks until we tracked down the bug in the data). So make sure to always check the both sides of the coin:
First, the data you're working with
Second, the code you wrote.

Codeigniter with google oauth2 adds hashtag php to redirect('usercp')

I want to be able to redirect to another controller but when user logins in with google and is success full it gets redirected to there usercp but for some reason it gets the # from the end of here
http://www.example.com/test/google?code=4/sorrynocodeshown#
And when redirects using codeigniter redirect() it adds # to it.
http://www.example.com/usercp#
Question When redirecting to new page once successful login how to stop # from being added.
I use https://github.com/moemoe89/google-login-ci3
I also use vhost with xammp
Controller function
public function google() {
if ($this->input->get('code')) {
$googleplus_auth = $this->googleplus->getAuthenticate();
$googleplus_info = $this->googleplus->getUserInfo();
$google_data = array(
'google_id' => $googleplus_info['id'],
'google_name' => $googleplus_info['name'],
'google_link' => $googleplus_info['link'],
'image' => $googleplus_info['picture'],
'email' => $googleplus_info['email'],
'firstname' => $googleplus_info['given_name'],
'lastname' => $googleplus_info['family_name']
);
$login_google_userid = $this->login_model->login_with_google($googleplus_info['id'], $google_data);
$_SESSION['user_id'] = $login_google_userid;
redirect('usercp');
}
}
config/googleplus.php settings
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
$config['googleplus']['application_name'] 'Somename';
$config['googleplus']['client_id'] = '*****';
$config['googleplus']['client_secret'] = '*****';
$config['googleplus']['redirect_uri'] = 'http://www.mysetname.com/account/login/google';
$config['googleplus']['api_key'] = '*****';
$config['googleplus']['scopes'] = array();
I am using HMVC with codeigniter
application/modules/account/controllers/Login.php
Full Controller
<?php
class Login extends MX_Controller {
private $error = array();
public function __construct() {
parent::__construct();
$this->load->library('form_validation');
$this->load->library('googleplus');
}
public function index() {
if ($this->login_model->is_logged_in()) {
$this->session->set_flashdata('success', 'Welcome back! If you wish to logout ' . anchor('account/logout', 'Click Here'));
redirect(base_url('usercp'));
}
if (($this->input->server("REQUEST_METHOD") == 'POST') && $this->validateForm()) {
$this->load->model('account/login_model');
$user_info = $this->login_model->get_user($this->input->post('username'));
if ($user_info) {
$_SESSION['user_id'] = $user_info['user_id'];
redirect(base_url('usercp'));
}
}
$data['login_url'] = $this->googleplus->loginURL();
if (isset($this->error['warning'])) {
$data['error_warning'] = $this->error['warning'];
} else {
$data['error_warning'] = '';
}
if (isset($this->error['username'])) {
$data['error_username'] = $this->error['username'];
} else {
$data['error_username'] = '';
}
if (isset($this->error['password'])) {
$data['error_password'] = $this->error['password'];
} else {
$data['error_password'] = '';
}
// Common
$data['header'] = Modules::run('common/header/index');
$data['navbar'] = Modules::run('common/navbar/index');
$data['footer'] = Modules::run('common/footer/index');
$this->load->view('login', $data);
}
public function validateForm() {
$this->form_validation->set_rules('username', 'username', 'required');
$this->form_validation->set_rules('password', 'password', 'required');
if ($this->form_validation->run() == FALSE) {
$this->error['username'] = form_error('username', '<div class="text-danger">', '</div>');
$this->error['password'] = form_error('password', '<div class="text-danger">', '</div>');
}
if ($this->input->post('username') && $this->input->post('password')) {
$this->load->model('account/login_model');
if (!$this->login_model->verify_password($this->input->post('username'), $this->input->post('password'))) {
$this->error['warning'] = 'Incorrect login credentials';
}
}
return !$this->error;
}
public function google() {
if ($this->input->get('code')) {
$googleplus_auth = $this->googleplus->getAuthenticate();
$googleplus_info = $this->googleplus->getUserInfo();
$google_data = array(
'google_id' => $googleplus_info['id'],
'google_name' => $googleplus_info['name'],
'google_link' => $googleplus_info['link'],
'image' => $googleplus_info['picture'],
'email' => $googleplus_info['email'],
'firstname' => $googleplus_info['given_name'],
'lastname' => $googleplus_info['family_name']
);
$login_google_userid = $this->login_model->login_with_google($googleplus_info['id'], $google_data);
$_SESSION['user_id'] = $login_google_userid;
redirect('usercp');
}
}
}
Codeigniter's redirect() function uses the php header() function in 2 ways:
switch ($method)
{
case 'refresh':
header('Refresh:0;url='.$uri);
break;
default:
header('Location: '.$uri, TRUE, $code);
break;
}
using the refresh parameter will not add the hashtag.
You find more about this in system/helpers/url_helper.php
you can use this to your advantage in google_login.php changing
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
accordingly to
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Refresh:0;url=' . filter_var($redirect, FILTER_SANITIZE_URL));
When calling the redirect, you should be able to drop the hash by using the refresh param:
redirect('usercp', 'refresh');
You can modifying the url by doing something like
$url = strstr($url, '#', true);
But otherwise since it's a client-side stuff there's not a lot of options. You could also remove it from javascript when the client load the page with
history.pushState('', document.title, window.location.pathname + window.location.search)
since this is too long in the comment section, here goes:
try to use your browser's debug mode/developer tools, and see the network part of it. in there, you could see the sequence of requests when your page are loading.
if you are using chrome, thick the preserve log option before doing the oauth.
do the oauth and then try to find the request to google that redirects to your page.
click on the request, you will get the details of the request.
see for the response header, it should be 302 status and the destination should be your http://www.example.com/usercp url.
if you did not see the #, then you have problems in your part, try to check your .htaccess file.
if it's there in the destination, then the problem lies in google part, and not much you can do about it

joomla - router change url when getting the name of product

I have build my own component in joomla and client wants now a friendly urls f.e
website.com/someplace/{product-id}-{product-name}. So i Build my own router like this.
function componentBuildRoute(&$query)
{
$segments = [];
if (isset($query['view'])) {
$segments[] = "szkolenie";
unset($query['view']);
}
if (isset($query['product_id'])) {
$productName = JFilterOutput::stringURLSafe(strtolower(getProductName($query['product_id'])));
$newName = $query['product_id'] . '-' . $productName;
$segments[] = $newName;
unset($query['product_id']);
}
return $segments;
}
and parse route function
function componentParseRoute($segments)
{
$app = JFactory::getApplication();
$menu = $app->getMenu();
$item =& $menu->getActive();
$count = count($segments);
switch ($item->query['view']) {
case 'catalogue' : {
$view = 'training';
$id = $segments[1];
}
break;
}
$data = [
'view' => $view,
'product_id' => $id
];
return $data;
}
While on the end of buildroute function segments are ok I have exactly what I want that on the beginning of parse route I have something like
website.com/szkolenie/1-krakow <-- I dont know wtf is this krakow( I know it is city i Poland) but still where is it get from ? The getProductName function implementation is
function getProductName($productId)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('#__component_training.id as id, #__component_product' . name)
->from($db->quoteName('#__component_training'))
->where('#__s4edu_product.product_id = ' . $productId)
->leftJoin('#__component_product ON
#__component_training.product_id=#__component_product.product_id');
$training = $db->loadObject();
return trim($training->name);
}
So taking all this into consideration I think that something is happening between the buildRoute and parseRoute, something what filters the $segment[1] variable, but how to disable that and why is it happening ?
P.S
Please do not send me to https://docs.joomla.org/Joomla_Routes_%26_SEF
I already know all the tutorials on joomla website which contains anything with sef.
P.S.S
It is built on joomla 3.7.0
You do not have a product named "krakow" ?
If not you can try to remove the $productName from the build function, just to check if this "krakow" is added automaticaly or it's from the getProductName() function.
Also i noticed that you have an error i guess in the function getProductName()
->where('#__s4edu_product.product_id = ' . $productId)
It's should be
->where('#__component_product.product_id = ' . $productId)

Joomla, Sp Page Builder and ReCaptcha

It's the First time that I use SP Page Builder component with Joomla. I want to use their contact form, but it doesn't support Google ReCaptcha.
I'm good enough with coding to thought that I could manually add it into : /com_sppagebuilder/addons/ajax_contact/site.php and get it to work.
I did add : <div class="g-recaptcha" data-sitekey="My_Key"></div>;
And the Joomla ReCaptcha plugin is activated.
I didn't know if I had to, but I added <script src='https://www.google.com/recaptcha/api.js'></script> into the head tag.
With this the ReCaptcha is showing fine.
My problem is with the validation.
I did try to add some validation code in the site.php but I believe SP Page Builder uses JFactory::getMailer(); to get the email ready and send it, and I don't know anything about that.
Thus, I do not know where I can add my ReCaptcha validation code, and as I did find few versions of that code online, I really don't know which one to use.
I've been searching everywhere for some answers to how to do this verification... and I tried many things, but it's still not working.
Can anyone help me through this one ?
Thank you very much !
EDIT
I think my question is not clear enough :
I want to add Recaptcha, that is already working fine in other forms on my website (so it's not a configuration with Joomla problem). I want to use the following SP Page Builder contact form and not a RSFormPro as on the rest of the Website. The validation process should be done around this section, but I tried to add the Google validation code, and I tried a few versions of it I found around the Internet, and it's not working at all :
public static function getAjax() {
$input = JFactory::getApplication()->input;
$mail = JFactory::getMailer();
//inputs
$inputs = $input->get('data', array(), 'ARRAY');
foreach ($inputs as $input) {
if( $input['name'] == 'recipient' ) {
$recipient = base64_decode($input['value']);
}
if( $input['name'] == 'email' ) {
$email = $input['value'];
}
if( $input['name'] == 'name' ) {
$name = $input['value'];
}
if( $input['name'] == 'subject' ) {
$subject = $input['value'];
}
if( $input['name'] == 'message' ) {
$message = nl2br( $input['value'] );
}
}
/*Try at the validation*/
$captcha_plugin = JFactory::getConfig()->get('captcha');
if ($captcha_plugin != '0') {
$captcha = JCaptcha::getInstance($captcha_plugin);
$field_id = 'google-recaptcha';
print $captcha->display($field_id, $field_id, 'g-recaptcha');
}
$sender = array($email, $name);
$mail->setSender($sender);
$mail->addRecipient($recipient);
$mail->setSubject($subject);
$mail->isHTML(true);
$mail->Encoding = 'base64';
$mail->setBody($message);
if ($mail->Send()) {
return '<span class="sppb-text-success">'. JText::_('COM_SPPAGEBUILDER_ADDON_AJAX_CONTACT_SUCCESS') .'</span>';
} else {
return '<span class="sppb-text-danger">'. JText::_('COM_SPPAGEBUILDER_ADDON_AJAX_CONTACT_FAILED') .'</span>';
}
}
Any suggestions ?
Thank you !
I have successfully added captcha to the Ajax contact form. Although the code still needs some improvements, Here is what I did:
See that I am using the n3tseznamcaptcha captcha plugin, I still need to implement the changes for other captchas to work (recaptcha,etc) but you can adapt it to your needs.
An SP Pagebuilder addon consists of two files, admin, and site. In the admin site I removed the default captcha, which lacks many security measures. Then in the site part I added the following:
function ajax_contact_addon($atts)
{
global $formcaptcha;
(...)
if($formcaptcha)
{
// TODO: Add Joomla's captcha:
JPluginHelper::importPlugin('captcha');
$dispatcher = JDispatcher::getInstance();
// This will put the code to load CAPTCHA's JavaScript file into your <head>
$dispatcher->trigger('onInit', 'dynamic_captcha_1');
// This will return the array of HTML code.
$captcha = $dispatcher->trigger('onDisplay', array(null, 'dynamic_captcha_1', 'class=""'));
// I have only 1 recaptcha plugin enabled so the HTML is at 0 index, this will be improved in next version, following the contact component
$output .= (isset($captcha[0])) ? $captcha[0] : '';
$output .= '<div class="clearfix"></div><p></p>';
}
(...)
}
function ajax_contact_get_ajax()
{
global $formcaptcha;
$jinput = JFactory::getApplication()->input;
$mail = JFactory::getMailer();
$config = JFactory::getConfig();
// TODO: CHECK CAPTCHA and add a Helper Class to get the captchas fields
$captchaset = 'n3tseznamcaptcha';
if ($captchaset === 'n3tseznamcaptcha')
{
$captcha_field_hash = 'n3t_seznam_captcha_hash';
$captcha_field_answer = 'n3t_seznam_captcha';
}
//inputs
$inputs = $jinput->get('data', array(), 'ARRAY');
foreach ($inputs as $input)
{
if( $input['name'] == 'title' )
{
$title = $input['value'];
}
if( $input['name'] == 'recipient' )
{
$recipient = base64_decode($input['value']);
}
if( $input['name'] == 'email' )
{
$email = $input['value'];
}
(...)
if( $input['name'] == $captcha_field_hash )
{
$captcha_hash = $input['value'];
}
if( $input['name'] == $captcha_field_answer )
{
$captcha_answer = $input['value'];
}
}
if($formcaptcha)
{
// get the plugin
JPluginHelper::importPlugin('captcha');
$dispatcher = JEventDispatcher::getInstance();
// In order the plugin can check the code, we have to insert it into the request data:
$jinput->set('n3t_seznam_captcha_hash', $captcha_hash);
$jinput->set('n3t_seznam_captcha', $captcha_answer);
// Here we check for the code:
$res = $dispatcher->trigger('onCheckAnswer', $captcha_answer);
if(!$res[0])
{
// There is a problem with pagebuilder cache and captchas, so we need to clean the cache, to renew the captcha code:
$cache = JFactory::getCache('page');
$cache->clean();
return '<span class="pb-text-danger">'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_FORM_WRONG_CAPTCHA') .'</span>';
}
}
}
I think that's all. Hope it helps you to find out.
So here you have the complete solution. Note that I changed a few things in the admin side too. This version will display and validate the default captcha selected in Joomla config, but it will only work for recaptcha and n3tsezam.. other should be added manually. The reason is that this addon does not add the challenge and response fields in the request, which the captcha plugins use for validation, therefor we need to retrieve it and write to the jinput within our ajax function (ajax_contact_get_ajax), and what complicates the whole thing is that every captcha plugin use different fields. Anyway.. if you need any other captcha plugin just can add it to the switch and you should be done.
function ajax_contact_addon($atts)
{
extract(AddonAtts(array(
"title" => '',
"show_title" => '',
"heading_selector" => 'h3',
"title_fontsize" => '',
"title_fontweight" => '',
"title_text_color" => '',
"title_margin_top" => '',
"title_margin_bottom" => '',
"recipient_email" => '',
"formcaptcha" => '',
"class" => '',
), $atts));
JHtml::script('media/com_pagebuilder/js/ajax-contact.js');
// There is a problem with pagebuilder cache and captchas
$cache = JFactory::getCache('page');
$cache->clean();
$output = '<div class="pb-addon pb-addon-ajax-contact ' . $class . '">';
if(boolval($show_title) && $title)
{
$title_style = '';
if($title_margin_top !='') $title_style .= 'margin-top:' . (int) $title_margin_top . 'px;';
if($title_margin_bottom !='') $title_style .= 'margin-bottom:' . (int) $title_margin_bottom . 'px;';
if($title_text_color) $title_style .= 'color:' . $title_text_color . ';';
if($title_fontsize) $title_style .= 'font-size:'.$title_fontsize.'px;line-height:'.$title_fontsize.'px;';
if($title_fontweight) $title_style .= 'font-weight:'.$title_fontweight.';';
$output .= '<'.$heading_selector.' class="pb-addon-title" style="' . $title_style . '">' . $title . '</'.$heading_selector.'>';
}
$output .= '<div class="pb-addon-content">';
$output .= '<form class="pb-ajax-contact-form">';
$output .= '<div class="pb-form-group">';
$output .= '<input type="text" name="name" class="pb-form-control" placeholder="'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_NAME') .'" required="required">';
$output .= '</div>';
$output .= '<div class="pb-form-group">';
$output .= '<input type="email" name="email" class="pb-form-control" placeholder="'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_EMAIL') .'" required="required">';
$output .= '</div>';
$output .= '<div class="pb-form-group">';
$output .= '<input type="text" name="subject" class="pb-form-control" placeholder="'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_SUBJECT') .'" required="required">';
$output .= '</div>';
$output .= '<div class="pb-form-group">';
$output .= '<textarea type="text" name="message" rows="5" class="pb-form-control" placeholder="'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_MESSAGE') .'" required="required"></textarea>';
$output .= '</div>';
if($formcaptcha)
{
JPluginHelper::importPlugin('captcha');
$dispatcher = JDispatcher::getInstance();
$dispatcher->trigger('onInit', 'dynamic_captcha_1');
$captchas = $dispatcher->trigger('onDisplay', array(null, 'dynamic_captcha_1', 'class=""'));
$index = 0;
foreach (JPluginHelper::getPlugin('captcha') as $plugin)
{
if (JFactory::getApplication()->get('captcha', '0') === $plugin->name)
{
$captcha = $captchas[$index];
break;
}
$index++;
}
$output .= (isset($captcha)) ? $captcha : '';
$output .= '<div class="clearfix"></div><p></p>';
}
$output .= '<input type="hidden" name="recipient" value="'. base64_encode($recipient_email) .'">';
$output .= '<input type="hidden" name="title" value="'. $title .'">';
$output .= '<button type="submit" class="btn btn-default"><i class="fa"></i> '. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_SEND') .'</button>';
$output .= '</form>';
$output .= '<div style="display:none;margin-top:10px;" class="pb-ajax-contact-status"></div>';
$output .= '</div>';
$output .= '</div>';
return $output;
}
function ajax_contact_get_ajax()
{
$config = JFactory::getConfig();
$jinput = JFactory::getApplication()->input;
//inputs
$inputs = $jinput->get('data', array(), 'ARRAY');
$mail = JFactory::getMailer();
// TODO: Find the way to check if captcha is enabled in the addon
$formcaptcha = true;
$message = "";
// TODO: CHECK CAPTCHA and add a Helper Class to get the captchas
switch (JFactory::getApplication()->get('captcha', '0'))
{
case 'recaptcha':
// v.1:
//$captcha_challenge_field = 'recaptcha_challenge_field';
//$captcha_answer_field = 'recaptcha_response_field';
// v.2:
$captcha_challenge_field = '';
$captcha_answer_field = 'g-recaptcha-response';
break;
case 'n3tseznamcaptcha':
$captcha_challenge_field = 'n3t_seznam_captcha_hash';
$captcha_answer_field = 'n3t_seznam_captcha';
break;
default:
// disable captcha as we could not find the right fields
$formcaptcha = false;
}
foreach ($inputs as $input)
{
if( $input['name'] == 'title' )
{
$title = $input['value'];
}
if( $input['name'] == 'recipient' )
{
$recipient = base64_decode($input['value']);
}
if( $input['name'] == 'email' )
{
$email = $input['value'];
}
if( $input['name'] == 'name' )
{
$name = $input['value'];
}
if( $input['name'] == 'subject' )
{
$subject = $input['value'];
}
if( $input['name'] == 'message' )
{
$message = nl2br( $input['value'] );
}
if( $input['name'] == $captcha_challenge_field )
{
$captcha_challenge = $input['value'];
}
if( $input['name'] == $captcha_answer_field )
{
$captcha_answer = $input['value'];
}
}
$valid_captcha = true;
if($formcaptcha)
{
// get the plugin
JPluginHelper::importPlugin('captcha');
$dispatcher = JEventDispatcher::getInstance();
$jinput->set($captcha_challenge_field, $captcha_challenge);
$jinput->set($captcha_answer_field, $captcha_answer);
$res = $dispatcher->trigger('onCheckAnswer', $captcha_answer);
$index = 0;
foreach (JPluginHelper::getPlugin('captcha') as $plugin)
{
if (JFactory::getApplication()->get('captcha', '0') === $plugin->name)
{
$valid_captcha = $res[$index];
break;
}
$index++;
}
if(!$valid_captcha)
{
$msg = '<span class="pb-text-danger">'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_FORM_WRONG_CAPTCHA') .'</span>';
}
}
if ($valid_captcha)
{
// We do not want to send the email as a fake user, it may cause spam problems
$sender = array(
$config->get( 'mailfrom' ),
$config->get( 'fromname' )
);
$subject = (($title)? '['.$title.'] ' : '') . $subject;
$message .= JText::sprintf('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_EMAIL_SIGNATURE', JUri::getInstance()->toString(), JUri::getInstance());
$mail->setSender($sender);
$mail->addRecipient($recipient);
$mail->setSubject($subject);
$mail->AddReplyTo($email);
$mail->isHTML(true);
$mail->Encoding = 'base64';
$mail->setBody($message);
if ($mail->Send())
{
$msg = '<span class="pb-text-success">'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_SUCCESS') .'</span>';
} else {
$msg = '<span class="pb-text-danger">'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_FAILED') .'</span>';
}
}
// There is a problem with pagebuilder cache and captchas
$cache = JFactory::getCache('page');
$cache->clean();
return $msg;
}
That functionality is now integrated into SP Page Builder Contact Form Addon.
1) Grab the reCaptcha API keys from the console: https://www.google.com/recaptcha/admin
2) Enable reCaptcha plugin in Joomla's backend:
Joomla Control Panel and navigate to Extensions > Plugins > captcha - reCaptcha
3) Enable reCaptcha in your Joomla configuration:
Go to System > Global Configuration > Site Settings > Default Captcha
4) Go to your Contact Form (or create a new one) and enable captcha. Then choose "CAPTCHA - reCAPTCHA" in Captcha type selector.
After completing the above steps, if you don't see a reCAPTCHA box on the contact form frontend, it means that your template uses the old contact addon code. In most cases, you can safely take a backup and then delete the (bold) folder: templates\YOUR-TEMPLATE-NAME\sppagebuilder\addons\ajax_contact
All the info you need is available in this article: https://www.joomshaper.com/blog/google-recaptcha-joomla-contact-forms-integration

Passing Two Arrays to View

OK, below is a get_members function in my controller that I pulled and manipulated from the interwebs... i can print out the information from $output in the controller, but I don't want to do that... I cannot figure out how to get it to be part of my view so I can list info from it freely...
I know it has something to do with the $data array in the index function... can anyone assist?
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Phonedirectory extends CI_Controller {
function get_members($group=FALSE,$inclusive=FALSE) {
// Active Directory server
$ldap_host = "fps";
// Active Directory DN
$ldap_dn = "OU=Users,DC=xxx,DC=org";
// User attributes we want to keep
$keep = array(
"samaccountname",
"displayName",
"telephonenumber"
);
// Connect to AD
$ldap = ldap_connect($ldap_host) or die("Could not connect to LDAP");
ldap_set_option ($ldap, LDAP_OPT_REFERRALS, 0);
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_bind($ldap, "CN=LDAP Reader,OU=Users - Special,DC=xxx,DC=org", "xxx") or die("Could not bind to LDAP");
// Begin building query
if($group) $query = "(&"; else $query = "";
$query .= "(&(objectClass=user)(objectCategory=person))";
// Filter by memberOf, if group is set
if(is_array($group)) {
// Looking for a members amongst multiple groups
if($inclusive) {
// Inclusive - get users that are in any of the groups
// Add OR operator
$query .= "(|";
} else {
// Exclusive - only get users that are in all of the groups
// Add AND operator
$query .= "(&";
}
// Append each group
foreach($group as $g) $query .= "(memberOf=OU=$g,$ldap_dn)";
$query .= ")";
} elseif($group) {
// Just looking for membership of one group
$query .= "(memberOf=OU=$group,$ldap_dn)";
}
// Close query
if($group) $query .= ")"; else $query .= "";
// Uncomment to output queries onto page for debugging
// print_r($query);
// Search AD
$results = ldap_search($ldap,$ldap_dn,$query);
$entries = ldap_get_entries($ldap, $results);
// Remove first entry (it's always blank)
array_shift($entries);
$output = array(); // Declare the output array
$i = 0; // Counter
// Build output array
foreach($entries as $u) {
foreach($keep as $x) {
// Check for attribute
if(isset($u[$x][0])) $attrval = $u[$x][0]; else $attrval = NULL;
// Append attribute to output array
$output[$i][$x] = $attrval;
}
$i++;
}
return $output;
}
public function index() {
$data = array('title' => 'Phone Directory', 'main_content' => 'pages/phoneDirectory');
$this->load->view('template/main', $data);
}
}
Correct me if I'm wrong, but it sounds like you just want the output sent to the view?
If that's the case, then add this to the index function
public function index() {
$data = array('title' => 'Phone Directory', 'main_content' => 'pages/phoneDirectory');
$data['members'] = $this->get_members();
$this->load->view('template/main', $data);
}
or however you want to append that to your data array.
Then in the view you can do:
<?php echo print_r($members, TRUE); ?>

Resources