05. 테마 사용을 위한 CI_Controller 확장

application/core 폴더에 MY_Controller.php 파일을 추가시켜 줍니다.

CI_Contoller 를 확장자를 이용하여 테마등을 손쉽게 세팅할수 있도록 할것입니다.
소스코드는 http://github.com/jamierumbelow/codeigniter-base-controller 를 기본으로 하여 조금 수정한것입니다.

<?php
defined('BASEPATH') OR exit();
/**
 * A base controller for CodeIgniter with view autoloading, layout support,
 * model loading, helper loading, asides/partials and per-controller 404
 *
 * @link http://github.com/jamierumbelow/codeigniter-base-controller
 * @copyright Copyright (c) 2012, Jamie Rumbelow <http://jamierumbelow.net>
 */

class MY_Controller extends CI_Controller
{    
    protected $view = FALSE;        // 불러올 파일
    protected $data = array();      // view를 불러올때 넘겨줄 변수들
    protected $asides = array();    // 메인 view 이외에 추가로 불러올 뷰파일 (좌측메뉴등...)
    public $theme = FALSE;          // 불러올 테마
    public $theme_file = "theme";    // 테마 레이아웃파일중 불러올파일 기본으로 theme.php 파일을 불러옴 
    
    public $active 	= NULL;     // 메뉴등에서 현재페이지를 지정하기위한 변수
    public $sub_active = NULL;
    
    public $skin	= NULL;         // 게시판등 멀티스킨을 이용해야할때 해당 스킨파일을 지정함.
    public $skin_type = NULL;

    public function __construct()
    {
        parent::__construct();
    }

    public function _remap($method)
    {
        if (method_exists($this, $method)) call_user_func_array(array($this, $method), array_slice($this->uri->rsegments, 2));
        else
        {
            if (method_exists($this, '_404')) call_user_func_array(array($this, '_404'), array($method));
            else show_404(strtolower(get_class($this)).'/'.$method);
        }

        $this->_load_view();
    }

    protected function _load_view()
    {
        if( empty($this->view) ) return;

        $this->data['skin_url'] =  ( $this->skin && $this->skin_type ) ? base_url("views/".DIR_SKIN . '/' . $this->skin_type . '/' . $this->skin . '/') : NULL;
        $this->data['theme_url'] = (isset($this->theme) && $this->theme != FALSE) ? base_url("views/". DIR_THEME . "/" . $this->theme . "/") : NULL;

        if( $this->skin && $this->skin_type )
        {
            $view = DIR_SKIN . '/' . $this->skin_type . '/' . $this->skin . '/' . $this->view;
        }
        else if ( isset($this->theme) && $this->theme )
        {
            $view = DIR_THEME . '/' . $this->theme . '/' . $this->view;
        }
        else {
            $view = $this->view;
        }

        if (!empty($this->asides) && is_array($this->asides))
        {
            foreach ($this->asides as $name => $file)
            {
                $file_url = (isset($this->theme) && $this->theme) ? DIR_THEME . '/' . $this->theme .'/' . $file : $file;
                $this->data['asides_'.$name] = $this->load->view($file_url, $this->data, TRUE);
            }
        }

        $data['contents'] = $this->load->view($view, $this->data, TRUE);
        if( $this->skin && $this->skin_type )
        {
            $data['contents'] = "<div id=\"skin-{$this->skin_type}-{$this->skin}\">" . $data['contents'] . '</div>';
        }

        $data = array_merge($this->data, $data);
        $theme = (isset($this->theme) && $this->theme != FALSE) ? $this->theme : NULL;

        $output_data = ($theme) ?  $this->load->view( DIR_THEME . '/' . $theme. '/' . $this->theme_file , $data, TRUE) : $data['contents'];

        $output_data = preg_replace_callback('!\[widget([^\]]*)\]!is', array($this, '_widget_replace'), $output_data);

        $this->output->set_output($output_data);
    }

    protected function _widget_replace( $matches )
    {
        $vars = trim($matches[1]);
        $vars = preg_replace('/\r\n|\r|\n|\t/',' ',$vars);
        $vars = str_replace( array('"','  '), array('',' '), $vars );
        $vars = trim(str_replace( " ", '&', $vars ));

        parse_str($vars, $vars_array);

        $vars_array = array_merge( $vars_array, $this->data );
        $vars_array['CI'] = get_instance();

        // Name이 정의되지 않았다면 리턴
        if( ! isset($vars_array['name']) ) return $this->load->view('tools/widget_error', array("message"=>"위젯 속성중 [name] 값이 정의되지 않았습니다."), TRUE);
        if( ! file_exists( VIEWPATH . DIR_WIDGET . '/' . $vars_array['name']."/widget.php") ) return $this->load->view('tools/widget_error', array("message"=>"{$vars_array['name']} 위젯파일이 존재하지 않습니다."), TRUE);

        // CSS와 JS파일이 있다면 로드
        if( file_exists( VIEWPATH . DIR_WIDGET . '/' . $vars_array['name']."/widget.css") ) $this->site->add_css( '/views/' . DIR_WIDGET . '/' . $vars_array['name'] . "/widget.css");
        if( file_exists( VIEWPATH . DIR_WIDGET . '/' . $vars_array['name']."/widget.js") ) $this->site->add_js( '/views/' . DIR_WIDGET . '/' . $vars_array['name'] . "/widget.js");

        return "<div class=\"widget-{$vars_array['name']}\">". $this->load->view( DIR_WIDGET . '/' . $vars_array['name'] . '/widget', $vars_array, TRUE ) . "</div>";
    }
}

스킨, 위젯등을 사용하기위해 조금 확장한 소스입니다.
원리를 간단하게 설명하자면 $theme 가 설정되어있으면 theme 레이아웃 파일을 먼저 불러오고 그안에 $contents 라는 변수를 출력하면 $view에 설정한 파일을 거기에 불러오도록 하는것입니다.

추가로 앞으로 개발시 조금 편의를 위해 CI_Input 도 조금 확장하도록 하겠습니다.
application/core 폴더에 MY_Input.php 파일을 추가하고 아래와 같은 코드를 추가합시다.

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class MY_Input extends CI_Input
{

    /**
     * Fetch from array
     *
     * Internal method used to retrieve values from global arrays.
     *
     * @param	array	&$array		$_GET, $_POST, $_COOKIE, $_SERVER, etc.
     * @param	mixed	$index		Index for item to be fetched from $array
     * @param	bool	$xss_clean	Whether to apply XSS filtering
     * @return	mixed
     */
    protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = NULL, $default_value =NULL)
    {
        is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;

        // If $index is NULL, it means that the whole $array is requested
        isset($index) OR $index = array_keys($array);

        // allow fetching multiple keys at once
        if (is_array($index))
        {
            $output = array();
            foreach ($index as $key)
            {
                $output[$key] = $this->_fetch_from_array($array, $key, $xss_clean);
            }

            return $output;
        }

        if (isset($array[$index]))
        {
            $value = $array[$index];
        }
        elseif (($count = preg_match_all('/(?:^[^\[]+)|\[[^]]*\]/', $index, $matches)) > 1) // Does the index contain array notation
        {
            $value = $array;
            for ($i = 0; $i < $count; $i++)
            {
                $key = trim($matches[0][$i], '[]');
                if ($key === '') // Empty notation will return the value as array
                {
                    break;
                }

                if (isset($value[$key]))
                {
                    $value = $value[$key];
                }
                else
                {
                    return $default_value;
                }
            }
        }
        else
        {
            return $default_value;
        }

        return ($xss_clean === TRUE)
            ? $this->security->xss_clean($value)
            : $value;
    }

    // --------------------------------------------------------------------

    /**
     * Fetch an item from the GET array
     *
     * @param	mixed	$index		Index for item to be fetched from $_GET
     * @param	bool	$xss_clean	Whether to apply XSS filtering
     * @return	mixed
     */
    public function get($index = NULL, $xss_clean = NULL, $default_value = NULL)
    {
        return $this->_fetch_from_array($_GET, $index, $xss_clean, $default_value);
    }

    // --------------------------------------------------------------------

    /**
     * Fetch an item from the POST array
     *
     * @param	mixed	$index		Index for item to be fetched from $_POST
     * @param	bool	$xss_clean	Whether to apply XSS filtering
     * @return	mixed
     */
    public function post($index = NULL, $xss_clean = NULL, $default_value = NULL)
    {
        return $this->_fetch_from_array($_POST, $index, $xss_clean, $default_value);
    }

    // --------------------------------------------------------------------

    /**
     * Fetch an item from POST data with fallback to GET
     *
     * @param	string	$index		Index for item to be fetched from $_POST or $_GET
     * @param	bool	$xss_clean	Whether to apply XSS filtering
     * @return	mixed
     */
    public function post_get($index, $xss_clean = NULL, $default_value = NULL)
    {
        return isset($_POST[$index])
            ? $this->post($index, $xss_clean, $default_value)
            : $this->get($index, $xss_clean, $default_value);
    }

    // --------------------------------------------------------------------

    /**
     * Fetch an item from GET data with fallback to POST
     *
     * @param	string	$index		Index for item to be fetched from $_GET or $_POST
     * @param	bool	$xss_clean	Whether to apply XSS filtering
     * @return	mixed
     */
    public function get_post($index, $xss_clean = NULL, $default_value = NULL)
    {
        return isset($_GET[$index])
            ? $this->get($index, $xss_clean, $default_value)
            : $this->post($index, $xss_clean, $default_value);
    }

    // --------------------------------------------------------------------

    /**
     * Fetch an item from the COOKIE array
     *
     * @param	mixed	$index		Index for item to be fetched from $_COOKIE
     * @param	bool	$xss_clean	Whether to apply XSS filtering
     * @return	mixed
     */
    public function cookie($index = NULL, $xss_clean = NULL, $default_value = NULL)
    {
        return $this->_fetch_from_array($_COOKIE, $index, $xss_clean, $default_value);
    }

    // --------------------------------------------------------------------

    /**
     * Fetch an item from the SERVER array
     *
     * @param	mixed	$index		Index for item to be fetched from $_SERVER
     * @param	bool	$xss_clean	Whether to apply XSS filtering
     * @return	mixed
     */
    public function server($index, $xss_clean = NULL, $default_value = NULL)
    {
        return $this->_fetch_from_array($_SERVER, $index, $xss_clean, $default_value);
    }

}

이 코어 확장의 용도는 기존에 사용하는 $this->input->post() 등의 함수에 마지막 패러미터 인수에 값이 없을시 default 값을 설정할수 있게 할수 있는 확장클래스 입니다.

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다

This site uses Akismet to reduce spam. Learn how your comment data is processed.