Drupal 6 forms and optgroup arrays - php

The following array is produced by converting xml to a array (using xml2array). However its not the exactly the right format I need for a optgroup in a Drupal 6 form.
Array (
[root] => Array ([attr] => Array ([id] => 1) [label] => Array ([value] => My Root)
[node] => Array (
[0] => Array ([attr] => Array([id] => 2) [label] => Array([value] => Category 1)
[node] => Array(
[0] => Array ([attr] => Array ([id] => 14) [label] => Array ([value] => Sub-Category 1))
[1] => Array([attr] => Array ([id] => 15) [label] => Array([value] => Sub-Category2))
I think the array has too be reduced to this format with id values intact for the sub-categories. However I can't confirm this with the drupal docs as they don't mention anything about assigning values to a option.
Array (
[Category 1] => Array(
[14] => Sub-Category 1
[15] => Sub-Category 2
)
)
So my questions are 1) is what is the correct array format for Drupal optgroups with my specified values and 2) how do I reduce my array to match?

1)
The correct format for an option group array is (I will use a list of states as an example):
$state_list = array(
'AL'=>"Alabama",
'AK'=>"Alaska",
'AZ'=>"Arizona",
'AR'=>"Arkansas",
...
);
This would display a list of the state names, accessible by the state initials as keys.
In order to use subgroups, you would modify the above like:
$state_list = array(
'A'=> array(
'AL'=>"Alabama",
'AK'=>"Alaska",
'AZ'=>"Arizona",
'AR'=>"Arkansas",
...
),
'C'=> array(
'CA'=>'California',
'CO'=>'Colorado',
...
),
...
);
So, you would need the following format for your translated data as given:
$options = array(
'My Root' => array(
'Category 1' => array(
'14' => 'Sub-Category 1',
'15' => 'Sub-Category 2'
)
)
)
However, if 'My Root' is the name of the select element, use this instead (I'll show you a form definition for each one below):
$options = array(
'Category 1' => array(
'14' => 'Sub-Category 1',
'15' => 'Sub-Category 2'
)
)
Your forms API definition would look like this:
function mymodule_form() {
$options = array(
'My Root' => array(
'Category 1' => array(
'14' => 'Sub-Category 1',
'15' => 'Sub-Category 2'
)
)
);
...
$form['Select Box Name'] = array(
'#type' => 'select',
'#title' => 'Select a Category',
'#options'=> $options,
);
...
return $form;
}
Or like this, if 'My Root' is the name of the select element and not one of it's categories:
function mymodule_form() {
$options = array(
'Category 1' => array(
'14' => 'Sub-Category 1',
'15' => 'Sub-Category 2'
)
);
...
$form['My Root'] = array(
'#type' => 'select',
'#title' => 'Select a Category',
'#options'=> $options,
);
...
return $form;
}
In this definition, your subcategories are keyed using integers - I am not sure this is what you want. Many times Drupal developers use arrays with identical keys and values (e.g. '[CA}=>[CA]') to make things easier.
A side-effect of this format is that 'Category 1' is not itself selectable (since your XML source has keys for both 'Root' and "Category 1' it would seem to me that they were selectable in their previous incarnation); I am not sure if HTML option group sub-category labels even are, so I am not sure if this is a problem or not.

I don't believe that CCK can out of the box do hierarchical options. You could probably reduce to to groups with fields and options but I don't know if that would be generic enough.
As for asssigning values to options that is easier.
From the docs:
Values: An array in the form of array(t('Display value 1'), t('Display value 2')) or array('return_value1' => t('Display Value 1'), 'return_value2' => t('Display Value 2')) if specific return values are required.
So your snippet above would be something like:
$form['Category 1'] = array(
'#type' => 'radios',
'#title' => t('Category 1'),
'#options' => array(
'14' => t('Sub-Category 1'),
'15' => t('Sub-Category 2')
),
);

Related

Build up multidimensional array

I'm struggling building up a multidimesional array from database to display data in a calendar... Basically, I have a table, where there always is a date, a description and a link to the event. I then want to display that data in a calendar and found a little php programmed one, that looks okay.
Now this PHP code takes a $events variable to display events, the structure of the array has to be the following:
$events = [
'2020-04-05' => [
'text' => "An event for the 5 july 2015",
'href' => "http://example.com/link/to/event"
],
'2020-04-23' => [
'text' => "An event for the 23 july 2015",
'href' => "/path/to/event"
],
];
Now as I didn't work too much with multidimensional arrays in PHP (except the ones received as database result), I tried building this array up, but I can't seem to be able to..
What I get from my db is an array, that looks like the following:
array (
0 =>
array (
'ID' => '1',
'link' => 'example.com/link',
'description' => 'that\'s a description',
'eventDate' => '2020-04-07 01:04:25',
),
1 =>
array (
'ID' => '6',
'link' => 'example.com/link',
'description' => 'that\'s a description',
'eventDate' => '2020-04-15 00:00:00',
),
2 =>
array (
'ID' => '7',
'link' => 'example.com/link',
'description' => 'that\'s a description',
'eventDate' => '2020-04-16 07:24:11',
),
3 =>
array (
'ID' => '8',
'link' => 'example.com/link',
'description' => 'that\'s a description',
'eventDate' => '2020-04-26 07:07:10',
),
)
So I thought of a foreach over that array, create a new array for the events before and build it up by something like $events[$foreachVar["date"] = "test" in order to at least get that index, but not even that helps..
Can anybody help me out with that or is there a better way to do it (a better calendar, that integrates the database better?)
PS: If it minds, I'm using Fat Free Framework as a little microframework.
Thanks in advance!
You can iterate over your database result, getting the date portion of eventDate as the output array key and selecting the description and link elements for the output:
$events = array();
foreach ($data as $event) {
$events[date('Y-m-d', strtotime($event['eventDate']))] = array(
'text' => $event['description'],
'href' => $event['link']
);
}
var_export($events);
Output (for your sample data):
array (
'2020-04-07' =>
array (
'text' => 'that\'s a description',
'href' => 'example.com/link',
),
'2020-04-15' =>
array (
'text' => 'that\'s a description',
'href' => 'example.com/link',
),
'2020-04-16' =>
array (
'text' => 'that\'s a description',
'href' => 'example.com/link',
),
'2020-04-26' =>
array (
'text' => 'that\'s a description',
'href' => 'example.com/link',
),
)
Demo on 3v4l.org
Note I've been a bit paranoid with the date, wanting to allow for any format in the database. If it's definitely in yyyy-mm-dd HH:ii:ss form, you can just use substr($event['eventDate'], 0, 10) to extract the date portion i.e.
foreach ($data as $event) {
$events[substr($event['eventDate'], 0, 10)] = array(
'text' => $event['description'],
'href' => $event['link']
);
}
Try this
$events = [];
foreach($array as $key => $value){
$events[$value['date']] = $value;
}
print $events and you will get idea.
ask me if you need more help.

PHP multidimensional Array to follow a defined key structure

I like an array to follow a defined structure like this:
array (
'id' => '',
'name' => '',
'quantity' => '',
)
This is the structure I would like to follow in a multidimensional array list. Example:
array (
array (
'id' => 'GFKHF312',
'name' => 'Item 1',
'quantity' => 1
),
array (
'id' => 'YUKKU134',
'name' => 'item 2',
'quantity' => 5
),
array (
'id' => 'TRUT243',
'name' => 'item 3',
'quantity' => 10
)
)
So I would like, to:
In every other name keys passed, when trying to add a new row to the list , it should be removed or filtered.
Example:
# When passed this data
array (
'id' => 'GFKHF312',
'name' => 'Item',
'quantity' => 1,
'new_key' => 120,
'other_key' => 'fsdfs',
)
# It should filter to this data
array (
'id' => 'GFKHF312',
'name' => 'Item',
'quantity' => 1
)
Second, if it doesn't have all the keys ('id', 'name', 'quantity') defined in structure it should fail (return false or null).
Example:
# When passed this data
array (
'id' => 'GFKHF312',
'quantity' => 1,
)
# It should return this data
false
Is it possibly to use a php array function, like array_diff, for that or cycles is needed to accomplish this.
Thanks for the help!

Remove Child Array If Value of A Key is Duplicate

I want to remove a child array from a multi-dimensional array in case a duplicate value found for a particular key. The answer(s) here didn't work at all. The answer here works, however, for large amount of arrays, that gets pretty slower. Looking for a cleaner and faster solution.
Example PHP Array
$args = array();
$args[] = array(
'section' => array(
'id' => 'section1',
'name' => 'Section 1',
),
'name' => 'Shortcode Name',
'action' => 'shortcodeaction',
'icon' => 'codeicon',
'image' => 'codeimage',
);
$args[] = array(
'section' => array(
'id' => 'section2',
'name' => 'Section 2',
),
'name' => 'Shortcode2 Name',
'action' => 'shortcodeaction2',
'icon' => 'codeicon2',
'image' => 'codeimage2',
);
$args[] = array(
'section' => array(
'id' => 'section3',
'name' => 'Section 3',
),
'name' => 'Shortcode3 Name',
'action' => 'shortcodeaction3',
'icon' => 'codeicon3',
'image' => 'codeimage3',
);
$args[] = array(
'section' => array(
'id' => 'section1',
'name' => 'Section 4',
),
'name' => 'Shortcode4 Name',
'action' => 'shortcodeaction4',
'icon' => 'codeicon4',
'image' => 'codeimage4',
);
$args[] = array(
'section' => array(
'id' => 'section5',
'name' => 'Section 5',
),
'name' => 'Shortcode5 Name',
'action' => 'shortcodeaction5',
'icon' => 'codeicon5',
'image' => 'codeimage5',
);
$sections = array();
foreach ( $args as $arg ) {
$sections[] = $arg['section'];
}
And, the print_r($sections) result.
Array
(
[0] => Array
(
[id] => section1
[name] => Section 1
)
[1] => Array
(
[id] => section2
[name] => Section 2
)
[2] => Array
(
[id] => section3
[name] => Section 3
)
[3] => Array
(
[id] => section1
[name] => Section 4
)
[4] => Array
(
[id] => section5
[name] => Section 5
)
)
Both Array[0] and Array[3] has the same value for the key id, therefor the entire Array[3] has to be removed in my case to avoid duplicates.
This is working for me though, but it gets really slow when there are 100s or more arrays.
$knownIds = array();
foreach( $sections AS $key=>$item ) {
if( array_key_exists($item['id'], $knownIds) === true ) {
unset( $sections[$key] );
} else {
$knownIds[$item['id']] = $key;
}
}
$sections = array_values($sections);
Tried several answers here in StackOverflow (including this), but none of them helped in my case.
Thanks
You can modify the whole using array_column and array_filter -
//get all the sections value
$section = array_column($args, 'section');
//store ids in temp array
$idArray = array_unique(array_column($section, 'id'));
//filter the array having unique id
$uniqueSections = array_filter($section, function ($key, $value) use ($idArray) {
return in_array($value, array_keys($idArray));
}, ARRAY_FILTER_USE_BOTH);
var_dump($uniqueSections);
For PHP <5.5
$section = array_map(function($args) {
return $args['section'];
}, $args);
$idArray = array_unique(array_map(function($section){return $section['id'];}, $section));

PHP split array by key

I have an array which looks like this:
array (
'id' => 1,
'channel_id' => 1,
'field_group' => 1,
'url_title' => 'the_very_first_entry',
'title' => 'The Very First Entry',
'fields' =>
array (
0 =>
array (
'label' => 'Enter Item Name:',
'type' => 'text',
'channel_data_id' => 1,
'value' => 'Item one',
'field_id' => 1
),
1 =>
array (
'label' => 'Enter Item Description',
'type' => 'textarea',
'channel_data_id' => 2,
'value' => 'Some long text blah blah',
'field_id' => 2
)
)
)
I want to split this into 2 arrays, one containing the fields, and the other containing everything else, ie.
Array 1:
array (
'id' => 1,
'channel_id' => 1,
'field_group' => 1,
'url_title' => 'the_very_first_entry',
'title' => 'The Very First Entry'
);
Array 2:
array (
0 =>
array (
'label' => 'Enter Item Name:',
'type' => 'text',
'channel_data_id' => 1,
'value' => 'Item one',
'field_id' => 1
),
1 =>
array (
'label' => 'Enter Item Description',
'type' => 'textarea',
'channel_data_id' => 2,
'value' => 'Some long text blah blah',
'field_id' => 2
)
)
Is there a better solution that iterating through the original array with a foreach loop?
Is there a better solution that iterating through the original array with a foreach loop
You know the split-key so there's no real use for foreach:
$src = array(...); // your source array
$fields_array = $src['fields'];
unset($src['fields']);
If I understood your question correct.
<?php
$base = array(...); // your array
// array values
$baseArrays = array_filter($base, function($item){
return is_array($item);
});
// not array values
$not = array_diff($base, $baseArrays);
As an alternative solution, if the fields key is always the last element of the array, you can use array_pop.
$fields = array_pop($array);
And that's it. Demo.

cakephp combining associated array fields

I've an associated array with 20 elements whose child array looks like
(int) 2 => array(
'Comment' => array(
'id' => '5',
'user_id' => '13',
'time' => '2012-05-18 14:47:36'
),
'User' => array(
'name' => 'User name'
)
)
Now I want to extract the field name from its child array User with cakephp's set utility and append it to the child array Comment. Is there a one way step to do this other than using a for or foreach loop?
(int) 2 => array(
'Comment' => array(
'id' => '5',
'user_id' => '13',
'time' => '2012-05-18 14:47:36',
'name =>'User name'
)
)
It doesn't answer your question, but doing this with a foreach is a one way step too:
foreach ($arrays as $array)
$array['Comment']['name'] = $array['User']['name'];
I believe there's no need to use some utility, just for the sake of using an utility.
Especially that it'll do a foreach itself.

Categories