<?php

/**
 * CMDB MultiEdit view.
 *
 * @package     i-doit
 * @subpackage  CMDB_Views
 * @author      Dennis Stücken <dstuecken@i-doit.de>
 * @version     0.9
 * @copyright   synetics GmbH
 * @license     http://www.i-doit.com/license
 */
class isys_cmdb_view_multiedit extends isys_cmdb_view
{
    /**
     *
     * @var  boolean
     */
    private $m_custom_category = false;

    /**
     * @var  isys_cmdb_dao_multiedit
     */
    private $m_dao = null;

    /**
     * @var  isys_cmdb_dao_connection
     */
    private $m_dao_connection = null;

    /**
     * @var int
     */
    private $m_iterator = 0;

    /**
     * @var null
     */
    private $m_multivalued = null;

    /**
     * @var array
     */
    private $m_recorded_unallowed_objects = [];

    /**
     * Array of smarty plugins used in this multiedit.
     *
     * @var   array
     */
    private $m_smarty_plugins = [];

    /**
     * Returns the view-ID.
     *
     * @return  integer
     */
    public function get_id()
    {
        return C__CMDB__VIEW__MULTIEDIT;
    }

    public function get_mandatory_parameters(&$l_gets)
    {
        $l_gets = [];
    }

    /**
     * Returns the view-name.
     *
     * @return  string
     */
    public function get_name()
    {
        return "MultiEdit";
    }

    public function get_optional_parameters(&$l_gets)
    {
        $l_gets = [];
    }

    public function handle_navmode($p_navmode)
    {
        ;
    }

    public function process()
    {
        $this->init();
    }

    /**
     * Inititialize this view
     */
    private function init()
    {
        global $index_includes, $g_comp_database;

        isys_auth_cmdb::instance()
            ->check(isys_auth::EXECUTE, 'MULTIEDIT');

        try {
            // Intialize multiedit dao.
            $this->m_dao = new isys_cmdb_dao_multiedit($g_comp_database);
            $this->m_dao_connection = new isys_cmdb_dao_connection($g_comp_database);

            // Activate editmode, disable default buttons.
            isys_application::instance()->template->activate_editmode()
                ->smarty_tom_add_rule('tom.content.bottom.buttons.*.p_bInvisible=1');

            isys_component_template_navbar::getInstance()
                ->set_js_onclick('Multiedit.save()', C__NAVBAR_BUTTON__SAVE)
                ->set_active(true, C__NAVBAR_BUTTON__SAVE);

            // Ajax request detected.
            if ($_POST["request"]) {
                try {
                    $this->handle_ajax_request($_POST);
                } catch (Exception $e) {
                    echo '<p class="exception m10 p5">' . $e->getMessage() . '</p><script type="text/javascript">$(\'listLoadButton\').show();</script>';
                }

                // Stop processing after handling the ajax request.
                die;
            }

            // Initialize variables
            $l_category_list = [];

            /**
             * Process ui.
             */
            $l_category_blacklist[C__CMDB__CATEGORY__TYPE_GLOBAL] = [
                C__CATG__CLUSTER_SERVICE               => true,
                C__CATG__ITS_LOGBOOK                   => true,
                C__CATG__IT_SERVICE_RELATIONS          => true,
                C__CATG__FILE                          => true,
                C__CATG__CLUSTER_SHARED_STORAGE        => true,
                C__CATG__CLUSTER_SHARED_VIRTUAL_SWITCH => true,
                C__CATG__LOGBOOK                       => true,
                C__CATG__LDEV_CLIENT                   => true,
                C__CATG__LDEV_SERVER                   => true,
                C__CATG__RELATION                      => true,
                C__CATG__SNMP                          => true,
                C__CATG__SOA_STACKS                    => true,
                C__CATG__VIRTUAL_TICKETS               => true,
                C__CATG__VIRTUAL_DEVICE                => true,
                C__CATG__VIRTUAL_SWITCH                => true,
                C__CATG__WORKFLOW                      => true,
                C__CATG__CABLING                       => true,
                C__CATG__DATABASE_ASSIGNMENT           => true,
                C__CMDB__SUBCAT__STORAGE__DEVICE       => true, // @todo  Remove in i-doit 1.12
                C__CATG__STORAGE_DEVICE                => true,
                C__CATG__GUEST_SYSTEMS                 => true,
                C__CATG__STORAGE                       => true,
                C__CATG__SANPOOL                       => true,
                C__CATG__NETWORK                       => true,
                C__CATG__VOIP_PHONE_LINE               => true,
                C__CATG__RAID                          => true,
                C__CATG__BACKUP__ASSIGNED_OBJECTS      => true,
                C__CATG__CONTRACT_ASSIGNMENT           => true,
                C__CATG__VIRTUAL_AUTH                  => true,
                C__CATG__LDAP_DN                       => true,
                C__CATG__CMK_TAG                       => true,
                C__CATG__CMK                           => true
            ];

            $l_category_blacklist[C__CMDB__CATEGORY__TYPE_SPECIFIC] = [
                C__CATS__PDU_OVERVIEW                              => true,
                C__CATS__FILE                                      => true,
                C__CMDB__SUBCAT__FILE_VERSIONS                     => true, // @todo  Remove in i-doit 1.12
                C__CATS__FILE_VERSIONS                             => true,
                C__CMDB__SUBCAT__FILE_ACTUAL                       => true, // @todo  Remove in i-doit 1.12
                C__CATS__FILE_ACTUAL                               => true,
                C__CMDB__SUBCAT__FILE_OBJECTS                      => true, // @todo  Remove in i-doit 1.12
                C__CATS__FILE_OBJECTS                              => true,
                C__CATS__APPLICATION_ASSIGNED_OBJ                  => true,
                C__CATS__RELATION_DETAILS                          => true,
                C__CATS__PARALLEL_RELATION                         => true,
                C__CATS__PDU_BRANCH                                => true,
                C__CATS__CHASSIS                                   => true,
                C__CATS__CHASSIS_CABLING                           => true,
                C__CATS__CHASSIS_DEVICES                           => true,
                C__CATS__CHASSIS_VIEW                              => true,
                C__CATS__DATABASE_SCHEMA                           => true,
                C__CATS__DATABASE_ACCESS                           => true,
                C__CATS__NET_IP_ADDRESSES                          => true,
                C__CATS__LAYER2_NET                                => true,
                C__CATS__LAYER2_NET_ASSIGNED_PORTS                 => true,
                C__CATS__LICENCE                                   => true,
                C__CATS__PERSON_LOGIN                              => true,
                C__CATS__PERSON_GROUP_MEMBERS                      => true,
                C__CATS__PERSON_NAGIOS                             => true,
                C__CATS__PERSON_GROUP_NAGIOS                       => true,
                C__CATS__NET                                       => true,
                C__CMDB__SUBCAT__EMERGENCY_PLAN                    => true, // @todo  Remove in i-doit 1.12
                C__CATS__EMERGENCY_PLAN_ATTRIBUTE                  => true,
                C__CATS__GROUP_TYPE                                => true,
                C__CATS__PDU                                       => true,
                C__CATS__PDU_BRANCH                                => true,
                C__CATS__PDU_OVERVIEW                              => true,
                C__CATS__ORGANIZATION_CONTACT_ASSIGNMENT           => true,
                C__CATS__ORGANIZATION_PERSONS                      => true,
                C__CATS__BASIC_AUTH                                => true,
                C__CATS__ROUTER                                    => true,
                C__CATS__SAN_ZONING                                => true,
                C__CATS__PERSON_MASTER                             => true,
                C__CATS__PERSON_GROUP_MASTER                       => true,
                C__CATS__ORGANIZATION_MASTER_DATA                  => true,
                C__CATS__CONTRACT_INFORMATION                      => true,
                C__CATS__CONTRACT_ALLOCATION                       => true,
                C__CATS__CLUSTER_SERVICE                           => true,
                C__CMDB__SUBCAT__EMERGENCY_PLAN_LINKED_OBJECT_LIST => true, // @todo  Remove in i-doit 1.12
                C__CATS__EMERGENCY_PLAN_LINKED_OBJECTS             => true,
                C__CMDB__SUBCAT__LICENCE_OVERVIEW                  => true, // @todo  Remove in i-doit 1.12
                C__CATS__LICENCE_OVERVIEW                          => true
            ];

            $l_categories = $this->m_dao->get_all_catg(null,
                ' AND isysgui_catg__type IN(' . isys_cmdb_dao_category::TYPE_EDIT . ', ' . isys_cmdb_dao_category::TYPE_FOLDER . ', ' . isys_cmdb_dao_category::TYPE_ASSIGN .
                ', ' . isys_cmdb_dao_category::TYPE_REAR . ')');
            $l_multivalued_categories = [];

            while ($l_row = $l_categories->get_row()) {
                $l_parent_folder = '';

                if (!isset($l_category_blacklist[C__CMDB__CATEGORY__TYPE_GLOBAL][$l_row['isysgui_catg__id']]) && !strstr($l_row['isysgui_catg__const'], '_ROOT') &&
                    !strstr($l_row['isysgui_catg__const'], '_NAGIOS')) {
                    if ($l_row['isysgui_catg__parent'] > 0) {
                        $l_parent_folder = isys_application::instance()->container->get('language')
                            ->get($this->m_dao->get_catg_name_by_id_as_string($l_row['isysgui_catg__parent']));
                    }

                    if ($l_parent_folder != '') {
                        $l_category_title = ' ' . isys_application::instance()->container->get('language')
                                ->get($l_row['isysgui_catg__title']) . ' (' . isys_application::instance()->container->get('language')
                                ->get('LC__MULTIEDIT__SUBCATEGORY_OF') . ' ' . $l_parent_folder . ')';
                    } else {
                        $l_category_title = ' ' . isys_application::instance()->container->get('language')
                                ->get($l_row['isysgui_catg__title']);
                    }

                    $l_category_list[isys_application::instance()->container->get('language')
                        ->get('LC__CMDB__GLOBAL_CATEGORIES')][C__CMDB__CATEGORY__TYPE_GLOBAL . '_' . $l_row['isysgui_catg__id']] = $l_category_title;

                    if ($l_row['isysgui_catg__list_multi_value'] > 0) {
                        $l_multivalued_categories[C__CMDB__CATEGORY__TYPE_GLOBAL . '_' . $l_row['isysgui_catg__id']] = true;

                        $l_sql = 'SELECT isys_property_2_cat__prop_key FROM isys_property_2_cat
                        WHERE isys_property_2_cat__cat_const = ' . $this->m_dao->convert_sql_text($l_row['isysgui_catg__const']) . '
                            AND isys_property_2_cat__prop_type = ' . $this->m_dao->convert_sql_int(C__PROPERTY_TYPE__STATIC) . '
                            AND isys_property_2_cat__prop_key != ' . $this->m_dao->convert_sql_text('description') . '
                            AND isys_property_2_cat__prop_provides & ' . $this->m_dao->convert_sql_int(C__PROPERTY__PROVIDES__MULTIEDIT);
                        $l_res_check = $this->m_dao->retrieve($l_sql);
                        $l_property_count = $l_res_check->num_rows();
                        if ($l_property_count === 1) {
                            $l_prop_key = $l_res_check->get_row_value('isys_property_2_cat__prop_key');
                            $l_cat_dao = $l_row['isysgui_catg__class_name']::instance($this->m_dao->get_database_component());
                            $l_properties = $l_cat_dao->get_properties();
                            $l_data = $l_properties[$l_prop_key];

                            if ($l_data[C__PROPERTY__INFO][C__PROPERTY__INFO__TYPE] == C__PROPERTY__INFO__TYPE__OBJECT_BROWSER ||
                                $l_data[C__PROPERTY__INFO][C__PROPERTY__INFO__TYPE] == C__PROPERTY__INFO__TYPE__N2M) {
                                if ($l_data[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['multiselection'] === true) {
                                    $l_multivalued_categories[C__CMDB__CATEGORY__TYPE_GLOBAL . '_' . $l_row['isysgui_catg__id']] = false;
                                }
                                continue;
                            }
                        } elseif ($l_property_count === 0) {
                            // Remove category from list, because there are no properties which are usable for the multiedit list
                            unset($l_category_list[isys_application::instance()->container->get('language')
                                    ->get('LC__CMDB__GLOBAL_CATEGORIES')][C__CMDB__CATEGORY__TYPE_GLOBAL . '_' . $l_row['isysgui_catg__id']]);
                        }
                    }
                }
            }

            unset($l_categories);

            $l_categories = $this->m_dao->get_all_cats();

            while ($l_row = $l_categories->get_row()) {
                if (!isset($l_category_blacklist[C__CMDB__CATEGORY__TYPE_SPECIFIC][$l_row['isysgui_cats__id']]) && !strstr($l_row['isysgui_cats__const'], '_ROOT') &&
                    !strstr($l_row['isysgui_cats__const'], '_ASSIGN')) {
                    $l_objtypes = $this->m_dao->get_object_types_by_category($l_row['isysgui_cats__id'], 's', false);
                    $l_objtype_names = '(';
                    foreach ($l_objtypes AS $l_objtype) {
                        $l_objtype_names .= isys_application::instance()->container->get('language')
                                ->get($this->m_dao->get_objtype_name_by_id_as_string($l_objtype)) . ', ';
                    }
                    $l_objtype_names = rtrim($l_objtype_names, ', ') . ')';
                    $l_category_list[isys_application::instance()->container->get('language')
                        ->get('LC__CMDB__SPECIFIC_CATEGORIES')][C__CMDB__CATEGORY__TYPE_SPECIFIC . '_' . $l_row['isysgui_cats__id']] = ' ' .
                        isys_application::instance()->container->get('language')
                            ->get($l_row['isysgui_cats__title']) . ' ' . $l_objtype_names;

                    if ($l_row['isysgui_cats__list_multi_value'] > 0) {
                        $l_multivalued_categories[C__CMDB__CATEGORY__TYPE_SPECIFIC . '_' . $l_row['isysgui_cats__id']] = true;

                        $l_sql = 'SELECT isys_property_2_cat__prop_key FROM isys_property_2_cat
                        WHERE isys_property_2_cat__cat_const = ' . $this->m_dao->convert_sql_text($l_row['isysgui_cats__const']) . '
                            AND isys_property_2_cat__prop_type = ' . $this->m_dao->convert_sql_int(C__PROPERTY_TYPE__STATIC) . '
                            AND isys_property_2_cat__prop_key != ' . $this->m_dao->convert_sql_text('description') . '
                            AND isys_property_2_cat__prop_provides & ' . $this->m_dao->convert_sql_int(C__PROPERTY__PROVIDES__MULTIEDIT);
                        $l_res_check = $this->m_dao->retrieve($l_sql);
                        $l_property_count = $l_res_check->num_rows();
                        if ($l_property_count === 1) {
                            $l_prop_key = $l_res_check->get_row_value('isys_property_2_cat__prop_key');
                            $l_cat_dao = $l_row['isysgui_cats__class_name']::instance($this->m_dao->get_database_component());
                            $l_properties = $l_cat_dao->get_properties();
                            $l_data = $l_properties[$l_prop_key];

                            if ($l_data[C__PROPERTY__INFO][C__PROPERTY__INFO__TYPE] == C__PROPERTY__INFO__TYPE__OBJECT_BROWSER ||
                                $l_data[C__PROPERTY__INFO][C__PROPERTY__INFO__TYPE] == C__PROPERTY__INFO__TYPE__N2M) {
                                if ($l_data[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['multiselection'] === true) {
                                    $l_multivalued_categories[C__CMDB__CATEGORY__TYPE_GLOBAL . '_' . $l_row['isysgui_catg__id']] = false;
                                }
                                continue;
                            }
                        } elseif ($l_property_count === 0) {
                            // Remove category from list, because there are no properties which are usable for the multiedit list
                            unset($l_category_list[isys_application::instance()->container->get('language')
                                    ->get('LC__CMDB__SPECIFIC_CATEGORIES')][C__CMDB__CATEGORY__TYPE_SPECIFIC . '_' . $l_row['isysgui_cats__id']]);
                        }
                    }
                }
            }

            unset($l_categories);

            $l_categories = $this->m_dao->get_all_catg_custom();
            $l_custom_fields_dao = new isys_custom_fields_dao($this->m_dao->get_database_component());

            while ($l_row = $l_categories->get_row()) {
                // @see  ID-4689  Check for the custom constant!
                $l_obj_types_res = $l_custom_fields_dao->get_assignments($l_row['isysgui_catg_custom__id']);
                $l_obj_types = '(';
                while ($l_obj_type_row = $l_obj_types_res->get_row()) {
                    if ($l_obj_type_row['isys_obj_type__id'] == C__OBJTYPE__GENERIC_TEMPLATE) {
                        continue;
                    }

                    $l_obj_types .= isys_application::instance()->container->get('language')
                            ->get($l_obj_type_row['isys_obj_type__title']) . ', ';
                }

                $l_obj_types = rtrim($l_obj_types, ', ') . ')';
                $l_category_list[isys_application::instance()->container->get('language')
                    ->get('LC__CMDB__CUSTOM_CATEGORIES')][C__CMDB__CATEGORY__TYPE_CUSTOM . '_' . $l_row['isysgui_catg_custom__id']] = ' ' .
                    isys_application::instance()->container->get('language')
                        ->get($l_row['isysgui_catg_custom__title']) . ' ' . $l_obj_types;
                if ($l_row['isysgui_catg_custom__list_multi_value'] > 0) {
                    $l_multivalued_categories[C__CMDB__CATEGORY__TYPE_CUSTOM . '_' . $l_row['isysgui_catg_custom__id']] = true;
                }
            }

            unset($l_categories);

            if (is_array($l_category_list[isys_application::instance()->container->get('language')
                ->get('LC__CMDB__SPECIFIC_CATEGORIES')])) {
                asort($l_category_list[isys_application::instance()->container->get('language')
                    ->get('LC__CMDB__SPECIFIC_CATEGORIES')]);
            }

            if (is_array($l_category_list[isys_application::instance()->container->get('language')
                ->get('LC__CMDB__GLOBAL_CATEGORIES')])) {
                asort($l_category_list[isys_application::instance()->container->get('language')
                    ->get('LC__CMDB__GLOBAL_CATEGORIES')]);
            }

            if (is_array($l_category_list[isys_application::instance()->container->get('language')
                ->get('LC__CMDB__CUSTOM_CATEGORIES')])) {
                asort($l_category_list[isys_application::instance()->container->get('language')
                    ->get('LC__CMDB__CUSTOM_CATEGORIES')]);
            }

            // Assign rules.
            $l_rules = [
                'C__MULTIEDIT__CATEGORY' => [
                    'p_arData'        => $l_category_list,
                    'p_bDbFieldNN'    => false,
                    'p_bSort'         => false,
                    'p_strSelectedID' => @$_GET[C__CMDB__GET__CATG]
                ],
                'C__MULTIEDIT__OBJECTS'  => [
                    isys_popup_browser_object_ng::C__MULTISELECTION   => true,
                    'p_strValue'                                      => @$_GET['preselect'],
                    isys_popup_browser_object_ng::C__CALLBACK__DETACH => "$('multiedit_list').update('');",
                ]
            ];

            isys_application::instance()->template->assign('multivalue_categories', isys_format_json::encode($l_multivalued_categories))
                ->smarty_tom_add_rules("tom.content.bottom.content", $l_rules);

            $l_error_message = false;

            // Some php limitation checks.
            if (extension_loaded('suhosin')) {
                $l_error_message[] = '* You should disable the php extension suhosin in order to use multiedit properly.';
            }

            if (intval(ini_get('post_max_size')) <= 4) {
                $l_error_message[] = '* You should increase your post_max_size php.ini setting in order to use multiedit. Current value is: ' . ini_get('post_max_size') .
                    ', Suggested value is 10M or higher.';
            }

            if (intval(ini_get('max_input_vars')) < 10000) {
                $l_error_message[] = isys_application::instance()->container->get('language')
                    ->get('LC__MULTIEDIT__ERROR_MAX_INPUT', ini_get('max_input_vars'));
            }

            if ($l_error_message) {
                isys_application::instance()->template->assign('message', '<p class="m10 p5 text-yellow">' . implode('<br />', $l_error_message) . '</p>');
            }
        } catch (isys_exception_cmdb $e) {
            throw $e;
        }

        $index_includes["contentbottomcontent"] = "modules/multiedit/main.tpl";
    }

    /**
     * Display the list after clicking on 'begin listedit' and saves the list.
     *
     * @param   array $p_data
     *
     * @throws  isys_exception_cmdb
     * @throws  Exception
     * @return  boolean
     */
    private function handle_ajax_request($p_data)
    {
        global $g_comp_database;

        try {

            $l_object_ids = [];

            if ($p_data['category'] < 0) {
                throw new isys_exception_cmdb(isys_application::instance()->container->get('language')
                    ->get('LC__MULTIEDIT__PLEASE_SELECT_CATEGORY'));
            }

            // Unpack request
            if (isset($p_data['object_ids'])) {
                $l_object_ids = isys_format_json::decode($p_data['object_ids'], true);
            }

            if (isset($p_data['C__MULTIEDIT__OBJECTS__HIDDEN'])) {
                $l_object_ids = isys_format_json::decode($p_data['C__MULTIEDIT__OBJECTS__HIDDEN'], true);
            }

            if (isset($p_data['filter'])) {
                $l_filter = $p_data['filter'];
            } else {
                $l_filter = '';
            }

            $l_changes_in_entry = isys_format_json::decode($p_data['changes_in_entry']);
            $l_changes_in_object = isys_format_json::decode($p_data['changes_in_object']);

            list($l_category_type, $l_category_id) = explode('_', $p_data['category']);

            if (!is_array($l_object_ids) || count($l_object_ids) == 0) {
                throw new isys_exception_cmdb(isys_application::instance()->container->get('language')
                    ->get('LC__MULTIEDIT__MINIMUM_OBJECT'));
            }

            // Switch category types.
            switch ($l_category_type) {
                case C__CMDB__CATEGORY__TYPE_GLOBAL:
                    $l_category = $this->m_dao->get_all_catg($l_category_id)
                        ->__to_array();
                    $l_category_class = $l_category['isysgui_catg__class_name'];
                    $l_source_table = $l_category['isysgui_catg__source_table'] . '_list';

                    if ($l_category['isysgui_catg__id'] == C__CATG__OBJECT) {
                        $l_source_table = 'isys_catg_location_list';
                    }

                    // Check if selected objects own the selected category and remove them from the listedit
                    $l_check = $this->check_objects_with_global_category($l_object_ids, $l_category_id);
                    break;
                case C__CMDB__CATEGORY__TYPE_SPECIFIC:
                    $l_category = $this->m_dao->get_all_cats($l_category_id)
                        ->__to_array();
                    $l_category_class = $l_category['isysgui_cats__class_name'];
                    $l_source_table = $l_category['isysgui_cats__source_table'];

                    // Check if selected objects own the selected category and remove them from the listedit
                    $l_check = $this->check_objects_with_specific_category($l_object_ids, $l_category_id);
                    break;
                case C__CMDB__CATEGORY__TYPE_CUSTOM;
                    $l_category = $this->m_dao->get_all_catg_custom($l_category_id)
                        ->__to_array();
                    $l_category_class = $l_category['isysgui_catg_custom__class_name'];
                    $l_source_table = $l_category['isysgui_catg_custom__source_table'];

                    $l_check = $this->check_object_with_custom_category($l_object_ids, $l_category_id);
                    break;
                default:
                    //'';
                    throw new isys_exception_cmdb('Wrong request: Could not determine type of selected category.');
                    break;
            }

            if (count($l_check) > 0) {
                foreach ($l_check AS $l_remove_obj_id) {
                    unset($l_object_ids[array_search($l_remove_obj_id, $l_object_ids)]);
                }
            }

            if (count($l_object_ids) == 0) {
                throw new isys_exception_cmdb(isys_application::instance()->container->get('language')
                    ->get('LC__MULTIEDIT__NO_CATEGORY_ASSIGNMENT'));
            }

            if (class_exists($l_category_class)) {
                /**
                 * Get instance of category dao
                 *
                 * @var $l_cat_dao isys_cmdb_dao_category_global
                 */
                $l_cat_dao = new $l_category_class($g_comp_database);
                if ($l_cat_dao->get_category_id() == C__CATG__CUSTOM_FIELDS && method_exists($l_cat_dao, 'set_catg_custom_id')) {
                    $l_cat_dao->set_catg_custom_id($l_category_id);
                    $this->m_custom_category = true;
                }

                unset($l_category);

                if (is_object($l_cat_dao)) {
                    // Handle request.
                    switch ($p_data['request']) {
                        case 'loadList':
                            // Render list and print it.
                            $l_list = $this->render_list($l_cat_dao, $l_object_ids, $l_source_table, $l_filter);

                            if (count($this->m_recorded_unallowed_objects) == count($l_object_ids)) {
                                echo '<p class="exception m10 p5">' . isys_application::instance()->container->get('language')
                                        ->get('LC__MULTIEDIT__NO_AUTHORIZATION_ON_SELECTED_OBJECTS') .
                                    '</p><script type="text/javascript">$(\'listLoadButton\').show();</script>';
                            } elseif ($l_list) {
                                if (count($this->m_recorded_unallowed_objects) > 0) {
                                    isys_notify::error(isys_application::instance()->container->get('language')
                                        ->get('LC__MULTIEDIT__NO_AUTHORIZATION_ON_SELECTED_OBJECTS_PLACEHOLDER', '<ul class=""><li>' .
                                            ((count($this->m_recorded_unallowed_objects) > 10) ? implode('</li><li>',
                                                    array_slice($this->m_recorded_unallowed_objects, 0, 10)) . '<li>...</li>' : implode('</li><li>',
                                                $this->m_recorded_unallowed_objects)) . '</li></ul>'));
                                }
                                echo $l_list;
                            } else {
                                echo '<p class="exception m10 p5">' . isys_application::instance()->container->get('language')
                                        ->get('LC__MULTIEDIT__NO_RESULTS') . '.</p><script type="text/javascript">$(\'listLoadButton\').show();</script>';
                            }
                            break;

                        case 'renderTemplateRow':
                            $this->m_iterator = $_POST['row_counter'];
                            $l_template_row = $this->render_list($l_cat_dao, $l_object_ids, $l_source_table, $l_filter, true);

                            if ($l_template_row !== false) {
                                echo $l_template_row;
                            } else {
                                isys_notify::warning('Neue Werte können über den Objektbrowser hinzugefügt werden.');
                            }

                            break;

                        case 'saveList':
                            if (!isset($l_changes_in_entry[0]) || !$l_changes_in_entry[0]) {
                                $l_changes_in_entry = [];
                            }

                            if (count($p_data['C__MULTIEDIT__NEW_ENTRIES']) > 0) {
                                // Prepare data for new entries
                                $l_new_entries = $p_data['C__MULTIEDIT__NEW_ENTRIES'];
                                $l_changes = count($l_new_entries);
                                $l_new_key = key($l_new_entries) + 1;

                                $p_data['changes_in_entry'] += $l_changes;
                                $p_data['changes_in_object'] += $l_changes;

                                // Iterate through every object and add it
                                foreach ($l_new_entries AS $l_ident => $l_val) {
                                    $l_remove_ident = null;
                                    if ($l_val === '-1') {
                                        foreach ($l_object_ids AS $l_obj_id) {
                                            // Check for rights before processing
                                            if (!isys_auth_cmdb_categories::instance()
                                                    ->has_rights_in_obj_and_category(isys_auth_cmdb::CREATE, $l_obj_id, $l_cat_dao->get_category_const())) {
                                                continue;
                                            }

                                            foreach ($p_data AS $l_key => $l_data) {
                                                if (is_array($l_data)) {
                                                    if (isset($l_data['new' . $l_ident])) {
                                                        $p_data[$l_key]['new' . $l_new_key] = $l_data['new' . $l_ident];
                                                    }
                                                }
                                            }
                                            $p_data['C__MULTIEDIT__NEW_ENTRIES'][$l_new_key] = $l_obj_id;
                                            $l_new_key++;
                                        }

                                        foreach ($p_data AS $l_key => $l_data) {
                                            if (is_array($l_data)) {
                                                if (isset($l_data['new' . $l_ident])) {
                                                    unset($p_data[$l_key]['new' . $l_ident]);
                                                }
                                            }
                                        }
                                        unset($p_data['C__MULTIEDIT__NEW_ENTRIES'][$l_ident]);
                                    }
                                }
                            }

                            // Save data.
                            $this->m_dao->save($l_cat_dao, $l_object_ids, $l_source_table, $p_data, $l_changes_in_entry, $l_changes_in_object);
                            break;

                        default:
                            throw new Exception("Invalid request! {" . $p_data . "}");
                    }
                } else {
                    throw new isys_exception_cmdb('Wrong request: Class \'' . $l_category_class . '\' does not exist.');
                }

                unset($l_category_class);
            }
        } catch (Exception $e) {
            throw $e;
        }

        return true;
    }

    /**
     * Render the multiedit list
     *
     * @param isys_cmdb_dao_category $p_cat_dao
     * @param array                  $p_objects
     * @param string                 $p_source_table
     * @param mixed                  $p_filter
     * @param boolean                $p_template
     *
     * @throws Exception
     * @throws isys_exception_database
     * @return string
     */
    private function render_list($p_cat_dao, array $p_objects, $p_source_table, $p_filter = '', $p_template = false)
    {
        if (!is_object($p_cat_dao)) {
            throw new Exception('Error rendering list. No category DAO instantiated.');
        }

        if (!$p_source_table) {
            $p_source_table = $p_cat_dao->get_source_table();

            if (!$p_source_table) {
                throw new Exception('Error: source_table not found. (Category-DAO: ' . get_class($p_cat_dao) . ')');
            }
        }

        $this->m_multivalued = $p_cat_dao->is_multivalued();

        // Initialize.
        $i = $this->m_iterator;
        $l_list = '<table class="mainTable border-bottom border-grey"><thead><tr>';

        if ($p_cat_dao->get_category_id() != C__CATG__GLOBAL) {
            $l_list .= '<th>' . isys_application::instance()->container->get('language')
                    ->get('LC_UNIVERSAL__OBJECT') . '</th>';
        }

        // Cache smarty plugins.
        $this->m_smarty_plugins = [
            'f_link'                        => new isys_smarty_plugin_f_text(),
            C__PROPERTY__UI__TYPE__TEXT     => new isys_smarty_plugin_f_text(),
            C__PROPERTY__UI__TYPE__TEXTAREA => new isys_smarty_plugin_f_textarea(),
            C__PROPERTY__UI__TYPE__DATE     => new isys_smarty_plugin_f_popup(),
            C__PROPERTY__UI__TYPE__DATETIME => new isys_smarty_plugin_f_popup(),
            C__PROPERTY__UI__TYPE__DIALOG   => new isys_smarty_plugin_f_dialog(),
            C__PROPERTY__UI__TYPE__POPUP    => new isys_smarty_plugin_f_popup(),
        ];

        /* Object specification condition */
        $l_condition = ' AND (isys_obj__id ' . $p_cat_dao->prepare_in_condition($p_objects) . ')';

        /* ..and it's properties */
        $l_properties = $p_cat_dao->get_properties(C__PROPERTY__WITH__VALIDATION);

        /* We don´t need the description property*/
        unset($l_properties['description']);

        // Remove unsupported properties
        foreach ($l_properties AS $l_key => $l_property) {
            if (!$l_property[C__PROPERTY__PROVIDES][C__PROPERTY__PROVIDES__MULTIEDIT]) {
                $l_unsupported_properties[$l_key] = $l_properties[$l_key];
                unset($l_properties[$l_key]);
            }
        }

        if ($p_cat_dao->get_category_id() == C__CATG__GLOBAL) {
            if (C__SYSID__READONLY === true) {
                unset($l_properties['sysid']);
            } else {
                unset($l_properties['sysid'][C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_bDisabled']);
            }
        } else {
            // Property should only be available in global category
            unset($l_properties['sysid']);
        }

        $l_assignment_category = false;
        $l_check_properties = [];

        // Check if its an assignment category.
        if (count($l_properties) == 1) {
            $l_check_properties = $l_properties;
            $l_check_properties = array_pop($l_check_properties);
            if ($l_check_properties[C__PROPERTY__FORMAT][C__PROPERTY__FORMAT__CALLBACK][1] == 'connection' ||
                $l_check_properties[C__PROPERTY__FORMAT][C__PROPERTY__FORMAT__CALLBACK][1] == 'object') {
                $l_assignment_category = true;
            }
        }

        if ($this->m_custom_category) {
            /* Prepare header */
            foreach ($l_properties as $l_key => $l_propdata) {
                if ($l_propdata[C__PROPERTY__PROVIDES][C__PROPERTY__PROVIDES__MULTIEDIT] &&
                    ($l_propdata[C__PROPERTY__PROVIDES][C__PROPERTY__PROVIDES__MULTIEDIT] && $l_propdata[C__PROPERTY__UI][C__PROPERTY__UI__TYPE] != 'html' &&
                        $l_propdata[C__PROPERTY__UI][C__PROPERTY__UI__TYPE] != 'hr')) {
                    $l_mandatory = '';

                    if (isset($l_propdata[C__PROPERTY__CHECK][C__PROPERTY__CHECK__MANDATORY]) && $l_propdata[C__PROPERTY__CHECK][C__PROPERTY__CHECK__MANDATORY]) {
                        $l_mandatory = '<strong class="red" title="' . isys_application::instance()->container->get('language')
                                ->get('LC__SETTINGS__CMDB__VALIDATION__BUTTON__MANDATORY') . '">*</strong>';
                    }

                    $l_list .= '<th>' . isys_application::instance()->container->get('language')
                            ->get($l_propdata[C__PROPERTY__INFO][C__PROPERTY__INFO__TITLE]) . $l_mandatory . '</th>';
                } else {
                    // Unset unsupported properties
                    unset($l_properties[$l_key]);
                }
            }

            $l_list .= '</tr></thead><tbody>';

            $l_smarty_params = [
                'p_onChange'                                      => 'Multiedit.overwriteAll(this);',
                isys_popup_browser_object_ng::C__CALLBACK__ACCEPT => 'Multiedit.overwriteAll(\'%%id%%\');',
                isys_popup_browser_object_ng::C__CALLBACK__DETACH => 'Multiedit.overwriteAll(\'%%id%%\');'
            ];

            /* Render first row */
            $l_list .= $this->render_row_custom_fields($l_properties, [
                'isys_obj__title' => (($p_cat_dao->get_category_id() == C__CATG__GLOBAL) ? isys_application::instance()->container->get('language')
                    ->get('LC__MULTIEDIT__ALL_OBJECTS') : '<strong>' . isys_application::instance()->container->get('language')
                        ->get('LC__MULTIEDIT__ALL_OBJECTS') . '</strong>')
            ], $p_cat_dao, $p_source_table, $i++, $l_smarty_params, 'skip');

            if ($p_template === true) {

                return $this->render_row_custom_fields($l_properties, [
                    $p_source_table . '__id' => 'new' . $this->m_iterator,
                    'objects'                => $p_objects
                ], $p_cat_dao, $p_source_table, $this->m_iterator, [], null, true);
            }

            foreach ($p_objects AS $l_object) {
                $l_list_data = $p_cat_dao->get_data(null, $l_object, null, $p_filter, C__RECORD_STATUS__NORMAL);

                $l_data = [];

                if ($l_list_data->num_rows() > 0) {
                    while ($l_list_row = $l_list_data->get_row()) {
                        $l_identifier = $l_list_row['isys_catg_custom_fields_list__field_type'] . '_' . $l_list_row['isys_catg_custom_fields_list__field_key'];

                        if (!isset($l_data[$l_list_row['isys_catg_custom_fields_list__data__id']]['isys_obj__title'])) {
                            $l_data[$l_list_row['isys_catg_custom_fields_list__data__id']]['isys_obj__title'] = $p_cat_dao->get_obj_name_by_id_as_string($l_list_row['isys_catg_custom_fields_list__isys_obj__id']);
                            $l_data[$l_list_row['isys_catg_custom_fields_list__data__id']]['isys_obj__id'] = $l_list_row['isys_catg_custom_fields_list__isys_obj__id'];
                        }

                        if ($l_properties[$l_identifier][C__PROPERTY__UI][C__PROPERTY__UI__PARAMS][isys_popup_browser_object_ng::C__MULTISELECTION] > 0) {
                            $l_data[$l_list_row['isys_catg_custom_fields_list__data__id']][$l_identifier][] = $l_list_row;
                        } else {
                            $l_data[$l_list_row['isys_catg_custom_fields_list__data__id']][$l_identifier] = $l_list_row;
                        }
                    }
                }

                if (count($l_data) > 0) {
                    foreach ($l_data AS $l_data_id => $l_data_arr) {
                        $l_list .= $this->render_row_custom_fields($l_properties, $l_data_arr, $p_cat_dao, $p_source_table, $i++, [], $l_data_id);
                    }
                } else {
                    $l_data['isys_obj__id'] = $l_object;
                    $l_data['isys_obj__title'] = $p_cat_dao->get_obj_name_by_id_as_string($l_object);
                    $l_list .= $this->render_row_custom_fields($l_properties, $l_data, $p_cat_dao, $p_source_table, $i++, [], null);
                }
            }

            return $l_list . '</tbody></table>';
        } else {
            /* Prepare header */
            foreach ($l_properties as $l_key => $l_propdata) {
                if (($l_propdata[C__PROPERTY__PROVIDES][C__PROPERTY__PROVIDES__MULTIEDIT] && ($l_propdata[C__PROPERTY__PROVIDES][C__PROPERTY__PROVIDES__MULTIEDIT] ||
                        $l_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_object_ng' ||
                        $l_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_object_relation' ||
                        $l_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_cable_connection_ng' ||
                        $l_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_location'))) {
                    $l_mandatory = '';

                    if (isset($l_propdata[C__PROPERTY__CHECK][C__PROPERTY__CHECK__MANDATORY]) && $l_propdata[C__PROPERTY__CHECK][C__PROPERTY__CHECK__MANDATORY]) {
                        $l_mandatory = '<strong class="red" title="' . isys_application::instance()->container->get('language')
                                ->get('LC__SETTINGS__CMDB__VALIDATION__BUTTON__MANDATORY') . '">*</strong>';
                    }

                    $l_list .= '<th>' . isys_application::instance()->container->get('language')
                            ->get($l_propdata[C__PROPERTY__INFO][C__PROPERTY__INFO__TITLE]) . $l_mandatory . '</th>';
                } else {
                    // Unset unsupported properties
                    unset($l_properties[$l_key]);
                }
            }

            $l_list .= '</tr></thead><tbody>';

            /* Render first row */
            $l_list .= $this->render_row($l_properties, [
                'isys_obj__title'        => (($p_cat_dao->get_category_id() == C__CATG__GLOBAL) ? isys_application::instance()->container->get('language')
                    ->get('LC__MULTIEDIT__ALL_OBJECTS') : '<strong>' . isys_application::instance()->container->get('language')
                        ->get('LC__MULTIEDIT__ALL_OBJECTS') . '</strong>'),
                $p_source_table . '__id' => 'skip'
            ], $p_cat_dao, $p_source_table, $i++, [
                'p_onChange'                                      => 'Multiedit.overwriteAll(this);',
                isys_popup_browser_object_ng::C__CALLBACK__ACCEPT => 'Multiedit.overwriteAll(\'%%id%%\');',
                isys_popup_browser_object_ng::C__CALLBACK__DETACH => 'Multiedit.overwriteAll(\'%%id%%\');'
            ]);

            if ($p_template === true) {
                if ($l_assignment_category === true) {
                    return false;
                }

                return $this->render_row($l_properties, [
                    $p_source_table . '__id' => 'new' . $this->m_iterator,
                    'objects'                => $p_objects
                ], $p_cat_dao, $p_source_table, $this->m_iterator, [], true);
            }
        }

        // Iterate through data.
        if ($this->m_multivalued) {
            //@todo solution for categories which list consists only of objects, at the moment each object connection is displayed.

            // Get category data.
            if ($p_cat_dao->get_category_id() != C__CATG__APPLICATION) {
                $l_list_data = $p_cat_dao->get_data(null, $p_objects, '', $p_filter, C__RECORD_STATUS__NORMAL);
            } else {
                if (method_exists($p_cat_dao, 'get_data_ng')) {
                    $l_list_data = $p_cat_dao->get_data_ng(null, $p_objects,
                        ' AND reference.isys_obj__title LIKE ' . $p_cat_dao->convert_sql_text('%' . addslashes($p_filter) . '%') . ' ', null, C__RECORD_STATUS__NORMAL);
                }
            }

            if (isset($l_list_data) && $l_list_data instanceof isys_component_dao_result) {
                /* object pool of objects already processed */
                $l_objectpool = [];

                if ($l_assignment_category) {
                    $l_list .= $this->render_row_object_browser($l_check_properties, $p_objects, $l_list_data, $p_cat_dao, $p_source_table, $i++);
                } else {
                    /* Return false if there where no results found */
                    //if ($l_list_data->num_rows() === 0) return false;
                    if ($l_list_data->num_rows() > 0) {
                        /* Iterate through category rows */
                        while ($l_row = $l_list_data->get_row()) {
                            /* Render this row */
                            $l_list .= $this->render_row($l_properties, $l_row, $p_cat_dao, $p_source_table, $i++);
                        }
                    }
                }

                unset($l_objectpool);
            }

        } else {
            // Separate iteration for single value, because if theres no list entry for a single value category, get_data won't return any row.
            $l_list_data = $this->m_dao->retrieve('SELECT * FROM isys_obj WHERE TRUE ' . $l_condition . ' ORDER BY isys_obj__title ASC;');

            if ($l_assignment_category) {
                $l_list_data = $p_cat_dao->get_data(null, $p_objects, null, null, C__RECORD_STATUS__NORMAL);
                $l_list .= $this->render_row_object_browser($l_check_properties, $p_objects, $l_list_data, $p_cat_dao, $p_source_table, $i++);
            } else {
                while ($l_row = $l_list_data->get_row()) {
                    // Get data for current object.
                    $l_category_data = $p_cat_dao->get_data(null, $l_row['isys_obj__id'], '', $p_filter, C__RECORD_STATUS__NORMAL);

                    $l_check = true;

                    // See ID-3022
                    if (isys_strlen(trim($p_filter)) !== 0) {
                        // See ID-2964
                        $l_check = !!count($l_category_data);
                    }

                    if ($l_check) {
                        $l_category_row = $l_category_data->get_row();
                        $l_category_row['isys_obj__title'] = $l_row['isys_obj__title'];
                        $l_category_row['isys_obj__id'] = $l_row['isys_obj__id'];

                        $l_list .= $this->render_row($l_properties, $l_category_row, $p_cat_dao, $p_source_table, $i++);
                    }

                    // Free some memory.
                    $l_category_data->free_result();
                    unset($l_category_row);
                }
            }
        }

        return $l_list . '</tbody></table>';
    }

    /**
     * Renders a row with an object browser for assignment categories.
     *
     * @param   array                     $p_property
     * @param   array                     $p_objects
     * @param   isys_component_dao_result $p_res
     * @param   isys_cmdb_dao_category    $p_cat_dao
     * @param   string                    $p_source_table
     * @param   integer                   $p_iterator
     *
     * @return  string
     * @author  Van Quyen Hoang <qhoang@i-doit.org>
     */
    private function render_row_object_browser($p_property, $p_objects, $p_res, $p_cat_dao, $p_source_table, $p_iterator)
    {
        // Get right field.
        if (isset($p_property[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD_ALIAS])) {
            $l_field = $p_property[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD_ALIAS];
        } else {
            $l_field = $p_property[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD];
        }

        $l_arr_objects = [];
        /* Get Objects */
        while ($l_row = $p_res->get_row()) {
            if ($p_cat_dao->get_category_id() == C__CATG__OBJECT) {
                // @todo find a better solution
                $l_arr_objects[$l_row['isys_catg_location_list__parentid']][] = (int)$l_row[$l_field];
            } elseif ($p_cat_dao->get_category_id() == C__CATG__PERSON_ASSIGNED_WORKSTATION) {
                // @todo find a better solution
                $l_arr_objects[$l_row[$p_source_table . '__isys_obj__id__parent']][] = (int)$l_row[$l_field];
            } elseif ($p_cat_dao->get_category_id() == C__CATG__ASSIGNED_LOGICAL_UNIT) {
                // @todo find a better solution
                $l_arr_objects[$l_row['isys_catg_logical_unit_list__isys_obj__id__parent']][] = (int)$l_row[$l_field];
            } elseif ($p_cat_dao->get_category_id() == C__CATG__CLUSTER_MEMBERSHIPS || $p_cat_dao->get_category_id() == C__CATG__IT_SERVICE ||
                $p_cat_dao->get_category_id() == C__CATG__GROUP_MEMBERSHIPS) {
                // @todo find a better solution
                $l_arr_objects[$l_row['isys_connection__isys_obj__id']][] = (int)$l_row[$l_field];
            } elseif ($p_cat_dao->get_object_id_field() != 'isys_obj__id') {
                $l_arr_objects[$l_row[$p_cat_dao->get_object_id_field()]][] = (int)$l_row[$p_cat_dao->get_connected_object_id_field()];
            } elseif (((isset($p_property[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][0]) &&
                        $p_property[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][0] == 'isys_connection') ||
                    $p_property[C__PROPERTY__FORMAT][C__PROPERTY__FORMAT__CALLBACK][1] == 'connection') && $l_row[$l_field] > 0) {
                $l_arr_objects[$l_row[$p_source_table . '__isys_obj__id']][] = (int)$this->m_dao_connection->get_object_id_by_connection($l_row[$l_field]);
            } else {
                $l_arr_objects[$l_row[$p_source_table . '__isys_obj__id']][] = (int)$l_row[$l_field];
            }
        }

        $l_list = '';
        $l_empty_value = isys_tenantsettings::get('gui.empty_value', '-');
        foreach ($p_objects as $l_object) {
            // Get plugin name.
            $l_name = $p_property[C__PROPERTY__UI][C__PROPERTY__UI__ID] . '[object-' . $l_object . ']';

            // Smarty base param initialization.
            $l_params = array_merge([
                'name'              => $l_name,
                'p_onChange'        => "Multiedit.changed(this, '" . $l_name . "');Multiedit.changesInObject('" . $l_object . "');",
                'p_bInfoIconSpacer' => false,
                'editMode'          => true,
                'p_strClass'        => $p_property[C__PROPERTY__UI][C__PROPERTY__UI__ID],
            ], $p_property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]);

            if (isset($l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT])) {
                $l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT] = str_replace('%%id%%', $p_property[C__PROPERTY__UI][C__PROPERTY__UI__ID],
                    $l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT]);
            }

            if (isset($l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH])) {
                $l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH] = str_replace('%%id%%', $p_property[C__PROPERTY__UI][C__PROPERTY__UI__ID],
                    $l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH]);
            }

            if ($p_property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_object_ng' ||
                $p_property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_object_relation' ||
                $p_property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_cable_connection_ng' ||
                $p_property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_location') {
                $l_params[isys_popup_browser_object_ng::C__EDIT_MODE] = true;

                if (isset($l_arr_objects[$l_object])) {
                    if ($l_params['multiselection'] === true) {
                        $l_params['p_strSelectedID'] = $l_arr_objects[$l_object];
                        unset($l_params['p_strValue']);
                    } else {
                        $l_params['p_strValue'] = array_pop($l_arr_objects[$l_object]);
                        unset($l_params['p_strSelectedID']);
                    }
                } else {
                    $l_strValue = true;
                    $l_value = null;
                    $l_obj = null;
                    if (isset($l_params['p_strValue']) && is_object($l_params['p_strValue']) && is_a($l_params['p_strValue'], 'isys_callback')) {
                        $l_obj = $l_params['p_strValue'];
                        unset($l_params['p_strSelectedID']);
                    } elseif (isset($l_params['p_strSelectedID']) && is_object($l_params['p_strSelectedID']) && is_a($l_params['p_strSelectedID'], 'isys_callback')) {
                        $l_obj = $l_params['p_strSelectedID'];
                        $l_strValue = false;
                        unset($l_params['p_strValue']);
                    }

                    if (is_object($l_obj)) {
                        $l_value = $l_obj->execute(isys_request::factory()
                            ->set_object_id($l_object));
                        if (is_object($l_value) && is_a($l_value, 'isys_component_dao_result')) {
                            $l_new_value = [];
                            while ($l_vrow = $l_value->get_row()) {
                                $l_new_value[] = array_pop($l_vrow);
                            }
                            $l_value = $l_new_value;
                        }
                    }

                    if ($l_strValue) {
                        $l_params['p_strValue'] = $l_value;
                    } else {
                        $l_params['p_strSelectedID'] = $l_value;
                    }
                }

                $l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT] .= "Multiedit.changed(null, '" . ($l_params['id'] ?: $l_params['name']) . "');Multiedit.changesInObject('" . $l_object . "');";
                $l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH] .= "Multiedit.changed(null, '" . ($l_params['id'] ?: $l_params['name']) . "');Multiedit.changesInObject('" . $l_object . "');";
            }
            $l_title = $p_cat_dao->get_obj_name_by_id_as_string($l_object);

            // Check rights
            if ($l_object !== null && !isys_auth_cmdb::instance()
                    ->has_rights_in_obj_and_category(isys_auth::EDIT, $l_object, $p_cat_dao->get_category_const())) {
                $this->m_recorded_unallowed_objects[$l_object] = $l_title . ' (' . isys_application::instance()->container->get('language')
                        ->get($p_cat_dao->get_objtype_name_by_id_as_string($p_cat_dao->get_objTypeID($l_object))) . ')';
                continue;
            }

            $l_list .= '<tr class="' . ($p_iterator % 2 == 0 ? 'CMDBListElementsEven' : 'CMDBListElementsOdd') . '" style="cursor:default;">';

            $l_list .= '<td title="' . $l_title . '">' . '<input type="hidden" name="category_data[object-' . $l_object . ']" value="' . $l_object . '" /> ' .
                '<input type="hidden" name="sort-dummy" value="' . $l_title . '" /> ' . isys_glob_str_stop($l_title, 35) . '</td>';

            if (method_exists($this->m_smarty_plugins[$p_property[C__PROPERTY__UI][C__PROPERTY__UI__TYPE]], 'navigation_edit')) {
                $l_list .= '<td>' .
                    $this->m_smarty_plugins[$p_property[C__PROPERTY__UI][C__PROPERTY__UI__TYPE]]->navigation_edit(isys_application::instance()->template, $l_params) . '</td>';
            } else {
                $l_list .= '<td>' . $l_empty_value . '</td>';
            }

            $l_list .= '</tr>';
        }

        return $l_list;
    }

    /**
     * Renders a single row
     *
     * @param                        $p_properties
     * @param                        $p_row
     * @param isys_cmdb_dao_category $p_cat_dao
     * @param                        $p_source_table
     * @param int                    $p_iterator
     * @param array                  $p_smarty_params
     *
     * @return string
     */
    private function render_row($p_properties, $p_row, $p_cat_dao, $p_source_table, $p_iterator = 0, $p_smarty_params = [], $p_template = false)
    {
        if (!isset($p_row[$p_source_table . '__id']) && isset($p_row['isys_obj__id'])) {
            /* Mark missing category entries with "new-" prefix */
            $p_row[$p_source_table . '__id'] = 'new-' . $p_row['isys_obj__id'];
        }

        $l_list = '<tr class="' . ($p_iterator % 2 == 0 ? 'CMDBListElementsEven' : 'CMDBListElementsOdd') . ' ' . ($p_template === true ? 'NewEntry' : '') .
            '" style="cursor:default;" data-category-id="' . $p_row[$p_source_table . '__id'] . '">';

        if ($p_template === false) {
            if (!empty($p_row['isys_obj__title']) && isset($p_row[$p_cat_dao->get_object_id_field()])) {
                $l_title = $p_cat_dao->get_obj_name_by_id_as_string($p_row[$p_cat_dao->get_object_id_field()]);
            } else {
                $l_title = $p_row['isys_obj__title'];
            }
            // Check rights
            if ($p_row['isys_obj__id'] !== null && !isys_auth_cmdb::instance()
                    ->has_rights_in_obj_and_category(isys_auth::EDIT, $p_row['isys_obj__id'], $p_cat_dao->get_category_const())) {
                $this->m_recorded_unallowed_objects[$p_row['isys_obj__id']] = $l_title . ' (' . isys_application::instance()->container->get('language')
                        ->get($p_cat_dao->get_objtype_name_by_id_as_string($p_cat_dao->get_objTypeID($p_row['isys_obj__id']))) . ')';

                return '';
            }

            /* Show object title if category is not the global one */
            if ($p_cat_dao->get_category_id() != C__CATG__GLOBAL) {
                $l_list .= '<td title="' . $l_title . '">' . '<input type="hidden" name="category_data[' . $p_row[$p_source_table . '__id'] . '-' . $p_row['isys_obj__id'] .
                    ']" value="' . $p_row[$p_source_table . '__id'] . '" /> ' . '<input type="hidden" name="sort-dummy" value="' . $l_title . '" /> ' .
                    isys_glob_str_stop($l_title, 35) . '</td>';
            }
        } else {
            // First column for the object chosen dialog
            $l_list .= '<td >' . '<input type="hidden" name="category_data[' . $p_row[$p_source_table . '__id'] . ']" value="' . $p_row[$p_source_table . '__id'] . '" /> ';

            $l_objects = $p_row['objects'];
            $l_arr = ['-1' => 'Alle Objekte'];

            foreach ($l_objects AS $l_obj_id) {
                // Check for rights before adding object to selection
                if (isys_auth_cmdb_categories::instance()->has_rights_in_obj_and_category(isys_auth::CREATE, $l_obj_id, $p_cat_dao->get_category_const())) {
                    $l_arr[$l_obj_id] = $this->m_dao->get_obj_name_by_id_as_string($l_obj_id);
                }
            }

            $l_params = [
                'chosen'            => 1,
                'p_arData'          => $l_arr,
                'p_bDbFieldNN'      => true,
                'p_bSort'           => false,
                'p_strSelectedID'   => '-1',
                'p_bInfoIconSpacer' => 0,
                'p_strClass'        => 'input-mini',
                'p_bEnableMetaMap'  => 0,
                'name'              => 'C__MULTIEDIT__NEW_ENTRIES[' . $this->m_iterator . ']'
            ];

            $l_list .= $this->m_smarty_plugins[C__PROPERTY__UI__TYPE__DIALOG]->navigation_edit(isys_application::instance()->template, $l_params);

            $l_list .= '</td>';
        }

        /* Iterate through properties */
        foreach ($p_properties as $l_propdata) {
            $l_list .= $this->render_cell($l_propdata, $p_row, $p_source_table, $p_smarty_params, $p_properties);
        }
        $l_list .= '</tr>';

        return $l_list;
    }

    /**
     * @param array                                  $p_properties
     * @param array                                  $p_row
     * @param isys_cmdb_dao_category_g_custom_fields $p_cat_dao
     * @param string                                 $p_source_table
     * @param int                                    $p_iterator
     * @param array                                  $p_smarty_params
     * @param null                                   $p_data_id
     *
     * @return string
     */
    private function render_row_custom_fields(
        $p_properties,
        $p_row,
        $p_cat_dao,
        $p_source_table,
        $p_iterator = 0,
        $p_smarty_params = [],
        $p_data_id = null,
        $p_template = false
    ) {
        if (!empty($p_row['isys_obj__title']) && isset($p_row[$p_cat_dao->get_object_id_field()])) {
            $l_title = $p_cat_dao->get_obj_name_by_id_as_string($p_row[$p_cat_dao->get_object_id_field()]);
        } else {
            $l_title = $p_row['isys_obj__title'];
        }

        // @see ID-4689 Check rights of the custom category
        $customCategoryConst = $p_cat_dao->get_category_info($p_cat_dao->get_catg_custom_id())['isysgui_catg_custom__const'];

        if ($p_row['isys_obj__id'] !== null && !isys_auth_cmdb::instance()
                ->has_rights_in_obj_and_category(isys_auth::EDIT, $p_row['isys_obj__id'], $customCategoryConst)) {
            $this->m_recorded_unallowed_objects[$p_row['isys_obj__id']] = $l_title . ' (' . isys_application::instance()->container->get('language')
                    ->get($p_cat_dao->get_objtype_name_by_id_as_string($p_cat_dao->get_objTypeID($p_row['isys_obj__id']))) . ')';

            return '';
        }

        $l_list = '<tr class="' . ($p_iterator % 2 == 0 ? 'CMDBListElementsEven' : 'CMDBListElementsOdd') . '" data-category-id="' . $p_data_id . '" style="cursor:default;">';

        if ($p_template === false) {
            /* Show object title if category is not the global one */
            $l_list .= '<td title="' . $l_title . '">' . '<input type="hidden" name="category_data[' . $p_data_id . '-' . $p_row['isys_obj__id'] . ']" value="' . $p_data_id .
                '" /> ' . '<input type="hidden" name="sort-dummy" value="' . $l_title . '" /> ' . isys_glob_str_stop($l_title, 35) . '</td>';
        } else {
            $l_list .= '<td >' . '<input type="hidden" name="category_data[' . $p_row[$p_source_table . '__id'] . ']" value="' . $p_row[$p_source_table . '__id'] . '" /> ';

            $l_objects = $p_row['objects'];
            $l_arr = ['-1' => 'Alle Objekte'];

            foreach ($l_objects AS $l_obj_id) {
                if (isys_auth_cmdb::instance()->has_rights_in_obj_and_category(isys_auth_cmdb::CREATE, $l_obj_id, $customCategoryConst)) {
                    $l_arr[$l_obj_id] = $this->m_dao->get_obj_name_by_id_as_string($l_obj_id);
                }
            }

            $l_params = [
                'chosen'            => 1,
                'p_arData'          => $l_arr,
                'p_bDbFieldNN'      => true,
                'p_bSort'           => false,
                'p_strSelectedID'   => '-1',
                'p_bInfoIconSpacer' => 0,
                'p_strClass'        => 'input-mini',
                'p_bEnableMetaMap'  => 0,
                'name'              => 'C__MULTIEDIT__NEW_ENTRIES[' . $this->m_iterator . ']'
            ];

            $l_list .= $this->m_smarty_plugins[C__PROPERTY__UI__TYPE__DIALOG]->navigation_edit(isys_application::instance()->template, $l_params);

            $l_list .= '</td>';
        }

        /* Mark missing category entries with "new-" prefix */
        if (!isset($p_data_id)) {
            $p_data_id = 'new';
        }

        /* Iterate through properties */
        foreach ($p_properties as $l_prop_id => $l_propdata) {
            $l_list .= $this->render_cell_custom_fields($l_propdata, $p_row, $p_smarty_params, $l_prop_id, $p_data_id, $p_template);
        }
        $l_list .= '</tr>';

        return $l_list;
    }

    /**
     * @param   array   $p_propdata
     * @param   array   $p_row
     * @param   array   $p_smarty_params
     * @param   string  $p_prop_key
     * @param   mixed   $p_data_id
     * @param   boolean $p_template
     *
     * @param   boolean $p_template
     *
     * @return  string
     * @throws  \idoit\Exception\JsonException
     */
    private function render_cell_custom_fields($p_propdata = [], $p_row = [], $p_smarty_params = [], $p_prop_key = '', $p_data_id = null, $p_template = false)
    {
        $l_list = '';

        // Get plugin name.
        if ($p_data_id != 'skip' && isset($p_row['isys_obj__id'])) {
            $l_name = $p_prop_key . '[' . $p_data_id . '-' . $p_row['isys_obj__id'] . ']';
        } elseif ($p_template === true) {
            $l_name = $p_prop_key . '[' . $p_data_id . $this->m_iterator . ']';

        } else {
            $l_name = $p_prop_key . '[skip]';
        }

        if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS][isys_popup_browser_object_ng::C__MULTISELECTION] > 0 && $p_data_id != 'skip') {
            $l_strValue = [];
            if (isset($p_row[$p_prop_key])) {
                foreach ($p_row[$p_prop_key] AS $l_data) {
                    $l_strValue[] = $l_data['isys_catg_custom_fields_list__field_content'];
                }
            }
            $l_strValue = isys_format_json::encode($l_strValue);

            $l_plugin_params = [
                'name'              => $l_name,
                'p_onChange'        => "Multiedit.changed(this, '" . $l_name . "');Multiedit.changesInEntry('" . $p_data_id . "');",
                'p_bInfoIconSpacer' => false,
                'editMode'          => true,
                'p_strClass'        => $p_prop_key,
                'p_strValue'        => $l_strValue
            ];
        } else {
            $l_plugin_params = [
                'name'              => $l_name,
                'p_onChange'        => "Multiedit.changed(this, '" . $l_name . "');Multiedit.changesInEntry('" . $p_data_id . "');",
                'p_bInfoIconSpacer' => false,
                'editMode'          => true,
                'p_strClass'        => $p_prop_key,
                'p_strValue'        => $p_row[$p_prop_key]['isys_catg_custom_fields_list__field_content'],
                'p_strSelectedID'   => $p_row[$p_prop_key]['isys_catg_custom_fields_list__field_content'],
            ];
        }

        // Smarty base param initialization.
        $l_params = array_merge($l_plugin_params, $p_smarty_params);

        switch ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__TYPE]) {
            case 'datetime':
            case 'popup':
            case 'f_popup':
                $l_smarty_plugin = $this->m_smarty_plugins[C__PROPERTY__UI__TYPE__POPUP];
                $l_params['p_strPopupType'] = ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['popup'] !=
                    'browser_object') ? $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['popup'] : 'browser_object_ng';

                if (isset($l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT])) {
                    $l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT] = str_replace('%%id%%', $p_prop_key,
                        $l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT]);
                } else {
                    $l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT] .= "Multiedit.changed(null, '" . ($l_params['id'] ?: $l_params['name']) . "');Multiedit.changesInEntry('" . $p_data_id . "');";
                }

                if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['popup'] == 'browser_object') {
                    if (isset($l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH])) {
                        $l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH] = str_replace('%%id%%', $p_prop_key,
                            $l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH]);
                    } else {
                        $l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH] .= "Multiedit.changed(null, '" . ($l_params['id'] ?: $l_params['name']) . "');Multiedit.changesInEntry('" . $p_data_id . "');";
                    }

                    if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS][isys_popup_browser_object_ng::C__MULTISELECTION]) {
                        $l_params[isys_popup_browser_object_ng::C__MULTISELECTION] = 1;
                    }
                } elseif ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['popup'] == 'dialog_plus') {
                    if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['multiselection']) {
                        if (isys_format_json::is_json_array($l_params['p_strValue'])) {
                            $l_params['p_strValue'] = implode(',', isys_format_json::decode($l_params['p_strValue']));
                        }

                        $l_params['p_strSelectedID'] = $l_params['p_strValue'];
                        $l_params['p_multiple'] = true;
                        $l_params['chosen'] = true;
                        $l_params['p_bDbFieldNN'] = true;
                    }

                    $l_params['p_strTable'] = 'isys_dialog_plus_custom';
                    $l_params['p_identifier'] = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['identifier'];
                    $l_params['condition'] = 'isys_dialog_plus_custom__identifier = \'' . $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['identifier'] . '\'';
                } elseif ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['popup'] == 'calendar') {
                    $l_params['cellCallback'] = 'function(){$(this._relative).simulate(\'change\');}';
                }
                break;

            case 'dialog':
            case 'f_dialog':
                $l_smarty_plugin = $this->m_smarty_plugins[C__PROPERTY__UI__TYPE__DIALOG];
                if (isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['extra'])) {
                    $l_params['p_bDbFieldNN'] = 1;
                    // Yes-No Dialog
                    $l_params['p_arData'] = [
                        'LC__UNIVERSAL__YES' => isys_application::instance()->container->get('language')
                            ->get('LC__UNIVERSAL__YES'),
                        'LC__UNIVERSAL__NO'  => isys_application::instance()->container->get('language')
                            ->get('LC__UNIVERSAL__NO')
                    ];
                } else if (isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData'])) {
                    $l_params['p_arData'] = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData'];
                }
                break;

            case 'text':
            case 'f_link':
            case 'f_text':
            default:
                $l_smarty_plugin = $this->m_smarty_plugins[C__PROPERTY__UI__TYPE__TEXT];

                if (isset($p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__ENCRYPT]) && $p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__ENCRYPT] === true) {
                    $l_smarty_plugin = new isys_smarty_plugin_f_password();
                    $l_params['p_strValue'] = isys_helper_crypt::encrypt($l_params['p_strValue']);
                }
                break;
        }

        // @deprecated  Do not set sizes like this, when input-groups are being used.
        // Set size, so that every form field looks same and is not too big.
        // $l_params['p_strStyle'] = 'width:' . isys_tenantsettings::get('cmdb.multiedit.text-size-in-px', '140') . 'px;';

        // Set some further defaults.
        if ($p_data_id == 'skip') {
            if (!($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['popup'] == 'dialog_plus' &&
                $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['multiselection'])) {
                $l_params['p_strSelectedID'] = '-1';
                $l_params['p_bDbFieldNN'] = 0;
            }
        }

        if (method_exists($l_smarty_plugin, 'navigation_edit')) {
            $l_list .= '<td>' . $l_smarty_plugin->navigation_edit(isys_application::instance()->template, $l_params) . '</td>';
        }

        return $l_list;
    }

    /**
     * Renders a single cell
     *
     * @param array  $p_propdata
     * @param array  $p_row
     * @param string $p_source_table
     * @param array  $p_smarty_params
     * @param array  $p_properties
     *
     * @return string
     */
    private function render_cell($p_propdata = [], $p_row = [], $p_source_table = '', $p_smarty_params = [], $p_properties = [])
    {
        global $g_convert;

        $l_list = '';
        $l_used_plugin = null;

        if ((($p_propdata[C__PROPERTY__PROVIDES][C__PROPERTY__PROVIDES__MULTIEDIT] ||
            $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_object_ng' ||
            $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_object_relation' ||
            $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_cable_connection_ng' ||
            $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_location'))) {
            $l_empty_value = isys_tenantsettings::get('gui.empty_value', '-');

            /* Get plugin name */
            if ($p_row[$p_source_table . '__id'] != 'skip' && isset($p_row['isys_obj__id'])) {
                $l_name = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID] . '[' . $p_row[$p_source_table . '__id'] . '-' . $p_row['isys_obj__id'] . ']';
            } else {
                $l_name = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID] . '[' . $p_row[$p_source_table . '__id'] . ']';
            }

            // Smarty base param initialization.
            $l_params = array_merge([
                'name'              => $l_name,
                'p_onChange'        => "Multiedit.changed(this, '" . $l_name . "');Multiedit.changesInEntry('" . $p_row[$p_source_table . '__id'] . "');",
                'p_bInfoIconSpacer' => false,
                'editMode'          => true,
                'p_strValue'        => ((empty($p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD_ALIAS])) ? $p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD]] : $p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD_ALIAS]]),
                'p_strSelectedID'   => ((empty($p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD_ALIAS])) ? $p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD]] : $p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD_ALIAS]]),
            ], $p_smarty_params);

            // Also merge property params.
            if (isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]) && is_array($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS])) {
                if (isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS][isys_popup_browser_object_ng::C__CALLBACK__ACCEPT])) {
                    $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS][isys_popup_browser_object_ng::C__CALLBACK__ACCEPT] .= $l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT] .
                        ';';
                }

                if (isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_onChange'])) {
                    $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_onChange'] = 'try{ ' . $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_onChange'] .
                        ' } catch(err) { } ';
                    $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_onChange'] .= $l_params['p_onChange'] . ';';
                }

                $l_params = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS] + $l_params;
            }

            // We set the UI ID to the string instead of appending it. See: ID-1060
            $l_params['p_strClass'] = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID];

            if (isset($p_propdata[C__PROPERTY__CHECK][C__PROPERTY__CHECK__VALIDATION]) && isset($p_propdata[C__PROPERTY__CHECK][C__PROPERTY__CHECK__VALIDATION][0]) &&
                $p_propdata[C__PROPERTY__CHECK][C__PROPERTY__CHECK__VALIDATION][0] == 'VALIDATE_BY_TEXTFIELD' &&
                $p_propdata[C__PROPERTY__CHECK][C__PROPERTY__CHECK__VALIDATION][1]['as-select'] === true) {
                // Change the input field to a dialog box.
                $l_params['force_dialog'] = true;
                $l_params['force_dialog_data'] = explode("\n", $p_propdata[C__PROPERTY__CHECK][C__PROPERTY__CHECK__VALIDATION][1]['value']);
            }

            /* If we use $p_source_table . '__id' as data field, there is always an helper needed to retrieve the selection,
                so we should unset the value and selected id because a browser tries to select anything wrong then */
            if ($p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD] == $p_source_table . '__id' &&
                ($p_source_table != 'isys_catg_connector_list' && $p_source_table == 'isys_catg_application_list')) {
                unset($l_params['p_strSelectedID'], $l_params['p_strValue']);
            }

            // Set some defaults.
            if ($p_row[$p_source_table . '__id'] == 'skip') {
                $l_params['p_strSelectedID'] = '-1';
                $l_params['p_bDbFieldNN'] = 0;

                // Disable first row for calendar.
                if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID] == 'C__CATG__LOCATION_POS') {
                    return '<td>' . $l_empty_value . '</td>';
                }
            }

            if (isset($p_smarty_params['p_onChange'])) {
                $l_params['p_onChange'] = str_replace('Multiedit.overwriteAll(this)', '', rtrim($l_params['p_onChange'], ';')) . ';' . $p_smarty_params['p_onChange'];
            }

            $l_param_id = $p_row[$p_source_table . '__id'];
            if (isset($p_row['isys_obj__id'])) {
                $l_param_id .= '-' . $p_row['isys_obj__id'];
            }

            // For global category "model" we have to set the parameter "p_ajaxIdentifier".
            if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID] == 'C__CATG__MODEL_MANUFACTURER') {
                $l_params['p_ajaxIdentifier'] = $p_row[$p_source_table . '__id'] != 'skip' ? 'C__CATG__MODEL_TITLE_ID\[' . $l_param_id .
                    '\]' : 'C__CATG__MODEL_TITLE_ID\[skip\]';
            }

            // For global category "share access" we have to set the parameter "p_ajaxIdentifier".
            if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID] == 'C__CATG__SHARE_ACCESS__ASSIGNED_OBJECTS') {
                $l_id = ($p_row[$p_source_table . '__id'] != 'skip') ? $l_param_id : 'skip';
                $l_js = "window.get_shares_from_object(\$F('C__CATG__SHARE_ACCESS__ASSIGNED_OBJECTS__HIDDEN[" . $l_id . "]'), 'C__CATG__SHARE_ACCESS__ASSIGNED_SHARE[" .
                    $l_id . "]');";

                $l_params['p_onChange'] .= $l_js;
                $l_params['callback_accept'] .= $l_js;
                $l_params['callback_detach'] .= $l_js;
            }

            if (isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['secTableID'])) {
                $l_params['secTableID'] = $p_row[$l_params['secTable'] . '__id'];

                // Only add score if necessary. Prevent producing [skip-].
                $l_params['p_strSecTableIdentifier'] = $l_params['p_strSecTableIdentifier'] . '[' . $p_row[$p_source_table . '__id'];
                if ($p_row[$p_source_table . '__id'] != 'skip' && isset($p_row['isys_obj__id'])) {
                    $l_params['p_strSecTableIdentifier'] .= '-' . $p_row['isys_obj__id'];
                }

                $l_params['p_strSecTableIdentifier'] .= ']';
            }

            // Special handling for category location.
            if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID] == 'C__CATG__LOCATION_PARENT') {
                $l_params['callback_accept'] = str_replace('C__CATG__LOCATION_POS', 'C__CATG__LOCATION_POS[' . $l_param_id . ']', $l_params['callback_accept']);
            }

            // @deprecated  Do not set sizes like this, when input-groups are being used.
            // Set size that every form field has the same size.
            // $l_params['p_strStyle'] = 'min-width:115px;width:68%;';
            $l_params['p_strClass'] .= ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__TYPE] == C__PROPERTY__UI__TYPE__POPUP ? ' input-small' : ' input-mini');
            $l_params['inputGroupMarginClass'] = '';

            // Use callback methods to fill p_arData.
            if (isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData']) && is_object($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData']) &&
                is_a($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData'], 'isys_callback')) {
                $l_arData = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData']->execute(isys_request::factory()
                    ->set_object_id($p_row['isys_obj__id'])
                    ->set_row($p_row)
                    ->set_object_type_id($p_row['isys_obj_type__id'])
                    ->set_category_type(C__CMDB__CATEGORY__TYPE_GLOBAL)
                    ->set_category_data_id($p_row[$p_source_table . '__id']));

                $l_params['p_arData'] = $l_arData;
            }

            // Use callback methods to fill data. This is actualy only needed by multiselect.
            if (isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['data']) && is_object($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['data']) &&
                is_a($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['data'], 'isys_callback')) {
                $l_arData = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['data']->execute(isys_request::factory()
                    ->set_object_id($p_row['isys_obj__id'])
                    ->set_row($p_row)
                    ->set_object_type_id($p_row['isys_obj_type__id'])
                    ->set_category_type(C__CMDB__CATEGORY__TYPE_GLOBAL)
                    ->set_category_data_id($p_row[$p_source_table . '__id']));

                $l_params['data'] = (is_array($l_arData)) ? json_encode($l_arData) : $l_arData;
            }

            // Use callback methods to fill p_strValue.
            if (isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strValue']) && is_object($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strValue']) &&
                is_a($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strValue'], 'isys_callback')) {
                $l_tmp = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strValue']->execute(isys_request::factory()
                    ->set_object_id($p_row['isys_obj__id'])
                    ->set_row($p_row)
                    ->set_object_type_id($p_row['isys_obj_type__id'])
                    ->set_category_type(C__CMDB__CATEGORY__TYPE_GLOBAL)
                    ->set_category_data_id($p_row[$p_source_table . '__id']));

                // Convert it to JSON if needed.
                if (is_array($l_tmp) || is_object($l_tmp)) {
                    $l_tmp = isys_format_json::encode($l_tmp);
                }

                $l_params["p_strValue"] = $l_tmp;
                unset($l_params["p_strSelectedID"]);
            }

            // Use callback methods to fill p_strSelectedID.
            if (isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strSelectedID']) &&
                is_object($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strSelectedID']) &&
                is_a($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strSelectedID'], 'isys_callback')) {
                $l_tmp = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strSelectedID']->execute(isys_request::factory()
                    ->set_object_id($p_row['isys_obj__id'])
                    ->set_row($p_row)
                    ->set_object_type_id($p_row['isys_obj_type__id'])
                    ->set_category_type(C__CMDB__CATEGORY__TYPE_GLOBAL)
                    ->set_category_data_id($p_row[$p_source_table . '__id']));

                /* Convert it to JSON if needed */
                if (is_array($l_tmp) || is_object($l_tmp)) {
                    $l_tmp = isys_format_json::encode($l_tmp);
                }

                $l_params["p_strSelectedID"] = $l_tmp;
                unset($l_params["p_strValue"]);
            }

            // Value for multi dialog list
            if (!isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strSelectedID']) &&
                !isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strValue']) &&
                $p_propdata[C__PROPERTY__INFO][C__PROPERTY__INFO__TYPE] == C__PROPERTY__INFO__TYPE__MULTISELECT &&
                $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['multiselect'] == true && isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strTable']) &&
                $p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD]] > 0) {
                $l_query = $l_root_table = $l_select_field = $l_condition_field = '';
                if (isset($p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__JOIN])) {
                    $l_joins = $p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__JOIN];
                    if (count($l_joins)) {
                        /**
                         * @var $l_join \idoit\Module\Report\SqlQuery\Structure\SelectJoin
                         */

                        foreach ($l_joins AS $l_join) {
                            $l_table = $l_join->getTable();
                            if ($l_root_table == '') {
                                if ($l_table != $p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][0]) {
                                    continue;
                                } else {

                                    $l_root_table = $l_table;
                                    $l_condition_field = $l_join->getOnLeft();
                                    continue;
                                }
                            }
                            $l_select_field = $l_join->getOnRight();
                            break;
                        }

                    }
                } else {
                    // Table is connected to isys_obj
                    $l_root_table = $p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][0];
                    $l_select_field = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strTable'] . '__id';
                    $l_condition_field = $p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD];
                }

                if ($l_select_field != '') {
                    $l_query = 'SELECT ' . $l_select_field . ' FROM ' . $l_root_table . ' WHERE ' . $l_condition_field . ' = ' .
                        $this->m_dao->convert_sql_id($p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD]]);
                }
                if ($l_query != '') {
                    $l_res = $this->m_dao->retrieve($l_query);
                    if ($l_res->num_rows() > 0) {
                        $l_data = [];
                        while ($l_row = $l_res->get_row()) {
                            $l_data[] = $l_row[$l_select_field];
                        }
                        $l_params['p_strSelectedID'] = $l_params['p_strValue'] = implode(',', $l_data);
                    }
                }
            }

            if (isset($this->m_smarty_plugins[$p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__TYPE]])) {
                $l_used_plugin = $this->m_smarty_plugins[$p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__TYPE]];
                if (isset($p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__ENCRYPT]) && $p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__ENCRYPT] === true) {
                    $l_used_plugin = new isys_smarty_plugin_f_password();
                }
            }

            if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__TYPE] == C__PROPERTY__UI__TYPE__TEXT) {
                /* Convert content */
                if ($p_propdata[C__PROPERTY__FORMAT][C__PROPERTY__FORMAT__CALLBACK]) {
                    switch ($p_propdata[C__PROPERTY__FORMAT][C__PROPERTY__FORMAT__CALLBACK][1]) {
                        case 'convert':
                            if (class_exists($p_propdata[C__PROPERTY__FORMAT][C__PROPERTY__FORMAT__CALLBACK][0]) && $l_params['p_strValue'] != '') {
                                if ($p_propdata[C__PROPERTY__FORMAT][C__PROPERTY__FORMAT__CALLBACK][2][0]) {
                                    $l_convert_method = $p_propdata[C__PROPERTY__FORMAT][C__PROPERTY__FORMAT__CALLBACK][2][0];
                                    if (method_exists($g_convert, $l_convert_method)) {
                                        $l_params['p_strValue'] = $g_convert->$l_convert_method($l_params['p_strValue'],
                                            $p_row[$p_properties[$p_propdata[C__PROPERTY__FORMAT][C__PROPERTY__FORMAT__UNIT]][C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD]],
                                            C__CONVERT_DIRECTION__BACKWARD);
                                    }
                                }
                            }
                            break;
                        case 'exportIpReference':
                            switch ($p_row['isys_catg_ip_list__isys_net_type__id']) {
                                case C__CATS_NET_TYPE__IPV4:
                                    if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID] != 'C__CATP__IP__ADDRESS_V4') {
                                        $p_row['isys_cats_net_ip_addresses_list__title'] = null;
                                        $l_params['p_bDisabled'] = 'disabled';
                                    }
                                    break;
                                case C__CATS_NET_TYPE__IPV6:
                                    if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID] != 'C__CMDB__CATG__IP__IPV6_ADDRESS') {
                                        $p_row['isys_cats_net_ip_addresses_list__title'] = null;
                                        $l_params['p_bDisabled'] = 'disabled';
                                    }
                                    break;
                            }

                            $l_params['p_strValue'] = $p_row['isys_cats_net_ip_addresses_list__title'];
                            break;
                    }
                }

                if (isset($p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__ENCRYPT]) && $p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__ENCRYPT] === true) {
                    $l_params['p_strValue'] = isys_helper_crypt::decrypt($l_params['p_strValue']);
                }
            } else {
                if (isset($l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT])) {
                    $l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT] = str_replace('%%id%%', $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID],
                        $l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT]);
                }

                if (isset($l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH])) {
                    $l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH] = str_replace('%%id%%', $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID],
                        $l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH]);
                }

                switch ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__TYPE]) {
                    case C__PROPERTY__UI__TYPE__POPUP:

                        if (isset($p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][0]) &&
                            $p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][0] == 'isys_connection' && $l_params['p_strValue'] > 0) {
                            $l_params['p_strSelectedID'] = $l_params['p_strValue'] = $this->m_dao_connection->get_object_id_by_connection((isset($p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][1]]) ? $p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][1]] : $l_params['p_strValue']));
                        } elseif (isset($p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][0]) &&
                            $p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][0] != 'isys_connection' &&
                            isset($p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][1]]) && $l_params['p_strValue'] === null &&
                            $l_params['p_strSelectedID'] === null) {

                            /**
                             * @todo This is causing problems in some scenarios:
                             *
                             *       Whenever attribute is not set and p_strValue is equal NULL
                             *       this lines will try to get the reference field which
                             *       will be isys_obj__id in most cases - so the holder of the
                             *       category entry will be selected automatically.
                             */
                            $l_params['p_strSelectedID'] = $l_params['p_strValue'] = $p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][1]];
                        }

                        if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_object_ng' ||
                            $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_object_relation' ||
                            $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_cable_connection_ng' ||
                            $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_location' ||
                            $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'browser_file') {

                            $l_params[isys_popup_browser_object_ng::C__EDIT_MODE] = true;

                            if (isset($p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES]) &&
                                $p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][1] !== 'isys_connection__id') {
                                $l_params[isys_popup_browser_object_ng::C__SELECTION] = (isset($p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][1]]) ? $p_row[$p_propdata[C__PROPERTY__DATA][C__PROPERTY__DATA__REFERENCES][1]] : $l_params['p_strValue']);
                            } else {
                                $l_params[isys_popup_browser_object_ng::C__SELECTION] = $l_params['p_strValue'];
                            }

                            $l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT] .= "Multiedit.changed(null, '" . ($l_params['id'] ?: $l_params['name']) . "');Multiedit.changesInEntry('" .
                                $p_row[$p_source_table . '__id'] . "');";

                            // ID-5574  Cascading detaches from `first row` to entires needs invokation of `Multiedit.overwriteAll()`
                            if ($p_row[$p_source_table . '__id'] === 'skip') {
                                $l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH] .= "Multiedit.overwriteAll('". $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__ID] ."');";
                            }

                            $l_params[isys_popup_browser_object_ng::C__CALLBACK__DETACH] .= "Multiedit.changed(null, '" . ($l_params['id'] ?: $l_params['name']) . "');Multiedit.changesInEntry('" .
                                $p_row[$p_source_table . '__id'] . "');";
                        }

                        if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strPopupType'] == 'dialog_plus') {
                            if ($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['multiselect']) {
                                $l_params['chosen'] = true;
                            }
                            $l_params[isys_popup_browser_object_ng::C__CALLBACK__ACCEPT] .= "Multiedit.changed(null, '" . ($l_params['id'] ?: $l_params['name']) . "');Multiedit.changesInEntry('" . $p_row[$p_source_table . '__id'] . "');";
                        }
                        break;

                    case C__PROPERTY__UI__TYPE__DATE:
                        $l_params['cellCallback'] = 'function(){$(this._relative).simulate(\'change\');}';
                        break;
                }
            }

            if ($l_params['p_strSelectedID'] === null && $l_params['p_strValue'] === null && isset($p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__DEFAULT])) {
                $l_params['p_strSelectedID'] = $l_params['p_strValue'] = $p_propdata[C__PROPERTY__UI][C__PROPERTY__UI__DEFAULT];
            }

            // Insert ui params and call navigation_edit on smarty plugin instance.
            if (is_object($l_used_plugin) && method_exists($l_used_plugin, 'navigation_edit')) {
                $l_list .= '<td>' . $l_used_plugin->navigation_edit(isys_application::instance()->template, $l_params) . '</td>';
            } else {
                $l_list .= '<td>' . $l_empty_value . '</td>';
            }
        }

        return $l_list;
    }

    /**
     * This method selects which object id has no assignment to the specified specific category id
     *
     * @param $p_object_ids
     * @param $p_category_id
     *
     * @return mixed
     * @author Van Quyen Hoang <qhoang@i-doit.org>
     */
    private function check_objects_with_specific_category($p_object_ids, $p_category_id)
    {
        $l_check_sql = 'SELECT isys_obj__id FROM isys_obj
				INNER JOIN isys_obj_type ON isys_obj_type__id = isys_obj__isys_obj_type__id
			WHERE isys_obj_type__id = isys_obj__isys_obj_type__id
			AND isys_obj__id IN (' . implode(',', $p_object_ids) . ')
			AND (isys_obj_type__isysgui_cats__id NOT IN
					(SELECT isysgui_cats_2_subcategory__isysgui_cats__id__parent
						FROM isysgui_cats_2_subcategory
						WHERE isysgui_cats_2_subcategory__isysgui_cats__id__child = ' . $p_category_id . ')
				AND isys_obj_type__isysgui_cats__id != ' . $p_category_id . ')';

        $l_res = $this->m_dao->retrieve($l_check_sql);
        $l_arr = [];
        if ($l_res->num_rows() > 0) {
            // Object type does not have this category
            while ($l_row = $l_res->get_row()) {
                $l_arr[] = $l_row['isys_obj__id'];
            }
        }

        return $l_arr;
    }

    /**
     * This method selects which object id has no assignment to the specified global category id.
     *
     * @param   array   $p_object_ids
     * @param   integer $p_category_id
     *
     * @return mixed
     * @author Van Quyen Hoang <qhoang@i-doit.org>
     */
    private function check_objects_with_global_category($p_object_ids, $p_category_id)
    {
        $l_check_sql = 'SELECT DISTINCT(isys_obj__id) FROM isys_obj
				INNER JOIN isys_obj_type ON isys_obj_type__id = isys_obj__isys_obj_type__id
				INNER JOIN isys_obj_type_2_isysgui_catg ON isys_obj_type__id = isys_obj_type_2_isysgui_catg__isys_obj_type__id
			WHERE isys_obj__id IN (' . implode(',', $p_object_ids) . ')
			AND isys_obj_type_2_isysgui_catg__isys_obj_type__id = isys_obj_type__id
			AND (isys_obj_type_2_isysgui_catg__isysgui_catg__id = ' . $this->m_dao->convert_sql_id($p_category_id) . '
				OR isys_obj_type_2_isysgui_catg__isysgui_catg__id = (SELECT isysgui_catg__parent FROM isysgui_catg WHERE isysgui_catg__id = ' .
            $this->m_dao->convert_sql_id($p_category_id) . '));';

        $l_res = $this->m_dao->retrieve($l_check_sql);

        if (count($l_res)) {
            // Object type does not have this category
            while ($l_row = $l_res->get_row()) {
                unset($p_object_ids[array_search($l_row['isys_obj__id'], $p_object_ids)]);
            }
        }

        return $p_object_ids;
    }

    /**
     *
     * @param   array   $p_object_ids
     * @param   integer $p_categoy_id
     *
     * @return  mixed
     */
    private function check_object_with_custom_category($p_object_ids, $p_categoy_id)
    {
        $l_check_sql = 'SELECT DISTINCT(isys_obj__id) FROM isys_obj
				INNER JOIN isys_obj_type ON isys_obj_type__id = isys_obj__isys_obj_type__id
				INNER JOIN isys_obj_type_2_isysgui_catg_custom ON isys_obj_type__id = isys_obj_type_2_isysgui_catg_custom__isys_obj_type__id
			WHERE isys_obj__id IN (' . implode(',', $p_object_ids) . ')
			AND isys_obj_type_2_isysgui_catg_custom__isys_obj_type__id = isys_obj_type__id
			AND isys_obj_type_2_isysgui_catg_custom__isysgui_catg_custom__id = ' . $this->m_dao->convert_sql_id($p_categoy_id);

        $l_res = $this->m_dao->retrieve($l_check_sql);

        if (count($l_res)) {
            // Object type does not have this category.
            while ($l_row = $l_res->get_row()) {
                unset($p_object_ids[array_search($l_row['isys_obj__id'], $p_object_ids)]);
            }
        }

        return $p_object_ids;
    }

    /**
     * Constructor.
     *
     * @param  isys_module_request $p_modreq
     */
    public function __construct(isys_module_request $p_modreq)
    {
        parent::__construct($p_modreq);
    }
}
