<?php
/**
 * SrbacModule class file.
 *
 * @author Spyros Soldatos <spyros@valor.gr>
 * @link http://code.google.com/p/srbac/
 */

/**
 * SrbacModule is the module that loads the srbac module in the application
 *
 * @author Spyros Soldatos <spyros@valor.gr>
 * @package srbac
 * @since 1.0.0
 */

class SrbacModule extends CWebModule {
//Constants
  const ICON_PACKS = "noia,tango";
  const PRIVATE_ATTRIBUTES = "_icons,_cssPublished,_imagesPublished,defaultController,controllerMap,preload,behaviors";
  const TABLE_NAMES_ERROR = "Srbac is installed but the CDBAuthManger table names in the database are different from those
    in the CDBAuthManager configuration.<br />A common mistake is that names in database are in lowercase.<br />Srbac may not work correctly!!!";

  //Private attributes
  /* @var $_icons String The path to the icons */
  private $_icons;
  /* @var $_yiiSupportedVersion String The yii version tha srbac supports */
  private $_yiiSupportedVersion = "1.1.0";
  /* @var $_version Srbac version */
  private $_version = "1.3beta";
  /* @var $_cssPublished boolean If css file exists and is published */
  private $_cssPublished = false;
  /* @var $_imagesPublished boolean If images files exists and are published */
  private $_imagesPublished = false;

  // Srbac Attributes
  /* @var $debug If srbac is in debug mode */
  private $_debug = false;
  /* @var $pagesize int The number of items displayed in each page*/
  private $_pageSize = 15;
  /* @var $alwaysAllowed mixed The actions that are always allowed*/
  private $_alwaysAllowed = array();
  /* @var $userActions mixed Operations assigned to users by default*/
  private $_userActions = array();
  /* @var $listBoxNumberOfLines integer The number of lines in the assign tabview listboxes  */
  private $_listBoxNumberOfLines = 10;
  /* @var $iconText boolean Display text next to the icons */
  private $_iconText = false;
  /* @var $_useHeader boolean Use header or not */
  private $_showHeader = false;
  /* @var $_useFooter boolean Use footer or not */
  private $_showFooter = false;
  /* @var $_cssUrl The url of the css file to register */
  private $_cssUrl;
  /* @deprecated $useAlwaysAllowedGui boolean */
  public $useAlwaysAllowedGui;
  /* @var $_message A warning/error message displayed in the top of each page */
  private $_message ="";

  /* @var $userid String The primary column of the users table*/
  public $userid = "userid";
  /* @var $username String The username column of the users table*/
  public $username = "username";
  /* @var $userclass String The name of the users Class*/
  public $userclass = "User";
  /* @var $superUser String The name of the superuser */
  public $superUser = "Authorizer";
  /* @var $css string The css to use */
  public $css = "srbac.css";
  /* @var $notAuthorizedView String The view to render when unathorized access*/
  public $notAuthorizedView = "srbac.views.authitem.unauthorized";
  /* @var $imagesPath string The path to srbac images*/
  public $imagesPath = "srbac.images";
  /* @var $imagesPack String The images theme to use*/
  public $imagesPack = "noia";
  /* @var $header String Srbac header*/
  public $header = "srbac.views.authitem.header";
  /* @var $footer String Srbac footer*/
  public $footer = "srbac.views.authitem.footer";
  /* @var $alwaysAllowedPath String */
  public $alwaysAllowedPath = "srbac.components";
  /* @var $delimeter The delimeter used in modules between moduleId and itemId */
  public $delimeter = "-";

  private $_assetsUrl;

  public function getAssetUrl(){
    if($this->_assetsUrl === null){
      $this->_assetsUrl = Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias('application.modules.srbac.assets',true, -1, true));
    }
    return $this->_assetsUrl; 
  }

  public function setAssetUrl($value){
    $this->_assetsUrl = $value;
  }

  /**
   * this method is called when the module is being created you may place code
   * here to customize the module or the application
   */
  public function init() {

    // import the module-level models and components
    $this->setImport(array(
      'srbac.models.*',
      'srbac.components.*',
      'srbac.controllers.SBaseController'
    ));
    //Set layout to main
    if($this->layout =="") {
      $this->layout = "application.modules.srbac.layouts.admin";
    }
    //Publish css
    $this->_cssPublished = Helper::publishCss($this->css);

    //Publish images
    $this->setIconsPath(Helper::publishImages($this->imagesPath,$this->imagesPack));
    $this->_imagesPublished = $this->getIconsPath() == "" ? false : true;

    //Create the translation component
    $this->setComponents(
      array(
      'tr'=>array(
        'class'=>'CPhpMessageSource',
        'basePath'=> dirname(__FILE__).DIRECTORY_SEPARATOR.'messages',
        'onMissingTranslation'=>"Helper::markWords"
      ),
      'user'=>array(
        'class'=>'CWebUser',
        'stateKeyPrefix'=>'srbac',
        'loginUrl'=>Yii::app()->createUrl($this->getId().'/default/login'),
        'guestName'=>'模块里面的默认用户'
      ),
      )
    );
  }

  // SETTERS & GETTERS

  public function setCssUrl($cssUrl) {
    $this->_cssUrl = $cssUrl;
  }
  public function getCssUrl() {
    return $this->_cssUrl;

  }
  public function setDebug($debug) {
    if(is_bool($debug)) {
      $this->_debug = $debug;
    } else {
      throw new CException("Wrong value for srbac attribute debug in srbac configuration.
      '".$debug."' is not a boolean.");
    }
  }
  public function getDebug() {
    return $this->_debug;
  }
  public function setPageSize($pageSize) {
    if(is_numeric($pageSize)) {
      $this->_pageSize = (int) $pageSize;
    } else {
      throw new CException("Wrong value for srbac attribute pageSize in srbac configuration.
      '".$pageSize."' is not an integer.");
    }
  }
  public function getPageSize() {
    return $this->_pageSize;
  }
  public function setAlwaysAllowed($alwaysAllowed) {
    $this->_alwaysAllowed = $alwaysAllowed;
  }
  public function getAlwaysAllowed() {
    $paramAllowed = array();
    if(!is_file($this->getAlwaysAllowedFile())) {
      $handle = fopen($this->getAlwaysAllowedFile(), "wb");
      fwrite($handle, "<?php\n return array();\n?>");
      fclose($handle);
    }
    $guiAllowed = include($this->getAlwaysAllowedFile());
    if(!is_array($guiAllowed)){
      $guiAllowed = array();
    }
    if(is_array($this->_alwaysAllowed)) {
      $paramAllowed = $this->_alwaysAllowed;
    }else if(is_file(Yii::getPathOfAlias($this->_alwaysAllowed).".php")) {
      $paramAllowed = include(Yii::getPathOfAlias($this->_alwaysAllowed).".php");
    } else if(is_string($this->_alwaysAllowed)) {
      $paramAllowed = split(",", $this->_alwaysAllowed);
    }
    return array_merge($guiAllowed, $paramAllowed);
  }

  public function getAlwaysAllowedFile() {
    return Yii::getPathOfAlias($this->alwaysAllowedPath).DIRECTORY_SEPARATOR."allowed.php";
  }

  public function setUserActions($userActions) {
    if(is_array($userActions)) {
      $this->_userActions = $userActions;
    } else {
      $this->_userActions = explode(",",$userActions);
    }
  }
  public function getUserActions() {
    return $this->_userActions;
  }
  public function setListBoxNumberOfLines($size) {
    if(is_numeric($size)) {
      $this->_listBoxNumberOfLines = (int) $size;
    } else {
      throw new CException("Wrong value for srbac attribute listBoxNumberOfLines in srbac configuration.
      '".$size."' is not an integer.");
    }
  }
  public function getListBoxNumberOfLines() {
    return $this->_listBoxNumberOfLines;
  }
  public function setIconText($iconText) {
    if(is_bool($iconText)) {
      $this->_iconText = $iconText;
    } else {
      throw new CException("Wrong value for srbac attribute iconText in srbac configuration.
      '".$iconText."' is not a boolean.");
    }
  }
  public function getIconText() {
    return $this->_iconText;
  }
  public function setShowHeader($useHeader) {
    if(is_bool($useHeader)) {
      $this->_showHeader = $useHeader;
    } else {
      throw new CException("Wrong value for srbac attribute useHeader in srbac configuration.
      '".$useHeader."' is not a boolean.");
    }
  }
  public function getShowHeader() {
    return $this->_showHeader;
  }
  public function setShowFooter($useFooter) {
    if(is_bool($useFooter)) {
      $this->_showFooter = $useFooter;
    } else {
      throw new CException("Wrong value for srbac attribute footer in srbac configuration.
      '".$useFooter."' is not a boolean.");
    }
  }
  public function getShowFooter() {
    return $this->_showFooter;
  }



  /**
   * Checks if srbac is installed by checking if Auth items table exists.
   * @return boolean Whether srbac is installed or not
   */
  public function isInstalled() {
    try {
      $tables = Yii::app()->authManager->db->schema->tableNames;
      $itemTableName = Yii::app()->authManager->itemTable;
      $itemChildTableName = Yii::app()->authManager->itemChildTable ;
      $assignmentTableName  = Yii::app()->authManager->assignmentTable ;
      $tablePrefix = AuthItem::model()->getDbConnection()->tablePrefix;
      if(!is_null($tablePrefix)) {
        $itemTableName = preg_replace('/{{(.*?)}}/',$tablePrefix.'\1',$itemTableName);
        $itemChildTableName = preg_replace('/{{(.*?)}}/',$tablePrefix.'\1',$itemChildTableName);
        $assignmentTableName = preg_replace('/{{(.*?)}}/',$tablePrefix.'\1',$assignmentTableName);
      }
      if(in_array($itemTableName, $tables) &&
        in_array($itemChildTableName, $tables) &&
        in_array($assignmentTableName, $tables)) {
        return true;
      }else {
        $tables = array_map('strtolower', $tables);
        if(in_array(strtolower($itemTableName), $tables) &&
          in_array(strtolower($itemChildTableName), $tables) &&
          in_array(strtolower($assignmentTableName), $tables)) {
          $this->_message = self::TABLE_NAMES_ERROR;
          return true;
        }
      }
      return false;
    } catch (CDbException  $ex ) {
      return false;
    }
  }
  /**
   * Gets the user's class
   * @return userclass
   */
  public function getUserModel() {
    return new $this->userclass;
  }


  /**
   * this method is called before any module controller action is performed
   * you may place customized code here
   * @param CController $controller
   * @param CAction $action
   * @return boolean
   */
  public function beforeControllerAction($controller, $action) {
    if(parent::beforeControllerAction($controller, $action)) {
      $route=$controller->id.'/'.$action->id;

      $publicPages=array(
        'default/login',
        'default/error',
        'default/logout',
        'default/shouye'
      );

      //判断是否不需要验证的页面
      if(in_array($route,$publicPages)){
        return true;
      }

      //判断是否登陆
      if(!Yii::app()->controller->module->getComponent('user')->isGuest){
        //判断是否有权限
        if(Yii::app()->controller->module->getComponent('user')->checkAccess($controller->id)){
          return true;
        }else{
          throw new CHttpException('404','没有权限');
        }
      }else{
        //跳转到登陆页面
        Yii::app()->request->redirect(Yii::app()->createUrl('/srbac/default/login'));
      }
    }else{
      return false;
    }

  }

  /**
   * Gets the path to the icon files
   * @return String The path to the icons
   */
  public function getIconsPath() {
    return $this->_icons;
  }
  public function setIconsPath($path) {
    $this->_icons = $path;
  }

  public function getSupportedYiiVersion() {
    return $this->_yiiSupportedVersion;
  }

  public function getVersion() {
    return $this->_version;
  }

  public function isCssPublished() {
    return $this->_cssPublished;
  }
  public function isImagesPublished() {
    return $this->_imagesPublished;
  }

  public function getAttributes() {
    return get_object_vars($this);
  }

  public function getMessage() {
    if($this->_message != ""){
    return Helper::translate("srbac",$this->_message);
    } else {
      return "";
    }
  }
}