Checkbox values in prestashop - checkbox

I'm working with prestashop and try to get value from a form with checkbox using a HelperForm
SO what I had is :
$fields_form[0]['form']= [
'legend'=> [
'title'=> $this->l('Indexation')
] ,
'input'=>[
[
'type'=>'text',
'label'=> $this->l('Base(s) à indexer'),
'name'=>'options',
'size'=>20,
'required'=>true
]
],
'submit'=>[
'title' => $this->l('Save'),
'class' => 'btn btn-default pull-right'
]
];
and then
$helper = new HelperForm();
[...]
$helper->toolbar_btn = array(
'save' =>
array(
'desc' => $this->l('Save'),
'href' => AdminController::$currentIndex.'&configure='.$this->name.'&save'.$this->name.
'&token='.Tools::getAdminTokenLite('AdminModules'),
),
'back' => array(
'href' => AdminController::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminModules'),
'desc' => $this->l('Back to list')
)
);
// Load current value
$helper->fields_value['options'] = Configuration::get('options');
return $helper->generateForm($fields_form);
and in my getContent I had :
$my_module_name = strval(Tools::getValue('options'));
return $my_module_name;
So until there I had no problem. I write 'test' in the text input and then 'test' is returned but I don't want a text input I want a checkbox input so I changed my form for :
$fields_form[0]['form']= [
'legend'=> [
'title'=> $this->l('Indexation')
] ,
'input'=>[
[
'type'=>'checkbox',
'label'=> $this->l('Base(s) à indexer'),
'name'=>'options',
'required'=>true,
'values'=>[
'query'=>$options,
'id'=>'id',
'name'=>'name'
]
]
],
'submit'=>[
'title' => $this->l('Save'),
'class' => 'btn btn-default pull-right'
]
];
and $options is :
$options = [
[
'id'=>1,
'name'=>'test'
],
[
'id'=>2,
'name'=>'test2'
]
];
and in my getContent(): return (Tools::getValue('options'));
But with that, nothing is displayed.
Also, if I do return sizeof(Tools::getValue('options)) It give me 1 no matter what I check with the checkbox

First you need to set the name of the field with []
$fields_form[0]['form']= [
'legend'=> [
'title'=> $this->l('Indexation')
] ,
'input'=>[
[
'type'=>'checkbox',
'label'=> $this->l('Base(s) à indexer'),
'name'=>'options[]',
'required'=>true,
'values'=>[
'query'=>$options,
'id'=>'id',
'name'=>'name'
]
]
],
'submit'=>[
'title' => $this->l('Save'),
'class' => 'btn btn-default pull-right'
]
];
Then, you options should have a value:
$options = [
[
'id'=>1,
'name'=>'test',
'val' => 1
],
[
'id'=>2,
'name'=>'test2',
'val' => 2
]
];
Then you can get the checked values with:
Tools::getValue('options')
Edit:
In 1.6 we have the admin tpl for the helper:
{foreach $input.values.query as $value}
{assign var=id_checkbox value=$input.name|cat:'_'|cat:$value[$input.values.id]}
<div class="checkbox{if isset($input.expand) && strtolower($input.expand.default) == 'show'} hidden{/if}">
{strip}
<label for="{$id_checkbox}">
<input type="checkbox" name="{$id_checkbox}" id="{$id_checkbox}" class="{if isset($input.class)}{$input.class}{/if}"{if isset($value.val)} value="{$value.val|escape:'html':'UTF-8'}"{/if}{if isset($fields_value[$id_checkbox]) && $fields_value[$id_checkbox]} checked="checked"{/if} />
{$value[$input.values.name]}
</label>
{/strip}
</div>
{/foreach}
So, to set the checkbox value to be returned we need to pass the val:
{if isset($value.val)} value="{$value.val|escape:'html':'UTF-8'}"{/if}
Also, to be checked or not when loading the page we pass the values to meet the criteria:
{if isset($fields_value[$id_checkbox]) && $fields_value[$id_checkbox]} checked="checked"{/if}

Related

How would I write a WordPress function to run a json_encode and file_put_contents whenever a specific CPT post is saved

I need to generate a custom JSON file from custom fields in a custom post type. But I'm not sure what the proper function is for accomplishing this, or if my syntax is anywhere close to correct in the first place. I haven't worked much with JSON, and have never attempted to create one from dynamic content before.
I'm using an example json file for the mapping plugin I'm using as my model, but I suspect that I'm not writing the array in the right format by using this other JSON file.
In any case, embarrassingly, here's what I've got so far (and it's definitely not working):
function wpdocs_retailers_json($post_id) {
$maplocations = Array( ?>
{
"mapwidth": "1000",
"mapheight": "500",
"categories": [ {
"id": "food",
"title": "Fast-foods & Restaurants",
"color": "#a5a5a2",
"show": "false"
},
{
"id": "dep",
"title": "Department Stores",
"color": "#a5a5a2",
"show": "true"
},
{
"id": "clothing",
"title": "Clothing & Accessories",
"color": "#a5a5a2",
"show": "true"
},
{
"id": "health",
"title": "Health & Cosmetics",
"color": "#a5a5a2",
"show": "true"
},
{
"id": "misc",
"title": "Miscellaneous",
"color": "#a5a5a2",
"show": "true"
} ],
<?php if(have_rows('mall_levels', 'option')) { ?>
"levels": [ {
<?php while(have_rows('mall_levels', 'option')) {
the_row();
$level_svg = get_sub_field('svg_mall_level');
$level = get_sub_field('what_level_is_this');
?>
"id": "<?php echo esc_html($level->slug); ?>",
"title": "<?php echo esc_html($level->name); ?>",
"map": "<?php echo $level_svg; ?>",
<?php $locargs = array(
'post_type' => 'retailers',
'post_status' => 'publish',
'posts_per_page' => 0,
'orderby' => 'title',
'order' => 'ASC'
);
$locloop = new WP_Query($locargs);
if($locloop->have_posts()) { ?>
"locations": [
<?php while($locloop->have_posts()) {
$locloop->the_post();
$space = get_field('space_id'); ?>
{
"id": "space-<?php echo $space; ?>",
"title": "<?php the_title(); ?>",
"about": "Lorem ipsum",
"description": "<?php the_content(); ?>",
<?php $cats = get_the_terms($post->ID, 'dir_cats');
$catsCount = count($cats);
if($catsCount = 0) { ?>
"category": "<?php echo $cat->name; ?>"
<?php }
if($catsCount > 0) { ?>
"category": [<?php echo '"' . __($cat->name) . '"'; ?>]
<?php } ?>
"link": "<?php the_permalink(); ?>",
"x": "0.3721",
"y": "0.4296"
},
<?php } //endwhile; ?>
]
<?php } //endif;
} //endwhile; ?>
},
]
<?php } //endif; ?>
}
<?php );
$json = json_encode($maplocations);
$bytes = file_put_contents('mall.json', $json);
}
add_action('save_post_retailers', 'wpdocs_retailers_json');
I think, at least in part, the array needs to be written more like this? But I'm not sure:
"mapwidth" => "1000",
"mapheight" =>"500",
"categories" => Array(
array(
"id" => "food",
"title" => "Fast-foods & Restaurants",
"color" => "#a5a5a2",
"show" =>"false"
),
array(
"id" => "dep",
"title" => "Department Stores",
"color" => "#a5a5a2",
"show" => "true"
),
...etc.
Thanks in advance for any guidance you can provide. I apologize for my utter lack of knowledge to begin with on this one. Please be kind.
(...) the array needs to be written more like this?
Yes, you want to use that array syntax to make your life easier in the long run (IMO at least).
Here are some changes to your code. Untested though so let me know how it goes and/or if you have any further comments/questions.
function wpdocs_retailers_json($post_id) {
$maplocations = array(
"mapwidth" => 1000,
"mapheight" => 500,
"categories" => array(
array(
"id" => "food",
"title" => "Fast-foods & Restaurants",
"color" => "#a5a5a2",
"show" => "false"
),
array(
"id" => "dep",
"title" => "Department Stores",
"color" => "#a5a5a2",
"show" => "false"
),
array(
"id" => "clothing",
"title" => "Clothing & Accessories",
"color" => "#a5a5a2",
"show" => "false"
),
array(
"id" => "health",
"title" => "Health & Cosmetics",
"color" => "#a5a5a2",
"show" => "false"
),
array(
"id" => "misc",
"title" => "Miscellaneous",
"color" => "#a5a5a2",
"show" => "false"
)
)
);
// We have map levels, save them to
// our json file
if(have_rows('mall_levels', 'option')) {
$maplocations['levels'] = array();
while(have_rows('mall_levels', 'option')) {
the_row();
$level_svg = get_sub_field('svg_mall_level');
$level = get_sub_field('what_level_is_this');
$level_data = array(
"id" => esc_html($level->slug),
"title" => esc_html($level->name),
"map" => $level_svg,
)
$locargs = array(
'post_type' => 'retailers',
'post_status' => 'publish',
'posts_per_page' => 0,
'orderby' => 'title',
'order' => 'ASC'
);
$locloop = new WP_Query($locargs);
// We have some locations, save them as well
if($locloop->have_posts()) {
$level_data['locations'] = array();
while($locloop->have_posts()) {
$locloop->the_post();
$space = get_field('space_id');
$title = get_the_title();
$content = get_the_content();
$cats = get_the_terms(get_the_ID(), 'dir_cats');
$permalink = get_permalink();
$level_data['locations']['id'] = 'space-' . esc_attr($space);
$level_data['locations']['title'] = esc_html($title);
$level_data['locations']['about'] = 'Lorem Ipsum';
$level_data['locations']['description'] = $content;
if ( count($cats) ) {
$level_data['category'] = join(', ', wp_list_pluck($cats, 'name'));
}
$level_data['locations']['link'] = esc_url( $permalink );
$level_data['locations']['x'] = '0.3721';
$level_data['locations']['y'] = '0.4296';
}
// Restore original post data
wp_reset_postdata();
}
// Add our $level_data array to $maplocations
$maplocations['levels'][] = $level_data;
}
}
// Convert PHP array into JSON string
$json = json_encode($maplocations);
// Save json string to mall.json
$bytes = file_put_contents('mall.json', $json);
}
add_action('save_post_retailers', 'wpdocs_retailers_json');
Note that file_put_contents('mall.json', $json); probably should use a full path to the folder where you want to store your mall.json file.
#cabrerahector Got me super close. After a little more trial and error, the last part of the above needs to go like this:
$mapjson = json_encode($maplocations);
$j_dir = get_stylesheet_directory();
$mapdata = '/json/mall.json';
file_put_contents($j_dir . $mapdata, $mapjson, LOCK_EX);
update_post_meta($post_id, 'mall, $date);
}
add_action('save_post_retailers', 'retailers_map_json', 20);
(note, I did change the name of the function to "retailers_map_json" instead of "wpdocs_retailers_json".

I'm getting a 404 error using Laminas Framework. Can anyone assist?

The error is:
A 404 error occurred
Page not found.
The requested URL could not be matched by routing.
No Exception available
I've registered my module and namespace with Composer and then ran Composer dump-autoload. My code is as follows:
module\Album\config\module.config.php
<?php
declare(strict_types=1);
namespace Album;
use Laminas\Router\Http\Segment;
use Laminas\ServiceManager\Factory\InvokableFactory;
return [
'router' => [
'routes' => [
'album' => [
'type' => Segment::class,
'options' => [
'route' => '/album[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\AlbumController::class,
'action' => 'index',
],
],
],
],
],
'controllers' => [
'factories' => [
Controller\AlbumController::class => InvokableFactory::class,
],
],
'view_manager' => [
'template_map' => [
'album/index' => __DIR__ . '/../view/album/album/index.phtml',
],
'template_path_stack' => [
'album' => __DIR__ . '/../view',
],
],
];
module\Album\src\Module.php
<?php
declare(strict_types=1);
namespace Album;
class Module
{
public function getConfig() : array
{
return include __DIR__ . '/../config/module.config.php';
}
}
module\Album\src\Controller\AlbumController.php
<?php
declare(strict_types=1);
namespace Album\Controller;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
class AlbumController extends AbstractActionController
{
public function indexAction()
{
return new ViewModel();
}
}
module\Album\view\album\album\index.phtml
Index page displays here...
As you specified the root as
'route' => '/album[/:action[/:id]]',
The url should look like http://laminas.com/album which will route to the indexAction as you have defined that action as the default, but http://laminas.com/album/index would have the same effect.

Laravel Multidimensional Array to Collection Object Values

I have an array that I'm wanting to recursively turn into a collection and to use the collection as object values.
I would like to use the collection object in similar ways that eloquent is used rather than using $contact['name'] and being able to use $collection->contacts->each vs foreach $collection->contacts .....)
$collection->contacts->each(function ($contact) {
// ability to use $contact->name (and not have to use $contact['name'])
});
Collection Macro:
Collection::macro('recursive', function () {
return $this->map(function ($value) {
if (is_array($value)) {
return (object)$value;
}
if (is_object($value)) {
return collect($value)->recursive();
}
return $value;
});
});
Example:
public function test_it_can_recursively_convert_array_to_collection()
{
$data = [
[
'name' => 'Michael Scott',
'emails' => [
'mscott#dundermifflin.com',
'michaelscarn#dundermifflin.com',
],
'contacts' => [
[
'name' => 'Dwight Schrute',
'emails' => [
'dschrute#dundermifflin.com',
],
],
[
'name' => 'Jim Halpert',
'emails' => [
'jhalpert#dundermifflin.com',
],
],
],
],
];
$collection = collect($data)->recursive();
$this->assertInstanceOf(Collection::class, $collection);
$collection->each(function ($item) {
$this->assertEquals('Michael Scott', $item->name);
$item->contacts->each(function ($contact) {
$this->assertNotNull($contact->name);
});
});
}
The original collection map works (e.g. $collection->each .... $item->name) but I can't seem to set convert the nested arrays to objects and get the object values.
Error: Call to a member function each() on array
Illuminate\Support\Collection^ {#632
#items: array:1 [
0 => {#13
+"name": "Michael Scott"
+"emails": array:2 [
0 => "mscott#dundermifflin.com"
1 => "michaelscarn#dundermifflin.com"
]
+"contacts": array:2 [
0 => array:2 [
"name" => "Dwight Schrute"
"emails" => array:1 [
0 => "dschrute#dundermifflin.com"
]
]
1 => array:2 [
"name" => "Jim Halpert"
"emails" => array:1 [
0 => "jhalpert#dundermifflin.com"
]
]
]
}
]
}

Perl: How to iterate over arrays in multiple objects and extract values from webservice

I request a web service and get a JSON response:
{
"timestamp" : "2019-06-11T08:04:35Z",
"version" : "0.5",
"document" : [
{
"href" : "http://opac.sub.uni-goettingen.de/DB=1/PPNSET?PPN=1629107239",
"item" : [
{
"href" : "http://opac.sub.uni-goettingen.de/DB=1/PPNSET?PPN=1629107239",
"label" : "40 623 a",
"id" : "http://uri.gbv.de/document/opac-de-7:epn:3421084610",
"available" : [
{
"service" : "presentation"
}
],
"unavailable" : [
{
"service" : "loan"
},
{
"service" : "interloan"
}
]
},
{
"href" : "http://opac.sub.uni-goettingen.de/DB=1/PPNSET?PPN=1629107239",
"label" : "40 623 b",
"id" : "http://uri.gbv.de/document/opac-de-7:epn:342108467X",
"available" : [
{
"service" : "presentation"
}
],
"unavailable" : [
{
"service" : "loan"
},
{
"service" : "interloan"
}
]
}
],
"id" : "http://uri.gbv.de/document/opac-de-7:ppn:1629107239"
}
],
"institution" : {
"href" : "http://www.sub.uni-goettingen.de",
"content" : "Niedersächsische Staats- und Universitätsbibliothek Göttingen",
"id" : "http://uri.gbv.de/organization/isil/DE-7"
}
}
Then I parse the JSON with Perls Dumper::Data module:
my $data = decode_json($resultJson);
print Dumper($data);
It looks like:
$VAR1 = {
'document' => [
{
'item' => [
{
'available' => [
{
'service' => 'presentation'
}
],
'id' => 'http://uri.gbv.de/document/opac-de-7:epn:3421084610',
'href' => 'http://opac.sub.uni-goettingen.de/DB=1/PPNSET?PPN=1629107239',
'label' => '40 623 a',
'unavailable' => [
{
'service' => 'loan'
},
{
'service' => 'interloan'
}
]
},
{
'available' => [
{
'service' => 'presentation'
}
],
'unavailable' => [
{
'service' => 'loan'
},
{
'service' => 'interloan'
}
],
'id' => 'http://uri.gbv.de/document/opac-de-7:epn:342108467X',
'label' => '40 623 b',
'href' => 'http://opac.sub.uni-goettingen.de/DB=1/PPNSET?PPN=1629107239'
}
],
'id' => 'http://uri.gbv.de/document/opac-de-7:ppn:1629107239',
'href' => 'http://opac.sub.uni-goettingen.de/DB=1/PPNSET?PPN=1629107239'
}
],
'institution' => {
'content' => "Nieders\x{e4}chsische Staats- und Universit\x{e4}tsbibliothek G\x{f6}ttingen",
'id' => 'http://uri.gbv.de/organization/isil/DE-7',
'href' => 'http://www.sub.uni-goettingen.de'
},
'timestamp' => '2019-06-11T08:04:35Z',
'version' => '0.5'
};
I would like to display the availability of each item, but I'm having a hard time iterating through the arrays inside the objects. My actual code looks like:
my $availability = $data->{document}[0]->{item}[0]->{available};
foreach my $key (#{$availability}) {
if (($key->{'service'}) eq "loan") {
print $rueckgabe = "Loan: available.\n";
} elsif (($key->{'service'}) eq "presentation") {
print $rueckgabe = "Presentation: available.\n";
} elsif (($key->{'service'}) eq "interloan") {
print $rueckgabe = "ILL: available.\n";
}
}
My expected result would be:
Item 1: Loan: available.
Item 2: Loan: available.
Iterate over the items, for each item, iterate over the availabilities.
for my $i (0 .. $#{ $data->{document}[0]{item} }) {
print 'Item ', $i + 1, ': ';
for my $availability ($data->{document}[0]{item}[$i]{available}) {
for my $key (#$availability) {
print { interloan => 'ILL' }->{ $key->{service} } || ucfirst $key->{service},
": available\n";
}
}
}

How to enclose an array in a conditional if?

For example, I have the following code:
<?php
$options = array(
array(
"type" => "section",
"icon" => "acera-icon-preference",
"title" => "General Settings",
"id" => "general",
"expanded" => "true"
),
array(
"under_section" => "ajax_login",
"type" => "checkbox",
"name" => "Who's Online Options",
"id" => array("tigu_whosonline_list", "tigu_whosonline_avatar"),
"display_checkbox_id" => "tigu_show_whosonline",
"img_desc" => "",
"options" => array("Who's Online List", "Who's Online Avatars"),
"desc" => "",
"default" => array("checked", "checked")
) );
?>
There a more arrays but I shortened the code to save space. The question is:
How can I include only the following code
array(
"type" => "section",
"icon" => "acera-icon-preference",
"title" => "General Settings",
"id" => "general",
"expanded" => "true"
),
in a conditional if somethink like this code (that get errors):
if(function_exists('bp_is_active') ):
array(
"type" => "section",
"icon" => "acera-icon-preference",
"title" => "General Settings",
"id" => "general",
"expanded" => "true"
),
endif;
The function bp_is_active it check if BuddyPress plugin is instaled. I need that code to be displayed on my wp admin panel only if BuddyPress plugin is instaled.
Thanks!
You could use the ?: ternary conditional operator:
$options = array(
function_exists('bp_is_active') // condition
? array(...stuff...) // if true
: array(), // if false
...more arrays...
);
That will use an empty array if the condition is false. If you want nothing there (as opposed to array()), you'll need something more complex.
I think you just need semicolon (;), following code is valid:
if(function_exists('bp_is_active') ):
array(
"type" => "section",
"icon" => "acera-icon-preference",
"title" => "General Settings",
"id" => "general",
"expanded" => "true"
); // <<--here
endif;
or without endif:
if(function_exists('bp_is_active') ){
array(
"type" => "section",
"icon" => "acera-icon-preference",
"title" => "General Settings",
"id" => "general",
"expanded" => "true"
); // <<--here
}

Resources