Gravityform - update ACF Repeater subfield mixed with dynamic pre-populate fields - dynamic

I have an ACF repeater field that create Courses with a certain amount of place available. This repeater is on each single custom-post-type courses.
In the other hand, I have a Gravityform that have a radio field who is auto-populated with those ACF repeater:
add_filter( 'gform_pre_render_3', 'populate_posts' );
add_filter( 'gform_pre_validation_3', 'populate_posts' );
add_filter( 'gform_pre_submission_filter_3', 'populate_posts' );
add_filter( 'gform_admin_pre_render_3', 'populate_posts' );
function populate_posts( $form ) {
foreach ( $form['fields'] as &$field ) {
// Vient check tous les fields du formulaire
if ( $field->type != 'radio' || strpos( $field->cssClass, 'populate-posts' ) === false ) {
// Choisit seulement les fields de type [radio] qui ont la class [populate-posts]
continue;
}
$date_type = get_field( 'date_type' );
$range_dates = get_field( 'date_range_repeater' );
$sinlge_dates = get_field( 'sinlge_dates_repeater' );
$choices = array();
if( $date_type === 'date_type_range' ){
foreach ( $range_dates as $range_date ) {
$dateformatstring = "j F Y";
$dateclean_start = strtotime( $range_date['date_starting'] );
$final_date_start = date_i18n($dateformatstring, $dateclean_start);
$dateclean_end = strtotime( $range_date['date_ending'] );
$final_date_end = date_i18n($dateformatstring, $dateclean_end);
$choices[] = array(
'text' => 'Du '.$final_date_start.' au '.$final_date_end.'<br />'.$range_date['availability'].' places disponibles',
'value' => 'Du '.$final_date_start.' au '.$final_date_end
);
}
}elseif( $date_type === 'date_type_single' ){
foreach ( $sinlge_dates as $sinlge_date ) {
$dateformatstring = "j F Y";
$dateclean_start = strtotime( $sinlge_date['date_starting'] );
$final_date_start = date_i18n($dateformatstring, $dateclean_start);
$dateclean_end = strtotime( $sinlge_date['date_ending'] );
$final_date_end = date_i18n($dateformatstring, $dateclean_end);
$choices[] = array(
'text' => 'Du '.$final_date_start.' au '.$final_date_end.'<br />'.$sinlge_date['availability'].' places disponibles',
'value' => 'Du '.$final_date_start.' au '.$final_date_end
);
}
}else{}
// update 'Select a Post' to whatever you'd like the instructive option to be
$field->placeholder = 'Select a Post';
$field->choices = $choices;
}
return $form;
}
I want that after each submission the available place number decrease from 1. I have figured out how to manage this with this ACF function:
https://www.advancedcustomfields.com/resources/update_sub_field/
This is my code for this:
add_action( 'gform_after_submission', 'set_post_content', 10, 2 );
function set_post_content( $entry, $form ) {
//$radio_value = rgar( $entry, '11' );
$repeater = 'date_range_repeater';
$acf_repeater = get_field('date_range_repeater' ); // get all the rows
$row = 0;
$specific_row = $acf_repeater[$row];
$sub_field = 'availability';
$current_availability = $specific_row['availability'];
$availability_new = --$current_availability;
update_sub_field( array($repeater, ++$row, $sub_field), $availability_new );
//echo $radio_value;
}
The thing is I have to select manually which row must be used to update de subfield. How can I manage to detect in which ACF repeater row is my submitted value ?
Thanks !

Maybe you can add some hidden fields in your GF and populate them in your function populate_posts( $form ){}like that you should have accessible directly in your after_submit function.

Related

Display In stock available variations in WooCommerce single product

I have variable products with many variations where only a few items are actually In Stock while the majority of other variations are ''available on backorder''
I would like to be able to display a quick list of ONLY the items that are IN STOCK in the short product description of each product page so the customer doesn't have to try all variations one-by-one to finally find out which ones are in stock.
add_filter( 'woocommerce_short_description', 'display_in_stock_variations_to_short_description' );
function display_in_stock_variations_to_short_description( $excerpt ){
global $product;
if ( ! is_product() || empty($product) || ! is_a( $product, 'WC_Product' ) )
return $excerpt;
if( $product->is_type('variable') ) {
// Loop through visible children
foreach( $product->get_children() as $variation_id ) {
$variation = wc_get_product( $variation_id );
// Hide out of stock variations if 'Hide out of stock items from the catalog' is checked.
if ( ! $variation || ! $variation->exists() || ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) && ! $variation->is_in_stock() ) ) {
continue;
}
// Filter 'woocommerce_hide_invisible_variations' to optionally hide invisible variations (disabled variations and variations with empty price).
if ( apply_filters( 'woocommerce_hide_invisible_variations', true, $product->get_id(), $variation ) && ! $variation->variation_is_visible() ) {
continue;
}
$max_qty = 0 < $variation->get_max_purchase_quantity() ? $variation->get_max_purchase_quantity() : $variation->get_stock_quantity();
$term_names = []; // Initializing
// Loop through variation attributes for current varation
foreach ( $variation->get_variation_attributes() as $attribute => $term_slug ) {
// Set the term name in an array
$term_names[] = ucfirst( str_replace( ['-', '_'],[' ', ' '], $term_slug ) );
}
if ( $max_qty > 0 ) {
$excerpt .= sprintf( '<br/>%s: %s %s',
implode(', ', $term_names),
$max_qty,
__('in stock', 'woocommerce')
);
}
}
}
return $excerpt;
}
// Avoid additional content from product short description to be displayed in variation description
add_filter( 'woocommerce_available_variation', 'filter_wc_available_variation_desscription', 10, 3);
function filter_wc_available_variation_desscription( $data, $product, $variation ) {
$max_qty = 0 < $variation->get_max_purchase_quantity() ? $variation->get_max_purchase_quantity() : $variation->get_stock_quantity();
if( $max_qty > 0 )
$data['variation_description'] = get_post_meta( $variation->get_id(), '_variation_description', true );
return $data;
}
This code displays an inventory, but my website language is Persian and the names of the variables are defined in Persian, and this line does not display the variable name code correctly.
How can I fix his language?
And I want to translate the word instock into موجود
And the next point is that I want a button to be displayed on the page first with the title Show product inventory and when the method clicks, the customer will open a pop-up and display the inventory.
Here is the soultion with Persian language:
change
// Loop through variation attributes for current varation
foreach ( $variation->get_variation_attributes() as $attribute => $term_slug ) {
// Set the term name in an array
$term_names[] = ucfirst( str_replace( ['-', '_'],[' ', ' '], $term_slug ) );
}
if ( $max_qty > 0 ) {
$excerpt .= sprintf( '<br/>%s: %s %s',
implode(', ', $term_names),
$max_qty,
__('in stock', 'woocommerce')
);
}
to
// Loop through variation attributes for current varation
foreach ( $variation->get_variation_attributes() as $attribute => $term_name ) {
// Set the term name in an array
$taxonomy = str_replace('attribute_', '', $attribute);
$attribute_name = wc_attribute_label($taxonomy);
$term_name = get_term_by( 'slug', $term_name, $taxonomy)->name;
$term_names[] = $term_name;
}
if ( $max_qty > 0 ) {
$excerpt .= sprintf( '<br/>%s: %s %s',
implode(', ', $term_names),
$max_qty,
__('موجود')
);
}

What I did wrong with Db::getInstance()->insert('product', $dimension)); not inserting data to database?

I am developing a module that would save a custom field from product admin.. but my code is not inserting data into database.. below is my code.
public function hookActionProductUpdate($params)
{
if(Tools::isSubmit('submitDimension'))
{
$name = Tools::getValue('name');
$length = Tools::getValue('custom_length');
$width = Tools::getValue('custom_width');
if(empty($name) || !Validate::isGenericName($name))
$this->errors[] = $this->module->l('Invalid name');
if(empty($length) || !Validate::isGenericName($length))
$this->errors[] = $this->module->l('Invalid length');
if(empty($width) || !Validate::isGenericName($width))
$this->errors[] = $this->module->l('Invalid width');
if(!$this->errors)
{
$dimension = array(
'name' => $name,
'custom_length' => $length,
'custom_width' => $width
);
if(!Db::getInstance()->insert('product', $dimension));
$this->errors[] = Tools::displayError('Error while updating database');
}
}
}
Anyone can help me please..
Here is my install function
function install()
{
if (!parent::install() ||
!$this->alterProductTable() ||
!$this->registerHook('extraright') ||
!$this->registerHook('displayAdminProductsExtra') ||
!$this->registerHook('actionProductSave') ||
!$this->registerHook('actionProductUpdate') ||
!$this->registerHook('header')
)
return false;
return true;
}
Here is my alter table function
private function alterProductTable($method = 'add')
{
if($method = 'add')
$sql = '
ALTER TABLE '._DB_PREFIX_.'product
ADD COLUMN `custom_length` decimal(20,6) NOT NULL,
ADD COLUMN `custom_width` decimal(20,6) NOT NULL,
ADD COLUMN `name` VARCHAR(64) NOT NULL';
if(!Db::getInstance()->Execute($sql))
return false;
return true;
}
.. the columns are there..
And here is my display admin hook
public function hookDisplayAdminProductsExtra($params)
{
$name = Db::getInstance()->getValue('SELECT `name` FROM '._DB_PREFIX_.'product WHERE id_product = '.Tools::getValue('id_product'));
$length = Db::getInstance()->getValue('SELECT custom_length FROM '._DB_PREFIX_.'product WHERE id_product = '.(int)Tools::getValue('id_product'));
$width = Db::getInstance()->getValue('SELECT custom_width FROM '._DB_PREFIX_.'product WHERE id_product = '.(int)Tools::getValue('id_product'));
$this->context->smarty->assign(array(
'name' => $name,
'length' => $length,
'width' => $width
));
return $this->display(__FILE__, 'views/templates/hook/adminProductsExtra.tpl');
}
I have been looking at this for 2 days.. and I cant seem to find what I did wrong.. I have gone to prestashop forum but no help so far.. I hope I can get something from good people here. thanks in advance!
Do you check the Prestashop db best practice guide if not than please check first.
This is not the correct way to insert data you also need to mention fields in which you want to insert data particular table.
Best Practices of the Db Class - Prestashop
All is wrong, you are trying to insert data in a table which have many other fields required, and you are trying also to insert data in columns that doesn't exist in that table. The best way to create new products by code is using their object, like this...
$product = new Product()
$product->id_tax_rules_group = 1;
$product->redirect_type = '404';
$product->name = array(
$id_lang => 'Product name in this lang',
$id_lang => 'Product name in this lang',
);
/*
* And so on all the mandatory fields
*/
$product->save();

get table rate shipping data in Woocommerce REST API

I am trying to get all active shipping methods in Woocommerce REST API. How can I achieve this. I am new to woocommerce REST API, Any help is much appreciated.
I want response something like this -
{
"shipping_methods": {
"method_id": "method_title"
}
}
I , finally, come up with the solution. It may help others.
Below is complete code to get all table rate shipping data including shipping zones, shipping methods by zone and rates by zone -
header('Content-type: application/json');
$json_file=file_get_contents('php://input');
$jsonvalue= json_decode($json_file,true);
global $wpdb;
global $woocommerce;
$active_methods = array();
$shipping_methods = $woocommerce->shipping->load_shipping_methods();
//echo "<pre>";print_r($shipping_methods);
foreach ( $shipping_methods as $id => $shipping_method ) {
if ( isset( $shipping_method->enabled ) && 'yes' === $shipping_method->enabled ) {
$data_arr = array( 'title' => $shipping_method->title, 'tax_status' => $shipping_method->tax_status );
if($id=='table_rate'){
$raw_zones = $wpdb->get_results("SELECT zone_id, zone_name, zone_order FROM {$wpdb->prefix}woocommerce_shipping_zones order by zone_order ASC;");
//echo "<pre>";print_r($raw_zones);
$shipping = array();
$shippingarr = array();
foreach ($raw_zones as $raw_zone) {
$zones = new WC_Shipping_Zone($raw_zone->zone_id);
$zone_id = $zones->zone_id;
$zone_name = $zones->zone_name;
$zone_enabled = $zones->zone_enabled;
$zone_type = $zones->zone_type;
$zone_order = $zones->zone_order;
$shipping['zone_id'] = $zone_id;
$shipping['zone_name'] = $zone_name;
$shipping['zone_enabled'] = $zone_enabled;
$shipping['zone_type'] = $zone_type;
$shipping['zone_order'] = $zone_order;
$shipping_methods = $zones->shipping_methods;
foreach($shipping_methods as $shipping_method){
$methodid = $shipping_method["number"];
$raw_rates[$methodid]['rates'] = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}woocommerce_shipping_table_rates WHERE shipping_method_id={$methodid};",ARRAY_A);
}
$shipping['shipping_methods'] = $raw_rates;
$raw_country = $wpdb->get_results("SELECT location_code FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE zone_id={$zone_id};",ARRAY_N);
$shipping['countries'] = $raw_country;
$shippingarr[] = $shipping;
}
$data_arr['shipping_zones'] = $shippingarr;
}
$active_methods[ $id ] = $data_arr;
}
}
if(!empty($shippingarr)){
$result['success']='true';
$result['error']="0";
$result['msg']='Shipping methos found.';
$result['data']=$active_methods;
}else{
$result['success']='true';
$result['error']="0";
$result['msg']='Shipping methos found.';
$result['data']= array();
}
echo json_encode($result); `

get values between two dates in silverstripe

i have added two date fields. i want to retrieve the data between those two table.PaymentDate and ChequePostedDate are two fields. so i need to get the rows between two dates.
simply search content have two date fields. i want to retrieve the rows(data) between those two dates
public function __construct($modelClass, $fields = null, $filters = null) {
$fields = new FieldList(array(
DateField::create('PaymentDate','Payment Date : from')
->setConfig('dateformat', 'yyyy-MM-dd')
->setConfig('showcalendar', true)
->setAttribute('placeholder','YYYY-MM-DD')
->setDescription(sprintf(
_t('FormField.Example', 'e.g. %s', 'Example format'),
Convert::raw2xml(Zend_Date::now()->toString('yyyy-MM-dd'))
)),
DateField::create('ChequePostedDate','cr Date : to')
->setConfig('dateformat', 'yyyy-MM-dd')
->setConfig('showcalendar', true)
->setAttribute('placeholder','YYYY-MM-DD')
->setDescription(sprintf(
_t('FormField.Example', 'e.g. %s', 'Example format'),
Convert::raw2xml(Zend_Date::now()->toString('yyyy-MM-dd'))
)),
));
$filters = array(
'PaymentDate' => new PartialMatchFilter('PaymentDate'),
'ChequePostedDate' => new PartialMatchFilter('ChequePostedDate'),
);
parent::__construct($modelClass, $fields, $filters);
}
public function getQuery($searchParams, $sort = false, $limit = false, $existingQuery = null) {
$dataList = parent::getQuery($searchParams, $sort, $limit, $existingQuery);
$params = is_object($searchParams) ? $searchParams->getVars() : $searchParams;
$query = $dataList->dataQuery();
if(!is_object($searchParams)) {
if (isset($params['PaymentDate'])&& $params['ChequePostedDate'] ) {
$query->where('`PaymentNote`.PaymentDate BETWEEN \''.$params['PaymentDate'].' \' AND \''.$params['ChequePostedDate'].'\'');
}
}
return $dataList->setDataQuery($query);
}
}
You can also use WithinRangeFilter something like the following, but you need to use the setMin(), setMax() methods as per this forum response: https://www.silverstripe.org/community/forums/form-questions/show/11685
public function getQuery($searchParams, $sort = false, $limit = false, $existingQuery = null) {
$dataList = parent::getQuery($searchParams, $sort, $limit, $existingQuery);
$params = is_object($searchParams) ? $searchParams->getVars() : $searchParams;
$query = $dataList->dataQuery();
if(!is_object($searchParams)) {
if (!empty($params['PaymentDate'] && !empty($params['ChequePostedDate'])) {
return $dataList->filter('PaymentDate:WithinRange', [$params['PaymentDate'], $params['ChequePostedDate']]);
}
}
return $dataList;
}
i solved it..
simply remove $filters
$filters = array(
// 'PaymentDate' => new PartialMatchFilter('PaymentDate'),
//'ChequePostedDate' => new PartialMatchFilter('ChequePostedDate'),
);
then it works

CDbCriteria throwing column name is ambigous

I have the following method in a controller of my Yii app.
public function actionManage($typeid=0, $locationid=0, $page=1, $rows=12, $sidx='date_input', $sord='desc', $kategori='')
{
if (Yii::app()->request->isAjaxRequest) {
// Jika dilakukan operasi 'edit' pada row
if (isset($_REQUEST['oper']))
{
$oper = $_REQUEST['oper'];
$id = $_REQUEST['id'];
if ($oper == 'edit')
{
$value = $_REQUEST['value'];
$record = InputData::model()->findByPk($id);
$record->value = $value;
$record->update();
}
if($oper == 'delete'){
$model = InputData::model()->findByPk($id);
$model->delete();
}
}
// inisialisasi criteria query
$criteria = new CDbCriteria();
$criteria->order = "$sidx $sord";
// filter lokasi
if (is_numeric($locationid) && $locationid !== 0)
{
$criteria->with = array('data'=>array(
'condition'=>'data.locationid=:locationid',
'params'=>array(':locationid'=>$locationid)
));
} else {
if (is_numeric($typeid) && $typeid !== 0)
{
$criteria->with = array('data.location'=>array(
'with'=>array(
'type'=>array(
'condition'=>'type.typeid=:typeid',
'params'=>array(':typeid'=>$typeid)
)
)
));
} else {
$criteria->with = array('data.location'=>array(
'with'=>array(
'type'=>array(
'condition'=>'type.type_desc=:type_desc',
'params'=>array(':type_desc'=>$kategori)
)
)
));
}
}
// filter range tanggal
if (isset($_REQUEST['startdate'], $_REQUEST['enddate']))
{
$startdate = $_REQUEST['startdate'];
$enddate = $_REQUEST['enddate'];
$criteria->condition = 'date_input <= :enddate AND date_input >= :startdate';
$criteria->params = array(':startdate'=>$startdate, ':enddate'=>$enddate);
}
if(isset($_REQUEST['dataid'])){
$dataid = $_REQUEST['dataid'];
$criteria->addCondition("dataid = $dataid");
}
$dataProvider = new CActiveDataProvider('InputData', array(
'criteria'=>$criteria,
'pagination'=>array(
'currentPage'=>$page-1,
'pageSize'=>$rows
)
));
$count = $dataProvider->totalItemCount;
$total_pages = $count > 0 ? ceil($count/$rows) : 0;
if ($page > $total_pages) $page=$total_pages;
// generate response untuk jqgrid
$response = new stdClass();
$response->page = $page;
$response->total = $total_pages;
$response->records = $count;
foreach($dataProvider->getData() as $row)
{
$response->rows[] = array(
'id'=>$row->inputdataid,
'cell'=>array(
$row->inputdataid,
$row->date_input,
$row->time_input,
$row->data->location->location_name,
$row->data->data_name,
$row->data->variable->var_name,
round($row->value, 3),
$row->data->variable->unit->uom_name,
($row->inputOfficer !== NULL ? $row->inputOfficer->officer_name:''),
'<i class="fa fa-pencil-square-o"></i> Edit <i class="fa fa-trash-o"></i> Delete'
)
);
}
echo json_encode($response);
} else {
$url = $this->createUrl("dataAir/manage");
$delurl = $this->createUrl("dataAir/deleteRow");
$startdate = '2013-01-01';
$enddate = date_format(new DateTime(), 'Y-m-d');
$this->render('jqgrid', array(
'kategori'=>$kategori,
'url'=>$url,
'delurl'=>$delurl,
'startdate'=>$startdate,
'enddate'=>$enddate
));
}
}
this line causing the problem
if(isset($_REQUEST['dataid'])){
$dataid = $_REQUEST['dataid'];
$criteria->addCondition("dataid = $dataid");
}
when, I remove those lines the method work just fine. what could be the problem causing ambigous colum name? here is the error log
SELECT COUNT(DISTINCT "t"."inputdataid") FROM "app_inputdata" "t" LEFT OUTER JOIN "app_ref_periodicdata" "data" ON ("t"."dataid"="data"."dataid") WHERE ((date_input <= :enddate AND date_input >= :startdate) AND (dataid = 7)) AND (data.locationid=:locationid). Bound with :startdate='2013-01-01', :enddate='2015-02-02', :locationid='6'
You need to add the table alias t to your condition:
$criteria->addCondition("t.dataid = $dataid");
Also, since $dataid is being obtained from a $_REQUEST it is best to pass it as a parameter. This can be done in two ways:
$criteria->addCondition("t.dataid = :dataid", [":dataid" => $dataid]);
$criteria->compare("t.dataid", $dataid);
you have used table aliases,
'with'=>array(
'type'=>array(
'condition'=>'type.type_desc=:type_desc', <<- I mean here you have used alias : type
'params'=>array(':type_desc'=>$kategori)
)
you just have to remember that the main model that you are working with, will always need alias t to unambigufy! (not sure if that is an actual word :D )