Профессионал
Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007
Откуда: Berlin
Помог: 707 раз(а)
Выделено в отдельную тему из темы "Скрипт, программа - переносить файлы " Достаточно стандартная задача.
Взяв
отсюда ,
отсюда и
отсюда минут за 30 вышло примерно следующее:
app.php (Отобразить ) CODE (
php ):
скопировать код в буфер обмена
APPLICATION_PATH. '/lib' . PATH_SEPARATOR.
{
return require_once ( str_replace ( '_' , '/' , $sClass ) . '.php' ) ; } ) ;
$rgConfig = [ ] ;
if ( count ( $_SERVER [ 'argv' ] ) ) {
$rParser = new CLI_Parser( ) ;
$rParser -> setSynonyms ( Config_Handler:: getInstance ( ) -> getCLISynonyms ( ) ) ;
$rgConfig = $rParser -> parseString ( ) ;
}
$rgConfig = Config_Handler:: getInstance ( ) -> getConfig ( $rgConfig ) ;
$rHandler = new Handler(
$rgConfig [ Handler:: HANDLE_SOURCE ] ,
$rgConfig [ Handler:: HANDLE_DESTINATION ] ,
[ Handler:: SEARCH_STRING => $rgConfig [ Handler:: SEARCH_STRING ] ] ,
[ Handler:: SEARCH_REGEX => $rgConfig [ Handler:: SEARCH_REGEX ] ]
) ,
$rgConfig [ Handler:: HANDLE_EXTENSION ] ,
$rgConfig [ Handler:: HANDLE_MODE ]
) ;
$rHandler -> processFiles ( ) ;
- это просто само приложение. Нужен минимум php 5.4. Далее то, что оно использует:
lib/CLI/Parser.php (Отобразить ) CODE (
php ):
скопировать код в буфер обмена
class CLI_Parser
{
const PARSER_DELIMITER_COMMAND = ' ' ;
const PARSER_DELIMITER_VALUE = '=' ;
const PARSER_MARKER_SHORTKEY = '-' ;
const PARSER_MARKER_LONGKEY = '--' ;
protected $_rgSynonyms = null ;
protected $_sData = '' ;
public function __construct( $sData = null )
{
$this -> _sData
= isset ( $sData ) ?
( string
) $sData : join ( ' ' , $_SERVER [ 'argv' ] ) ; }
/**
*
* @param type $rgSynonyms - an array that contains synonyms.
* Each row of $rgSynonyms contains an array in format [synonym]=>array(key0,key1,...)
*/
public function setSynonyms( $rgSynonyms )
{
$this -> _rgSynonyms= $rgSynonyms ;
}
/**
*
* @param type $sData - optional string to parse
* @param type $bAllowSynonyms - including synonyms flag, true by default
* @return mixed
*/
public function parseString( $sData = null , $bAllowSynonyms = true )
{
$sData = isset ( $sData ) ?
( string
) $sData : $this -> _sData
; if ( ! $sData )
{
return null ;
}
$rgCLI = preg_split ( '/[' . preg_quote ( self :: PARSER_DELIMITER_COMMAND ) . ']+/' , $sData , - 1
, PREG_SPLIT_NO_EMPTY
) ; foreach ( $rgCLI as $sCLI )
{
$rgValue = preg_split ( '/[' . preg_quote ( self :: PARSER_DELIMITER_VALUE ) . ']+/' , $sCLI , - 1
, PREG_SPLIT_NO_EMPTY
) ; {
$rgResult [ $rgMatches [ 1
] ] = isset ( $rgValue [ 1
] ) ?
$rgValue [ 1
] : true ; }
{
{
$rgResult [ $sKey ] = isset ( $rgValue [ 1
] ) ?
$rgValue [ 1
] : true ; } ;
}
}
if ( $bAllowSynonyms && isset ( $this -> _rgSynonyms
) && is_array ( $this -> _rgSynonyms
) ) {
array_walk ( $this -> _rgSynonyms
, function ( $rgSynonym , $sKey ) use
( & $rgResult ) {
foreach ( $rgSynonym as $sSynonym )
{
{
$rgResult [ $sKey ] = $rgResult [ $sSynonym ] ;
array_walk ( $rgSynonym , function ( $sOldKey ) use
( & $rgResult ) {
unset ( $rgResult [ $sOldKey ] ) ; } ) ;
break ;
}
}
} ) ;
}
return $rgResult ;
}
}
lib/Config/Handler.php (Отобразить ) CODE (
php ):
скопировать код в буфер обмена
class Config_Handler
{
const INI_SECTION_DEFAULT = 'main' ;
const INI_KEY_CLI = 'cli' ;
static protected $rInstance = null ;
protected $_rgIni ;
public static function getInstance( )
{
if ( ! self :: $rInstance )
{
self :: $rInstance = new self ( ) ;
}
return self :: $rInstance ;
}
public function getKey( $sKey )
{
{
throw new Exception( 'Could not get key "' . $sKey . '" in section "' . $sSection . '"' ) ;
}
return $this -> _rgIni[ $sKey ] ;
}
public function getCLISynonyms( )
{
$rgCli = $this -> getKey ( self :: INI_KEY_CLI ) ;
$rgResult = [ ] ;
$rgResult [ $rgCli [ 'search' ] [ 'string' ] [ 'name' ] ] = $rgCli [ 'search' ] [ 'string' ] [ 'key' ] ;
$rgResult [ $rgCli [ 'search' ] [ 'regex' ] [ 'name' ] ] = $rgCli [ 'search' ] [ 'regex' ] [ 'key' ] ;
$rgResult [ $rgCli [ 'extension' ] [ 'name' ] ] = $rgCli [ 'extension' ] [ 'key' ] ;
$rgResult [ $rgCli [ 'path' ] [ 'destination' ] [ 'name' ] ] = $rgCli [ 'path' ] [ 'destination' ] [ 'key' ] ;
$rgResult [ $rgCli [ 'path' ] [ 'destination' ] [ 'name' ] ] = $rgCli [ 'path' ] [ 'destination' ] [ 'key' ] ;
$rgResult [ $rgCli [ 'mode' ] [ 'name' ] ] = $rgCli [ 'mode' ] [ 'key' ] ;
return $rgResult ;
}
//cli has priority
public function getConfig( $rgCli = [ ] )
{
}
private function __construct( $sPath = null )
{
if ( ! $sPath )
{
}
$this -> _rgIni = Config_Ini:: parse ( $sPath ) ;
}
}
lib/Config/Ini.php (Отобразить ) CODE (
php ):
скопировать код в буфер обмена
class Config_Ini
{
public static function parse( $sFilename )
{
{
return false ;
}
self :: _fix_ini_multi( $rgIni ) ;
return $rgIni ;
}
private static function _fix_ini_multi( & $rgIni )
{
foreach ( $rgIni AS $key => & $value )
{
{
self :: _fix_ini_multi( $value ) ;
}
{
$mElem = & $rgIni ;
foreach ( $rgKey AS $mStep )
{
if ( ! isset ( $mElem [ $mStep ] ) ) {
$mElem [ $mStep ] = array ( ) ; }
$mElem = & $mElem [ $mStep ] ;
}
$mElem [ $sLastKey ] = $value ;
}
}
}
}
lib/Handler.php (Отобразить ) CODE (
php ):
скопировать код в буфер обмена
class Handler
{
//in general, this should match ini file:
const HANDLE_DESTINATION = 'destination' ;
const HANDLE_SOURCE = 'source' ;
const HANDLE_EXTENSION = 'extension' ;
const HANDLE_MODE = 'mode' ;
const HANDLE_MODE_COPY = 'copy' ;
const HANDLE_MODE_MOVE = 'move' ;
const SEARCH_REGEX = 'search_regex' ;
const SEARCH_STRING = 'search_string' ;
const CREATE_MODE_DEFAULT = 0755 ;
protected $_sSrc = null ;
protected $_sDst = null ;
protected $_rgSearch = [ ] ;
protected $_rgExt = [ ] ;
protected $_sMode = null ;
public function __construct( $sSrc , $sDst , $rgSearch , $rgExt = [ ] , $sMode = self :: HANDLE_MODE_COPY )
{
{
throw new Exception( 'Process could not be handled due to permissions issues' ) ;
}
{
throw new Exception( 'Process could not be handled: either source or destination is not a directory' ) ;
}
{
throw new Exception( 'No search data specified' ) ;
}
$this -> _sSrc = $sSrc ;
$this -> _sDst = $sDst ;
$this -> _rgSearch= $rgSearch ;
$this -> _sMode = $sMode ;
$this -> _rgExt = $rgExt ;
}
public function processFiles( $rgIgnoreFiles = [ ] , $iCreateMode = self :: CREATE_MODE_DEFAULT )
{
$rgIgnoreFiles = is_array ( $rgIgnoreFiles ) && count
( $rgIgnoreFiles ) ?
$rgIgnoreFiles : [ '.' , '..' ] ; $rDir = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $this -> _sSrc) , RecursiveIteratorIterator:: CHILD_FIRST ) ;
foreach ( $rDir as $sPath )
{
{
{
mkdir ( $this -> _sDst
. $sRelativePath , $iCreateMode , true ) ; }
if ( ! is_dir ( $sPath ) && $this -> _check_extension
( $sPath ) && $this -> _check_file
( $sPath ) ) {
copy ( $sPath , $this -> _sDst
. $sRelativePath . '/' . basename ( $sPath ) ) ; if ( $this -> _sMode== self :: HANDLE_MODE_MOVE )
{
}
}
}
}
}
protected function _check_file( $sFile )
{
{
return false ;
}
$rFile = fopen ( $sFile , 'r' ) ; while ( ! feof ( $rFile ) && $sData = fgets ( $rFile ) ) {
if ( $this -> _check_substring( $sData ) || $this -> _check_regex( $sData ) )
{
return true ;
}
}
return false ;
}
protected function _check_substring( $sData )
{
foreach ( $this -> _rgSearch[ self :: SEARCH_STRING ] as $sSearch )
{
if ( false !== strpos ( $sData , $sSearch ) ) {
return true ;
}
}
return false ;
}
protected function _check_regex( $sData )
{
foreach ( $this -> _rgSearch[ self :: SEARCH_REGEX ] as $sSearch )
{
{
return true ;
}
}
return false ;
}
protected function _check_extension( $sFile )
{
return preg_match ( '/\.(.*?)$/' , $sFile , $rgMatches ) && in_array ( $rgMatches [ 1
] , $this -> _rgExt
) ; }
}
config/app.ini (Отобразить ) CODE (
text ):
скопировать код в буфер обмена
;cli
cli.search.string.name = search_string
cli.search.string.key.0 = s
cli.search.string.key.1 = string
cli.search.regex.name = search_regex
cli.search.regex.key.0 = e
cli.search.regex.key.1 = regex
cli.extension.name = extension
cli.extension.key.0 = x
cli.extension.key.1 = extensions
cli.path.source.name = source
cli.path.source.key.0 = f
cli.path.source.key.1 = from
cli.path.destination.name = destination
cli.path.destination.key.0 = t
cli.path.destination.key.1 = to
cli.mode.name = mode
cli.mode.key.0 = m
cli.mode.key.1 = mode
;if you want to use cli properly, then cli.{***}.name should match names below:
;search
plain.search_string.0 = foo
plain.search_string.1 = bar
plain.search_regex.0 = fo[ao]
plain.search_regex.1 = b?r
;extensions
plain.extension.0 = txt
plain.extension.1 = htm
plain.extension.2 = html
;paths
plain.source = /var/www/data/dev/grep/src
plain.destination = /var/www/data/dev/grep/dst
;mode = move|copy
plain.mode = copy
Для простоты - структура всего этого:
map (Отобразить ) CODE (
text ):
скопировать код в буфер обмена
/app
|
/config/
| |
| +app.ini
|
/lib/
| |
| /CLI/
| | |
| | +Parser.php
| |
| /Config/
| | |
| | +Handler.php
| | |
| | +Ini.php
| |
| +Handler.php
|
+app.php
Насчёт тестирования - пару обычных тестов этот код прошёл. Ну, остальное, уверен, сами найдёте.
DeepVarvar
- есть и более наглядные способы показать несостоятельность подобных цен. Уверен, что деньги стоит просить хотя бы не за то, что есть почти полностью в Сети.
Более того, если бы речь шла о *nix, задача почти полностью решается одной командой ОС.
-----Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.