How to create one plugin in drupal 7 custom module? - javascript

Im trying to create a custom module plugin in drupal 7, but im having any issues that i cant resolve.
I've created other plugins previously, but this is provoke to me more problems that i supposed.
Well, im creating any charts with Progressbar.js library. The idea is generate one chart per plugin, filling the form fields from page_manager, for example, if i want to create 3 charts in any page of my site, i should call 3 plugins.
The problem is that when i go to the page where the charts must to show, only generate one chart (last plugin that i call from pane).
The logic of operation, is that I enter the values of the fields through the form of the plugin. These values are sent to the script to generate the graphics with the library ProgressBar.js and thus render the graphic to html.
I noticed that the plugin is not sending the data to the javascript script. Just send the data to the script the last plugin that I created. The previous two do not. When i use console.log in the script, only get values from last plugin, when it should show 3 logs with their respectives values.
This is directory of my custom module.
├── obs_home_page.features.inc
├── obs_home_page.info
├── obs_home_page.module
├── obs_home_page.pages_default.inc
├── plugins
│ └── content_types
│ ├── obs_home_page_show.inc
└── scripts
└── ProgressBar.js
obs_home_page.module:
<?php
/**
* #file
* Code for the Home page feature.
*/
include_once 'obs_home_page.features.inc';
function obs_home_page_ctools_plugin_directory($owner, $plugin) {
return 'plugins/' . $plugin;
}
obs_home_page_show.inc:
<?php
$plugin = array(
'single' => TRUE, // Just do this one, it is needed.
'title' => t('Relojes'), // Title to show up on the pane screen.
'description' => t('Reloj de derecho ipara la portada home'), // Description to show up on the pane screen.
'category' => t('Custom'), // A category to put this under.
'edit form' => 'obs_home_page_show_edit_form', // A function that will return the settings form for the pane.
'render callback' => 'obs_home_page_show_render', // A function that will return the renderable content.
'admin info' => 'obs_home_page_show_admin_info', // A function that will return the information displayed on the admin screen (optional).
'defaults' => array( // Array of defaults for the settings form.
'right' => '',
'maxValue' => '33',
'value' => '',
'description' => ''
),
'all contexts' => TRUE, // This is NEEDED to be able to use substitution strings in your pane.
);
/**
* An edit form for the pane's settings.
*/
function obs_home_page_show_edit_form($form, &$form_state) {
$conf = $form_state['conf'];
$form['right'] = array(
'#title' => t('Right'),
'#description' => t('Right ID'),
'#type' => 'textfield',
'#required' => TRUE,
'#default_value' => !empty($conf['right']) ? $conf['right'] : '',
);
$form['description'] = array(
'#title' => t('Description'),
'#description' => t('Right description'),
'#type' => 'textfield',
'#default_value' => !empty($conf['description']) ? $conf['description'] : '',
);
$form['maxValue'] = array(
'#title' => t('Max value'),
'#description' => t('Max value'),
'#type' => 'textfield',
'#size' => 11,
'#default_value' => !empty($conf['maxValue']) ? $conf['maxValue'] : '',
);
$form['value'] = array(
'#title' => t('Value'),
'#description' => t('Value'),
'#type' => 'textfield',
'#size' => 11,
'#required' => TRUE,
'#default_value' => !empty($conf['value']) ? $conf['value'] : '',
);
return $form;
}
/**
* Submit function, note anything in the formstate[conf] automatically gets saved
* Notice, the magic that automatically does that for you.
*/
function obs_home_page_show_edit_form_submit(&$form, &$form_state) {
foreach (array_keys($form_state['plugin']['defaults']) as $key) {
if (isset($form_state['values'][$key])) {
$form_state['conf'][$key] = $form_state['values'][$key];
}
}
}
/**
* Run-time rendering of the body of the block (content type)
* See ctools_plugin_examples for more advanced info
*/
function obs_home_page_show_render($subtype, $conf, $panel_args, $context) {
//Check context and validates input for each config field.
if (!empty($context) && !empty($conf['right']) && check_plain($conf['right'])) {
$right = ctools_context_keyword_substitute($conf['right'], array(), $context);
} else {
$right = arg(1); //fallback, uses the current nid
}
if (!empty($context) && !empty($conf['description']) && check_plain($conf['description'])) {
$description = ctools_context_keyword_substitute($conf['description'], array(), $context);
} else {
$description = null;
}
if (!empty($context) && !empty($conf['maxValue']) && check_plain($conf['maxValue'])) {
$maxValue = ctools_context_keyword_substitute($conf['maxValue'], array(), $context);
} else {
$maxValue = null;
}
if (!empty($context) && !empty($conf['value']) && check_plain($conf['value'])) {
$value = ctools_context_keyword_substitute($conf['value'], array(), $context);
} else {
$value = null;
}
$right = intval($conf['right']);
$maxValue = intval($conf['maxValue']);
$value = intval($conf['value']);
$tid = taxonomy_term_load($right);
$right_name = $tid->name;
$right_description = $tid->description;
if (empty($conf['description'])) {
$description = $right_description;
} else {
$description = $conf['description'];
}
$settings = array();
$settings['clock']['right'] = $right;
$settings['clock']['maxValue'] = $maxValue;
$settings['clock']['value'] = $value;
dsm($settings);
drupal_add_js($settings, 'setting');
drupal_add_js(drupal_get_path('module', 'obs_home_page') . '/scripts/ProgressBar.js');
dsm(drupal_get_path('module', 'obs_home_page') . '/scripts/ProgressBar.js');
$output = array(
'#type' => 'markup',
'#markup' => '<div class="home_page_progressbar">
<a href="'. base_path() .'taxonomy/term/'. $right .'">
<div id="progressbar-'. $right .'"></div>
<h2>'. $right_name .'</h2>
</a>
<div class="descripcion_clock_right_home">'. $description .'</div>
</div>',
);
$block = new stdClass();
$block->title = '';
$block->content = $output;
return $block;
}
/**
* 'admin info' callback for panel pane.
*/
function obs_home_page_show_admin_info($subtype, $conf, $contexts) {
if (!empty($conf)) {
$block = new stdClass;
$block->title = $conf['override_title'] ? $conf['override_title_text'] : '';
$block->content = t('<strong>Max Value:</strong> #maxValue<br />
<strong>Value:</strong> #value</p>',
array(
'#maxValue' => $conf['maxValue'],
'#value' => $conf['value'],
));
return $block;
}
}
ProgressBar.js:
/**
* #file Creacion de relojes para la portada home con libreria ProgressBar
*
*/
(function ($) {
Drupal.behaviors.obs_home_page = {
attach: function (context, settings) {
GenerarReloj(settings);
}
};
var GenerarReloj = function (settings) {
var right = parseInt(settings.clock.right);
var nominator = parseInt(settings.clock.value);
var denominator = parseInt(settings.clock.maxValue);
var bar_information = new ProgressBar.Circle('#progressbar-' + right, {
color: '#aaa',
// This has to be the same size as the maximum width to
// prevent clipping
strokeWidth: 10,
trailWidth: 10,
easing: 'easeInOut',
duration: 2000,
text: {
autoStyleContainer: false
},
from: { color: '#C5DC70', width: 10 },
to: { color: '#728530', width: 10 },
// Set default step function for all animate calls
step: function(state, circle) {
circle.path.setAttribute('stroke', state.color);
circle.path.setAttribute('stroke-width', state.width);
var value = Math.round(circle.value() * denominator);
if (value === 0) {
circle.setText('');
} else {
circle.setText(value);
}
}
});
// bar.text.style.fontFamily = '"Raleway", Helvetica, sans-serif';
bar_information.text.style.fontSize = '3rem';
var quotient = nominator / denominator;
bar_information.animate(quotient); // Number from 0.0 to 1.0
}
})(jQuery);

Related

php Redirect url to a Ifram

Please accept my apology in advance if my question is long.
I am using a payment gateway of woocommerce.
When click on checkout it goes to an external link. Then there We have button to click and Then It goes to another link which make it enable to pay via cards.
Now What I want to do is that.
I want to minimize some step.
1- If possible I want to bypass detail page which appears after click on Checkout button.
2- Is this possible to hide amount on detail page. As my website currecny is different and this payment gateway the show in different.
3- If above 1,2 not possible. Can simply put external pages in a iframe.
So if user click on check out. It should show a ifram on new page current page with redirected link.
Below code is from gateway plugin.
<?php
add_action( 'plugins_loaded', 'init_pp_woo_gateway');
function mib_ppbycp_settings( $links ) {
$settings_link = 'Setup';
array_push( $links, $settings_link );
return $links;
}
$plugin = plugin_basename( __FILE__ );
add_filter( "plugin_action_links_$plugin", 'mib_ppbycp_settings' );
function init_pp_woo_gateway(){
if ( ! class_exists( 'WC_Payment_Gateway' ) ) return;
class WC_Gateway_MIB_PayPro extends WC_Payment_Gateway {
// Logging
public static $log_enabled = false;
public static $log = false;
var $merchant_id;
var $merchant_password;
var $test_mode;
var $plugin_url;
var $timeout;
var $checkout_url;
var $api_url;
var $timeout_in_days;
public function __construct(){
global $woocommerce;
$this -> plugin_url = WP_PLUGIN_URL . DIRECTORY_SEPARATOR . 'woocommerce-paypro-payment';
$this->id = 'mibwoo_pp';
$this->has_fields = false;
$this->checkout_url = 'https://marketplace.paypro.com.pk/';
$this->icon = 'https://thebalmainworld.com/wp-content/uploads/2020/10/Credit-Card-Icons-copy-1.png';
$this->method_title = 'Paypro';
$this->method_description = 'Pay via Debit/Credit card.';
$this->title = "Paypro";
$this->description = "Pay via Debit/Credit card.";
$this->merchant_id = $this->get_option( 'merchant_id' );
$this->merchant_password = trim($this->get_option( 'merchant_password' ));
$this->merchant_secret = $this->get_option( 'merchant_secret' );
$this->test_mode = $this->get_option('test_mode');
$this->timeout_in_days = $this->get_option('timeout_in_days');
$this->debug = $this->get_option('debug');
$this->pay_method = "Paypro";
if($this->timeout_in_days==='yes'){
$this->timeout = trim($this->get_option( 'merchant_timeout_days' ));
}
else{
$this->timeout = trim($this->get_option( 'merchant_timeout_minutes' ));
}
if($this->test_mode==='yes'){
$this->api_url = 'https://demoapi.paypro.com.pk';
}
else{
$this->api_url = 'https://api.paypro.com.pk';
}
$this->init_form_fields();
$this->init_settings();
self::$log_enabled = $this->debug;
// Save options
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
// Payment listener/API hook
add_action( 'woocommerce_api_wc_gateway_mib_paypro', array( $this, 'paypro_response' ) );
}
function init_form_fields(){
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Yes', 'woocommerce' ),
'default' => 'yes'
),
'merchant_id' => array(
'title' => __( 'Merchant Username', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This Merchant Username Provided by PayPro', 'woocommerce' ),
'default' => '',
'desc_tip' => true,
),
'test_mode' => array(
'title' => __( 'Enable Test Mode', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Yes', 'woocommerce' ),
'default' => 'yes'
),
'merchant_password' => array(
'title' => __( 'Merchant Password', 'woocommerce' ),
'type' => 'password',
'description' => __( 'Merchant Password Provided by PayPro', 'woocommerce' ),
'default' => __( '', 'woocommerce' ),
'desc_tip' => true,
),
'merchant_secret' => array(
'title' => __( 'Secret Key', 'woocommerce' ),
'type' => 'password',
'description' => __( 'Any Secret Key Or Word with No Spaces', 'woocommerce' ),
'default' => __( rand(), 'woocommerce' ),
'desc_tip' => true,
),
'merchant_timeout_minutes' => array(
'title' => __( 'Timeout (In Minutes)', 'woocommerce' ),
'type' => 'number',
'description' => __( 'Timeout Before order expires it can be between 5 to 30 minutes', 'woocommerce' ),
'default' => __( 5, 'woocommerce' ),
'desc_tip' => true,
'custom_attributes' => array(
'min' => 5,
'max' => 30
)
),
'timeout_in_days' => array(
'title' => __( 'Enable Timeout in days', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Yes', 'woocommerce' ),
'default' => 'no'
),
'merchant_timeout_days' => array(
'title' => __( 'Timeout (In Days)', 'woocommerce' ),
'type' => 'number',
'description' => __( 'Minimum 1 day Max 3 Days. Remember, It works as due date you\'ve selected 1 day the expiration date of the PayPro id will be set as the day after today.', 'woocommerce' ),
'default' => __( 1, 'woocommerce' ),
'desc_tip' => true,
'custom_attributes' => array(
'min' => 1,
'max' => 3
)
),
'debug' => array(
'title' => __( 'Debug Log', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable logging', 'woocommerce' ),
'default' => 'no',
'description' => sprintf( __( 'Debug Information <em>%s</em>', 'woocommerce' ), wc_get_log_file_path( 'paypro' ) )
),
);
}
/**
* Logging method
* #param string $message
*/
public static function log( $message ) {
if ( self::$log_enabled ) {
if ( empty( self::$log ) ) {
self::$log = new WC_Logger();
}
$message = is_array($message) ? json_encode($message) : $message;
self::$log->add( 'paypro', $message );
}
}
/**
* Process the payment and return the result
*
* #access public
* #param int $order_id
* #return array
*/
function process_payment( $order_id ) {
$order = new WC_Order( $order_id );
$paypro_args = $this->get_paypro_args( $order );
$paypro_args = http_build_query( $paypro_args, '', '&' );
$this->log("========== Payment Processing Started: args =========");
$this->log($paypro_args);
//if demo is enabled
$checkout_url = $this->checkout_url;;
return array(
'result' => 'success',
// 'redirect' => 'http://localhost:8000/secureform?'.$paypro_args
'redirect' => 'https://marketplace.paypro.com.pk/secureform?'.$paypro_args
);
}
/**
* Get PayPro Args for passing to PP
*
* #access public
* #param mixed $order
* #return array
*/
function get_paypro_args( $order ) {
global $woocommerce;
$order_id = $order->get_id();
//Encrypting the username and password
$token1 = $this->merchant_id;
$token2 = $this->merchant_password;
$cipher_method = 'aes-128-ctr';
$secret_word = md5($this->merchant_secret);
$enc_key = openssl_digest($secret_word.date('d/m/y'), 'SHA256', TRUE);
$enc_iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher_method));
$crypted_token1 = openssl_encrypt($token1, $cipher_method, $enc_key, 0, $enc_iv) . "::" . bin2hex($enc_iv);
$crypted_token2 = openssl_encrypt($token2, $cipher_method, $enc_key, 0, $enc_iv) . "::" . bin2hex($enc_iv);
unset($token, $cipher_method, $enc_key, $enc_iv);
// PayPro Args
$paypro_args = array(
'mid' => $crypted_token1,
'mpw' => $crypted_token2,
'secret_public' => base64_encode($this->merchant_secret),
'is_encrypted' => 1,
'mode' => $this->test_mode,
'timeout_in_days' => $this->timeout_in_days,
'merchant_order_id' => $order_id,
'merchant_name' => get_bloginfo( 'name' ),
'request_is_valid' => 'true',
'request_from' => 'woocommerce',
// Billing Address info
'first_name' => $order->get_billing_first_name(),
'last_name' => $order->get_billing_last_name(),
'street_address' => $order->get_billing_address_1(),
'street_address2' => $order->get_billing_address_2(),
'city' => $order->get_billing_city(),
'state' => $order->get_billing_state(),
'zip' => $order->get_billing_postcode(),
'country' => $order->get_billing_country(),
'email' => $order->get_billing_email(),
'phone' => $order->get_billing_phone(),
);
if (!function_exists('is_plugin_active')) {
include_once(ABSPATH . 'wp-admin/includes/plugin.php');
}
if(is_plugin_active( 'custom-order-numbers-for-woocommerce/custom-order-numbers-for-woocommerce.php' )){
$paypro_args['paypro_order_id'] = time().'-'.get_option( 'alg_wc_custom_order_numbers_counter', 1 );
}
else{
$paypro_args['paypro_order_id'] = time().'-'.$order_id;
}
// Shipping
if ($order->needs_shipping_address()) {
$paypro_args['ship_name'] = $order->get_shipping_first_name().' '.$order->get_shipping_last_name();
$paypro_args['company'] = $order->get_shipping_company();
$paypro_args['ship_street_address'] = $order->get_shipping_address_1();
$paypro_args['ship_street_address2'] = $order->get_shipping_address_2();
$paypro_args['ship_city'] = $order->get_shipping_city();
$paypro_args['ship_state'] = $order->get_shipping_state();
$paypro_args['ship_zip'] = $order->get_shipping_postcode();
$paypro_args['ship_country'] = $order->get_shipping_country();
}
$paypro_args['x_receipt_link_url'] = $this->get_return_url( $order );
$paypro_args['request_site_url'] = get_site_url();
$paypro_args['request_site_checkout_url'] = wc_get_checkout_url();
$paypro_args['return_url'] = $order->get_cancel_order_url();
$paypro_args['issueDate'] = date('d/m/Y');
$paypro_args['cartTotal'] = $order->get_total();
$paypro_args['store_currency'] = get_woocommerce_currency();
$paypro_args['store_currency_symbol'] = get_woocommerce_currency_symbol();
//Getting Cart Items
$billDetails= array();
$flag = 0;
foreach ($order->get_items() as $item => $values){
// Get the product name
$product_name = $values['name'];
// Get the item quantity
$item_quantity = $order->get_item_meta($item, '_qty', true);
// Get the item line total
$item_total = $order->get_item_meta($item, '_line_total', true);
$price = $item_total/$item_quantity;
$billDetails[$flag]['LineItem'] = esc_html($product_name);
$billDetails[$flag]['Quantity'] = $item_quantity;
$billDetails[$flag]['UnitPrice'] = $price;
$billDetails[$flag++]['SubTotal'] = $item_total;
}
$paypro_args['cartItemList'] = urlencode(json_encode($billDetails));
////
//setting payment method
if ($this->pay_method)
$paypro_args['pay_method'] = $this->pay_method;
//if test_mode is enabled
if ($this -> test_mode == 'yes'){
$paypro_args['test_mode'] = 'Y';
}
//if timeout_in_days is enabled
if ($this -> timeout_in_days == 'yes'){
$paypro_args['timeout'] = $this->timeout;
}
else{
$paypro_args['timeout'] = $this->timeout*60;
}
$paypro_args = apply_filters( 'woocommerce_paypro_args', $paypro_args );
return $paypro_args;
}
/**
* this function is return product object for two
* different version of WC
*/
function get_product_object(){
return $product;
}
/**
* Check for PayPro IPN Response
*
* #access public
* #return void
*/
function paypro_response() {
global $woocommerce;
// woocommerce_log($_REQUEST);
$this->log(__("== INS Response Received == ", "PayPro") );
$this->log( $_REQUEST );
$wc_order_id = '';
if( !isset($_REQUEST['merchant_order_id']) ) {
if( !isset($_REQUEST['vendor_order_id']) ) {
$this->log( '===== NO ORDER NUMBER FOUND =====' );
exit;
} else {
$wc_order_id = $_REQUEST['vendor_order_id'];
}
} else {
$wc_order_id = $_REQUEST['merchant_order_id'];
}
$this->log(" ==== ORDER -> {$wc_order_id} ====");
// echo $wc_order_id;
$wc_order_id = apply_filters('woocommerce_order_no_received', $wc_order_id, $_REQUEST);
$this->log( "Order Received ==> {$wc_order_id}" );
// exit;
$wc_order = new WC_Order( absint( $wc_order_id ) );
$this->log("Order ID {$wc_order_id}");
$this->log("WC API ==> ".$_GET['wc-api']);
// If redirect after payment
if( isset($_GET['key']) && (isset($_GET['wc-api']) && strtolower($_GET['wc-api']) == 'wc_gateway_mib_paypro') ) {
$this->verify_order_by_hash($wc_order_id);
exit;
}
$message_type = isset($_REQUEST['message_type']) ? $_REQUEST['message_type'] : '';
$sale_id = isset($_REQUEST['sale_id']) ? $_REQUEST['sale_id'] : '';
$invoice_id = isset($_REQUEST['invoice_id']) ? $_REQUEST['invoice_id'] : '';
$fraud_status = isset($_REQUEST['fraud_status']) ? $_REQUEST['fraud_status'] : '';
$this->log( "Message Type/Fraud Status: {$message_type}/{$fraud_status}" );
switch( $message_type ) {
case 'ORDER_CREATED':
$wc_order->add_order_note( sprintf(__('ORDER_CREATED with Sale ID: %d', 'woocommerce'), $sale_id) );
$this->log(sprintf(__('ORDER_CREATED with Sale ID: %d', 'woocommerce'), $sale_id));
break;
case 'FRAUD_STATUS_CHANGED':
if( $fraud_status == 'pass' ) {
// Mark order complete
$wc_order->payment_complete();
$wc_order->add_order_note( sprintf(__('Payment Status Clear with Invoice ID: %d', 'woocommerce'), $invoice_id) );
$this->log(sprintf(__('Payment Status Clear with Invoice ID: %d', 'woocommerce'), $invoice_id));
add_action('woocommerce_order_completed', $order, $sale_id, $invoice_id);
} elseif( $fraud_status == 'fail' ) {
$wc_order->update_status('failed');
$wc_order->add_order_note( __("Payment Declined", 'woocommerce') );
$this->log( __("Payment Declined", 'woocommerce') );
}
break;
}
exit;
}
function verify_order_by_hash($wc_order_id) {
global $woocommerce;
#ob_clean();
$paypro_id = $_REQUEST['paypro_id'];
$tpaycode = $_REQUEST['tpaycode'];
$order_id = $_REQUEST['merchant_order_id'];
$wc_order = wc_get_order( $wc_order_id );
// $order_total = isset($_REQUEST['total']) ? $_REQUEST['total'] : '';
$order_total = $wc_order->get_total();
$compare_string = $this->merchant_id . $paypro_id . $order_total;
$compare_hash1 = strtoupper(md5($compare_string));
$this->log("Compare String ===>" .$compare_string);
$compare_hash2 = $_REQUEST['key'];
if ($compare_hash1 != $compare_hash2) {
$this->log("Hash_1 ==> {$compare_hash1}");
$this->log("Hash_2 ==> {$compare_hash2}");
wp_die( "PayPro Hash Mismatch... check your secret word." );
} else {
//Curl Request
$url = $this->api_url.'/cpay/gos?userName=' . $this->merchant_id . '&password=' . $this->merchant_password . '&cpayId=' . $tpaycode;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
// Submit the GET request
$result = curl_exec($ch);
if (curl_errno($ch)) //catch if curl error exists and show it
echo 'Curl error: ' . curl_error($ch);
else {
//Check if the order ID passed is the same or fake
$res = json_decode($result, true);
$returnedOrderID = explode('-',$res[1]['OrderNumber']);
if ($returnedOrderID[1]===$order_id) {
if (strtoupper($res[1]['OrderStatus']) == "PAID") {
$wc_order->add_order_note( sprintf(__('Payment completed via PayPro Order Number %d', 'paypro'), $tpaycode) );
// Mark order complete
$wc_order->payment_complete();
// Empty cart and clear session
$woocommerce->cart->empty_cart();
$order_redirect = add_query_arg('paypro','processed', $this->get_return_url( $wc_order ));
// Close cURL session handle
curl_close($ch);
wp_redirect( $order_redirect );
exit;
} elseif (strtoupper($res[1]['OrderStatus']) == "BLOCKED") {
$wc_order->add_order_note( sprintf(__('Error processing the payment of Order Number %d', 'paypro'), $tpaycode) );
$order_redirect = add_query_arg('paypro','canceled', $wc_order->get_cancel_order_url());
// Close cURL session handle
curl_close($ch);
wp_redirect( $order_redirect );
exit;
}
elseif (strtoupper($res[1]['OrderStatus']) == "UNPAID") {
$wc_order->add_order_note( sprintf(__('Error processing the payment of Order Number %d', 'paypro'), $tpaycode) );
$order_redirect = add_query_arg('paypro','pending', $wc_order->get_cancel_order_url());
// Close cURL session handle
curl_close($ch);
wp_redirect( $order_redirect );
exit;
}
}
}
}
}
function get_price($price){
$price = wc_format_decimal($price, 2);
return apply_filters('mib_get_price', $price);
}
}
}
function add_mib_payment_gateway( $methods ) {
$methods[] = 'WC_Gateway_MIB_PayPro';
return $methods;
}
add_filter( 'woocommerce_payment_gateways', 'add_mib_payment_gateway' );
function payproco_log( $log ) {
if ( true === WP_DEBUG ) {
if ( is_array( $log ) || is_object( $log ) ) {
$resp = error_log( print_r( $log, true ), 3, plugin_dir_path(__FILE__).'payproco.log' );
} else {
$resp = error_log( $log, 3, plugin_dir_path(__FILE__).'payproco.log' );
}
var_dump($resp);
}
}

How to add javascript file to custom form and pass the data to the js file

I'm working with Drupal 8 and I have custom ajax form it works fine when I test it using [Ajax htmlCommands]. but now I want to send the data to the javascript file to show it in a div and do some other things.
what I did is create js file under themes/custom/myform/assets/js/simple-form.js but nothing shows in the console when the element clicked.
Drupal.behaviors.simple_form = function(context) {
$('.btn-primary').click(function() {
console.log('clicked');
});
};
and add it to themes/custom/myform/myform.libraries.yml
simple-form-js:
js:
assets/js/simple-form.js: {}
my custom form
modules/custom/my_module/src/Form/SimpleForm.php
<?php
namespace Drupal\my_module\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
/**
* Our simple form class.
*/
class SimpleForm extends FormBase {
/**
* {#inheritdoc}
*/
public function getFormId() {
return 'my_module';
}
/**
* {#inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
//$form = parent::buildForm($form, $form_state);
$form['#theme'] = 'simple_form';
$form['massage'] = [
'#type' => 'markup',
'#markup' => '<div class="result_message"></div>',
];
$form['number_1'] = [
'#type' => 'textfield',
'#title' => $this->t('number 1'),
'#attributes' => ['class' => ['form-control ml-sm-2 w-100']],
'#required' => TRUE,
];
$form['number_2'] = [
'#type' => 'textfield',
'#title' => $this->t('number one'),
'#attributes' => ['class' => ['form-control ml-sm-2 w-100']],
'#required' => TRUE,
];
$form['actions'] = [
'#type' => 'button',
'#value' => $this->t('Calculate'),
'#attributes' => ['onclick'=>'return false;','class' => ['mt-3 btn btn-primary btn-me2']],
'#attached' => [
'library'=>[
'simple-form',
]
],
'#ajax' => [
'callback' => '::setMessage',
]
];
return $form;
}
public function setMessage(array &$form, FormStateInterface $form_state) {
$response = new AjaxResponse();
$letter = $form_state->getValue('number_1');
$code = $form_state->getValue('number_2');
$fetchUrl = 'http://example.com/api';
$responseAPI = \Drupal::httpClient()->get($fetchUrl, array('headers' => array('Accept' => 'text/plain')));
$data = (string) $responseAPI->getBody();
//drupal_set_message($data);
$response->addCommand(
new HtmlCommand(
'.result_message',
'<div class="my_top_message">' . $this->t('The result is #result', ['#result' => ($data)])
)
);
return $response;
}
public function validateForm(array &$form, FormStateInterface $form_state) {
}
/**
* {#inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
}
}
and themes/custom/myform/myform.theme
if($route_namee=="my_module.simple_form"){
$variables['#attached']['library'][] = 'myform/simple-form-css';
$variables['#attached']['library'][] = 'myform/simple-form-js';
}
You can use HOOK_form_alter to attach libraries
*/**
* Implements hook_form_alter().
*/
function my_module_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
if($form_id == "my_module") {
$form['#attached']['library'][] = 'myform/simple-form-js';
$form['#attached']['library'][] = 'myform/simple-form-css';
$form['#attached']['drupalSettings']['my_module']['variable'] = 'Your Custom values to JS';
return $form;
}
}
What you are looking for is a ajaxCommand and not a behavior.
Create a custom ajaxCommand and pass your variables to it when creating the ajax response.
Here is help https://weknowinc.com/blog/creating-custom-ajax-command-drupal-8
And get Inspired with how Drupal Cores InvokeCommand is working
To attach library you dont need theme or module files for example :
$form['#attached']['library'][] = 'core/drupal.dialog.ajax';
is enough to attach a library in your case you should call your js file like :
$form['#attached']['library'][] = 'simple-form-js';
Then files under your library will loaded with your form.

wordpress custom query - orderby title will not work

I am having a problem getting a custom query to alphabetize. It keeps defaulting to displaying in the order of the date it was posted. Below is my php function.
function json_info2() {
// The $_REQUEST contains all the data sent via ajax
if ( isset($_REQUEST) ) {
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
// get values for all three drop-down menus
$status = $_REQUEST['status'];
$industry = $_REQUEST['services'];
$state = $_REQUEST['state'];
// array of values for each of the three drop-downs
$statusAll = array('complete','incomplete');
$industryAll = array('mining','textile','machinery');
$statesAll = array('SC','TX','WA');
// set $statusArray dependent on whether or not "all" is selected in the dropdown menu
if($status == "all") {
$statusArray = array( 'key' => 'status', 'value' => $statusAll, 'compare' => 'IN');
} else {
$statusArray = array( 'key' => 'status', 'value' => $status, 'compare' => '=');
}
if($industry == "all") {
$industryArray = array( 'key' => 'industry', 'value' => $industryAll, 'compare' => 'IN');
} else {
$industryArray = array( 'key' => 'industry', 'value' => $industry, 'compare' => '=');
}
if($state == "all") {
$stateArray = array( 'key' => 'state', 'value' => $statesAll, 'compare' => 'IN');
} else {
$stateArray = array( 'key' => 'state', 'value' => $state, 'compare' => '=');
}
$pages = array(
'post_type' => 'page',
'orderby' => 'title',
'order' => 'ASC',
'paged' => $paged,
'posts_per_page' => 5,
'meta_query' => array(
'relation' => 'AND',
$statusArray,
$industryArray,
$stateArray,
array(
'key' => '_wp_page_template',
'value' => 'template-individual-project.php',
'compare' => '='
)
)
);
// query results by page template
$my_query = new WP_Query($pages);
if($my_query->have_posts()) :
while($my_query->have_posts()) :
$my_query->the_post();
<li>
<?php the_title(); ?>
</li>
<?php
endwhile;endif;
wp_reset_query();
} // end of isset
?>
<?php
die();
}
add_action( 'wp_ajax_json_info2', 'json_info2' );
add_action( 'wp_ajax_nopriv_json_info2', 'json_info2' );
?>
This above function is called by the ajax function that follows:
function do_ajax() {
// Get values from all three dropdown menus
var state = $('#states').val();
var markets = $('#markets').val();
var services = $('#services').val();
$.ajax({
url: ajaxurl,
data: {
'action' : 'json_info2',
'state' : state,
'status' : markets,
'services' : services
},
success:function(moredata) {
// This outputs the result of the ajax request
$('#project-list').html( moredata );
$('#project-list').fadeIn();
}/*,
error: function(errorThrown){
var errorMsg = "No results match your criteria";
$('#project-list').html(errorMsg);
}*/
}); // end of ajax call
} // end of function do_ajax
Is there something simple that I'm missing here? I have a similar custom query on the page when it loads (although that initial load query doesn't have the select menu values as args), and they display in alphabetical order just fine. It's only after the ajax call to filter the list that they are no longer in order.
I have found the issue after googling the problem for quite a while. I read that some of the people who were having this problem found that their theme was using a plugin called Post Types Order. It overrides the ability to set the orderby arg.
I looked at the plugins, and sure enough, Post Types Order was there. Everything I read said that the problem could be solved by unchecking "auto sort" in the settings for the plugin. However, I did that, and orderby still didn't work. I had to completely deactivate the plugin to get orderby title to work.

angularjs+cakephp black-holed request

I have created in the UsersController a method to add new users in database. In the cakephp ctp views files everything is okay, as my request is not black-holed. I am using post for this. But when I move the view to angularjs the request is black-holed. I don't get it. Can some one pls help me.
Here is the UsersController.php code,the function called add is the one doing the stuff:
<?php
class UsersController extends AppController {
public $components = array(
'RequestHandler',
'Security',
'Session',
'Auth'
);
public function login() {
if ($this->Session->read('Auth.User')) {
$this->set(array(
'message' => array(
'text' => __('You are logged in!'),
'type' => 'error'
),
'_serialize' => array('message')
));
}
if ($this->request->is('post')) {
if(!empty($this->request->data)){
$userDetails = $this->User->find('first', array(
'conditions' => array(
'User.username' => $this->request->data['username'],
'User.password' => $this->request->data['password']
)));
debug($userDetails);
debug($this->Auth->login());
}
if ($this->Auth->login()) {
$this->set(array(
'user' => $this->Session->read('Auth.User'),
'_serialize' => array('user')
));
} else {
$this->set(array(
'message' => array(
'text' => __('Invalid username or password, try again'),
'type' => 'error'
),
'_serialize' => array('message')
));
$this->response->statusCode(401);
}
}
}
public function logout() {
if ($this->Auth->logout()) {
$this->set(array(
'message' => array(
'text' => __('Logout successfully'),
'type' => 'info'
),
'_serialize' => array('message')
));
}
}
public function add(){
if($this->request->is('post')){
if(!empty($this->request->data)){
$password = $this->request->data['User']['password'];
$username = $this->request->data['User']['username'];
//$password = Security::hash($this->request->data['User']['password'], 'sha1', true);
$password = Security::hash($password.$username, 'sha1', true);
debug($password);
}
}
//$this->set(array('message',array('error' => __("No data sent")), '_serialize' => array('message')));
}
public function index() {
$this -> user = $this -> Auth -> user();
if ($this -> user) {
$this -> set('users', $this -> User -> find('all'));
$this -> set('_serialize', array('users'));
}
else {
$this -> set('error', 'user not logged in');
$this -> set('_serialize', array('error'));
}
}
public function user($id = null) {
$this -> layout = null;
if (!$id) {
throw new NotFoundException(__('Invalid user'));
}
$user = $this -> User -> findById($id);
if (!$user) {
throw new NotFoundException(__('Invalid user'));
}
$this -> set('user', $user);
}
}
?>
And this is the angular controller:
angular.module('addUser.controllers', []).controller('addUserCtrl', function($scope, $http) {
$scope.register = function() {
data = {'User':{
'username' : $scope.username,
'password' : $scope.password
}};
if(data.User.username != undefined && data.User.password != undefined){
$http.post('API/users/add', data).success(function(data) {
$scope.users = data.users;
console.log(data);
});
}else{
console.log('can\'t login');
}
/**/
};
});
PS: I am a beginner with cakephp.
Thanks a lot and happy coding ;)
I found the solution to the problem, as I went through the entire cakephp book and got this solution, don't know if it is the right one, but for me works okay.
This is the reference link and for me it was like the lines are in the book:
public function beforeFilter() {
$this -> Security -> blackHoleCallback = 'blackhole';
}
public function blackhole($type) {
return $type;// don't know if it is good or bad practice like this feel free to comment
}

Autocompleting a form in PHP/Javascript

I have been trying to make an autocomplete script for the whole day but I can't seem to figure it out.
<form method="POST">
<input type="number" id="firstfield">
<input type="text" id="text_first">
<input type="text" id="text_sec">
<input type="text" id="text_third">
</form>
This is my html.
what I am trying to do is to use ajax to autocomplete the first field
like this:
and when there are 9 numbers in the first input it fills the other inputs as well with the correct linked data
the script on the ajax.php sends a mysqli_query to the server and asks for all the
data(table: fields || rows: number, first, sec, third)
https://github.com/ivaynberg/select2
PHP Integration Example:
<?php
/* add your db connector in bootstrap.php */
require 'bootstrap.php';
/*
$('#categories').select2({
placeholder: 'Search for a category',
ajax: {
url: "/ajax/select2_sample.php",
dataType: 'json',
quietMillis: 100,
data: function (term, page) {
return {
term: term, //search term
page_limit: 10 // page size
};
},
results: function (data, page) {
return { results: data.results };
}
},
initSelection: function(element, callback) {
return $.getJSON("/ajax/select2_sample.php?id=" + (element.val()), null, function(data) {
return callback(data);
});
}
});
*/
$row = array();
$return_arr = array();
$row_array = array();
if((isset($_GET['term']) && strlen($_GET['term']) > 0) || (isset($_GET['id']) && is_numeric($_GET['id'])))
{
if(isset($_GET['term']))
{
$getVar = $db->real_escape_string($_GET['term']);
$whereClause = " label LIKE '%" . $getVar ."%' ";
}
elseif(isset($_GET['id']))
{
$whereClause = " categoryId = $getVar ";
}
/* limit with page_limit get */
$limit = intval($_GET['page_limit']);
$sql = "SELECT id, text FROM mytable WHERE $whereClause ORDER BY text LIMIT $limit";
/** #var $result MySQLi_result */
$result = $db->query($sql);
if($result->num_rows > 0)
{
while($row = $result->fetch_array())
{
$row_array['id'] = $row['id'];
$row_array['text'] = utf8_encode($row['text']);
array_push($return_arr,$row_array);
}
}
}
else
{
$row_array['id'] = 0;
$row_array['text'] = utf8_encode('Start Typing....');
array_push($return_arr,$row_array);
}
$ret = array();
/* this is the return for a single result needed by select2 for initSelection */
if(isset($_GET['id']))
{
$ret = $row_array;
}
/* this is the return for a multiple results needed by select2
* Your results in select2 options needs to be data.result
*/
else
{
$ret['results'] = $return_arr;
}
echo json_encode($ret);
$db->close();
Legacy Version:
In my example i'm using an old Yii project, but you can easily edit it to your demands.
The request encodes in JSON. (You don't need yii for this tho)
public function actionSearchUser($query) {
$this->check();
if ($query === '' || strlen($query) < 3) {
echo CJSON::encode(array('id' => -1));
} else {
$users = User::model()->findAll(array('order' => 'userID',
'condition' => 'username LIKE :username',
'limit' => '5',
'params' => array(':username' => $query . '%')
));
$data = array();
foreach ($users as $user) {
$data[] = array(
'id' => $user->userID,
'text' => $user->username,
);
}
echo CJSON::encode($data);
}
Yii::app()->end();
}
Using this in the View:
$this->widget('ext.ESelect2.ESelect2', array(
'name' => 'userID',
'options' => array(
'minimumInputLength' => '3',
'width' => '348px',
'placeholder' => 'Select Person',
'ajax' => array(
'url' => Yii::app()->controller->createUrl('API/searchUser'),
'dataType' => 'json',
'data' => 'js:function(term, page) { return {q: term }; }',
'results' => 'js:function(data) { return {results: data}; }',
),
),
));
The following Script is taken from the official documentation, may be easier to adopt to:
$("#e6").select2({
placeholder: {title: "Search for a movie", id: ""},
minimumInputLength: 1,
ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
url: "http://api.rottentomatoes.com/api/public/v1.0/movies.json",
dataType: 'jsonp',
data: function (term, page) {
return {
q: term, // search term
page_limit: 10,
apikey: "ju6z9mjyajq2djue3gbvv26t" // please do not use so this example keeps working
};
},
results: function (data, page) { // parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to alter remote JSON data
return {results: data.movies};
}
},
formatResult: movieFormatResult, // omitted for brevity, see the source of this page
formatSelection: movieFormatSelection // omitted for brevity, see the source of this page
});
This may be found here: http://ivaynberg.github.io/select2/select-2.1.html
You can optain a copy of select2 on the github repository above.

Categories

Resources