eFilesystem
[ class tree: eFilesystem ] [ index: eFilesystem ] [ all elements ]

Source for file eFilesystem.php

Documentation is available at eFilesystem.php

  1. <?php
  2. /**
  3.  * Project: eFilesystem:: eFilesystem:: 파일 시스템 확장 API<br>
  4.  * File:    eFilesystem.php<br>
  5.  * Depnedency: pear.oops.org/ePrint 1.0.1 이후 버전
  6.  *
  7.  * eFilesystem 클리스는 여러가지 확장된 시스템 function을 제공한다.
  8.  *
  9.  * @category    System
  10.  * @package     eFilesystem
  11.  * @author      JoungKyun.Kim <http://oops.org>
  12.  * @copyright   (c) 2018, OOPS.ORG
  13.  * @license     BSD
  14.  * @version     $Id$
  15.  * @link        http://pear.oops.org/package/eFilesystem
  16.  * @since       File available since relase 1.0.0
  17.  * @example     eFilesystem/test.php Sameple codes of eFilesystem class
  18.  * @filesource
  19.  */
  20.  
  21. /**
  22.  * myException 의존성
  23.  * pear.oops.org/myException
  24.  */
  25. require_once 'myException.php';
  26.  
  27. /**
  28.  * eFilesystem API는 pear.oops.org/ePrint pear package에 의존성이 있다.
  29.  * ePrint 패키지는 최소 1.0.1 버전을 필요로 한다.
  30.  */
  31. require_once 'ePrint.php';
  32.  
  33. /**
  34.  * 파일 시스템 확장 API를위한 기본 Class
  35.  * @package eFilesystem
  36.  */
  37. class eFilesystem extends ePrint {
  38.     // {{{ properties
  39.     const RELATIVE = 1;
  40.     const ABSOLUTE = 2;
  41.  
  42.     static private $make_ini_callback_key = null;
  43.     // }}}
  44.  
  45.     // {{{ static public (array) file_nr ($f, $use_include_path = false, $resource = null)
  46.     /**
  47.      * 파일을 읽어서 각 라인을 배열로 만들어 반환
  48.      *
  49.      * file_nr mothod는 php의 file 함수와 동일하게 작동을 한다. 하지만
  50.      * file_nr method는 file 함수와는 달리 각 행의 개행을 포함하지 않는다.
  51.      *
  52.      * 예제:
  53.      * {@example eFilesystem/test.php 27 3}
  54.      *
  55.      * @access public
  56.      * @return array|false파일의 각 행을 배열로 반환. 파일이 존재하지 않거나
  57.      *                      파일이 아니면 false를 반환한다.
  58.      * @param  string      파일 경로
  59.      * @param  boolean     (optional) true로 설정이 되면, php의 include_path
  60.      *                      에서 파일을 찾는다. 기본값은 false.
  61.      * @param  resource    (optional) file description resource가 지정이 되면,
  62.      *                      첫번째 파일 경로 인자의 값을 무시하고, 이 file
  63.      *                      description에서 파일의 내용을 읽는다. 기본값은 null
  64.      *                      이다.
  65.      */
  66.     static public function file_nr ($f, $use_include_path = false, $resource = null) {
  67.         $fp = is_resource ($resource) ? $res : fopen ($f, 'rb', $use_include_path);
  68.  
  69.         if ( ! is_resource ($fp) )
  70.             return false;
  71.  
  72.         $i = 0;
  73.         while ( ! feof ($fp) ) {
  74.             $buf = preg_replace ("/\r?\n$/", '', fgets ($fp, 1024));
  75.             $_buf[$i++] = $buf;
  76.         }
  77.  
  78.         if ( ! is_resource ($resource) )
  79.             fclose ($fp);
  80.  
  81.         if ( ! $_buf[--$i] )
  82.             unset ($_buf[$i]);
  83.  
  84.         return $_buf;
  85.     }
  86.     // }}}
  87.  
  88.     // {{{ static public (bool) mkdir_p ($path, $mode)
  89.     /**
  90.      * 주어진 경로에 디렉토리를 생성한다.
  91.      *
  92.      * 부모 디렉토리가 존재하지 않더라도, 이 API는 디렉토리를 생성하는데
  93.      * 실패 하지 않는다. 이 method는 php 의 mkdir (path, mode, true)와
  94.      * 동일하게 동작 한다. 시스템상에서 'mkdir -p path'와 같이 실행하는
  95.      * 것과 동일한 결과를 가진다.
  96.      *
  97.      *
  98.      * 예제:
  99.      * {@example eFilesystem/test.php 38 18}
  100.      *
  101.      * @access public
  102.      * @return boolean 생성에 실패하면 false를 반환하고, 성공하면 true를
  103.      *                  환한다.
  104.      * @param string   생성할 경로
  105.      * @param int      (optional) 기본값 0777. 이 의미는 누구나 접근 및
  106.      *                  쓰기가 가능함을 의미한다. mode에 대한 더 많은 정보는
  107.      *                  php의 {@link http://php.net/manual/en/function.chmod.php chmod()}
  108.      *                  문서를 참고 한다.
  109.      * @since 버전 1.0.2 부터 return 값이 boolean으로만 반환
  110.      */
  111.     static public function mkdir_p ($path, $mode = 0777) {
  112.         $_path = realpath ($path);
  113.  
  114.         if ( file_exists ($path) ) {
  115.             if ( is_dir ($path) )
  116.                 return false;
  117.             else
  118.                 return false;
  119.         }
  120.  
  121.         return mkdir ($path, $mode, true);
  122.     }
  123.     // }}}
  124.  
  125.     // {{{ static public (bool|int) safe_unlink ($f)
  126.     /**
  127.      * Deletes a file. If given file is directory, no error and return false.
  128.      * 파일을 삭제 한다.
  129.      *
  130.      * 주어진 값이 존재하지 않거나 디렉토리일 경우에도 에러를 발생 시키지
  131.      * 않는다.
  132.      *
  133.      * @access public
  134.      * @return bolean|int성공시에 true를 반환<br>
  135.      *                     삭제 실패시에 false를 반환<br>
  136.      *                     삭제할 파일이 없을 경우 2를 반환<br>
  137.      *                     삭제할 파일이 디렉토리일 경우 삭제하지 않고 3을 반환
  138.      * @param string      삭제할 경로
  139.      */
  140.     static public function safe_unlink ($f) {
  141.         if ( file_exists ($f) ) {
  142.             if ( is_dir ($f) )
  143.                 return 3;
  144.  
  145.             return @unlink ($f);
  146.         } else
  147.             return 2;
  148.  
  149.         return $r;
  150.     }
  151.     // }}}
  152.  
  153.     // {{{ private (string) safe_unlink_msg ($r, $path = 'Given path')
  154.     /**
  155.      * safe_unlink method의 반환 값을 문자열로 반환
  156.      *
  157.      * 이 함수는 eFilesystem Class 내부적으로 사용하기 위한 API이다.
  158.      *
  159.      * @access private
  160.      * @return string 
  161.      * @param  integer safe_unlink method의 반환 값
  162.      * @param  string  (optional) 경로
  163.      */
  164.     private function safe_unlink_msg ($r, $path = 'Given path') {
  165.         if ( $r === true )
  166.             return;
  167.  
  168.         #$func = ' for eFilesystem::safe_unlink()';
  169.  
  170.         switch ($r) {
  171.             case 2 : return "{$path} not found {$func}"; break;
  172.             case 3 : return "{$path} is directory {$func}"; break;
  173.         }
  174.  
  175.         return "{$path} don't be removed {$func}";
  176.     }
  177.     // }}}
  178.  
  179.     // {{{ static public (bool) unlink_r ($path)
  180.     /**
  181.      * 주어진 경로의 파일이나 디렉토리를 삭제
  182.      *
  183.      * 주어진 경로의 파일이나 디렉토리를 삭제 합니다. 디렉토리 삭제시에, 해당
  184.      * 디렉토리에 파일이나 하위 디렉토리가 포함하더라도 모두 삭제를 한다.
  185.      *
  186.      * 예제:
  187.      * {@example eFilesystem/test.php 57 3}
  188.      *
  189.      * @access public
  190.      * @return boolean 
  191.      * @param  string  삭제할 경로
  192.      *                  경로에 아스트리크(*)나 쉘 확장({a,b})을 사용할 수 있다.
  193.      */
  194.     static public function unlink_r ($path) {
  195.         if ( ! trim ($path) ) {
  196.             #parent::warning ('PATH is null string for eFilesystem::unlink_r()');
  197.             throw new myException ('PATH is empty string', E_USER_WARNING);
  198.             return false;
  199.         }
  200.  
  201.         // support glob and brace expend
  202.         if ( preg_match ('/([*])|({[^,]+,)/', $path) ) {
  203.             $l = glob ($path, GLOB_BRACE);
  204.             if ( $l === false || empty ($l) ) {
  205.                 #parent::warning ("11 {$path} not found for eFilesystem::unlink_r()");
  206.                 throw new myException (sprintf ('%s not found', $path), E_USER_WARNING);
  207.                 return false;
  208.             }
  209.  
  210.             foreach ( $l as $v ) {
  211.                 if ( is_dir ($v) )
  212.                     self::unlink_r ($v);
  213.                 else {
  214.                     self::safe_unlink ($v);
  215.                     if ( $r !== true ) {
  216.                         #parent::warning (self::safe_unlink_msg ($r, $path));
  217.                         throw new myException (self::safe_unlink_msg ($r, $path), E_USER_ERROR);
  218.                         return false;
  219.                     }
  220.                 }
  221.             }
  222.  
  223.             return true;
  224.         }
  225.  
  226.         if ( ! file_exists ($path) ) {
  227.             #parent::warning ("{$path} not found for eFilesystem::unlink_r()");
  228.             throw new myException (sprintf ('%s not found', $path), E_USER_WARNING);
  229.             return false;
  230.         }
  231.  
  232.         // path is not directory, remove here.
  233.         if ( ! is_dir ($path) ) {
  234.             $r = self::safe_unlink ($path);
  235.             if ( $r !== true ) {
  236.                 #parent::warning (self::safe_unlink_msg ($r, $path));
  237.                 throw new myException (self::safe_unlink_msg ($r, $path), E_USER_WARNING);
  238.                 return false;
  239.             }
  240.             return $r;
  241.         }
  242.  
  243.         // path is directory...
  244.         $dh = @opendir ($path);
  245.         if ( ! is_resource ($dh) )
  246.             return false;
  247.  
  248.         while ( ($f = @readdir ($dh)) ){
  249.             if ( $f == '.' || $f == '..' )
  250.                 continue;
  251.  
  252.             $fullpath = $path . '/' . $f;
  253.             //echo $fullpath . "\n";
  254.             if ( is_dir ($fullpath) )
  255.                 $r = self::unlink_r ($fullpath);
  256.             else {
  257.                 $r = self::safe_unlink ($fullpath);
  258.                 if ( $r !== true ) {
  259.                     #parent::warning (self::safe_unlink_msg ($r, $fullpath));
  260.                     throw new myException (self::safe_unlink_msg ($r, $fullpath), E_USER_WARNING);
  261.                 }
  262.             }
  263.  
  264.             if ( $r !== true ) {
  265.                 closedir ($dh);
  266.                 return false;
  267.             }
  268.         }
  269.         closedir ($dh);
  270.  
  271.         return @rmdir ($path);
  272.     }
  273.     // }}}
  274.  
  275.     // {{{ static public (array) dirlsit ($path, $fullpath = false)
  276.     /**
  277.      * 주어진 디렉토리 하위의 리스트를 배열로 반환
  278.      *
  279.      * 예제:
  280.      * {@example eFilesystem/test.php 61 6}
  281.      *
  282.      * @access public
  283.      * @return array|false
  284.      * @param  string  리스트를 얻을 디렉토리 경로
  285.      * @param  integer (optional) 기본값 false.<br>
  286.      *                  false일 경우, 파일 또는 디렉토리의 이름만 반환<br>
  287.      *                  eFilesystem::RELATIVE일 경우, 상대 경로로 반환<br>
  288.      *                  eFilesystem::ABSOLUTE일 경우, 절대 경로로 반환
  289.      */
  290.     static public function dirlist ($path, $fullpath = false) {
  291.         if ( ! $path )
  292.             return false;
  293.  
  294.         $path = preg_replace ('!/$!', '', $path);
  295.         $p = @opendir ($path);
  296.  
  297.         if ( ! is_resource ($p) )
  298.             return false;
  299.  
  300.         while ( ($list = readdir ($p)) ) {
  301.             if ( $list == '.' || $list == '..' )
  302.                 continue;
  303.  
  304.             switch ($fullpath) {
  305.                 case self::RELATIVE :
  306.                     $r[] = "$path/$list";
  307.                     break;
  308.                 case self::ABSOLUTE :
  309.                     $r[] = realpath ("$path/$list");
  310.                     break;
  311.                 default:
  312.                     $r[] = $list;
  313.             }
  314.         }
  315.         closedir ($p);
  316.  
  317.         return $r;
  318.     }
  319.     // }}}
  320.  
  321.     // {{{ static public (object) tree ($dir = '.', $prefix = '', $recursive = false)
  322.     /**
  323.      * 지정한 경로의 디렉토리 tree를 출력
  324.      *
  325.      * 시스템상의 tree 명령의 결과와 비슷하게 출력한다.
  326.      *
  327.      * 예제:
  328.      * {@example eFilesystem/test.php 38 18}
  329.      *
  330.      * @access public
  331.      * @return stdClass 파일과 디렉토리 수를 반환
  332.      *    <pre>
  333.      *    stdClass Object
  334.      *    (
  335.      *        [file] => 파일 수
  336.      *        [dir]  => 디렉토리 수
  337.      *    )
  338.      *    </pre>
  339.      * @param string  (optional) 주어진 경로. 기본값은 현재 디렉토리(./)
  340.      * @param string  (optional) 재귀 호출을 위해 사용. 이 파라미터는 사용하지
  341.      *                 않는다.
  342.      * @param boolean (optional) 재귀 호출을 위해 사용. 이 파라미터는 사용하지
  343.      *                 않는다.
  344.      */
  345.     static public function tree ($dir = '.', $prefix = '', $recursive = false) {
  346.         $n = new stdClass;
  347.         $n->file = 0;
  348.         $n->dir  = 0;
  349.  
  350.         if ( ! is_dir ($dir) ) return $n;
  351.         $dir = preg_replace ('!/$!', '', $dir);
  352.  
  353.         if ( $recursive === false ) {
  354.             if ( php_sapi_name () == 'cli' )
  355.                 parent::aPrintf ("blue", "%s/\n", $dir);
  356.             else
  357.                 echo "$dir/\n";
  358.         }
  359.  
  360.         if ( ($list = self::dirlist ($dir)) === false )
  361.             return $n;
  362.  
  363.         if ( is_array ($list) ) sort ($list);
  364.         $listno = count ($list);
  365.  
  366.         for ( $i=0; $i<$listno; $i++ ) {
  367.             $fullpath = $dir . '/' . $list[$i];
  368.             $last = ( $i === ($listno -1 ) ) ? true : false;
  369.  
  370.             $_prefix = $last ? '`-- ' : '|-- ';
  371.  
  372.             if ( php_sapi_name () == 'cli' && is_dir ($fullpath) )
  373.                 $fname = parent::asPrintf ('blue', "%s/", $list[$i]);
  374.             else {
  375.                 $fname = $list[$i];
  376.                 if ( is_dir ($fullpath) )
  377.                      $fname .= '/';
  378.             }
  379.  
  380.             printf ("%s%s%s\n", $prefix, $_prefix, $fname);
  381.             $_prefix = $prefix . preg_replace ('/`|-/', ' ', $_prefix);
  382.  
  383.             if ( is_dir ($fullpath) ) {
  384.                 $n->dir++;
  385.                 $_n = self::tree ($fullpath, $_prefix, true);
  386.                 $n->dir += $_n->dir;
  387.                 $n->file += $_n->file;
  388.             } else
  389.                 $n->file++;
  390.         }
  391.         return $n;
  392.     }
  393.     // }}}
  394.  
  395.     // {{{ static public (array) find ($path = './', $type = '', $norecursive = false)
  396.     /**
  397.      * 주어진 경로 하위의 디렉토리/파일 리스트를 배열로 반환
  398.      *
  399.      * 주어진 경로 하위의 디렉토리/파일들을 조건에 맞게 탐색을 하여 결과를
  400.      * 배열로 반환한다.
  401.      *
  402.      * 예제:
  403.      * {@example eFilesystem/test.php 68 4}
  404.      *
  405.      * @access public
  406.      * @return array|false파일 리스트를 배열로 반환. 경로를 지정하지 않았거나,
  407.      *                 또는 주어진 경로가 존재하지 않으면 false를 반환
  408.      * @param  string (optional) 탐색할 경로. 기본값은 현재 디렉토리(./)
  409.      * @param  string (optional) 탐색 조건. 기본값은 모든 파일/디렉토리를
  410.      *                 탐색한다.<br>
  411.      *                 - f (파일만 탐색)
  412.      *                 - d (디렉토리만 탐색)
  413.      *                 - l (링크만 탐색)
  414.      *                 - fd (파일과 디렉토리만 탐색)
  415.      *                 - fl (파일과 링크만 탐색)
  416.      *                 - dl (디렉토리와 링크만 탐색)
  417.      *                 - /regex/ (파일/디렉토리 이름을 정규식으로 탐색)
  418.      * @param  boolean (optional) 기본값 false. true로 설정하면, 재귀 검색을
  419.      *                 하지않고, 지정된 디렉토리의 리스트만 반환 한다.
  420.      */
  421.     static public function find ($path = './', $type= '', $norecursive = false) {
  422.         $path = preg_replace ('!/$!', '', $path);
  423.  
  424.         $_r = self::dirlist ($path, self::RELATIVE);
  425.  
  426.         if ( $_r === false || ! count ($_r) )
  427.             return false;
  428.  
  429.         $file = array ();
  430.         foreach ( $_r as $v ) {
  431.             switch ($type) {
  432.                 case 'f' :
  433.                     if ( is_file ($v) && ! is_link ($v) )
  434.                         $file[] = $v;
  435.                     break;
  436.                 case 'd' :
  437.                     if ( is_dir ($v) )
  438.                         $file[] = $v;
  439.                     break;
  440.                 case 'l' :
  441.                     if ( is_link ($v) )
  442.                         $file[] = $v;
  443.                     break;
  444.                 case 'fd' :
  445.                     if ( is_file ($v) || is_dir ($v) )
  446.                         $file[] = $v;
  447.                     break;
  448.                 case 'fl' :
  449.                     if ( is_file ($v) || is_link ($v) )
  450.                         $file[] = $v;
  451.                     break;
  452.                 case 'dl' :
  453.                     if ( is_dir ($v) || is_link ($v) )
  454.                         $file[] = $v;
  455.                     break;
  456.                 default :
  457.                     if ( $type ) {
  458.                         if ( preg_match ($type, $v) )
  459.                             $file[] = $v;
  460.                     } else
  461.                         $file[] = $v;
  462.             }
  463.  
  464.             if ( is_dir ($v) && $norecursive === false ) {
  465.                 $_rr = self::find ($v, $type);
  466.     
  467.                 if ( is_array ($_rr) ) {
  468.                     if ( ! $file ) array ();
  469.                     $file = array_merge ($file, $_rr);
  470.                 }
  471.             }
  472.         }
  473.  
  474.         return $file;
  475.     }
  476.     // }}}
  477.  
  478.     // {{{ static public (string) prompt ($prompt, $hidden = false)
  479.     /**
  480.      * 쉘 라인 프롬프트를 출력하고 입력된 값을 반환한다.
  481.      *
  482.      * @access public
  483.      * @return string 
  484.      * @param  string  stdout으로 출력할 프롬프트 문자열
  485.      * @param  boolean (optional) input 문자열을 hidden 처리 한다.
  486.      */
  487.     static public function prompt ($prompt, $hidden = false) {
  488.         $prompt = ! $prompt ? '$ ' : $prompt;
  489.  
  490.         if ( $hidden === false && function_exists ('readline') )
  491.             return readline ($prompt);
  492.  
  493.         printf ('%s', $prompt);
  494.  
  495.         if ( $hidden !== false )
  496.             system ('stty -echo >& /dev/null');
  497.  
  498.         $str = '';
  499.  
  500.         while ( $c != "\n" ) {
  501.             if ( ($c = fgetc (STDIN)) != "\n" ) {
  502.                 @ob_flush ();
  503.                 flush ();
  504.                 echo '*';
  505.                 $str .= $c;
  506.             }
  507.         }
  508.  
  509.         if ( $hidden !== false ) {
  510.             system ('stty echo >& /dev/null');
  511.             @ob_flush ();
  512.             flush ();
  513.             echo "\n";
  514.         }
  515.  
  516.         return $str;
  517.     }
  518.     // }}}
  519.  
  520.     // {{{ static public (array|stdClass) eFilesystem::parse_ini ($f)
  521.     /**
  522.      * 설정 파일 또는 설정 문자열을 분석
  523.      *
  524.      * @access  public
  525.      * @return  array|stdClass성공시에, 분석된 설정 내용을 배열로 반환 한다.
  526.      *                   실패시에 빈 배열을 반환한다.
  527.      * @param   string  설정 파일 또는 설정 문자열
  528.      * @param   bool    (optional) true로 선언시에, member들을 stdClass로
  529.      *                   반환한다. (1.0.3부터 지원)
  530.      * @since   버전 1.0.1
  531.      */
  532.     static public function parse_ini ($f, $obj = false) {
  533.         if ( is_array ($f) || is_object ($f) ) {
  534.             #parent::warning ('Invalid type of argument 1. File or string is valid');
  535.             throw new myException ('Invalid type of argument 1. File or string is valid', E_USER_WARNING);
  536.             return array ();
  537.         }
  538.  
  539.         if ( $obj )
  540.             return self::parse_ini_obj ($f);
  541.  
  542.         $contents = file_exists ($f) ? self::file_nr ($f) : preg_split ('/[\r\n]+/', $f);
  543.         if ( $contents === false || ! is_array ($contents) )
  544.             return array ();
  545.  
  546.         foreach ( $contents as $r ) {
  547.             $r = preg_replace ('/[ \t]*;.*/', '', $r);
  548.  
  549.             if ( ! $r )
  550.                 continue;
  551.  
  552.             if ( preg_match ('/^\[([^\]]+)\]$/', $r, $matches) ) {
  553.                 /* new variable */
  554.                 $varname = $matches[1];
  555.             } else {
  556.                 /**
  557.                  * invalid format
  558.                  * must variable = value format
  559.                  */
  560.                 if ( ! preg_match ('/^([^=]+)=(.*)$/', $r, $matches) )
  561.                     continue;
  562.  
  563.                 $_varname = trim ($matches[1]);
  564.                 $_value   = trim ($matches[2]);
  565.  
  566.                 $var = '$ret[\'' . $varname . '\']';
  567.                 if ( $_varname == 'value' ) {
  568.                     if ( preg_match ('/^(true|false|on|off|null|[01])$/', $_value, $matches) ) {
  569.                         switch ($matches[1]) {
  570.                             case 'true' :
  571.                             case 'on' :
  572.                             case '1' :
  573.                                 $var .= ' = 1;';
  574.                                 break;
  575.                             case 'null' :
  576.                                 $var .= ' = null;';
  577.                                 break;
  578.                             default :
  579.                                 $var .= ' = 0;';
  580.                         }
  581.                     } else
  582.                         $var .= ' = \'' . $_value . "';";
  583.                 } else {
  584.                     $_varname_r = explode ('.', $_varname);
  585.                     for ( $i=0; $i<count ($_varname_r); $i++ ) {
  586.                         $var_quote = is_numeric ($_varname_r[$i]) ? '' : '\'';
  587.                         $var .= '[' . $var_quote . $_varname_r[$i] . $var_quote . ']';
  588.                     }
  589.  
  590.                     if ( preg_match ('/^(true|false|on|off|null|[01])$/', $_value, $matches) ) {
  591.                         switch ($matches[1]) {
  592.                             case 'true' :
  593.                             case 'on' :
  594.                             case '1' :
  595.                                 $var .= ' = 1;';
  596.                                 break;
  597.                             case 'null' :
  598.                                 $var .= ' = null;';
  599.                                 break;
  600.                             default :
  601.                                 $var .= ' = 0;';
  602.                         }
  603.                     } else
  604.                         $var .= ' = \'' . $_value . "';";
  605.                 }
  606.                 //echo $var . "\n";
  607.                 eval ($var);
  608.             }
  609.         }
  610.  
  611.         return is_array ($ret) ? $ret : array ();
  612.     }
  613.     // }}}
  614.  
  615.     // {{{ private (stdClass) eFilesystem::parse_ini_obj ($f)
  616.     /**
  617.      * 설정 파일 또는 설정 문자열을 분석
  618.      *
  619.      * @access  public
  620.      * @return  stdClass 성공시에, 분석된 설정 내용을 stdClass로 반환 한다. 실패시에
  621.      *                    빈 stdClass를 반환한다.
  622.      * @param   string   설정 파일 또는 설정 문자열
  623.      * @since   버전 1.0.3
  624.      */
  625.     private static function parse_ini_obj (&$f) {
  626.         if ( is_array ($f) || is_object ($f) ) {
  627.             #parent::warning ('Invalid type of argument 1. File or string is valid');
  628.             throw new myException ('Invalid type of argument 1. File or string is valid', E_USER_WARNING);
  629.             return array ();
  630.         }
  631.  
  632.         $contents = file_exists ($f) ? self::file_nr ($f) : preg_split ('/[\r\n]+/', $f);
  633.         if ( $contents === false || ! is_array ($contents) )
  634.             return array ();
  635.  
  636.         $ret = new stdClass;
  637.  
  638.         foreach ( $contents as $r ) {
  639.             $r = preg_replace ('/[ \t]*;.*/', '', $r);
  640.  
  641.             if ( ! $r )
  642.                 continue;
  643.  
  644.             if ( preg_match ('/^\[([^\]]+)\]$/', $r, $matches) ) {
  645.                 /* new variable */
  646.                 $varname = $matches[1];
  647.                 eval ('$ret->' . $varname . ' = new stdClass;');
  648.                 #echo '$ret->' . $varname . ' = new stdClass;' . PHP_EOL;
  649.             } else {
  650.                 /**
  651.                  * invalid format
  652.                  * must variable = value format
  653.                  */
  654.                 if ( ! preg_match ('/^([^=]+)=(.*)$/', $r, $matches) )
  655.                     continue;
  656.  
  657.                 $_varname = trim ($matches[1]);
  658.                 $_value   = trim ($matches[2]);
  659.  
  660.                 $var = '$ret->' . $varname;
  661.                 if ( $_varname == 'value' ) {
  662.                     if ( preg_match ('/^(true|false|on|off|null|[01])$/', $_value, $matches) ) {
  663.                         switch ($matches[1]) {
  664.                             case 'true' :
  665.                             case 'on' :
  666.                             case '1' :
  667.                                 $var .= ' = 1;';
  668.                                 break;
  669.                             case 'null' :
  670.                                 $var .= ' = null;';
  671.                                 break;
  672.                             default :
  673.                                 $var .= ' = 0;';
  674.                         }
  675.                     } else
  676.                         $var .= ' = \'' . $_value . "';";
  677.                 } else {
  678.                     $_varname_r = explode ('.', $_varname);
  679.                     for ( $i=0; $i<count ($_varname_r); $i++ ) {
  680.                         $var_brace_start = is_numeric ($_varname_r[$i]) ? '{' : '';
  681.                         $var_brace_end   = is_numeric ($_varname_r[$i]) ? '}' : '';
  682.                         $var .= '->' . $var_brace_start . $_varname_r[$i] . $var_brace_end;
  683.                         eval ('if (!is_object(' . $var . ')) { ' . $var . ' = new stdClass; }');
  684.                     }
  685.  
  686.                     if ( preg_match ('/^(true|false|on|off|null|[01])$/', $_value, $matches) ) {
  687.                         switch ($matches[1]) {
  688.                             case 'true' :
  689.                             case 'on' :
  690.                             case '1' :
  691.                                 $var .= ' = 1;';
  692.                                 break;
  693.                             case 'null' :
  694.                                 $var .= ' = null;';
  695.                                 break;
  696.                             default :
  697.                                 $var .= ' = 0;';
  698.                         }
  699.                     } else
  700.                         $var .= ' = \'' . $_value . "';";
  701.                 }
  702.                 #echo $var . "\n";
  703.                 eval ($var);
  704.             }
  705.         }
  706.  
  707.         return $ret;
  708.     }
  709.     // }}}
  710.  
  711.     // {{{ static public (string) eFilesystem::make_ini ($array)
  712.     /**
  713.      * eFilesystem::parse_ini method에 대응되는 설정을 생성한다.
  714.      *
  715.      * @access public
  716.      * @return string 생성된 설정 문자열
  717.      * @param  array|stdClass eFilesystem::parse_ini와 동일한 형식을 가진 설정 배열
  718.      * @since  버전 1.0.2
  719.      */
  720.     static public function make_ini ($input) {
  721.         if ( ! is_array ($input) && ! is_object ($input) ) {
  722.             #parent::warning ('Invalid type of argument 1. Array is valid');
  723.             throw new myException ('Invalid type of argument 1. Array is valid', E_USER_WARNING);
  724.             return false;
  725.         }
  726.  
  727.         $buf = '';
  728.         foreach ( $input as $key => $v ) {
  729.             $r = "[{$key}]\n";
  730.  
  731.             if ( ! is_array ($v) && ! is_object ($v) ) {
  732.                 #parent::warning ('Invalid array data format');
  733.                 throw new myException ('Invalid array data format', E_USER_WARNING);
  734.                 return false;
  735.             }
  736.  
  737.             self::make_ini_callback ($r, $v);
  738.             $buf .= preg_replace ('/\.([\s]*)=[\s]* /', '\\1= ', $r) . "\n";
  739.             #$buf .= $r . "\n";
  740.         }
  741.  
  742.         return $buf;
  743.     }
  744.     // }}}
  745.  
  746.     // {{{ private (void) eFilesystem::make_ini_callback (&$buf, $v)
  747.     private function make_ini_callback (&$buf, $v) {
  748.         if ( ! is_array ($v) && ! is_object ($v) ) {
  749.             if ( ! is_numeric ($v) && ! $v )
  750.                 $v = 'null';
  751.             $buf .= sprintf (" = %s\n", $v);
  752.             return;
  753.         }
  754.  
  755.         foreach ( $v as $key => $val ) {
  756.             if ( ! is_array ($val) && ! is_object ($val) ) {
  757.                 $keyname = sprintf ('%s%s.', self::$make_ini_callback_key, $key);
  758.                 $buf .= sprintf ('  %-20s', $keyname);
  759.             }
  760.  
  761.             self::$make_ini_callback_key .= $key . '.';
  762.             self::make_ini_callback ($buf, $val);
  763.             self::$make_ini_callback_key = preg_replace ('/[^.]+\.$/', '', self::$make_ini_callback_key);
  764.         }
  765.  
  766.     }
  767.     // }}}
  768. }
  769.  
  770. ?>

Documentation generated on Fri, 30 Aug 2024 06:10:22 +0900 by phpDocumentor 1.4.4