PHP - Need help inserting arrays into Associative arrays at given keys
Asked Answered
N

2

6

Ok, so I have an array like so:

$buttons = array(
    'home' => array(
        'title' => $txt['home'],
        'href' => $scripturl,
        'show' => true,
        'sub_buttons' => array(
        ),
        'is_last' => $context['right_to_left'],
    ),
    'help' => array(
        'title' => $txt['help'],
        'href' => $scripturl . '?action=help',
        'show' => true,
        'sub_buttons' => array(
        ),
    ),
    'search' => array(
        'title' => $txt['search'],
        'href' => $scripturl . '?action=search',
        'show' => $context['allow_search'],
        'sub_buttons' => array(
        ),
    ),
    'admin' => array(
        'title' => $txt['admin'],
        'href' => $scripturl . '?action=admin',
        'show' => $context['allow_admin'],
        'sub_buttons' => array(
            'featuresettings' => array(
                'title' => $txt['modSettings_title'],
                'href' => $scripturl . '?action=admin;area=featuresettings',
                'show' => allowedTo('admin_forum'),
            ),
            'packages' => array(
                'title' => $txt['package'],
                'href' => $scripturl . '?action=admin;area=packages',
                'show' => allowedTo('admin_forum'),
            ),
            'errorlog' => array(
                'title' => $txt['errlog'],
                'href' => $scripturl . '?action=admin;area=logs;sa=errorlog;desc',
                'show' => allowedTo('admin_forum') && !empty($modSettings['enableErrorLogging']),
            ),
            'permissions' => array(
                'title' => $txt['edit_permissions'],
                'href' => $scripturl . '?action=admin;area=permissions',
                'show' => allowedTo('manage_permissions'),
                'is_last' => true,
            ),
        ),
    ),
    'moderate' => array(
        'title' => $txt['moderate'],
        'href' => $scripturl . '?action=moderate',
        'show' => $context['allow_moderation_center'],
        'sub_buttons' => array(
            'modlog' => array(
                'title' => $txt['modlog_view'],
                'href' => $scripturl . '?action=moderate;area=modlog',
                'show' => !empty($modSettings['modlog_enabled']) && !empty($user_info['mod_cache']) && $user_info['mod_cache']['bq'] != '0=1',
            ),
            'poststopics' => array(
                'title' => $txt['mc_unapproved_poststopics'],
                'href' => $scripturl . '?action=moderate;area=postmod;sa=posts',
                'show' => $modSettings['postmod_active'] && !empty($user_info['mod_cache']['ap']),
            ),
            'attachments' => array(
                'title' => $txt['mc_unapproved_attachments'],
                'href' => $scripturl . '?action=moderate;area=attachmod;sa=attachments',
                'show' => $modSettings['postmod_active'] && !empty($user_info['mod_cache']['ap']),
            ),
            'reports' => array(
                'title' => $txt['mc_reported_posts'],
                'href' => $scripturl . '?action=moderate;area=reports',
                'show' => !empty($user_info['mod_cache']) && $user_info['mod_cache']['bq'] != '0=1',
                'is_last' => true,
            ),
        ),
    ),
    'profile' => array(
        'title' => $txt['profile'],
        'href' => $scripturl . '?action=profile',
        'show' => $context['allow_edit_profile'],
        'sub_buttons' => array(
            'summary' => array(
                'title' => $txt['summary'],
                'href' => $scripturl . '?action=profile',
                'show' => true,
            ),
            'account' => array(
                'title' => $txt['account'],
                'href' => $scripturl . '?action=profile;area=account',
                'show' => allowedTo(array('profile_identity_any', 'profile_identity_own', 'manage_membergroups')),
            ),
            'profile' => array(
                'title' => $txt['forumprofile'],
                'href' => $scripturl . '?action=profile;area=forumprofile',
                'show' => allowedTo(array('profile_extra_any', 'profile_extra_own')),
                'is_last' => true,
            ),
        ),
    ),
    'pm' => array(
        'title' => $txt['pm_short'],
        'href' => $scripturl . '?action=pm',
        'show' => $context['allow_pm'],
        'sub_buttons' => array(
            'pm_read' => array(
                'title' => $txt['pm_menu_read'],
                'href' => $scripturl . '?action=pm',
                'show' => allowedTo('pm_read'),
            ),
            'pm_send' => array(
                'title' => $txt['pm_menu_send'],
                'href' => $scripturl . '?action=pm;sa=send',
                'show' => allowedTo('pm_send'),
                'is_last' => true,
            ),
        ),
    ),
    'calendar' => array(
        'title' => $txt['calendar'],
        'href' => $scripturl . '?action=calendar',
        'show' => $context['allow_calendar'],
        'sub_buttons' => array(
            'view' => array(
                'title' => $txt['calendar_menu'],
                'href' => $scripturl . '?action=calendar',
                'show' => allowedTo('calendar_post'),
            ),
            'post' => array(
                'title' => $txt['calendar_post_event'],
                'href' => $scripturl . '?action=calendar;sa=post',
                'show' => allowedTo('calendar_post'),
                'is_last' => true,
            ),
        ),
    ),
    'mlist' => array(
        'title' => $txt['members_title'],
        'href' => $scripturl . '?action=mlist',
        'show' => $context['allow_memberlist'],
        'sub_buttons' => array(
            'mlist_view' => array(
                'title' => $txt['mlist_menu_view'],
                'href' => $scripturl . '?action=mlist',
                'show' => true,
            ),
            'mlist_search' => array(
                'title' => $txt['mlist_search'],
                'href' => $scripturl . '?action=mlist;sa=search',
                'show' => true,
                'is_last' => true,
            ),
        ),
    ),
    'login' => array(
        'title' => $txt['login'],
        'href' => $scripturl . '?action=login',
        'show' => $user_info['is_guest'],
        'sub_buttons' => array(
        ),
    ),
    'register' => array(
        'title' => $txt['register'],
        'href' => $scripturl . '?action=register',
        'show' => $user_info['is_guest'],
        'sub_buttons' => array(
        ),
        'is_last' => !$context['right_to_left'],
    ),
    'logout' => array(
        'title' => $txt['logout'],
        'href' => $scripturl . '?action=logout;%1$s=%2$s',
        'show' => !$user_info['is_guest'],
        'sub_buttons' => array(
        ),
        'is_last' => !$context['right_to_left'],
    ),
);

Now I want to be able to insert an array into it, either before or after any of the keys within the array above. The array that I want to insert can look like this:

$new_menu_buttons['testing'] = array(
    'title' => $txt['testing'],
    'href' => $scripturl . '?action=testing',
    'show' => true,
    'target' => '_self',
    'active_button' => false,
);

Someone recommended functions to handle this and methods to use, but I'm not sure how to do this, they are wanting offsets for these functions also. Here is the function structure that someone recommended I use for this, than just call these functions when needed:

function array_insert_before($array, $key, $new_array)
{
    // Splice array in two at key, keeping key on the right side
    // Append new value on the left tail
    // Glue both arrays into a new array
    // Return new array
}
function array_insert_after($array, $key, $new_array)
{
    // Symmetric with right & left switched
}

So, I want to be able to call the functions like so:

If it needs to go after the key, 'home' that is specified:

$menu_buttons = array_insert_after($buttons, 'home', $new_menu_buttons);

If it needs to go before the key, 'home' that is specified:

$menu_buttons = array_insert_before($buttons, 'home', $new_menu_buttons);

Basically, I really need help with these functions, any help would be great.

Should I be using array_splice or array_slice? Would someone be willing to start me off in the right direction here with some actual code please?

Thanks guys :)

Nereen answered 28/6, 2011 at 5:13 Comment(2)
wouldnt it be easier to introduce a position value and sort it by that before creating the navigation? Or use an SplHeap or PriorityQueue to keep the navigation in order?Peregrination
If you feel that this question has been answered, then you should mark it answered (check button under the ratings for an answer).Unlisted
N
0

Ok, after playing with it for quite some time, I finally got it working the way I want it. I am using certain keys within the $new_menu_buttons to decide on what to do. e.g.: position tells me if it is after or before, parent tells me where to search for the key at, and slug gives me the key to use for each new menu array that gets added. array_splice isn't working for me, so I'm using the array_merge approach instead which works just great. Here it is for anyone else who gets stuck with this problem.

function array_insert_buttons($buttons, $new_menu_buttons)
{
    foreach($new_menu_buttons as $new)
    {
        $keys = array_keys($buttons);
        $position = (int)array_search($new['parent'], $keys);

        if ($new['position'] == 'after')
            $position = $position + 1;

        // Create the new array in the correct format, using the slug!
        $new_button = array();
        $new_button[$new['slug']] = $new;

        // Don't need these keys anymore.
        unset($new_button[$new['slug']]['position']);
        unset($new_button[$new['slug']]['parent']);
        unset($new_button[$new['slug']]['slug']);

        // Putting it all together now.
        $buttons = array_merge(
            array_slice($buttons, 0, $position),
            $new_button,
            array_slice($buttons, $position)
        );
    }

    return $buttons;
}

Thanks for your help guys :)

Nereen answered 28/6, 2011 at 9:0 Comment(0)
I
5

This should get you started. Note: I haven't tested this. It's off the top of my head.

/**
 * This will insert $new at the beginning if $key is not found
 */
function array_insert_before($array, $key, $new)
{
    $keys = array_keys($array);
    $pos = (int) array_search($key, $keys);
    return array_merge(
        array_slice($array, 0, $pos),
        $new,
        array_slice($array, $pos)
    );
}

array_insert_after() is pretty much the same, except $pos is increased by one. You should be able to figure that out by yourself.

Intersection answered 28/6, 2011 at 5:58 Comment(7)
@Sander Marechal - Instead of using your return array_merge(...) call, you could use return array_splice($array, $position, 0, $new);. If the length parameter is set to 0, it'll insert at the after offset and leave the rest intact.Hegelianism
hello Sander, $key will always be found, since this is a key from the same $array, it's NOT user-inputted. But it needs to be this way since I need to do this within the array, after it has been created. Thanks will give it a go and see if this helps me any.Nereen
SoLoGHoST - The return array_merge(...) is calling array_slice twice so that's a total of 3 function calls. You can replace it with what I wrote in my first comment (the return array_splice(...)). To answer your comment to @Sander Marechal, array_search is searching for the position of the key in the array and not whether or not it exists. The array_slice and array_splice both need to know the position and not the key.Hegelianism
@SoLoGHoSt - The line should have return in it actually. It should return on the next line (return $array); The other thing is in @Sander Marechal's code above, array_search($keys, $key) should be array_search($key, $keys);.Hegelianism
@Sander Marechal - The array_splice doesn't work, I think it's because the replacement parameter in the array_splice function does not PRESERVE the keys for the $new array. The way you had it worked PERFECT, cept you should have array_search($key, $keys;) instead. I used your method and adapted it better for my needs in the Answer below.Nereen
array_search($key, $keys); I meant to say.Nereen
@SoLoGHoST: You're correct. I've rolled back my edit and updated it with your correction.Intersection
N
0

Ok, after playing with it for quite some time, I finally got it working the way I want it. I am using certain keys within the $new_menu_buttons to decide on what to do. e.g.: position tells me if it is after or before, parent tells me where to search for the key at, and slug gives me the key to use for each new menu array that gets added. array_splice isn't working for me, so I'm using the array_merge approach instead which works just great. Here it is for anyone else who gets stuck with this problem.

function array_insert_buttons($buttons, $new_menu_buttons)
{
    foreach($new_menu_buttons as $new)
    {
        $keys = array_keys($buttons);
        $position = (int)array_search($new['parent'], $keys);

        if ($new['position'] == 'after')
            $position = $position + 1;

        // Create the new array in the correct format, using the slug!
        $new_button = array();
        $new_button[$new['slug']] = $new;

        // Don't need these keys anymore.
        unset($new_button[$new['slug']]['position']);
        unset($new_button[$new['slug']]['parent']);
        unset($new_button[$new['slug']]['slug']);

        // Putting it all together now.
        $buttons = array_merge(
            array_slice($buttons, 0, $position),
            $new_button,
            array_slice($buttons, $position)
        );
    }

    return $buttons;
}

Thanks for your help guys :)

Nereen answered 28/6, 2011 at 9:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.