Файл: qa-include/qa-page-admin-categories.php
Строк: 734
<?php
    
/*
    Question2Answer (c) Gideon Greenspan
    http://www.question2answer.org/
    
    File: qa-include/qa-page-admin-categories.php
    Version: See define()s at top of qa-include/qa-base.php
    Description: Controller for admin page for editing categories
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    More about this license: http://www.question2answer.org/license.php
*/
    if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
        header('Location: ../');
        exit;
    }
    require_once QA_INCLUDE_DIR.'qa-app-admin.php';
    require_once QA_INCLUDE_DIR.'qa-db-selects.php';
    require_once QA_INCLUDE_DIR.'qa-db-admin.php';
    
//    Get relevant list of categories
    $editcategoryid=qa_post_text('edit');
    if (!isset($editcategoryid))
        $editcategoryid=qa_get('edit');
    if (!isset($editcategoryid))
        $editcategoryid=qa_get('addsub');
        
    $categories=qa_db_select_with_pending(qa_db_category_nav_selectspec($editcategoryid, true, false, true));
    
//    Check admin privileges (do late to allow one DB query)
    if (!qa_admin_check_privileges($qa_content))
        return $qa_content;
        
        
//    Work out the appropriate state for the page
    
    $editcategory=@$categories[$editcategoryid];
    
    if (isset($editcategory)) {
        $parentid=qa_get('addsub');
        if (isset($parentid))
            $editcategory=array('parentid' => $parentid);
    
    } else {
        if (qa_clicked('doaddcategory'))
            $editcategory=array();
        
        elseif (qa_clicked('dosavecategory')) {
            $parentid=qa_post_text('parent');
            $editcategory=array('parentid' => strlen($parentid) ? $parentid : null);
        }
    }
    
    $setmissing=qa_post_text('missing') || qa_get('missing');
    
    $setparent=(!$setmissing) && (qa_post_text('setparent') || qa_get('setparent')) && isset($editcategory['categoryid']);
    
    $hassubcategory=false;
    foreach ($categories as $category)
        if (!strcmp($category['parentid'], $editcategoryid))
            $hassubcategory=true;
//    Process saving options
    $savedoptions=false;    
    if (qa_clicked('dosaveoptions')) {
        qa_set_option('allow_no_category', (int)qa_post_text('option_allow_no_category'));
        qa_set_option('allow_no_sub_category', (int)qa_post_text('option_allow_no_sub_category'));
        $savedoptions=true;
    }
//    Process saving an old or new category
    if (qa_clicked('docancel')) {
        if ($setmissing || $setparent)
            qa_redirect(qa_request(), array('edit' => $editcategory['categoryid']));
        elseif (isset($editcategory['categoryid']))
            qa_redirect(qa_request());
        else
            qa_redirect(qa_request(), array('edit' => @$editcategory['parentid']));
        
    } elseif (qa_clicked('dosetmissing')) {
        $inreassign=qa_get_category_field_value('reassign');
        qa_db_category_reassign($editcategory['categoryid'], $inreassign);
        qa_redirect(qa_request(), array('recalc' => 1, 'edit' => $editcategory['categoryid']));
    
    } elseif (qa_clicked('dosavecategory')) {
        
        if (qa_post_text('dodelete')) {
            if (!$hassubcategory) {
                $inreassign=qa_get_category_field_value('reassign');
                qa_db_category_reassign($editcategory['categoryid'], $inreassign);
                qa_db_category_delete($editcategory['categoryid']);
                qa_redirect(qa_request(), array('recalc' => 1, 'edit' => $editcategory['parentid']));
            }
        
        } else {
            require_once QA_INCLUDE_DIR.'qa-util-string.php';
            
            $inname=qa_post_text('name');
            $incontent=qa_post_text('content');
            $inparentid=$setparent ? qa_get_category_field_value('parent') : $editcategory['parentid'];
            $inposition=qa_post_text('position');
            $errors=array();
    
        //    Check the parent ID
        
            $incategories=qa_db_select_with_pending(qa_db_category_nav_selectspec($inparentid, true));
        
        //    Verify the name is legitimate for that parent ID
        
            if (empty($inname))
                $errors['name']=qa_lang('main/field_required');
            elseif (qa_strlen($inname)>QA_DB_MAX_CAT_PAGE_TITLE_LENGTH)
                $errors['name']=qa_lang_sub('main/max_length_x', QA_DB_MAX_CAT_PAGE_TITLE_LENGTH);
            else {
                foreach ($incategories as $category)
                    if (
                        (!strcmp($category['parentid'], $inparentid)) &&
                        strcmp($category['categoryid'], @$editcategory['categoryid']) &&
                        qa_strtolower($category['title']) == qa_strtolower($inname)
                    )
                        $errors['name']=qa_lang('admin/category_already_used');
            }
            
        //    Verify the slug is legitimate for that parent ID
        
            for ($attempt=0; $attempt<100; $attempt++) {
                switch ($attempt) {
                    case 0:
                        $inslug=qa_post_text('slug');
                        if (!isset($inslug))
                            $inslug=implode('-', qa_string_to_words($inname));
                        break;
                        
                    case 1:
                        $inslug=qa_lang_sub('admin/category_default_slug', $inslug);
                        break;
                        
                    default:
                        $inslug=qa_lang_sub('admin/category_default_slug', $attempt-1);
                        break;
                }
                
                $matchcategoryid=qa_db_category_slug_to_id($inparentid, $inslug); // query against DB since MySQL ignores accents, etc...
                
                if (!isset($inparentid))
                    $matchpage=qa_db_single_select(qa_db_page_full_selectspec($inslug, false));
                else
                    $matchpage=null;
                
                if (empty($inslug))
                    $errors['slug']=qa_lang('main/field_required');
                elseif (qa_strlen($inslug)>QA_DB_MAX_CAT_PAGE_TAGS_LENGTH)
                    $errors['slug']=qa_lang_sub('main/max_length_x', QA_DB_MAX_CAT_PAGE_TAGS_LENGTH);
                elseif (preg_match('/[\+\/]/', $inslug))
                    $errors['slug']=qa_lang_sub('admin/slug_bad_chars', '+ /');
                elseif ( (!isset($inparentid)) && qa_admin_is_slug_reserved($inslug)) // only top level is a problem
                    $errors['slug']=qa_lang('admin/slug_reserved');
                elseif (isset($matchcategoryid) && strcmp($matchcategoryid, @$editcategory['categoryid']))
                    $errors['slug']=qa_lang('admin/category_already_used');
                elseif (isset($matchpage))
                    $errors['slug']=qa_lang('admin/page_already_used');
                else
                    unset($errors['slug']);
                
                if (isset($editcategory['categoryid']) || !isset($errors['slug'])) // don't try other options if editing existing category
                    break;
            }
        //    Perform appropriate database action
            if (empty($errors)) {
                if (isset($editcategory['categoryid'])) { // changing existing category
                    qa_db_category_rename($editcategory['categoryid'], $inname, $inslug);
                    
                    $recalc=false;
                    
                    if ($setparent) {
                        qa_db_category_set_parent($editcategory['categoryid'], $inparentid);
                        $recalc=true;
                    } else {
                        qa_db_category_set_content($editcategory['categoryid'], $incontent);
                        qa_db_category_set_position($editcategory['categoryid'], $inposition);
                        $recalc=($hassubcategory && ($inslug !== $editcategory['tags']));
                    }
                    
                    qa_redirect(qa_request(), array('edit' => $editcategory['categoryid'], 'saved' => true, 'recalc' => (int)$recalc));
                    
                } else { // creating a new one
                    $categoryid=qa_db_category_create($inparentid, $inname, $inslug);
                    
                    qa_db_category_set_content($categoryid, $incontent);
                    
                    if (isset($inposition))
                        qa_db_category_set_position($categoryid, $inposition);
                    
                    qa_redirect(qa_request(), array('edit' => $inparentid, 'added' => true));
                }
            }
        }
    }
        
    
//    Prepare content for theme
    
    $qa_content=qa_content_prepare();
    $qa_content['title']=qa_lang_html('admin/admin_title').' - '.qa_lang_html('admin/categories_title');
    
    $qa_content['error']=qa_admin_page_error();
    
    if ($setmissing) {
        $qa_content['form']=array(
            'tags' => 'METHOD="POST" ACTION="'.qa_path_html(qa_request()).'"',
            
            'style' => 'tall',
            
            'fields' => array(
                'reassign' => array(
                    'label' => isset($editcategory)
                        ? qa_lang_html_sub('admin/category_no_sub_to', qa_html($editcategory['title']))
                        : qa_lang_html('admin/category_none_to'),
                    'loose' => true,
                ),
            ),
            
            'buttons' => array(
                'save' => array(
                    'label' => qa_lang_html('main/save_button'),
                ),
                
                'cancel' => array(
                    'tags' => 'NAME="docancel"',
                    'label' => qa_lang_html('main/cancel_button'),
                ),
            ),
            
            'hidden' => array(
                'dosetmissing' => '1', // for IE
                'edit' => @$editcategory['categoryid'],
                'missing' => '1',
            ),
        );
        qa_set_up_category_field($qa_content, $qa_content['form']['fields']['reassign'], 'reassign',
            $categories, @$editcategory['categoryid'], qa_opt('allow_no_category'), qa_opt('allow_no_sub_category'));
            
    
    } elseif (isset($editcategory)) {
        $qa_content['form']=array(
            'tags' => 'METHOD="POST" ACTION="'.qa_path_html(qa_request()).'"',
            
            'style' => 'tall',
            'ok' => qa_get('saved') ? qa_lang_html('admin/category_saved') : (qa_get('added') ? qa_lang_html('admin/category_added') : null),
            
            'fields' => array(
                'name' => array(
                    'id' => 'name_display',
                    'tags' => 'NAME="name" ID="name"',
                    'label' => qa_lang_html(count($categories) ? 'admin/category_name' : 'admin/category_name_first'),
                    'value' => qa_html(isset($inname) ? $inname : @$editcategory['title']),
                    'error' => qa_html(@$errors['name']),
                ),
                
                'questions' => array(),
                
                'delete' => array(),
                
                'reassign' => array(),
                
                'slug' => array(
                    'id' => 'slug_display',
                    'tags' => 'NAME="slug"',
                    'label' => qa_lang_html('admin/category_slug'),
                    'value' => qa_html(isset($inslug) ? $inslug : @$editcategory['tags']),
                    'error' => qa_html(@$errors['slug']),
                ),
                
                'content' => array(
                    'id' => 'content_display',
                    'tags' => 'NAME="content"',
                    'label' => qa_lang_html('admin/category_description'),
                    'value' => qa_html(isset($incontent) ? $incontent : @$editcategory['content']),
                    'error' => qa_html(@$errors['content']),
                    'rows' => 2,
                ),
            ),
            
            'buttons' => array(
                'save' => array(
                    'label' => qa_lang_html(isset($editcategory['categoryid']) ? 'main/save_button' : 'admin/add_category_button'),
                ),
                
                'cancel' => array(
                    'tags' => 'NAME="docancel"',
                    'label' => qa_lang_html('main/cancel_button'),
                ),
            ),
            
            'hidden' => array(
                'dosavecategory' => '1', // for IE
                'edit' => @$editcategory['categoryid'],
                'parent' =>  @$editcategory['parentid'],
                'setparent' => (int)$setparent,
            ),
        );
        
        
        if ($setparent) {
            unset($qa_content['form']['fields']['delete']);
            unset($qa_content['form']['fields']['reassign']);
            unset($qa_content['form']['fields']['questions']);
            unset($qa_content['form']['fields']['content']);
            
            $qa_content['form']['fields']['parent']=array(
                'label' => qa_lang_html('admin/category_parent'),
            );
                
            $childdepth=qa_db_category_child_depth($editcategory['categoryid']);
    
            qa_set_up_category_field($qa_content, $qa_content['form']['fields']['parent'], 'parent',
                isset($incategories) ? $incategories : $categories, isset($inparentid) ? $inparentid : @$editcategory['parentid'],
                true, true, QA_CATEGORY_DEPTH-1-$childdepth, @$editcategory['categoryid']);
                
            $qa_content['form']['fields']['parent']['options']['']=qa_lang_html('admin/category_top_level');
            
            @$qa_content['form']['fields']['parent']['note'].=qa_lang_html_sub('admin/category_max_depth_x', QA_CATEGORY_DEPTH);
        } elseif (isset($editcategory['categoryid'])) { // existing category
            if ($hassubcategory) {
                $qa_content['form']['fields']['name']['note']=qa_lang_html('admin/category_no_delete_subs');
                unset($qa_content['form']['fields']['delete']);
                unset($qa_content['form']['fields']['reassign']);
            } else {
                $qa_content['form']['fields']['delete']=array(
                    'tags' => 'NAME="dodelete" ID="dodelete"',
                    'label' =>
                        '<SPAN ID="reassign_shown">'.qa_lang_html('admin/delete_category_reassign').'</SPAN>'.
                        '<SPAN ID="reassign_hidden" STYLE="display:none;">'.qa_lang_html('admin/delete_category').'</SPAN>',
                    'value' => 0,
                    'type' => 'checkbox',
                );
            
                $qa_content['form']['fields']['reassign']=array(
                    'id' => 'reassign_display',
                    'tags' => 'NAME="reassign"',
                );
                
                qa_set_up_category_field($qa_content, $qa_content['form']['fields']['reassign'], 'reassign',
                    $categories, $editcategory['parentid'], true, true, null, $editcategory['categoryid']);
            }
            
            $qa_content['form']['fields']['questions']=array(
                'label' => qa_lang_html('admin/total_qs'),
                'type' => 'static',
                'value' => '<A HREF="'.qa_path_html('questions/'.qa_category_path_request($categories, $editcategory['categoryid'])).'">'.
                                ( ($editcategory['qcount']==1)
                                    ? qa_lang_html_sub('main/1_question', '1', '1')
                                    : qa_lang_html_sub('main/x_questions', number_format($editcategory['qcount']))
                                ).'</A>',
            );
            if ($hassubcategory && !qa_opt('allow_no_sub_category')) {
                $nosubcount=qa_db_count_categoryid_qs($editcategory['categoryid']);
                
                if ($nosubcount)
                    $qa_content['form']['fields']['questions']['error']=
                        strtr(qa_lang_html('admin/category_no_sub_error'), array(
                            '^q' => number_format($nosubcount),
                            '^1' => '<A HREF="'.qa_path_html(qa_request(), array('edit' => $editcategory['categoryid'], 'missing' => 1)).'">',
                            '^2' => '</A>',
                        ));
            }
            
            qa_set_display_rules($qa_content, array(
                'position_display' => '!dodelete',
                'slug_display' => '!dodelete',
                'content_display' => '!dodelete',
                'parent_display' => '!dodelete',
                'children_display' => '!dodelete',
                'reassign_display' => 'dodelete',
                'reassign_shown' => 'dodelete',
                'reassign_hidden' => '!dodelete',
            ));
        } else { // new category
            unset($qa_content['form']['fields']['delete']);
            unset($qa_content['form']['fields']['reassign']);
            unset($qa_content['form']['fields']['slug']);
            unset($qa_content['form']['fields']['questions']);
        
            $qa_content['focusid']='name';
        }
        
        if (!$setparent) {
            $pathhtml=qa_category_path_html($categories, @$editcategory['parentid']);
            
            if (count($categories)) {
                $qa_content['form']['fields']['parent']=array(
                    'id' => 'parent_display',
                    'label' => qa_lang_html('admin/category_parent'),
                    'type' => 'static',
                    'value' => (strlen($pathhtml) ? $pathhtml : qa_lang_html('admin/category_top_level')),
                );
                
                $qa_content['form']['fields']['parent']['value']=
                    '<A HREF="'.qa_path_html(qa_request(), array('edit' => @$editcategory['parentid'])).'">'.
                    $qa_content['form']['fields']['parent']['value'].'</A>';
                
                if (isset($editcategory['categoryid']))
                    $qa_content['form']['fields']['parent']['value'].=' - '.
                        '<A HREF="'.qa_path_html(qa_request(), array('edit' => $editcategory['categoryid'], 'setparent' => 1)).
                        '" STYLE="white-space: nowrap;"><SPAN>'.qa_lang_html('admin/category_move_parent').'</A>';
            }
            $positionoptions=array();
            
            $previous=null;
            $passedself=false;
            
            foreach ($categories as $key => $category)
                if (!strcmp($category['parentid'], @$editcategory['parentid'])) {
                    if (isset($previous))
                        $positionhtml=qa_lang_html_sub('admin/after_x', qa_html($passedself ? $category['title'] : $previous['title']));
                    else
                        $positionhtml=qa_lang_html('admin/first');
        
                    $positionoptions[$category['position']]=$positionhtml;
        
                    if (!strcmp($category['categoryid'], @$editcategory['categoryid']))
                        $passedself=true;
                        
                    $previous=$category;
                }
            
            if (isset($editcategory['position']))
                $positionvalue=$positionoptions[$editcategory['position']];
    
            else {
                $positionvalue=isset($previous) ? qa_lang_html_sub('admin/after_x', qa_html($previous['title'])) : qa_lang_html('admin/first');
                $positionoptions[1+@max(array_keys($positionoptions))]=$positionvalue;
            }
    
            $qa_content['form']['fields']['position']=array(
                'id' => 'position_display',
                'tags' => 'NAME="position"',
                'label' => qa_lang_html('admin/position'),
                'type' => 'select',
                'options' => $positionoptions,
                'value' => $positionvalue,
            );
            
            if (isset($editcategory['categoryid'])) {
                $catdepth=count(qa_category_path($categories, $editcategory['categoryid']));
                    
                if ($catdepth<QA_CATEGORY_DEPTH) {
                    $childrenhtml='';
                    
                    foreach ($categories as $category)
                        if (!strcmp($category['parentid'], $editcategory['categoryid']))
                            $childrenhtml.=(strlen($childrenhtml) ? ', ' : '').
                                '<A HREF="'.qa_path_html(qa_request(), array('edit' => $category['categoryid'])).'">'.qa_html($category['title']).'</A>'.
                                ' ('.$category['qcount'].')';
                    
                    if (!strlen($childrenhtml))
                        $childrenhtml=qa_lang_html('admin/category_no_subs');
                    
                    $childrenhtml.=' - <A HREF="'.qa_path_html(qa_request(), array('addsub' => $editcategory['categoryid'])).
                        '" STYLE="white-space: nowrap;"><B>'.qa_lang_html('admin/category_add_sub').'</B></A>';
                    
                    $qa_content['form']['fields']['children']=array(
                        'id' => 'children_display',
                        'label' => qa_lang_html('admin/category_subs'),
                        'type' => 'static',
                        'value' => $childrenhtml,
                    );
                } else {
                    $qa_content['form']['fields']['name']['note']=qa_lang_html_sub('admin/category_no_add_subs_x', QA_CATEGORY_DEPTH);
                }
                
            }
        }
            
    } else {
        $qa_content['form']=array(
            'tags' => 'METHOD="POST" ACTION="'.qa_path_html(qa_request()).'"',
            
            'ok' => $savedoptions ? qa_lang_html('admin/options_saved') : null,
            
            'style' => 'tall',
            
            'fields' => array(
                'intro' => array(
                    'label' => qa_lang_html('admin/categories_introduction'),
                    'type' => 'static',
                ),
            ),
            
            'buttons' => array(
                'save' => array(
                    'tags' => 'NAME="dosaveoptions"',
                    'label' => qa_lang_html('main/save_button'),
                ),
                
                'add' => array(
                    'tags' => 'NAME="doaddcategory"',
                    'label' => qa_lang_html('admin/add_category_button'),
                ),            
            ),
        );
        if (count($categories)) {
            unset($qa_content['form']['fields']['intro']);
            
            $navcategoryhtml='';
            foreach ($categories as $category)
                if (!isset($category['parentid']))
                    $navcategoryhtml.='<A HREF="'.qa_path_html('admin/categories', array('edit' => $category['categoryid'])).'">'.
                        qa_html($category['title']).'</A> - '.qa_lang_html_sub('main/x_questions', $category['qcount']).'<BR/>';
            $qa_content['form']['fields']['nav']=array(
                'label' => qa_lang_html('admin/top_level_categories'),
                'type' => 'static',
                'value' => $navcategoryhtml,
            );
                
            $qa_content['form']['fields']['allow_no_category']=array(
                'label' => qa_lang_html('options/allow_no_category'),
                'tags' => 'NAME="option_allow_no_category"',
                'type' => 'checkbox',
                'value' => qa_opt('allow_no_category'),
            );
            
            if (!qa_opt('allow_no_category')) {
                $nocatcount=qa_db_count_categoryid_qs(null);
                
                if ($nocatcount)
                    $qa_content['form']['fields']['allow_no_category']['error']=
                        strtr(qa_lang_html('admin/category_none_error'), array(
                            '^q' => number_format($nocatcount),
                            '^1' => '<A HREF="'.qa_path_html(qa_request(), array('missing' => 1)).'">',
                            '^2' => '</A>',
                        ));
            }
            
            $qa_content['form']['fields']['allow_no_sub_category']=array(
                'label' => qa_lang_html('options/allow_no_sub_category'),
                'tags' => 'NAME="option_allow_no_sub_category"',
                'type' => 'checkbox',
                'value' => qa_opt('allow_no_sub_category'),
            );
        } else
            unset($qa_content['form']['buttons']['save']);
    }
    if (qa_get('recalc')) {
        $qa_content['form']['ok']='<SPAN ID="recalc_ok">'.qa_lang_html('admin/recalc_categories').'</SPAN>';
        
        $qa_content['script_rel'][]='qa-content/qa-admin.js?'.QA_VERSION;
        $qa_content['script_var']['qa_warning_recalc']=qa_lang('admin/stop_recalc_warning');
        
        $qa_content['script_onloads'][]=array(
            "qa_recalc_click('dorecalccategories', document.getElementById('recalc_ok'), null, 'recalc_ok');"
        );
    }
    
    $qa_content['navigation']['sub']=qa_admin_sub_navigation();
    
    return $qa_content;
/*
    Omit PHP closing tag to help avoid accidental output
*/