.gitignore000064400000000036144761607140006545 0ustar00/vendor/ /tests/ composer.lockREADME.md000064400000003702144761607140006037 0ustar00## Table of contents * [General info](#general-info) * [Installing](#installing) * [Utilities Included](#utilities-included) * * [dhGlobal](#dhglobal) * * [dhOut](#dhout) * * [dhLogger](#dhlogger) ## General info dhUtils is a collection of basic utilities to make development easier. ## Installing In composer.json, add the following: ``` { "require": { "boru/dhutils": "dev-master" }, "repositories": [ { "type": "composer", "url": "https://satis.boruapps.com" } ] } ``` then run ``` composer install ``` ## Utilities Included This example sets up an instance of dhOut it then adds it to dhGlobals. Then it uses the global ``` //standard composer incldue: require_once "vendor/autoload.php"; //use statements to shortcut class names -- not required but is handy. //instead, you could use the full qualified class name //eg, instead of dhGlobal it would be \boru\dhutils\dhGlobal (or dhOut, or dhLogger, etc) use boru\dhutils\{dhGlobal,dhOut,dhLogger}; //create an instance of dhOut $dhOut = new dhOut(); //add it to dhGlobal dhGlobal::add("out",$dhOut); //add another variable dhGlobal::add("foo","bar"); //in some other piece of code somewhere: dhGlobal::add("logger",new dhLogger("debug",false,$dhOut)); //And in another class/function: dhGlobal::get("out")->add("testing dhOut from another class"); dhGlobal::get("out")->add("global var 'foo'=" . dhGlobal::get("bar")); dhGlobal::get("logger")->debug("debug notice here"); ``` ### dhGlobal Easily transport objects and variables across functions/classes without having to inject or initiate in each location Methods: * setup(bool stdOut, bool prefix, bool outFile, bool logFile) * * Shortcut to set up dhGlobal::get("out") and dhGlobal::get("logger") * add(string KEY, mixed ITEM); * get(string KEY, mixed DEFAULT); * isset(string KEY); * remove(string KEY); ### dhOut ### dhLogger composer.json000064400000001561144761607140007303 0ustar00{ "name": "boru/dhutils", "type": "library", "autoload": { "psr-4": { "boru\\dhutils\\": "src/" } }, "extra" : { "branch-alias" : {"dev-master" : "1.0.x-dev"} }, "authors": [ { "name": "Daniel Hayes", "email": "dhayes@boruapps.com" } ], "require": { "boru/dhcache": "*", "phpmailer/phpmailer": "^6.6", "php-imap/php-imap": "^3.1", "guzzlehttp/guzzle": "^6.5", "mailgun/mailgun-php": "^2.8" }, "suggest": { "boru/dhdb": "dhDB library for database", "boru/dhcli": "CLI toolkit/library for making CLI apps", "boru/dhapi": "Toolkit/library for creating API apps" }, "repositories": [ { "type": "composer", "url": "https://satis.boruapps.com" } ] } examples/dhThreads/exec.php000064400000001655144761607140011746 0ustar00uniqId(),"rand"=>["start"=>$randStart,"end"=>$randEnd,"rand"=>$rand]]);examples/dhThreads_class.php000064400000005717144761607140012212 0ustar00true, "jsonObject"=>false, "callback"=>function($thread) { $simpleOut = dhGlobal::get("simpleOut"); $simpleOut->done($thread->id()); $simpleOut->display(); //dhGlobal::outLine($thread->id(),"Completed"); //dhGlobal::outLine($thread->id(),$thread->meta()); //dhGlobal::outLine($thread->id(),$thread->output()); } ]; /** * The script to execute.. note that this is just a sample script that will sleep for a random time * in order to show it is multi-threaded */ $script = new File(["path"=>"dhThreads/exec.php"]); //push $threads commands through our threadpool.. for($i=0;$i<$threads;$i++) { $randStart = rand(1,3); $randEnd = $randStart+3; $threadPool->startScript($script,["randStart"=>$randStart,"randEnd"=>$randEnd],$options); } echo "Now waiting..\n"; //wait for all threads to complete $threadPool->wait(); class simpleOutput { public $threads = []; public $done = 0; public $total = 0; public function __construct($threads=10) { $this->total = $threads; $this->done = 0; for($i=0;$i<$threads;$i++) { $this->threads[$i] = "."; } } public function display() { $percent = $this->done / $this->total; $percent *= 100; dhGlobal::outLine(implode(" ",$this->threads)." ".dhGlobal::pad(number_format($percent,2),7," ",STR_PAD_LEFT)); } public function done($i) { $this->done++; $this->threads[$i] = 'x'; } } examples/dhThreads_global.php000064400000005457144761607140012346 0ustar00true, "jsonObject"=>false, "callback"=>function($thread) { $simpleOut = dhGlobal::get("simpleOut"); $simpleOut->done($thread->id()); $simpleOut->display(); //dhGlobal::outLine($thread->id(),$thread->command()); //dhGlobal::outLine($thread->id(),$thread->meta()); //dhGlobal::outLine($thread->id(),$thread->output()); }, "collectType"=>dhThreads::COLLECT_FULL, ]; /** * Build an array of commands to execute */ $commands = []; for($i=0;$i<$threads;$i++) { $randStart = rand(1,3); $randEnd = $randStart+3; $commands[] = [ "exec"=>"php -f ".__DIR__."/dhThreads/exec.php inline $randStart $randEnd", "meta"=>["randomData"=>"toInclude","someval"=>$i,"randStart"=>$randStart,"randEnd"=>$randEnd], ]; } $output = dhGlobal::threadMultiExec($commands,$options,$maxThreads,$throttleDelay); /** * global methods to wrap all of dhThreads_class example using just dhGlobal */ //Using threadMultiExec //dhGlobal::threadMultiExec($commands=[],$options=[],$numThreads=4,$throttleDelay=0.1) class simpleOutput { public $threads = []; public function __construct($threads=10) { for($i=0;$i<$threads;$i++) { $this->threads[$i] = "."; } } public function display() { dhGlobal::outLine(implode(" ",$this->threads)); } public function done($i) { $this->threads[$i] = 'x'; } } examples/general.php000064400000000422144761607140010520 0ustar00" "]) { $separator = dhGlobal::getVal($options,"separator"," "); if(!is_array($args)) { $this->args = explode($separator,$args); } else { $this->args = $args; } } public function shift() { if(!$this->hasNext()) { return false; } return array_shift($this->args); } public function next() { if(!$this->hasNext()) { return false; } return $this->args[$this->cursor++]; } public function peek($num) { $num-=1; return isset($this->args[$this->cursor+$num]) ? $this->args[$this->cursor+$num] : false; } public function markUsed($peek=false) { $num = $this->cursor; $num-=1; if($peek!==false) { $num+=$peek; } $this->argsUsed[$num]=true; } public function hasNext() { return isset($this->args[$this->cursor]); } public function isLongArg($arg) { //print_r($arg); if($arg[0] == "-" && $arg[1] == "-" && !empty($arg[2])) { return true; } return false; } public function isShortArg($arg) { if($arg[0] == "-" && $arg[1] != "-" && !empty($arg[1])) { return true; } return false; } public function isValue($arg) { return !$this->isArg($arg); } public function isArg($arg) { if($this->isLongArg($arg) || $this->isShortArg($arg)) { return true; } return false; } public function getArgValue($arg) { if($this->isShortArg($arg)) { $o = substr($arg,1); if(strlen($o)<=1) { $peek = $this->peek(1); if($peek === false || $this->isArg($peek)) { return false; } $this->markUsed(1); return $peek; } else { return substr($o,1); } } elseif($this->isLongArg($arg)) { $o = substr($arg,2); $p = strpos($o, '='); if($p) { return substr($o, $p+1); } else { $peek = $this->peek(1); if($peek === false || $this->isArg($peek)) { return false; } $this->markUsed(1); return $peek; } } return false; } public function getArgs($includeUsed=false) { if($includeUsed) { return $this->args; } else { $args = $this->args; foreach($this->argsUsed as $k=>$v) { unset($args[$k]); } return array_values($args); } } }src/base/dhObject.php000064400000006001144761607140010507 0ustar00set() and ->get() handler */ class dhObject implements \JsonSerializable { protected $data = null; protected $separator = "."; public function __construct($arr=null,$separator=".") { $this->setSeparator($separator); if(is_array($arr) && !empty($arr)) { foreach($arr as $k=>$v) { $this->set($k,$v); } } } public function set($key,$val="",$append=false) { $this->setArray($this->data,$key,$val,$append); return $this; } public function get($key=null,$default=null) { return $this->getArray($this->data,$key,$default); } public function remove($key) { dhGlobal::dotDelete($this->data,$key,$this->separator); return $this; } public function setArray(&$array,$key,$val="",$append=false) { if(strpos($key,$this->separator) !== false) { if($append) { $check = dhGlobal::getDot($array,$key,$this->separator); if(!is_null($check)) { if(is_array($check)) { $check[] = $val; $val = $check; } else { $narr = []; $narr[] = $check; $narr[] = $val; $val = $narr; } } } dhGlobal::dotAssign($array,$key,$val); } else { if(isset($array[$key]) && $append) { if(is_array($array[$key])) { $array[$key][] = $val; } else { $temp = $array[$key]; $array[$key] = []; $array[$key][] = $temp; $array[$key][] = $val; } } else { $array[$key] = $val; } } return $this; } public function getArray($array,$key=null,$default=null) { if(is_null($key)) { return !empty($array) ? $array : $default; } if(strpos($key,$this->separator) !== false) { $check = dhGlobal::getDot($array,$key,null,$this->separator); if(!is_null($check)) { return $check; } } return isset($array[$key]) ? $array[$key] : $default; } public function jsonSerialize($array=null) { if(is_null($array)) { $array = $this->data; } return $array; } /** * Get the value of dotSeparator */ public function getSeparator() { return $this->separator; } /** * Set the value of dotSeparator * * @return self */ public function setSeparator($separator) { $this->separator = $separator; return $this; } }src/dhGlobal.php000064400000013506144761607140007577 0ustar00$driver,"config"=>$config]); static::set("dhDB",$db); } $db = static::get("dhDB",false); if($db === false) { //try vtconfig.. maybe it exists if(static::fileIfExists("config.inc.php") !== false) { $db = $dbClass::fromVtigerConfig("config.inc.php"); static::set("dhDB",$db); } } return static::get("dhDB",false); } throw new \Exception("cannot init DB without dhDB being included"); } public static function dateIntervalToElapsed($dateInterval,$short=true,$includeZeros=false) { $parts=[]; if($dateInterval->y > 0 || $includeZeros) { $parts[] = $dateInterval->y. ($short?"Y":" ". static::pluralize($dateInterval->y,"year")); } if($dateInterval->m > 0 || $includeZeros) { $parts[] = $dateInterval->m. ($short?"M":" ". static::pluralize($dateInterval->m,"month")); } if($dateInterval->d > 0 || $includeZeros) { $parts[] = $dateInterval->d. ($short?"D":" ". static::pluralize($dateInterval->d,"day")); } if($dateInterval->h > 0 || $includeZeros) { $parts[] = $dateInterval->h. ($short?"h":" ". static::pluralize($dateInterval->h,"hour")); } if($dateInterval->i > 0 || $includeZeros) { $parts[] = $dateInterval->i. ($short?"m":" ". static::pluralize($dateInterval->i,"minute")); } if($dateInterval->s > 0 || $includeZeros) { $parts[] = $dateInterval->s. ($short?"s":" ". static::pluralize($dateInterval->s,"second")); } return implode(" ",$parts); } public static function pluralize($quantity, $singular, $plural=null) { if($quantity==1 || !strlen($singular)) return $singular; if($plural!==null) return $plural; $last_letter = strtolower($singular[strlen($singular)-1]); switch($last_letter) { case 'y': return substr($singular,0,-1).'ies'; case 's': return $singular.'es'; default: return $singular.'s'; } } }src/dhHttp.php000064400000010373144761607140007315 0ustar00true]; protected $client; protected $options; protected $response; protected $url; protected $method; public $debug_prefix = "dhHttp:: "; public $debugDoTrace = false; public $doDebug = false; /** * * @param mixed $request * @param array $options * @return \boru\dhutils\guzzle\Response * @throws GuzzleException */ public function send($request,$options=[]) { $method = $request->getMethod(); $url = $request->getUrl(); if(!empty($options)) { $request->replace($options); } $this->debug("Sending $method to $url"); $guzzleRequest = new \GuzzleHttp\Psr7\Request(strtoupper($method),$url); $tries = 0; $this->response = $this->client->send($guzzleRequest,$request->get()); while($this->response->getStatusCode() >= 500 && $tries < static::$retryLimit) { sleep(static::$retryDelay); $tries++; $this->debug("(retry $tries of ".static::$retryLimit.") Sending $method to $url"); $this->response = $this->client->send($guzzleRequest,$request->get()); } return $this->response; } public function __construct($method="",$url="",$options=[]) { $stack = new \GuzzleHttp\HandlerStack(); $stack->setHandler(new \GuzzleHttp\Handler\CurlHandler()); $stack->push(\GuzzleHttp\Middleware::mapResponse(function (\Psr\Http\Message\ResponseInterface $response) { return new \boru\dhutils\guzzle\Response($response); })); if(empty($options)) { $clientOpts = static::$clientOptions; } else { if(isset($options["trace"])) { $this->debugDoTrace = $options["trace"]; $this->doDebug = true; unset($options["trace"]); } elseif(isset($options["debug"])) { $this->doDebug = true; } $clientOpts = $options; } $clientOpts["handler"] = $stack; $this->client = new \GuzzleHttp\Client($clientOpts); if(!empty($method)) { $this->setMethod($method); } if(!empty($url)) { $this->setUrl($url); } } protected function debug(...$args) { if($this->doDebug) { array_unshift($args,$this->debug_prefix." - "); $level = $this->debugDoTrace ? "trace" : "debug"; array_unshift($args,$level); return call_user_func_array([$this,"log"],$args); } } public function log(...$args) { return dhGlobal::log(...$args); } /** * * @param mixed $method * @param mixed $url * @param array $options * @return Request */ public function request($method, $url, $options=[]) { return new \boru\dhutils\guzzle\Request($method,$url,$options,$this); } /** * Get the value of url */ public function getUrl() { return $this->url; } /** * Set the value of url * * @return self */ public function setUrl($url) { $this->url = $url; return $this; } /** * Get the value of method */ public function getMethod() { return $this->method; } /** * Set the value of method * * @return self */ public function setMethod($method) { $this->method = $method; return $this; } /** * Get the value of options */ public function getOptions() { return $this->options; } /** * Set the value of options * * @return self */ public function setOptions($options) { $this->options = $options; return $this; } }src/dhHttpLite.php000064400000004555144761607140010140 0ustar00setAuth($auth); } } public function newHeaders() { return new Params("header"); } public function newParams($type="array") { return new Params($type); } public static function params($array,$format="form") { return Params::fromArray($array,$format); } public function get($url,$params=null,$headers=null,$verbose=false) { return $this->call("get",$url,$params,$headers,$verbose); } public function post($url,$params=null,$headers=null,$verbose=false) { return $this->call("post",$url,$params,$headers,$verbose); } public function put($url,$params=null,$headers=null,$verbose=false) { return $this->call("put",$url,$params,$headers,$verbose); } public function delete($url,$params=null,$headers=null,$verbose=false) { return $this->call("delete",$url,$params,$headers,$verbose); } public function options($url,$params=null,$headers=null,$verbose=false) { return $this->call("options",$url,$params,$headers,$verbose); } public function call($method,$url,$params=null,$headers=null,$verbose=false) { $request = new Request(); $request ->method($method) ->url($url); if(!is_null($params)) { $request->param($params); } if(!is_null($headers)) { $request->header($headers); } if(!empty($this->auth)) { $args = []; $args = $this->auth; array_unshift($args,$this->authType); $request->auth(...$args); } $request->verbose($verbose); return $request->call(); } /** * Get the value of auth */ public function getAuth() { return $this->auth; } /** * Set the value of auth * * @return self */ public function setAuth($type="Basic",...$params) { $this->authType = $type; $this->auth = $params; return $this; } }src/dhLoader.php000064400000006637144761607140007614 0ustar00classPrefix(static::$classPrefix); } if($loader !== false) { static::addLoader($loader); } } public static function addLoader($loader) { if(!is_object($loader)) { $class = "\\boru\\dhutils\\loader\\".$loader; if(class_exists($class,true)) { $loader = new $class; } } $loader->init(); static::$loaders[] = $loader; } /** * Set the baseDir restriction for the dhLoader::includeOnce method * * dhLoader::includeOnce is utilized for the TypeClass loader, and is public static * @param mixed $baseDir * @return string|void */ public static function baseDir($baseDir=null) { if(is_null($baseDir)) { return static::$baseDir; } else { static::$baseDir = dhGlobal::trimString(DIRECTORY_SEPARATOR,$baseDir,dhGlobal::TRIM_END); } } /** * Wrapper for the TypeClass loader * @param string|null $prefix * @return string|void */ public static function classPrefix(string $prefix=null) { if(is_null($prefix)) { return static::$classPrefix; } else { static::$classPrefix = $prefix; } } public static function includeOnce($qualifiedName, $fileExtension="php",$supress=false) { if(isset(static::$includeCache[$qualifiedName])) { return true; } $file = static::resolveNameToPath($qualifiedName,$fileExtension); //dhGlobal::debug("file",$file); if (!file_exists($file)) { dhGlobal::error("File Doesnt Exist - dhLoader - Error when trying to include $file"); return false; } $status = -1; if ($supress) { $status = @include_once $file; } else { $status = include_once $file; } $success = ($status === 0)? false : true; if ($success) { static::$includeCache[$qualifiedName] = $file; } return $success; } public static function resolveNameToPath($qualifiedName, $fileExtension='php') { $allowedExtensions = array('php', 'js', 'css', 'less'); $file = ''; if(!in_array($fileExtension, $allowedExtensions)) { return ''; } $baseDir = static::baseDir(); if(empty($baseDir)) { $LOADER_FILE_DIR = ""; } else { $LOADER_FILE_DIR = $baseDir . DIRECTORY_SEPARATOR; } // TO handle loading vtiger files if (strpos($qualifiedName, '~~') === 0) { $file = str_replace('~~', '', $qualifiedName); $file = $LOADER_FILE_DIR . $file; } else if (strpos($qualifiedName, '~') === 0) { $file = str_replace('~', '', $qualifiedName); $file = $LOADER_FILE_DIR . $file; } else { $file = str_replace('.', DIRECTORY_SEPARATOR, $qualifiedName) . '.' .$fileExtension; $file = $LOADER_FILE_DIR . $file; } return $file; } }src/dhMail.php000064400000000640144761607140007254 0ustar00end(); } self::$instance = new self($stdOut,$fileName,$prefix,$prefixFormat,$prefixSpacer,$lineSeparator); return self::$instance; } /** * Used to get the singleton isntance, or init with default settings; * @return dhOut singlton */ public static function instance() { if(self::$instance === null) { self::$instance = self::init(); } return self::$instance; } public function __construct($stdOut=true,$fileName=false,$prefix=true,$prefixFormat="date:Y-m-d H:i:s",$prefixSpacer="\t",$lineSeparator=PHP_EOL) { $this->output = []; $this->setStdOut($stdOut); $this->setPrefix($prefix); $this->setPrefixFormat($prefixFormat); $this->setPrefixSpacer($prefixSpacer); $this->setFileName($fileName); $this->setLineSeparator($lineSeparator); } public function __destruct() { if(!empty($this->output)) { $this->end(); } } public function toOutput($content="") { $string = ""; if(empty($content)) { $prevLine = $this->prevLine(); if(!is_null($prevLine) && strlen($prevLine) == strlen(rtrim($this->prevLine(),$this->eol()))) { //$string.=$this->eol(); } $string .= $this->currentLine(); } else { $string = $content; } if($this->stdOut) { echo $string; } if(!is_null($this->file) && $this->fileName !== false) { $this->file->write($string,$this->fileAppend); } } public function clear() { $this->end(); } public function a($data,$expectAppend=false) { return $this->add($data,$expectAppend); } public function line(...$args) { $parts = []; foreach($args as $arg) { $parts[] = $this->argToString($arg); } $line = $this->prefix(); $line.= $this->indent(); $line.= implode(" ",$parts); if($this->indent>0) { $line = str_replace($this->eol(),$this->eol().$this->indent(),$line); } $this->output[] = $line; $this->cursor++; $this->toOutput(); $this->endLine(); return $this; } public function add($data,$expectAppend=false) { if($this->lineStarted) { $this->endLine(); } $line = $this->prefix(); $line.= $this->indent(); $line.= $this->argToString($data); if($this->indent>0) { $line = str_replace($this->eol(),$this->eol().$this->indent(),$line); } $this->output[] = $line; $this->cursor++; $this->toOutput(); if(!$expectAppend) { $this->endLine(); } return $this; } public function append($data,$last=false) { $this->lineStarted = true; if(is_array($data) || is_object($data)) { $string=print_r($data,true); } else { $string=$data; } rtrim($this->output[$this->cursor-1],$this->eol()); $this->output[$this->cursor-1] .= $string; $this->toOutput($string); if($last) { $this->endLine(); } return $this; } protected function argToString($arg) { if(is_array($arg) || is_object($arg)) { return print_r($arg,true); } else { return $arg; } } public function endLine() { $l = strlen($this->eol()); if(!empty($this->output) && substr($this->output[$this->cursor-1],-$l) != $this->eol()) { $this->output[$this->cursor-1] .= $this->eol(); $this->toOutput($this->eol()); } $this->lineStarted = false; } public function merge(dhOut $otherOut) { if(!empty($this->output)) { $this->toOutput($this->eol()); } $this->toOutput($otherOut->toString($this->eol(),false)); $this->output = array_merge($this->output,$otherOut->output); } public function end() { $this->endLine(); $this->output = []; $this->cursor=0; } public function indent() { if($this->indent>0) { return str_pad("",$this->indent," "); } return ""; } public function prefix() { if($this->prefix) { $tt = explode(":",$this->prefixFormat,2); if(count($tt)==2) { if($tt[0] == "date") { return date($tt[1]).$this->prefixSpacer; } } return $this->prefixFormat.$this->prefixSpacer; } return ""; } public function toFile($filename,$flags=FILE_APPEND) { file_put_contents($filename,$this->toString(),$flags); } public function toString($lineSeparator=null,$trailing=true) { if(is_null($lineSeparator)) { $lineSeparator = $this->eol(); } if($this->trailingNewLine && $trailing) { $o = $lineSeparator; } else { $o = ""; } return implode($lineSeparator,$this->output).$o; } public function __toString() { return $this->toString($this->eol()); } public function prevLine() { if($this->cursor>1) { return $this->output[$this->cursor-2]; } return null; } public function currentLine() { if($this->cursor>0) { return $this->output[$this->cursor-1]; } return null; } /** * Set the value of prefix * * @return self */ public function setPrefix($prefix) { $this->prefix = $prefix; return $this; } /** * Set the value of prefixFormat * * @return self */ public function setPrefixFormat($prefixFormat) { $this->prefixFormat = $prefixFormat; return $this; } /** * Set the value of trailingNewLine * * @return self */ public function setTrailingNewLine($trailingNewLine) { $this->trailingNewLine = $trailingNewLine; return $this; } /** * Set the value of fileName * * @return self */ public function setFileName($fileName) { if($fileName !== false) { $this->file = new File(["path"=>$fileName,"create"=>true]); } $this->fileName = $fileName; return $this; } /** * Set the value of stdOut * * @return self */ public function setStdOut($stdOut) { $this->stdOut = $stdOut; return $this; } /** * Set the value of prefixSpacer * * @return self */ public function setPrefixSpacer($prefixSpacer) { $this->prefixSpacer = $prefixSpacer; return $this; } /** * Set the value of fileAppend * * @return self */ public function setFileAppend($fileAppend) { $this->fileAppend = $fileAppend; return $this; } /** * Get the value of indent */ public function getIndent() { return $this->indent; } /** * Set the value of indent * * @return self */ public function setIndent($indent) { $this->indent = $indent; return $this; } private function eol() { return $this->lineSeparator; } /** * Get the value of lineSeparator * * @return mixed */ public function getLineSeparator() { return $this->lineSeparator; } /** * Set the value of lineSeparator * * @param mixed $lineSeparator * @return self */ public function setLineSeparator($lineSeparator) { $this->lineSeparator = $lineSeparator; return $this; } }src/dhRequest.php000064400000012027144761607140010024 0ustar00[ "scheme"=>"", "host"=>"", //"port"=>80, "path"=>"", "query"=>"" ], "get"=>[], "post"=>[], "body"=>[], "server"=>[], "headers"=>[] ]; use GetSetArray; public function __construct($get=[],$post=[],$headers=[]) { $this->setGet($get); $this->setPost($post); $this->setHeaders($headers); } public static function fromGlobals($jsonBody=false) { $instance = new self($_GET,$_POST,apache_request_headers()); $body = file_get_contents("php://input"); if(!empty($body)) { $instance->setBody($body,$jsonBody); } $instance->setServer($_SERVER); return $instance; } public function getGet($key=null,$default=null) { if(is_null($key)) { return $this->get("get",$default); } return $this->get("get.".$key,$default); } public function getPost($key=null,$default=null) { if(is_null($key)) { return $this->get("post",$default); } return $this->get("post.".$key,$default); } public function getBody($key=null,$default=null) { if(is_null($key)) { return $this->get("body",$default); } return $this->get("body.".$key,$default); } public function getHeader($key=null,$default=null) { if(is_null($key)) { return $this->get("headers"); } return $this->get("headers.".$key,$default); } public function getServer($key=null,$default=null) { if(is_null($key)) { return $this->get("server",$default); } return $this->get("server.".$key,$default); } public function setGet($get) { $this->set("get",$get); return $this; } public function setPost($post) { $this->set("post",$post); return $this; } public function setBody($body,$json=false) { if($json) { $tempobj=json_decode($body,true); if(!empty($tempobj) && is_array($tempobj)) { foreach($tempobj as $k=>$v) { $body[$k]=$v; } } } if(is_array($body)) { $body = dhGlobal::parseDots($body); } $this->set("body",$body); return $this; } public function getHeaders() { return $this->get("headers"); } public function setHeaders($headers) { $this->set("headers",$headers); return $this; } public function setServer($server) { $method = isset($server['REQUEST_METHOD']) ? $server['REQUEST_METHOD'] : 'GET'; $this->setMethod($method); $this->set("uri.scheme",isset($server["HTTPS"]) ? "https" : "http"); $hasPort = false; if (isset($server['HTTP_HOST'])) { list($host, $port) = self::extractHostAndPortFromAuthority($server['HTTP_HOST']); if ($host !== null) { $this->set("uri.host",$host); } if ($port !== null) { $hasPort = true; $this->set("uri.port",$port); } } elseif (isset($server['SERVER_NAME'])) { $this->set("uri.host",$server['SERVER_NAME']); } elseif (isset($server['SERVER_ADDR'])) { $this->set("uri.host",$server['SERVER_ADDR']); } if (!$hasPort && isset($server['SERVER_PORT'])) { $this->set("uri.port",$server['SERVER_PORT']); } $hasQuery = false; if (isset($server['REQUEST_URI'])) { $requestUriParts = explode('?', $server['REQUEST_URI'], 2); $this->set("uri.path",$requestUriParts[0]); if (isset($requestUriParts[1])) { $hasQuery = true; $this->set("uri.query",$requestUriParts[1]); } } if (!$hasQuery && isset($server['QUERY_STRING'])) { $this->set("uri.query",$server['QUERY_STRING']); } $this->set("server",$server); return $this; } public function setUri($uri=[]) { $this->set("uri",$uri); } private static function extractHostAndPortFromAuthority($authority) { $uri = 'http://' . $authority; $parts = parse_url($uri); if (false === $parts) { return [null, null]; } $host = isset($parts['host']) ? $parts['host'] : null; $port = isset($parts['port']) ? $parts['port'] : null; return [$host, $port]; } /** * Get the value of method * * @return mixed */ public function getMethod() { return $this->method; } /** * Set the value of method * * @param mixed $method * @return self */ public function setMethod($method) { $this->method = $method; return $this; } }src/dhScriptLock.php000064400000002630144761607140010450 0ustar00lockPath = $lockPath; $this->lockFile = $lockFile; } public function __destruct() { if(file_exists($this->lockFile())) { unlink($this->lockFile()); } } public function lockFile() { if(substr($this->lockPath,-strlen(DIRECTORY_SEPARATOR)) !== DIRECTORY_SEPARATOR) { $this->lockPath.=DIRECTORY_SEPARATOR; } return $this->lockPath.$this->lockFile; } public function isLocked() { # If lock file exists, check if stale. If exists and is not stale, return TRUE # Else, create lock file and return FALSE. if (file_exists($this->lockFile())) { # check if it's stale $lockingPID = trim(file_get_contents($this->lockFile())); # Get all active PIDs. $pids = explode("\n", trim(`ps -e | awk '{print $1}'`)); # If PID is still active, return true if (in_array($lockingPID, $pids)) return true; # Lock-file is stale, so kill it. Then move on to re-creating it. unlink($this->lockFile()); } file_put_contents($this->lockFile(), getmypid() . "\n"); return false; } }src/dhThreads.php000064400000017075144761607140007776 0ustar00maxThreads = $maxThreads; $this->throttleDelay = $throttleDelay; $this->setOptions($options); declare(ticks = 1); pcntl_signal(SIGINT,[$this,"__shutdown"]); } public function __destruct() { $this->killAll(); } public function __shutdown() { $this->__destruct(); usleep(0.5*1000); exit(); } public function killThread($thread) { if(is_object($thread)) { $thread->stop(); return true; } elseif(is_numeric($thread)) { posix_kill($thread, 0); return true; } else { return false; } } public function killAll() { if(!$this->stopped) { $this->stopped = true; foreach($this->runningThreads as $thread) { $thread->stop(); } } } public function startScript($file,$data=[],$options=[]) { $meta = []; if(!empty($data)) { $args = $this->packData($data); $meta["data"] = $data; } else { $args = ""; $meta = []; } if(is_object($file)) { $command = "php -f ".$file->path()." ".$args; } else { $command = "php -f ".$file." ".$args; } $this->start($command,$meta,$options); } public function start($command,$meta=[],$options=[]) { if(!$this->stopped) { $this->throttle(); $meta["id"] = $this->threadIndex; $this->threadIndex++; $thread = new Thread($command,$meta,$options); if($this->callbackVisualizer instanceof CallbackInterface) { $this->callbackVisualizer->threadStart($thread); } $this->runningThreads[] = $thread; dhGlobal::trace("[MT] Started thread with pid=".$thread->pid()); $this->countRunningThreads(); return $thread->pid(); } return false; } public function collect($options=[]) { $collectType = dhGlobal::getVal($options,"collectType",null); $this->wait(); if($collectType == static::COLLECT_ARRAY) { $return = []; foreach($this->finishedThreads as $thread) { $return[] = $thread->output(); } return $return; } elseif($collectType == static::COLLECT_FULL || $collectType == static::COLLECT_OBJECT) { return $this->finishedThreads; } return true; } public function wait() { $this->throttle(1); } protected function throttle($maxThreads=null) { if(is_null($maxThreads)) { $maxThreads = $this->maxThreads; } if($maxThreads > 0) { while(($count = $this->countRunningThreads()) >= $maxThreads) { dhGlobal::trace("[MT] $count runningThreads is >= $maxThreads.. waiting.",($this->throttleDelay * 1000000)); usleep($this->throttleDelay * 1000000); } } } protected function countRunningThreads() { foreach($this->runningThreads as $k=>$thread) { if($thread->finished()) { dhGlobal::trace("[MT] thread $k has completed"); if($this->callbackVisualizer instanceof CallbackInterface) { $this->callbackVisualizer->collect($thread->output()); } if($this->callbackVisualizer instanceof CallbackInterface) { $this->callbackVisualizer->threadFinished($thread); } $this->finishedThreads[] = $thread; unset($this->runningThreads[$k]); } } if($this->callbackVisualizer instanceof CallbackInterface) { $this->callbackVisualizer->loop($this); } return count($this->runningThreads); } public function setOptions($options=[]) { //visualizer object.. default to BlankVisualizer. //visualizer holds 3 callbacks, threadStarted, threadFinished, and throttleWait (queued) $cbVisualizerClass = dhGlobal::getVal($options,"callbackVisualizer",new BlankVisualizer()); if(!is_object($cbVisualizerClass) && !is_null($cbVisualizerClass)) { if(class_exists($cbVisualizerClass,true)) { $this->callbackVisualizer = new $cbVisualizerClass(); } } elseif($cbVisualizerClass instanceof CallbackInterface) { $this->callbackVisualizer = $cbVisualizerClass; } if(is_null($this->callbackVisualizer)) { $this->callbackVisualizer = new BlankVisualizer(); } if(($threadStartCallback = dhGlobal::getval($options,"threadStartCallback",false)) !== false) { $this->callbackVisualizer->setThreadStartCallback($threadStartCallback); } if(($threadFinishedCallback = dhGlobal::getval($options,"threadFinishedCallback",false)) !== false) { $this->callbackVisualizer->setThreadFinishedCallback($threadFinishedCallback); } if(($throttleWaitCallback = dhGlobal::getval($options,"throttleWaitCallback",false)) !== false) { $this->callbackVisualizer->setThrottleWaitCallback($throttleWaitCallback); } } public function packData($data) { return static::pack($data); } public function unpackData($packedData,$object=false) { return static::unpack($packedData,$object); } public static function pack($data) { if(is_array($data) || is_object($data)) { $data = json_encode($data); } return base64_encode($data); } public static function unpack($packedData,$object=false) { $data = base64_decode($packedData); $test = json_decode($data,!$object); if(is_array($test) || is_object($test)) { return $test; } return $data; } public static function sendChannel($runnerID,$channelType,$data) { if($channelType == static::CHANNEL_MEMCACHED) { if(class_exists('\Memcached')) { return dhGlobal::cache()->lockSet($runnerID,$data); } else { dhGlobal::error("Memcached not work"); } } } public static function readChannel($runnerID,$channelType) { if($channelType == static::CHANNEL_MEMCACHED) { if(class_exists('\Memcached')) { if(($data = dhGlobal::cache()->lockGet($runnerID))!==false) { return $data; } } else { dhGlobal::error("Memcached not work"); } } } }src/filesys/BasePath.php000064400000020305144761607140011223 0ustar00resolvePath($path,$expand); } $this->basePathDebug = $debug; } public static function path($path,$expand=false,$debug=false) { $instance = new self($path,$expand,$debug); return $instance->fullPath($expand); } public function fullPath($expand=false) { return $expand ? $this->expandedPath : $this->fullPath; } public function baseDir($expand=false) { return $expand ? $this->expandedBaseDir : $this->baseDir; } public function isDir() { return $this->isDir(); } public function isLink() { return $this->isLink(); } public function makeDir() { mkdir($this->fullPath,0777,true); $this->resolvePath($this->fullPath); } public function makeFile() { if(!empty($this->remaining) && is_array($this->remaining)) { $this->createBase(); } if(!file_exists($this->fullPath)) { touch($this->fullPath); $this->resolvePath($this->fullPath); } } public function createBase() { if(!empty($this->remaining) && is_array($this->remaining)) { $start = $this->baseDir; $dir = $start.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR,$this->remaining); if(!file_exists($dir)) { mkdir($dir,0777,true); $this->resolvePath($this->fullPath); } } } public function relative($testPath) { if(!is_object($testPath)) { $testPath = new BasePath($testPath); } $expandedParent = $testPath->fullPath(true); $fullPath = $this->fullPath(true); if(substr($fullPath,0,strlen($expandedParent)) !== $expandedParent) { return false; } $t = substr($fullPath,strlen($expandedParent)); if(substr($t,0,strlen(DIRECTORY_SEPARATOR)) == DIRECTORY_SEPARATOR) { $t = substr($t,strlen(DIRECTORY_SEPARATOR)); } return $t; } private function basePathDebug(...$args) { if($this->basePathDebug) { array_unshift($args,"debug"); return dhGlobal::log(...$args); } return false; } protected function resolvePathExists($path,$expand=false) { if(substr($path,-1) == "/") { $path = substr($path,0,-1); } $parts = explode("/",$path); $this->basePathDebug("file exists"); if(substr($path,0,1) !== "/") { $this->baseDir = is_link(getcwd()) ? readlink(getcwd()) : realpath(getcwd()); $this->baseDir.= "/".dirname($path); $this->basePathDebug("relative",$this->baseDir); } else { $this->baseDir = dirname($path); $this->basePathDebug("real",$this->baseDir); } $this->expandedBaseDir = is_link($this->baseDir) ? readlink($this->baseDir) : realpath($this->baseDir); if(is_dir($path)) { $this->isDir = true; } $this->fileName = array_pop($parts); $this->fullPath = $this->baseDir; if(!is_null($this->fileName)) { $this->fullPath .= "/". $this->fileName; } else { $this->fullPath .= "/".array_pop($parts); } if(is_link($this->fullPath)) { $this->isLink = true; $this->expandedPath = readlink($this->fullPath); } else { $this->expandedPath = realpath($this->fullPath); } if(is_dir($this->expandedPath)) { $this->isDir = true; } $this->formatOutput(); if($expand) { return $this->expandedPath; } return $this->fullPath; } public function resolvePath($path,$expand=false) { $path = $this->toLinuxSlash($path); $this->basePathDebug("using $path"); if(substr($path,-1) == "/") { $this->isDir = true; $path = substr($path,0,-1); } $remaining = false; $parts = explode("/",$path); while(end($parts) == ".") { array_pop($parts); $parts = explode("/",implode("/",$parts)); } if(empty($parts) || count($parts) === 1 && empty($parts[0])) { $path = getcwd(); $parts = explode("/",$path); } if(file_exists($path)) { return $this->resolvePathExists($path,$expand); } $this->basePathDebug("file doesnt exist"); if(substr($path,0,1) !== "/") { $this->baseDir = getcwd(); $this->basePathDebug("relative ".$this->baseDir); } else { $this->baseDir = "/"; $this->basePathDebug("real ".$this->baseDir); } $newParts = []; while(!empty($parts)) { $part = array_shift($parts); if(!empty($part)) { if(file_exists($this->baseDir."/".implode("/",$newParts)."/".$part)) { $newParts[] = $part; } else { array_unshift($parts,$part); break; } } } $this->baseDir.= !empty($newParts) ? "/".implode("/",$newParts) : ""; if(!empty($parts)) { $remaining = implode("/",$parts); $this->fileName = array_pop($parts); } unset($newParts); $this->basePathDebug("basedir= ".$this->baseDir); $this->baseDir = $this->baseDir; $this->expandedBaseDir = realpath($this->baseDir); if($remaining !== false) { $this->basePathDebug("remaining= $remaining"); $this->remaining = $parts; $this->fullPath = $this->baseDir."/".$remaining; $this->expandedPath = realpath($this->baseDir); $this->expandedPath.="/".$remaining; } else { $this->fullPath = $this->baseDir; $this->expandedPath = realpath($this->baseDir); } $this->formatOutput(); if($expand) { return $this->expandedPath; } return $this->fullPath; } protected function formatOutput() { $this->fullPath = !is_null($this->fullPath) ? $this->formatPathOut($this->fullPath) : null; $this->expandedPath = !is_null($this->expandedPath) ? $this->formatPathOut($this->expandedPath) : null; $this->baseDir = !is_null($this->baseDir) ? $this->formatPathOut($this->baseDir) : null; $this->expandedBaseDir = !is_null($this->expandedBaseDir) ? $this->formatPathOut($this->expandedBaseDir) : null; //$this->baseDir = !is_null($this->baseDir) ? $this->formatPathOut($this->baseDir) : null; //$this->baseDir = !is_null($this->baseDir) ? $this->formatPathOut($this->baseDir) : null; } private function formatPathOut($path) { return $this->toDirSeparator($this->toLinuxSlash($path)); } private function toLinuxSlash($path) { //make all separators into / style separators if(DIRECTORY_SEPARATOR !== '/') { $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); } $path = str_replace("\\","/",$path); while(strpos($path,"//") !== false) { $path = str_replace("//","/",$path); } //clean out useles '.' references $path = dhGlobal::trimString("./",$path,dhGlobal::TRIM_START); $path = dhGlobal::trimString("/.",$path,dhGlobal::TRIM_END); $path = str_replace('/./','/',$path); return $path; } private function toDirSeparator($path) { return str_replace("/",DIRECTORY_SEPARATOR,$path); } }src/filesys/ConfigFile.php000064400000003375144761607140011551 0ustar00file = new File(["path"=>$fileopt,"create"=>true]); } else { $this->file = $fileopt; } $this->prettyJson = dhGlobal::getVal($options,"prettyJson",false); $this->sort = dhGlobal::getVal($options,"sort",true); $this->load(); } public function load() { $content = $this->file->content(["json"=>true]); $this->data = []; if(is_array($content) && !empty($content)) { if($this->sort) { ksort($this->data); } foreach($content as $k=>$v) { $this->set($k,$v); } } return $this; } public function save() { if($this->sort) { ksort($this->data); } if($this->prettyJson) { $this->file->write(json_encode($this,JSON_PRETTY_PRINT)); } else { $this->file->write(json_encode($this)); } return $this; } }src/filesys/DirDiff.php000064400000010753144761607140011051 0ustar00directory = $directory; $this->files = $directory->files(); if(isset($this->files[$this->directory->getMetaFileName()])) { unset($this->files[$this->directory->getMetaFileName()]); } $this->diff(); } public function diff($meta=null) { if(is_null($meta)) { $meta = $this->directory->meta(); } if(!$this->hasMetaData($meta)) { $this->new = array_keys($this->files); } else { $this->metaFiles = $meta["files"]; foreach($this->files as $fileName=>$file) { if(!isset($this->metaFiles[$fileName])) { $this->new[] = $fileName; } } foreach($this->metaFiles as $fileName=>$info) { if(!isset($this->files[$fileName])) { $this->missing[] = $fileName; } elseif($info["sha1"] != $this->files[$fileName]->sha1()) { $this->changed[] = $fileName; } else { $this->unchanged[] = $fileName; } } } if(!empty($this->new)) { sort($this->new); } if(!empty($this->missing)) { sort($this->missing); } if(!empty($this->changed)) { sort($this->changed); } if(!empty($this->unchanged)) { sort($this->unchanged); } } private function hasMetaData($meta) { if(is_null($meta) || empty($meta) || (is_array($meta) && !isset($meta["files"])) || (is_array($meta) && empty($meta["files"]))) { return false; } return true; } /** @return File|array|false */ public function getFile($fileName) { if(isset($this->files[$fileName])) { return $this->files[$fileName]; } elseif(isset($this->metaFiles[$fileName])) { return $this->metaFiles[$fileName]; } return false; } /** @return array|false */ public function getNewOrChanged() { $merged = array_unique(array_merge( is_array($this->new) ? $this->new : [], is_array($this->changed) ? $this->changed : [] )); sort($merged); return !empty($merged) ? $merged : false; } public function commitNew($pretty=false) { if($this->getNew() !== false) { foreach($this->getNew() as $fileName) { $this->directory->metaAdd($this->getFile($fileName)); } $this->directory->metaCommit(false,$pretty); $this->diff(); } } public function commitChanged($pretty=false) { if($this->getChanged() !== false) { foreach($this->getChanged() as $fileName) { $this->directory->metaAdd($this->getFile($fileName)); } $this->directory->metaCommit(false,$pretty); $this->diff(); } } public function commitMissing($pretty=false) { if($this->getMissing() !== false) { foreach($this->getMissing() as $fileName) { $this->directory->metaDel($fileName); } $this->directory->metaCommit(false,$pretty); $this->diff(); } } public function commitAll($pretty=false) { $this->directory->metaCommit(true,$pretty); $this->diff(); } /** * Get the value of new * * @return array|false */ public function getNew() { return !empty($this->new) ? $this->new : false; } /** * Get the value of missing * * @return array|false */ public function getMissing() { return !empty($this->missing) ? $this->missing : false; } /** * Get the value of changed * * @return array|false */ public function getChanged() { return !empty($this->changed) ? $this->changed : false; } /** * Get the value of unchanged * * @return array */ public function getUnchanged() { return $this->unchanged; } }src/filesys/Directory.php000064400000024167144761607140011512 0ustar00null, "name"=>null, "scanned"=>0 ]; protected $path; protected $name; protected $pathTrimmed; protected $separator = DIRECTORY_SEPARATOR; protected $files = []; protected $dirs = []; protected $expandSymlink = false; /** @var File */ protected $metaFile; protected $meta; protected $metaFileName = ".bmeta"; protected $metaPerms = "0600"; protected $scanned = false; /** * Valid options: * * path (default:current directory) path of the directory to load * * scan (default:true) * * recursive (default:false) * * expandSymlink (default:false) * * create (default:false) - create the directory (recursively) if it doesn't exist * * metaFile - sets the filename of the meta file (if meta is saved), default is .bmeta * * metaPerms - sets the file perms of the meta file (if meta is saved), default is 0600 */ public function __construct($options=[]) { $path = dhGlobal::getDot($options,"path",null); $scan = dhGlobal::getDot($options,"scan",true); $recursive = dhGlobal::getDot($options,"recursive",false); $this->create = dhGlobal::getDot($options,"create",false); $this->expandSymlink = dhGlobal::getDot($options,"expandSymlink",false); if(($metaFileName = dhGlobal::getDot($options,"metaFile",false)) !== false) { $this->metaFileName = $metaFileName; } if(($metaPerms = dhGlobal::getDot($options,"metaPerms",false)) !== false) { $this->metaPerms = $metaPerms; } if(!is_null($path)) { $this->setDirectory($path); } else { $this->setDirectory(getcwd()); } if($scan && is_dir($this->path())) { $this->scan($recursive); } } public function isScanned() { return $this->get("scanned",0) > 0 ? true : false; } /** @return DirDiff */ public function metaDiff() { return new DirDiff($this,$this->meta()); } /** Commits meta to file. If no meta exists, it is generated. * @param bool $all if true, overwrites existing meta with current file meta * @return array|null * */ public function metaCommit($all=false,$pretty=false) { $meta = $this->meta(); if(is_null($meta) || empty($meta) || $all) { $this->metaClear(); if(!$this->isScanned()) { $this->scan(); } foreach($this->files() as $file) { $meta["files"][$file->name()]=$file->meta(); } } $meta["generated"] = date("U"); $meta["path"] = $this->path(); if(!isset($meta["files"])) { $meta["files"]=[]; } if(isset($meta["files"][$this->metaFileName])) { unset($meta["files"][$this->metaFileName]); } ksort($meta["files"]); if($pretty) { $this->metaFile->write(json_encode($meta,JSON_PRETTY_PRINT)); } else { $this->metaFile->write(json_encode($meta)); } return $this->meta(true); } public function metaAdd($fileOrName) { $this->meta(); if(($file = $this->getFileFromFileOrName($fileOrName)) !== false) { $this->meta["files"][$file->name()] = $file->meta(); } return $this; } public function metaDel($fileOrName) { $this->meta(); if(($fileName = $this->getFileFromFileOrName($fileOrName,true)) !== false) { if(isset($this->meta[$fileName])) { unset($this->meta[$fileName]); } } return $this; } protected function getFileFromFileOrName($fileOrName,$name=false) { if(!is_object($fileOrName)) { $file = dhGlobal::fileIfExists($fileOrName); if($file !== false) { return $name ? $file->name() : $file; } return false; } return $name ? $fileOrName->name() : $fileOrName; } /** @return array|null */ public function meta($reload=false) { if(is_null($this->metaFile)) { $this->metaFile = new File(["path"=>$this->path($this->metaFileName)]); $this->metaFile->perms($this->metaPerms); } if(is_null($this->meta) || $reload) { $this->metaClear(); $this->meta = $this->metaFile->content(["json"=>true]); if(isset($this->meta["path"]) && $this->meta["path"] != $this->path()) { $this->metaClear(); } } return $this->meta; } protected function metaClear() { $this->meta = ["generated"=>date("U"),"path"=>$this->path(),"files"=>[]]; } public function path($fileOrDirName=null) { $path = $this->get("path",null); if(is_null($path)) { return null; } if(!is_null($fileOrDirName)) { return $path.$this->separator.$fileOrDirName; } return $path; } public function name() { return $this->get("name",null); } public function files($objects=true) { if($objects) { return $this->files; } $arr = []; foreach($this->files as $file) { $arr[$file->name()] = $file->get(); } return $arr; } public function dirs($objects=true) { if($objects) { return $this->dirs; } $arr = []; foreach($this->dirs as $dir) { $arr[$dir->name()] = $dir->get(); } return $arr; } public function file($name=null) { return $this->_getFile($name); } public function dir($name=null) { return $this->_getDir($name); } public function createFile($name,$touchOnExists=true) { $parts = explode($this->separator,$name); $name = array_pop($parts); $filename = $this->path().$this->separator.$name; if(file_exists($filename)) { if(!$touchOnExists) { throw new \Exception("File already exists ".$name,-1); } else { touch($filename); $file = new File([ "path"=>$filename, "expandSymlink"=>$this->expandSymlink, ]); } } else { touch($filename); $file = new File([ "path"=>$filename, "expandSymlink"=>$this->expandSymlink, ]); $this->_addFile($name,$file); } clearstatcache(); return $file; } public function scan($recursive=false) { if($handle = opendir($this->path())) { while (false !== ($entry = readdir($handle))) { if($entry != "." && $entry != "..") { if(is_dir($this->path($entry))) { $dir = new Directory([ "path"=>$this->path($entry), "scan"=>$recursive, "recursive"=>$recursive, "expandSymlink"=>$this->expandSymlink, ]); $this->_addDir($entry,$dir); } else { $file = new File([ "path"=>$this->path($entry), "expandSymlink"=>$this->expandSymlink, ]); $this->_addFile($entry,$file); } } } } $size=0; foreach($this->files as $file) { $size+=!is_null($file->size()) ? $file->size() : 0; } $this->set("fileSize",$size); $this->set("scanned",time()); return $this; } /** @return File|null */ public function getMetaFile() { return $this->metaFile; } /** @return string */ public function getMetaFileName() { return $this->metaFileName; } /** * Set the value of path * * @return self */ public function setDirectory($path) { $pathObj = new BasePath($path,$this->expandSymlink); if(!file_exists($pathObj->fullPath()) && $this->create) $pathObj->makeDir(); $this->set("path",$pathObj->fullPath($this->expandSymlink)); $this->set("pathObj",$pathObj); $pathTrimmed = substr($this->get("path"), strlen($this->separator)); //$this->set("pathTrimmed",$pathTrimmed); $arr = explode($this->separator,$pathTrimmed); $this->set("name",array_pop($arr)); return $this; } /** * Get the value of separator */ public function getSeparator() { return $this->separator; } /** * Set the value of separator * * @return self */ public function setSeparator($separator) { $this->separator = $separator; return $this; } public function _addFile($name,$file=null) { if(is_null($file)) { $file = new File([ "path"=>$this->getPath.$this->separator.$name ]); } $this->setArray($this->files,$name,$file,false); return $this; } public function _getFile($name=null) { return $this->getArray($this->files,$name,false); } public function _addDir($name,$dir=null) { if(is_null($dir)) { $dir = new Directory([ "path"=>$this->getPath.$this->separator.$name ]); } $this->setArray($this->dirs,$name,$dir,false); return $this; } public function _getDir($name=null) { return $this->getArray($this->dirs,$name,false); } }src/filesys/File.php000064400000031555144761607140010424 0ustar00null, "name"=>null, "size"=>null, "type"=>null, "mtime"=>null, "ctime"=>null, "atime"=>null, "perms"=>null, ]; protected $content; protected $stream; protected $separator = DIRECTORY_SEPARATOR; protected $expandSymlink = false; /** * Opens a File Object instance on a file. This object provides easy access to read/write/meta information of a file. * * Valid options * * string "path" - (required) - the path, including the filename, of hte file to load * * bool "readMeta" - (default:true) - pre-read basic meta information of the file if it exists * * bool "create" - (default:true) - create a file, including subdirs, if the path/filename does not exist * * bool "overwrite" - (default:false) - overwrite an existing file if it already exists, creating a new file * * string "content" - (optional) - Content to write to the file. If overwrite=false, it is appended to the file if the file exists. * * int "maxAge" - in seconds, if ctime is older than maxAge ago, replace the file */ public function __construct($options=[]) { $path = dhGlobal::getDot($options,"path",null); $readMeta = dhGlobal::getDot($options,"readMeta",true); $this->create = dhGlobal::getDot($options,"create",true); $this->maxAge = dhGlobal::getDot($options,"maxAge",false); $overwrite = dhGlobal::getDot($options,"overwrite",false); $content = dhGlobal::getDot($options,"content",null); $this->expandSymlink = dhGlobal::getDot($options,"expandSymlink",false); //$path="",$readMeta=true,$createIfNotExist=false if(!is_null($path)) { if(is_dir($path)) { throw new \Exception("$path is a directory and cannot be loaded as a File instance. Please use a Directory instance instead"); } if(is_link($path) && !$this->expandSymlink) { //$path = } $this->setFile($path); if(file_exists($path) && !is_dir($path)) { if($overwrite) { if(!is_null($content)) { $this->write($content,false); } else { if(($h = fopen($path,"w")) !== false) { fclose($h); } } } else { if(!is_null($content)) { $this->write($content,true); } } if($readMeta) { $this->readMeta(); } } else { throw new \Exception("$path does not exist."); } } } public function __destruct() { $this->streamClose(); } public function path() { return $this->get("path",null); } public function name() { return $this->get("name",null); } public function dirPath() { return $this->get("dirPath",null); } public function type() { if(is_null($this->get("type",null))) { if(($type = filetype($this->path())) !== false) { $this->set("type",$type); } } return $this->get("type",null); } public function mimeType() { if(is_null($this->get("mimeType",null))) { if(($mimeType = mime_content_type($this->path())) !== false) { $this->set("mimeType",$mimeType); } } return $this->get("mimeType",null); } public function size() { if(is_null($this->get("size",null))) { if(($size = filesize($this->path())) !== false) { $this->set("size",$size); } } return $this->get("size",null); } public function mtime($timeFormat="timestamp") { if(is_null($this->get("mtime",null))) { if(($mtime = filemtime($this->path())) !== false) { $this->set("mtime",$mtime); } } return $this->timeFormat($this->get("mtime",null),$timeFormat); } public function ctime($timeFormat="timestamp") { if(is_null($this->get("ctime",null))) { if(($ctime = filectime($this->path())) !== false) { $this->set("ctime",$ctime); } } return $this->timeFormat($this->get("ctime",null),$timeFormat); } public function atime($timeFormat="timestamp") { if(is_null($this->get("atime",null))) { if(($atime = fileatime($this->path())) !== false) { $this->set("atime",$atime); } } return $this->timeFormat($this->get("atime",null),$timeFormat); } public function meta() { return [ "mtime"=>$this->mtime("U"), "size"=>$this->size(), "sha1"=>$this->sha1(), "type"=>$this->type(), ]; } /** * * @param null|int if set, chmod's the file.. prefix with 0 (eg 0600 or 0777) * @return int|null */ public function perms($newPerms=null) { if(!is_null($newPerms)) { chmod($this->path(),intval($newPerms, 8)); clearstatcache(true,$this->path()); if(($perms = fileperms($this->path())) !== false) { $perms = decoct($perms & 0777); $this->set("perms",$perms); } } if(is_null($this->get("perms",null))) { if(($perms = fileperms($this->path())) !== false) { $perms = decoct($perms & 0777); $this->set("perms",$perms); } } return $this->get("perms",null); } public function sha1($useStream=false) { if(is_null($this->get("sha1",null))) { if($useStream) { $stream = $this->streamOpen("r"); $context = hash_init("sha1"); hash_update_stream($context,$stream); $hash = hash_final($context); $this->streamClose(); $this->set("sha1",$hash); } else { $hash = sha1($this->content()); $this->set("sha1",$hash); } } return $this->get("sha1"); } public function delete($recreate=false) { unlink($this->path()); $this->clearMeta(); if($recreate) { touch($this->path()); if($this->readMeta) { $this->readMeta(); } } } public function streamOpen($mode="a+") { if(is_null($this->stream)) { $this->stream = fopen($this->path(),$mode); } return $this->stream; } public function streamClose() { if(!is_null($this->stream)) { fclose($this->stream); } $this->stream = null; } /** * Retrieve the content of the file * * Return the raw contents (default), or use options to transform it. * * Options: * * json - boolean (default:false), parse the contents as json into an array. * * jsonObject - boolean (default:false), parse the contents as json into an object. * * filter - callable, filter/modify the content before returning it through json/jsonObject/plain * * save - boolean (default:true), save (cache) the raw content to the object.. not added to the get() output. */ public function content($options=[]) { $json = dhGlobal::getVal($options,"json",false); $jsonObject = dhGlobal::getVal($options,"jsonObject",false); $lineFilter = dhGlobal::getVal($options,"lineFilter",false); $lineEnding = dhGlobal::getVal($options,"lineEnding",PHP_EOL); $filter = dhGlobal::getVal($options,"filter",false); $save = dhGlobal::getVal($options,"save",true); if(!is_null($this->content) && $save) { $content = $this->content; } else { $content = file_get_contents($this->path()); if($save) { $this->content = $content; } } if(!is_null($lineFilter) && is_callable($lineFilter)) { $newContent = []; foreach(explode($lineEnding,$content) as $line) { if(($line = $lineFilter($line)) !== false) { $newContent[] = $line; } } $content = implode($lineEnding,$newContent); } if(!is_null($filter) && is_callable($filter)) { $content = $filter($content); } if($json) { return json_decode($content,true); } elseif($jsonObject) { return json_decode($content); } else { return $content; } } public function write($content,$append=false) { if($append) { file_put_contents($this->path(),$content,FILE_APPEND); } else { file_put_contents($this->path(),$content); } } protected function timeFormat($timestampValue,$format="timestamp") { if(empty($timestampValue) || is_null($timestampValue) || $timestampValue <= 0) { return $timestampValue; } if(empty($format) || is_null($format)) { return $timestampValue; } try { $dt = new \DateTime(date("Y-m-d H:i:s",$timestampValue),new \DateTimeZone(date_default_timezone_get())); } catch (\Exception $e) { return $timestampValue; } if(!is_array($format)) { $objVals = ["datetime","dt","object"]; if($format == "timestamp") { return $timestampValue; } elseif($format == "millis") { return $timestampValue*1000; } elseif(in_array(strtolower($format),$objVals)) { return $dt; } else { try { $out = $dt->format($format); } catch (\Exception $e) { $out = $timestampValue; } return $out; } } else { if(count($format) >= 2) { if(isset($format["format"]) && isset($format["timezone"])) { $fmt = $format["format"]; $tz = $format["timezone"]; } else { $fmt = $format[0]; $tz = $format[1]; } try { $dt->setTimezone(new \DateTimeZone($tz)); $out = $dt->format($fmt); } catch (\Exception $e) { $out = $timestampValue; } return $out; } return $timestampValue; } return $timestampValue;//shouldn't get here.. but just in case } /** * Set the value of path * * @return self */ public function setFile($path,$readMeta=true,$root=null) { $pathObj = new BasePath($path,$this->expandSymlink); if(!file_exists($path) && $this->create) { $pathObj->makeFile(); } if(file_exists($path)) { $this->set("path",$pathObj->fullPath($this->expandSymlink)); } else { throw new \Exception("File not found ".$path,-1); } if($this->maxAge !== false) { if($this->ctime() < time()-($this->maxAge)) { $this->delete(true); } } $pathTrimmed = substr($this->get("path"), strlen($this->separator)); //$this->set("pathTrimmed",$pathTrimmed); $arr = explode($this->separator,$pathTrimmed); $this->set("name",array_pop($arr)); $this->set("dirPath",$this->separator.implode($this->separator,$arr)); return $this; } public function readMeta() { if(file_exists($this->path())) { $this->size(); $this->type(); $this->mtime(); $this->atime(); $this->ctime(); $this->perms(); $this->mimeType(); } return $this; } public function clearMeta() { $this->set("size",null); $this->set("type",null); $this->set("mtime",null); $this->set("atime",null); $this->set("ctime",null); $this->set("perms",null); $this->set("mimeType",null); } public function reloadMeta() { $this->clearMeta(); $this->readMeta(); } }src/guzzle/Request.php000064400000011220144761607140011022 0ustar00parent = &$parent; } if(!empty($method)) { $this->setMethod($method); } if(!empty($url)) { $this->setUrl($url); } } /** * * @return \boru\dhutils\guzzle\Response */ public function send() { return $this->parent->send($this); } public function run() { return $this->send(); } public function replace($opts=[]) { $this->data = $opts; } protected function mset($primary,$key,$value=null,$append=false) { if(is_array($key) && is_null($value)) { foreach($key as $k=>$v) { $this->set($primary.".".$k,$v,$append); } } else { $this->set($primary.".".$key,$value,$append); } } public function auth($user,$pass) { $this->set(\GuzzleHttp\RequestOptions::AUTH,[$user,$pass]); return $this; } public function authBasic($user,$pass) { $this->set(\GuzzleHttp\RequestOptions::AUTH,[$user,$pass]); return $this; } public function authToken($token) { $this->mset(\GuzzleHttp\RequestOptions::HEADERS,"Authorization",$token); return $this; } public function authBearer($token) { $this->mset(\GuzzleHttp\RequestOptions::HEADERS,"Authorization","Bearer ".$token); return $this; } public function header($key,$value) { $this->mset(\GuzzleHttp\RequestOptions::HEADERS,$key,$value); return $this; } public function json($key,$value=null) { $this->mset(\GuzzleHttp\RequestOptions::JSON,$key,$value); return $this; } public function rawBody($body) { $this->set(\GuzzleHttp\RequestOptions::BODY,$body); return $this; } public function body($key,$value=null) { if(is_null($value)) { return $this->rawBody($key); } $this->mset(\GuzzleHttp\RequestOptions::BODY,$key,$value); return $this; } public function debug($value=true) { $this->set(\GuzzleHttp\RequestOptions::DEBUG,$value); return $this; } public function ipResolve($value="ipv4") { $this->set(\GuzzleHttp\RequestOptions::FORCE_IP_RESOLVE,$value); return $this; } public function form($key,$value=null) { $this->mset(\GuzzleHttp\RequestOptions::FORM_PARAMS,$key,$value); return $this; } public function multipart($value) { $mp = $this->get(\GuzzleHttp\RequestOptions::MULTIPART,[]); $mp[] = $value; $this->set(\GuzzleHttp\RequestOptions::MULTIPART,$mp); return $this; } public function query($key,$value=null) { $this->mset(\GuzzleHttp\RequestOptions::QUERY,$key,$value); return $this; } public function sink($value) { $this->set(\GuzzleHttp\RequestOptions::SINK,$value); return $this; } public function stream($value=true) { $this->set(\GuzzleHttp\RequestOptions::STREAM,$value); return $this; } public function verify($value=false) { $this->set(\GuzzleHttp\RequestOptions::VERIFY,$value); return $this; } public function timeout($value=0) { $this->set(\GuzzleHttp\RequestOptions::TIMEOUT,$value); return $this; } /** * Get the value of parent */ public function getParent() { return $this->parent; } /** * Set the value of parent * * @return self */ public function setParent($parent) { $this->parent = &$parent; return $this; } /** * Get the value of method */ public function getMethod() { return $this->method; } /** * Set the value of method * * @return self */ public function setMethod($method) { $this->method = $method; return $this; } /** * Get the value of url */ public function getUrl() { return $this->url; } /** * Set the value of url * * @return self */ public function setUrl($url) { $this->url = $url; return $this; } }src/guzzle/Response.php000064400000005061144761607140011176 0ustar00response = $response; } public function code() { return $this->getStatusCode(); } public function phrase() { return $this->getReasonPhrase(); } public function header($header=null,$default=false) { if(is_null($header)) { return $this->getHeaders(); } if(!$this->hasHeader($header)) { return $default; } return $this->getHeader($header); } /** * * @param bool $json * @param bool $arr * @return mixed */ public function body($json=false,$arr=true) { if($json) { return json_decode($this->getBody(),$arr); } else { return $this->getBody(); } } //ResponseInterface methods: public function getStatusCode() { return $this->response->getStatusCode(); } public function withStatus($code, $reasonPhrase = '') { return $this->response->getStatusCode($code, $reasonPhrase); } public function getReasonPhrase() { return $this->response->getReasonPhrase(); } public function getProtocolVersion() { return $this->response->getProtocolVersion(); } public function withProtocolVersion($version) { return $this->response->withProtocolVersion($version); } public function getHeaderLine($name) { return $this->response->getHeaderLine($name); } public function withHeader($name, $value) { return $this->response->withHeader($name, $value); } public function withAddedHeader($name, $value) { return $this->response->withAddedHeader($name, $value); } public function withoutHeader($name) { return $this->response->withoutHeader($name); } public function hasHeader($header) { return $this->response->hasHeader($header); } public function getHeader($header) { return $this->response->getHeader($header); } public function getHeaders() { return $this->response->getHeaders(); } public function getBody() { return $this->response->getBody(); } public function withBody(\Psr\Http\Message\StreamInterface $body) { return $this->response->withBody($body); } }src/httplite/client/Params.php000064400000005501144761607140012415 0ustar00data = []; if(!empty($format)) { $this->format($format); } } public function getAll($format="") { if(empty($format)) { $format = $this->format; } if($format == "json") { return json_encode($this->data); } elseif($format == "url" || $format == "form") { return http_build_query($this->data); } elseif($format == "header") { $d = []; foreach($this->data as $k=>$v) { $d[] = $k.": ".$v; } return $d; } else { return $this->data; } } public function format($format) { $this->format = $format; } public function pos() { return count($this->data); } public static function fromArray($array,$format="form") { $params = new self($format); if($format == "header" && !dhGlobal::isAssoc($array)) { foreach($array as $k=>$v) { $temp = explode(": ",$v,2); if(count($temp)==2) { $v = isset($temp[1]) ? $temp[1] : ""; $params->set($temp[0],$v); } else { $params->set($k,$v); } } } else { foreach($array as $k=>$v) { $params->set($k,$v); } } return $params; } public static function fromJSON($json,$format="form") { $array = json_decode($json,true); self::FromArray($array,$format); } /** * Header param specifc shortcut for making auth easy */ public function auth($type="Basic",...$params) { $token = ""; $parts = $params; if(!empty($type)) { array_unshift($parts,$type); } switch(strtolower($type)) { case "basic": if(count($params)===1) { $token = "Basic ".$params[0]; } if(count($params)==2) { $token = "Basic ".base64_encode(implode(":",$params)); } break; default: $token = implode(" ",$parts); break; } $this->set("Authorization",$token); } private function isNumericArray($arr) { foreach($arr as $k=>$v) { if($k !== (int) $k) { return false; } } return true; } }src/httplite/client/Request.php000064400000016354144761607140012632 0ustar00headers = $headers; } elseif(is_array($headers)) { $this->headers = Params::fromArray($headers,"header"); } else { if(is_null($this->headers)) { $this->headers = new Params("header"); } $this->headers->set($headers,$val); } return $this; } public function param($params=[],$val=null) { if(is_object($params)) { $this->params = $params; } elseif(is_array($params)) { $this->params = Params::fromArray($params,$this->bodyType); } else { if(is_null($this->params)) { $this->params = new Params($this->bodyType); } $this->headers->set($params,$val); } return $this; } public function url($url) { $this->url = $url; return $this; } public function method($method) { $this->method = $method; return $this; } public function sslVerify($sslVerify) { $this->sslVerify = $sslVerify; return $this; } public function verbose($verbose) { $this->verbose = $verbose; return $this; } public function returnType($type=false) { $this->returnType = $type; return $this; } public function sendType($type="json") { $this->bodyType = $type; return $this; } public function sendJson() { $this->bodyType = "json"; return $this; } public function sendForm() { $this->bodyType = "form"; return $this; } public function auth($type="Basic",...$params) { $token = ""; $parts = $params; if(!empty($type)) { array_unshift($parts,$type); } switch(strtolower($type)) { case "basic": if(count($params)===1) { $token = "Basic ".$params[0]; } if(count($params)==2) { $token = "Basic ".base64_encode(implode(":",$params)); } break; default: $token = implode(" ",$parts); break; } $this->header("Authorization",$token); } public function call() { if(is_null($this->headers)) { $this->headers = new Params("header"); } if(is_null($this->params)) { $this->params = new Params("form"); } $ch = curl_init(); $url = $this->url; curl_setopt($ch, CURLOPT_URL, $url); if($this->verbose === true) { curl_setopt($ch, CURLOPT_VERBOSE, $this->verbose); } curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers->getAll()); curl_setopt($ch, CURLOPT_HEADER,true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->sslVerify); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); switch(strtoupper($this->method)) { case 'GET': curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($this->method)); if(!empty($this->params)) { curl_setopt($ch, CURLOPT_POSTFIELDS, $this->params->getAll()); } break; case 'POST': curl_setopt($ch, CURLOPT_POST, true); if(!empty($this->params)) { curl_setopt($ch, CURLOPT_POSTFIELDS, $this->params->getAll()); } break; case 'DELETE': case 'PUT': case 'OPTIONS': default: curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($this->method)); if(!empty($this->params)) { curl_setopt($ch, CURLOPT_POSTFIELDS, $this->params->getAll()); } } dhGlobal::log("info","dhHttp request to ".$url." started"); $timingStart = microtime(true); $response = curl_exec($ch); $timingEnd = microtime(true); $timingExec = $timingEnd - $timingStart; if(curl_errno($ch)){ $this->setResponse([ "error"=>curl_errno($ch), "message"=>curl_error($ch), "code"=>-1, "headers"=>null, "body"=>null, "execTime"=>$timingExec ]); } else { $info = curl_getinfo($ch); curl_close($ch); $this->setResponse([ "error"=>false, "message"=>false, "code"=>$info["http_code"], "headers"=>trim(substr($response,0,$info['header_size'])), "body"=>substr($response,$info['header_size']), "execTime"=>$timingExec ]); } return $this->getResponse(); } /** * Get the value of response */ public function getReturnType() { return $this->returnType; } /** * Set the value of response * * @return self */ public function setReturnType($returnType) { $this->returnType = $returnType; return $this; } /** * Get the value of response */ public function getResponse($type=null) { if(is_null($this->response)) { return false; } if(is_null($type)) { $type = $this->returnType; } if($type == "object") { if($this->response["error"]!==false) { $resp = new Response($this->response["code"],null,null,$this->response["execTime"]); $resp->setErrorCode($this->response["error"]); $resp->setErrorMessage($this->response["message"]); } else { return new Response($this->response["code"],$this->response["headers"],$this->response["body"],$this->response["execTime"]); } } else { return $this->response; } } /** * Set the value of response * * @return self */ public function setResponse($response) { $this->response = $response; return $this; } /** * Get the value of headers */ public function getHeaders() { if(is_object($this->headers)) { return $this->headers->getAll(); } return $this->headers; } /** * Get the value of params */ public function getParams($json=false) { if(is_object($this->params)) { return $json ? json_encode($this->params->getAll()) : $this->params->getAll(); } return $json ? json_encode($this->params) : $this->params; } }src/httplite/client/Response.php000064400000012433144761607140012772 0ustar00setCode($code); $this->headers = new Params("array"); if(!is_null($headers)) { $this->setHeaders($headers); } if(!is_null($body)) { $this->setBody($body); } $extra = ""; if(!is_null($execTime)) { $this->setExecTime($execTime); $extra = "after ".round($execTime,3)."s "; } dhGlobal::log("info","dhHttp response created ".$extra."with status code ".$code); } public function get($json=false) { $o = $this->getInfo(true); if($json) { $o["json"] = $this->getJson(); } if(!$json || !isset($o["json"]) || is_null($o["json"])) { $o["body"] = $this->getBody(); } return $o; } public function getInfo($headers=false) { $o = [ "code"=>$this->getCode(), "codeMessage"=>$this->getCodeMessage(), "version"=>$this->getVersion(), "execTime"=>$this->getExecTime() ]; if($headers) { $o["headers"] = $this->getHeaders(); } return $o; } public function getVersion() { return !is_null($this->version) ? $this->version : false; } public function getCode() { return !is_null($this->code) ? $this->code : false; } public function getCodeMessage() { return !is_null($this->codeMessage) ? $this->codeMessage : false; } public function getExecTime() { return !is_null($this->execTime) ? $this->execTime : false; } public function getHeaders($header=null) { $array = $this->headers->get(); if(empty($header) || is_null($header)) { return $array; } return isset($array[$header]) ? $array[$header] : null; } public function getBody() { return $this->body; } public function getJson($item=null,$default=null) { if(is_null($this->jsonArray)) { $try = json_decode($this->body,true); if(is_array($try) || is_object($try)) { $this->jsonArray = $try; } } if(empty($item) || is_null($item)) { return $this->jsonArray; } if(strpos($item,".") !== false) { $check = dhGlobal::getDot($this->jsonArray,$item); if(!is_null($check)) { return $check; } } return isset($this->jsonArray[$item]) ? $this->jsonArray[$item] : $default; } public function getJsonObject() { if(is_null($this->jsonObject)) { $try = json_decode($this->body); if(is_object($try)) { $this->jsonObject = $try; } } return $this->jsonObject; } public function setHeaders($headers) { $harr = explode("\n",$headers); if(strpos($harr[0],":") === false && strpos($harr[0],"HTTP") !== false) { $t = explode(" ",$harr[0],3); $this->version = $t[0]; $this->codeMessage = $t[2]; $this->headers->set("@",$harr[0]); array_shift($harr); } foreach($harr as $header) { $temp = explode(": ",trim($header)); $v = isset($temp[1]) ? $temp[1] : ""; $this->headers->set($temp[0],$v); } } public function setBody($body) { $this->body = $body; } public function setExecTime($time) { $this->execTime = $time; } /** * Set the value of code * * @return self */ public function setCode($code) { $this->code = $code; return $this; } /** * Get the value of isError */ public function isError() { return $this->isError; } /** * Set the value of isError * * @return self */ public function setIsError($isError) { $this->isError = $isError; return $this; } /** * Get the value of errorCode */ public function getErrorCode() { return $this->errorCode; } /** * Set the value of errorCode * * @return self */ public function setErrorCode($errorCode) { $this->errorCode = $errorCode; return $this; } /** * Get the value of errorMessage */ public function getErrorMessage() { return $this->errorMessage; } /** * Set the value of errorMessage * * @return self */ public function setErrorMessage($errorMessage) { $this->errorMessage = $errorMessage; return $this; } }src/loader/PSR4.php000064400000003571144761607140010062 0ustar00getClassMap($className)) === false) { //Class is not within our defined map, move on to the next autoloader (if any) return; } $basePath = $map["path"]; $prefix = $map["prefix"]; // get the relative class name $relative_class = substr($className, strlen($prefix)); // replace the namespace prefix with the base directory, replace namespace // separators with directory separators in the relative class name, append // with .php $file = $basePath.str_replace('\\', '/', $relative_class); //dhGlobal::debug("Autoload attempt",$file); // if the file exists, require it if (file_exists($file.".".$this->extension)) { return dhLoader::includeOnce($file,$this->extension); } return; } public function add($prefix="some\\prefix\\",$path=".") { if(substr($path,strlen(DIRECTORY_SEPARATOR)) != DIRECTORY_SEPARATOR) { $path.=DIRECTORY_SEPARATOR; } $this->classMap[$prefix] = $path; } public function getClassMap($className) { foreach($this->classMap as $prefix => $path) { //dhGlobal::debug("checking",$prefix,$path); if (strncmp($prefix, $className, strlen($prefix)) === 0) { return ["prefix"=>$prefix,"path"=>$path]; } } return false; } }src/loader/TypeClass.php000064400000005165144761607140011242 0ustar00 types/Type.php * * Class_Type -> types/Class.php * * Subtype_Class_Type -> types/subtypes/Class.php * * Subtype_Subtype1_Class_Type -> types/subtypes/subtype1s/Class.php * * Subtype_Subtype1_Subtype2_Class_Type -> types/subtypes/subtype1s/subtype2s/Class.php */ class TypeClass { /** * Only attempts to autoLoad if the className begins with this prefix. Default is blank (all classes) * * Useful if adding this loader on top of other loaders that you don't want to interfere with. */ protected $classPrefix = ""; public $debug = false; public function init() { spl_autoload_register([$this,"autoload"]); } /** * Directories are all lowercase, Classe * * Type -> types/Type.php * * Class_Type -> types/Class.php * * Subtype_Class_Type -> types/subtypes/Class.php * * Subtype_Subtype1_Class_Type -> types/subtypes/subtype1s/Class.php * * Subtype_Subtype1_Subtype2_Class_Type -> types/subtypes/subtype1s/subtype2s/Class.php */ public function autoload($className) { //Ipad_Index_View //Ipad_Users_Login_Action $parts = explode('_', $className); $prefix = $this->classPrefix(); if(!empty($prefix)) { $first = array_shift($parts); if($first !== $prefix || empty($parts)) { return false; } } $classParts = []; $type = array_pop($parts); if(empty($parts)) { //Type -> types/Type.php $classParts = [strtolower($type)."s",$type]; } else { $class = array_pop($parts); if(empty($parts)) { //Class_Type -> types/Class.php $classParts = [strtolower($type)."s",$class]; } else { $classParts = [$class]; while(!empty($parts)) { array_unshift($classParts,strtolower(array_pop($parts))."s"); } array_unshift($classParts,strtolower($type)."s"); } } if($this->debug) { dhGlobal::debug("Autoload attempt",$classParts); } return dhLoader::includeOnce(implode(".",$classParts)); } public function classPrefix(string $prefix=null) { if(is_null($prefix)) { return $this->classPrefix; } else { $this->classPrefix = $prefix; } } }src/logger/Handler.php000064400000024410144761607140010713 0ustar00 dhGlobal::LOG_TRACE, "debug" => dhGlobal::LOG_DEBUG, "info" => dhGlobal::LOG_INFO, "warn" => dhGlobal::LOG_WARN, "error" => dhGlobal::LOG_ERROR, ]; protected $logLevelRanges = [ "trace" => [401,500], "debug" => [301,400], "info" => [201,300], "warn" => [101,200], "error" => [1 ,100], "off" => [0,0] ]; protected $logLevels = [ "trace" =>500, "debug" =>400, "info" =>300, "warn" =>200, "error" =>100, "off" =>0, ]; protected $prefixLength = 8; protected $prefixWrapper = ["[","] "]; protected $logPrefix = [ "trace" => "TRACE", "debug" => "DEBUG", "info" => "INFO", "warn" => "WARN", "error" => "ERROR", "off" => "", ]; /** * * @var dhOut[] */ protected $loggers = []; protected $levelLoggers = [ "trace"=>[], "debug"=>[], "info"=>[], "warn"=>[], "error"=>[] ]; /** * Creates a new logger and sets it to the appropriate level * @param mixed $name -- name to identify this logger with * @param array $levels -- bitmask from dhGlobal::LOG_* constants * @param bool $stdOut -- obvious? * @param bool $file -- filename to enable output file logging, false to disabke * @param string $lineSeparator * @return void * @throws Exception */ public function logger($name,$levels=[],$stdOut=true,$file=false,$lineSeparator=PHP_EOL) { if(empty($levels) || (!is_array($levels) && !is_int($levels))) { throw new \Exception("Logger levels must be defined and must be either an array of levels -- eg ['debug'] or ['error','warn'], OR use the dhGlobal::LOG_* constants as a bit mask -- eg LOG_ALL & ~LOG_TRACE"); } $this->loggers[$name] = new dhOut($stdOut,$file,true,"date:Y-m-d H:i:s","\t",$lineSeparator); if(!is_array($levels) && is_int($levels)) { foreach($this->logLevelsToBitMask as $level=>$mask) { if($levels & $mask) { $this->levelLoggers[$level][$name] = &$this->loggers[$name]; } } } if(is_array($levels)) { foreach($levels as $level) { if(isset($this->logLevels[$level])) { $this->levelLoggers[$level][$name] = &$this->loggers[$name]; } } } } public function log($level, ...$params) { $label = $this->getLevelLabel($level); $parent = $this->getParentLabel($level); $haveLoggers = false; if(isset($this->levelLoggers[$label]) && !empty($this->levelLoggers[$label])) { $haveLoggers = true; } if($parent != $label) { if(isset($this->levelLoggers[$parent]) && !empty($this->levelLoggers[$parent])) { $haveLoggers = true; } } if(!$haveLoggers) { return false; } $prefix = $this->getLevelPrefix($label); if(isset($this->levelLoggers[$label]) && !empty($this->levelLoggers[$label])) { foreach($this->levelLoggers[$label] as $logger) { if(!empty($params)) { $logParams = $params; array_unshift($logParams,$this->logPrefix($prefix)); call_user_func_array([$logger,"line"],$logParams); /*$logger->add($this->logPrefix($prefix),true); foreach($params as $param) { $logger->append(" "); $logger->append($param); }*/ unset($logParams); } else { $logger->add(""); } $logger->end(); } } if($parent != $label && isset($this->levelLoggers[$parent]) && !empty($this->levelLoggers[$parent])) { foreach($this->levelLoggers[$parent] as $logger) { if(!empty($params)) { $logger->add($this->logPrefix($prefix),true); foreach($params as $param) { $logger->append(" "); $logger->append($param); } } else { $logger->add(""); } $logger->end(); } } } /** * define a custom log level. * * Example: * * $logger->defineLogLevel("query","debug","QRY1") -- adds a 'query' level to the debug log display * * @param string $name the name of the level used for logging (eg: $logger->log($name,stuff,to,print)) * @param string $level optional level to add the new level to, ['trace','debug','info','warn','error'] * @param string $prefix optional prefix used if different from the name. 5 characters * @return boolean true if successful, false if failed */ public function defineLogLevel($name,$level,$prefix=null) { if(is_null($prefix)) { $prefix = $name; } if(!is_numeric($level)) { $level = isset($this->logLevels[$level]) ? $level : "debug"; list($start,$end) = $this->logLevelRanges[$level]; $number = false; $levels = array_flip($this->logLevels); for($i=$start;$i<$end;$i++) { if(!isset($levels[$i])) { $number = $i; break; } } if($number === false) { return false; } } else { $number = $level; } $levels = $this->logLevels; $levels[$name] = $number; $temp = array_flip($levels); krsort($temp); $this->logLevels = array_flip($temp); $this->logPrefix[$name] = $prefix; return true; } public function logPrefix($prefix) { if(strlen($prefix)>$this->prefixLength) { $prefix = substr($prefix,0,$this->prefixLength); } elseif(strlen($prefix)<$this->prefixLength) { $prefix = str_pad($prefix,$this->prefixLength," ",STR_PAD_BOTH); } list($left,$right) = $this->prefixWrapper; return $left.strtoupper($prefix).$right; } public function getLogLevels() { return $this->logLevels; } public function getLogPrefixes() { return $this->logPrefix; } public function getLabelLevel($label) { return isset($this->logLevels[$label]) ? $this->logLevels[$label] : false; } public function getLevelPrefix($level) { $label = $this->getLevelLabel($level); if($label === false) { return false; } if(isset($this->logPrefix[$level])) { return $this->logPrefix[$level]; } return false; } public function getLevelLabel($level) { if(!is_numeric($level) && isset($this->logLevels[$level])) { return $level; } if(is_numeric($level)) { $tflip = array_flip($this->logLevels); if(isset($tflip[$level])) { return $tflip[$level]; } } return $this->getParentLabel($level); } public function getParentLabel($level) { if(!is_numeric($level) && isset($this->logLevels[$level])) { $level = $this->logLevels[$level]; } if(is_numeric($level)) { foreach($this->logLevelRanges as $name=>$range) { if($level >= $range[0] && $level <= $range[1]) { return $name; } } } return false; } public function trace(...$data) { array_unshift($data,"trace"); call_user_func_array( [$this,"log"], $data); } public function debug(...$data) { array_unshift($data,"debug"); call_user_func_array( [$this,"log"], $data); } public function info(...$data) { array_unshift($data,"info"); call_user_func_array( [$this,"log"], $data); } public function warn(...$data) { array_unshift($data,"warn"); call_user_func_array( [$this,"log"], $data); } public function error(...$data) { array_unshift($data,"error"); call_user_func_array( [$this,"log"], $data); } protected static $instance; /** * Used to init the singleton with specific settings * @return dhlogger singlton */ public static function init($level=null,$file=null,$dhOut=null) { if(self::$instance !== null) { self::instance()->end(); } self::$instance = new self($level,$file,$dhOut); return self::$instance; } /** * Used to get the singleton isntance, or init with default settings; * @return dhlogger singlton */ public static function instance() { if(self::$instance === null) { self::$instance = self::init(); } return self::$instance; } /** * Get the value of prefixLength */ public function getPrefixLength() { return $this->prefixLength; } /** * Set the value of prefixLength * * @return self */ public function setPrefixLength($prefixLength) { $this->prefixLength = $prefixLength; return $this; } /** * Get the value of prefixWrapper */ public function getPrefixWrapper() { return $this->prefixWrapper; } /** * Set the value of prefixWrapper * * @return self */ public function setPrefixWrapper($prefixWrapper) { $this->prefixWrapper = $prefixWrapper; return $this; } }src/logger/Logger.php000064400000020253144761607140010556 0ustar00500, "debug" =>400, "info" =>300, "warn" =>200, "error" =>100, "off" =>0, ]; protected $logPrefix = [ "trace" => "[TRACE]", "debug" => "[DEBUG]", "info" => "[ INFO]", "warn" => "[ WARN]", "error" => "[ERROR]", "off" => "", ]; protected $logLevel = 0; public function __construct($level=null,$file=null,$dhOut=null) { if(!is_null($dhOut)) { $this->client = $dhOut; } else { $this->client = new dhOut(); } if(!is_null($level)) { $this->setLogLevel($level); } if(!is_null($file)) { $this->setFile($file); } } public function trace(...$data) { array_unshift($data,"trace"); call_user_func_array( [$this,"log"], $data); } public function debug(...$data) { array_unshift($data,"debug"); call_user_func_array( [$this,"log"], $data); } public function info(...$data) { array_unshift($data,"info"); call_user_func_array( [$this,"log"], $data); } public function warn(...$data) { array_unshift($data,"warn"); call_user_func_array( [$this,"log"], $data); } public function error(...$data) { array_unshift($data,"error"); call_user_func_array( [$this,"log"], $data); } public function log($level, ...$params) { if(is_numeric($level)) { $ln = false; $temp = $this->logLevels; $tlevels = array_flip($temp); ksort($tlevels); foreach($tlevels as $lvl=>$nm) { if($lvl>=$level && $ln === false) { $ln = $nm; } } if($ln !== false) { $prefix = $this->logPrefix[$ln]; } else { $this->makeLogLevelPrefix($level); } } elseif(!is_numeric($level) && isset($this->logLevels[$level])) { $prefix = $this->logPrefix[$level]; $level = $this->logLevels[$level]; } else { $level = $this->logLevel; $prefix = $this->makeLogLevelPrefix($level); } if($this->logLevel>0 && $level<=$this->logLevel) { if(empty($params)) { $this->client->add(""); } else { $this->client->add($prefix." "); foreach($params as $param) { $this->client->append(" "); $this->client->append($param); } } $this->client->end(); } } public function setFile($file) { $this->file = $file; $this->client->setFileName($file); } public function setLogLevel($level) { if($level === false) { $this->logLevel = 0; } if(is_numeric($level)) { $this->logLevel = $level; } elseif(isset($this->logLevels[strtolower($level)])) { $this->logLevel = $this->logLevels[strtolower($level)]; } } public function level($level) { return $this->setLogLevel($level); } public function logLevel($level=null) { if(is_null($level)) { return $this->logLevel; } return $this->setLogLevel($level); } public function setLevel($level) { return $this->setLogLevel($level); } public function getMaxLevelForName($name) { $temp = $this->logLevels; $tlevels = array_flip($temp); ksort($tlevels); $max =0; $found = false; $level = $this->logLevels[$name]; foreach($tlevels as $lvl=>$nm) { if($found) { $max = $lvl-1; break; } else { if($nm == $name) { $found = true; } } } if($max>0) { return $max; } { return 9999; } } /** * Add a level to the logger. * * Example: * * $logger->addLogLevel("query","QUERY","debug") -- adds a 'query' level to the debug log display * * @param string $name the name of the level used for logging (eg: $logger->log($name,stuff,to,print)) * @param string $level optional level to add the new level to, ['trace','debug','info','warn','error'] * @param string $prefix optional prefix used if different from the name. 5 characters * @return boolean true if successful, false if failed */ public function addLogLevel($name,$level=null,$prefix=null) { if(is_null($prefix)) { $prefix = $name; } $prefix = $this->makeLogLevelPrefix($prefix); if(!is_numeric($level)) { $start = 999; $end = 0; if(!is_null($level)) { if(isset($this->logLevels[$level])) { $start = $this->logLevels[$level]; $nextLevel = $this->getHigherLogLevel($level); $end = $this->logLevels[$nextLevel]; } } $number = false; $levels = array_flip($this->logLevels); for($i=$end+1;$i<$start;$i++) { if(!isset($levels[$i])) { $number = $i; break; } } if($number === false) { return false; } } else { $number = $level; } $levels = $this->logLevels; $levels[$name] = $number; $temp = array_flip($levels); krsort($temp); $this->logLevels = array_flip($temp); $this->logPrefix[$name] = $prefix; return true; } public function makeLogLevelPrefix($prefix) { if(strlen($prefix)>5) { $prefix = substr($prefix,0,5); } elseif(strlen($prefix)<5) { $prefix = str_pad($prefix,5," ",STR_PAD_BOTH); } return "[".strtoupper($prefix)."]"; } public function getLogLevels() { return $this->logLevels; } public function getLogPrefixes() { return $this->logPrefix; } /** * Standard method wrapper */ public function __call($method,$args) { return call_user_func_array( [$this->client,$method], $args); } protected static $instance; /** * Used to init the singleton with specific settings * @return dhlogger singlton */ public static function init($level=null,$file=null,$dhOut=null) { if(self::$instance !== null) { self::instance()->end(); } self::$instance = new self($level,$file,$dhOut); return self::$instance; } /** * Used to get the singleton isntance, or init with default settings; * @return dhlogger singlton */ public static function instance() { if(self::$instance === null) { self::$instance = self::init(); } return self::$instance; } public function getLabelForLevel($level=100) { $name = false; $temp = $this->logLevels; $tlevels = array_flip($temp); ksort($tlevels); foreach($tlevels as $lvl=>$lvlName) { if($lvl>=$level && $name === false) { $name = $lvlName; return $name; } } } public function getHigherLogLevel($level) { if(is_numeric($level)) { $level = $this->getLabelForLevel($level); } $keys = array_keys($this->logLevels); $current = array_search($level, $keys); $nextKey = $keys[($current===false ? -1 : $current)+1] ?: $keys[0]; return $nextKey; } }src/mail/Imap.php000064400000004444144761607140007674 0ustar00false,"valid"=>[],"invalid"=>[]]; protected $mailConfig = [ "host"=>"", "port"=>0, "user"=>"", "pass"=>"", "options"=>["imap","ssl"], "mailbox"=>"INBOX", "attachmentsDir"=>null, "extra"=>[ "doCount"=>false ] ]; protected $mailbox; public function __construct($mailConfig=[]) { if(!empty($mailConfig)) { $this->config($mailConfig); } } public function setConfig($item,$value) { if(isset($this->mailConfig[$item])) { $this->mailConfig[$item] = $value; } else { $this->mailConfig["extra"][$item] = $value; } } public function getConfig($item,$default=null) { } public function config($mailConfig) { foreach($this->mailConfig as $cfg=>$v) { if(isset($mailConfig[$cfg])) { $this->mailConfig[$cfg] = $mailConfig[$cfg]; unset($mailConfig[$cfg]); } } if(!empty($mailConfig)) { $this->mailConfig["extra"] = $mailConfig; } $v = $this->validateConfig(); } public function getMailbox($connString,$user,$pass,$attachmentsDir=null,$encoding="UTF-8") { return new \PhpImap\Mailbox($connString, $user, $pass, $attachmentsDir,$encoding); } protected function validateConfig($cfg = []) { if(empty($cfg)) { $cfg = $this->mailConfig; } $valid = [ "host"=>false, "port"=>false, "user"=>false, "pass"=>false, "mailbox"=>false ]; foreach($valid as $name=>$false) { if(!empty($this->mailConfig[$name])) { $valid[$name] = true; } } $invalid = []; $overall = true; foreach($valid as $k=>$v) { if(!$v) { $overall=false; $invalid[$k]=true; unset($valid[$k]); } } $this->validateConfig = ["overall"=>$overall,"valid"=>$valid,"invalid"=>$invalid]; return $overall; } }src/mail/SMTP.php000064400000004325144761607140007567 0ustar00"", "port"=>0, "user"=>"", "pass"=>"", "auth"=>true, "secure"=>false, "extra"=>[] ]; protected PHPMailer $client; protected $isConfiged = false; public function __construct($mailConfig=[]) { if(!empty($mailConfig)) { $this->config($mailConfig); } $this->client = new PHPMailer(true); } public function config($mailConfig) { foreach($this->mailConfig as $cfg=>$v) { if(isset($mailConfig[$cfg])) { $this->mailConfig[$cfg] = $mailConfig[$cfg]; unset($mailConfig[$cfg]); } } if(!empty($mailConfig)) { $this->mailConfig["extra"] = $mailConfig; } $this->client->Host = $this->mailConfig["host"]; $this->client->Port = $this->mailConfig["port"]; $this->client->SMTPAuth = $this->mailConfig["auth"]; $this->client->Username = $this->mailConfig["user"]; $this->client->SMTPSecure = $this->mailConfig["secure"]; $this->isConfiged = true; } public function output($success=true,$code=0,$message=null) { return ["success"=>$success,"code"=>$code,"message"=>$message]; } public function send() { if(!$this->isConfiged) { return $this->output(false,-100,"Must configure before sending"); } $success=false; $code=-1; $message=null; try { $this->client->send(); $success=true; $code=0; } catch (\Exception $e) { $message = $e->getMessage(); $code = $e->getCode(); } return $this->output($success,$code,$message); } public function __call($method, $args) { if(!method_Exists($this->client, $method)) { throw new \Exception("Method $method does not exist on PHPMailer object",-1); } call_user_func_array(array($this->client, $method), $args); } }src/misc/PSR4Bootstrap.php000064400000003633144761607140011444 0ustar00threadStartCallback)) { $cb = $this->threadStartCallback; $cb($thread); } } /** * @param \boru\dhutils\dhThreads\multithread\Thread $thread * @return void */ public function threadFinished($thread) { if(is_callable($this->threadStartCallback)) { $cb = $this->threadStartCallback; $cb($thread); } } /** * @param \boru\dhutils\dhThreads $pool * @return void */ public function loop($pool) { $this->lastLoopTime = $this->loopTime; $this->loopTime = microtime(true); if(is_callable($this->loopCallback)) { $cb = $this->loopCallback; $cb($pool); } } /** * @param mixed $data * @return void */ public function collect($data) { if(is_callable($this->collectCallback)) { $cb = $this->collectCallback; $cb($data); } } /** * Get the value of threadStartCallback * * @return callable|null */ public function getThreadStartCallback() { return $this->threadStartCallback; } /** * Set the value of threadStartCallback * * @param callable $threadStartCallback * @return self */ public function setThreadStartCallback(callable $threadStartCallback) { $this->threadStartCallback = $threadStartCallback; return $this; } /** * Get the value of threadFinishedCallback * * @return callable */ public function getThreadFinishedCallback() { return $this->threadFinishedCallback; } /** * Set the value of threadFinishedCallback * * @param callable $threadFinishedCallback * @return self */ public function setThreadFinishedCallback(callable $threadFinishedCallback) { $this->threadFinishedCallback = $threadFinishedCallback; return $this; } /** * Get the value of throttleWaitCallback * * @return callable|null */ public function getThrottleWaitCallback() { return $this->loopCallback; } /** * Set the value of throttleWaitCallback * * @param callable $throttleWaitCallback * @return self */ public function setThrottleWaitCallback(callable $throttleWaitCallback) { $this->loopCallback = $throttleWaitCallback; return $this; } /** * Get the value of throttleWaitCallback * * @return callable|null */ public function getCollectCallback() { return $this->collectCallback; } /** * Set the value of throttleWaitCallback * * @param callable $throttleWaitCallback * @return self */ public function setCollectCallback(callable $collectCallback) { $this->collectCallback = $collectCallback; return $this; } /** * Get the value of loopCallback * * @return callable|null */ public function getLoopCallback() { return $this->loopCallback; } /** * Set the value of loopCallback * * @param callable $collectCallback * @return self */ public function setLoopCallback(callable $loopCallback) { $this->loopCallback = $loopCallback; return $this; } /** * Returns the microtime float difference between the last loop and this loop * @return float */ public function timeSinceLastLoop() { return $this->loopTime - $this->lastLoopTime; } }src/multithread/CallbackInterface.php000064400000004040144761607140013713 0ustar00id = dhGlobal::getVal($data,"id",false); $this->command = dhGlobal::getVal($data,"command",false); $this->return = dhGlobal::getVal($data,"return",false); $this->channelType = dhGlobal::getVal($data,"channelType",dhThreads::CHANNEL_NONE); $this->bootstrap = dhGlobal::getVal($data,"bootstrap",false); if($this->bootstrap !== false && file_exists($this->bootstrap)) { include $this->bootstrap; } dhThreads::sendChannel($this->id,$this->channelType,$this->run()); } public function run() { ob_start(); passthru($this->command); $data = ob_get_contents(); ob_end_clean(); return $data; } }src/multithread/Thread.php000064400000014041144761607140011607 0ustar00wraper = $wrapper; } $this->json = dhGlobal::getVal($options,"json",false); $this->jsonObject = dhGlobal::getVal($options,"jsonObject",false); $this->channelType = dhGlobal::getVal($options,"channelType",dhThreads::CHANNEL_MEMCACHED); $this->id = dhGlobal::getVal($meta,"id",uniqid()); $this->complete = false; $this->command = $command; $this->started = new \DateTime(); $this->meta = $meta; $this->runnerId = uniqid("dhmt",true); $this->setupCallbacks($options); $this->execute(); } public function __destruct() { $this->stop(); } protected function execute() { $packet = $this->makePacket(); $runCMD = "php -f ".$this->wrapper." ". dhThreads::pack($packet); $this->pid = exec($runCMD.' > /dev/null 2>&1 & echo $!'); dhGlobal::trace("[MT-T] ".$runCMD); } protected function makePacket() { $packet = [ "id"=>$this->runnerId, "command"=>$this->command, "return"=>true, "channelType"=>$this->channelType ]; if($this->bootstrap !== false) { $packet["bootstrap"] = $this->bootstrap; } return $packet; } protected function setupCallbacks($options=[]) { $this->bootstrap = false; if(($bootstrapFile = dhGlobal::getVal($options,"bootstrap",false)) !== false) { if(file_exists($bootstrapFile)) { $this->bootstrap = $bootstrapFile; } } //default 'thread finished' callback that does not use a visualizer to process. $this->callback = dhGlobal::getVal($options,"callback",null); } /** * Terminates the thread */ public function stop() { if(!$this->finished() && !$this->stopped) { $this->stopped = true; posix_kill($this->pid, 9); if($this->finished()) { dhGlobal::trace("[MT-T] ".$this->pid()." Stopped by request."); } else { dhGlobal::trace("[MT-T] ".$this->pid()." Recieved stop request.. kill signal sent"); } } } public function collect() { $data = dhThreads::readChannel($this->runnerId,$this->channelType); if($data !== false) { if($this->json) { return json_decode($data,!$this->jsonObject); } return $data; } return false; } /** * Returns true if the thread has completed, false if running */ public function finished() { if($this->complete) { return true; } if(!is_null($this->pid)) { if(!posix_getpgid($this->pid)) { $this->complete = true; $this->output = $this->collect(); if(is_callable($this->callback)) { $cb = $this->callback; $cb($this); } return true; } } $now = time(); if($this->timeout>0 && $this->started->format("U")+$this->timeout > $now) { $this->stop(); return true; } $this->complete = false; return false; } /** * Returns true if the thread has completed, false if running */ public function complete() { return $this->finished(); } /** * Returns true if the thread has completed, false if running */ public function isDone() { return $this->finished(); } /** * Returns true if the thread has completed, false if running */ public function done() { return $this->finished(); } /** * Terminates the thread */ public function kill() { $this->stop(); } /** * Get the value of pid * * @return mixed */ public function pid() { return is_numeric($this->pid) ? $this->pid : false; } /** * Get the value of command * * @return mixed */ public function command() { return $this->command; } /** * Get the value of started * * @return mixed */ public function started() { return $this->started; } /** * Get the value of meta * * @return mixed */ public function meta() { return $this->meta; } /** * Get the value of output * * @return mixed */ public function output() { return $this->output; } /** * Get the value of runnerId * * @return mixed */ public function id() { return $this->id; } /** * Get the value of runnerId * * @return mixed */ public function runnerId() { return $this->runnerId; } public function get() { return [ "pid"=>$this->pid(), "complete"=>$this->complete(), "command"=>$this->command(), "started"=>$this->started(), "meta"=>$this->meta(), ]; } public function jsonSerialize($array=null) { if(is_null($array)) { $array = $this->get(); } return $array; } public function __toString() { return json_encode($this); } }src/multithread/visualizer/BlankVisualizer.php000064400000000372144761607140015704 0ustar00total = !is_null($totalWorkload) ? $totalWorkload : $threads; $this->done = 0; for($i=0;$i<$threads;$i++) { $this->threadStatus[$i] = " "; } if(!is_null($statsCallback) && is_callable($statsCallback)) { $this->statsCallback = $statsCallback; } } /** * @param \boru\dhutils\dhThreads\multithread\Thread $thread * @return void */ public function threadStart($thread) { if(is_null($this->startTime)) { $this->startTime = microtime(true); } parent::threadStart($thread); $this->started++; $this->threadMap[$thread->runnerId()] = $this->nextIndex(); $this->threadStatus[$this->threadMap[$thread->runnerId()]] = '.'; if($this->started>$this->total) { $this->total = $this->started; } } /** * @param \boru\dhutils\dhThreads\multithread\Thread $thread * @return void */ public function threadFinished($thread) { parent::threadFinished($thread); $this->done++; $this->threadStatus[$this->threadMap[$thread->runnerId()]] = 'x'; unset($this->threadMap[$thread->runnerId()]); $this->display(); } /** * @param \boru\dhutils\dhThreads $pool * @return void */ public function loop($pool) { parent::loop($pool); $this->display(); } /** * @param mixed $data * @return void */ public function collect($data) { parent::collect($data); if(is_callable($this->statsCallback)) { $cb = $this->statsCallback; $this->collectStats = $cb($data,$this); } } public function display() { if(!$this->canDisplay()) { return; } $extraStats=""; if(!empty($this->collectStats)) { $arr = []; foreach($this->collectStats as $k=>$v) { $arr[] = "$k: $v"; } $extraStats = implode(", ",$arr); } $this->lastDisplayTime = microtime(true); dhGlobal::outLine(implode(" ",$this->threadStatus)." ".$this->formatPercent(),$this->formatRuntime(),$extraStats); } protected function formatPercent() { $percent = (float) $this->done / (float) $this->total; $percent *= 100; $percent = "%".dhGlobal::pad(sprintf("%01.2f",$percent),6," ",STR_PAD_LEFT); return dhGlobal::pad($percent,12," ",STR_PAD_LEFT); } protected function formatRuntime() { $runTime = $this->runTime(); if($runTime<=60) { $str = sprintf("%01.2f",$runTime)."s"; } else { $runTime = round($runTime); $dtF = new \DateTime('@0'); $dtT = new \DateTime("@$runTime"); $str = dhGlobal::dateIntervalToElapsed($dtF->diff($dtT),true,false); } return "runTime: ".dhGlobal::pad($str,6," ",STR_PAD_LEFT); } protected function canDisplay() { if(microtime(true) - $this->lastDisplayTime >= $this->getDisplayLoopTime()) { return true; } return false; } /** * time elapsed since threads started * @return float */ protected function runTime() { return !is_null($this->startTime) ? microtime(true) - $this->startTime : 0; } protected function nextIndex() { foreach($this->threadStatus as $i=>$s) { if($s == ' ') { return $i; } } foreach($this->threadStatus as $i=>$s) { if($s == 'x') { return $i; } } } /** * Get time in seconds between display prints * * @return float */ public function getDisplayLoopTime() { return $this->displayLoopTime; } /** * Set time in seconds between display prints * * @param float $displayLoopTime Time in seconds between display prints * @return self */ public function setDisplayLoopTime(float $displayLoopTime) { $this->displayLoopTime = $displayLoopTime; return $this; } }src/scripts/thread.php000064400000001157144761607140011020 0ustar00commandResult = $result; $cmdName = $result["commandName"]; if(method_exists($this,"cmd_".$cmdName)) { $cmd = "cmd_".$cmdName; $this->$cmd($result); return true; } elseif(method_exists($this,"cmd_default")) { $cmd = "cmd_default"; $this->$cmd($result); return true; } return false; } public function getCommandOption($dotKey,$default=false) { return dhGlobal::getVal($this->commandResult["options"],$dotKey,$default); } }src/traits/GetOption.php000064400000001120144761607140011266 0ustar00setGetSetSeparator($separator); if(is_array($arr) && !empty($arr)) { foreach($arr as $k=>$v) { $this->set($k,$v); } } } public function set($key,$val="",$append=false) { $arr = $this->GetSetMainArray; $this->setArray($this->$arr,$key,$val,$append); return $this; } public function get($key=null,$default=null) { $arr = $this->GetSetMainArray; return $this->getArray($this->$arr,$key,$default); } public function exists($key=null) { $arr = $this->GetSetMainArray; return $this->existsArray($this->$arr,$key); } public function remove($key) { $arr = $this->GetSetMainArray; unset($this->$arr[$key]); return $this; } public function setArray(&$array,$key,$val="",$append=false) { if(strpos($key,$this->GetSetSeparator) !== false) { if($append) { $check = dhGlobal::getDot($array,$key,$this->GetSetSeparator); if(!is_null($check)) { if(is_array($check)) { $check[] = $val; $val = $check; } else { $narr = []; $narr[] = $check; $narr[] = $val; $val = $narr; } } } dhGlobal::dotAssign($array,$key,$val); } else { if(isset($array[$key]) && $append) { if(is_array($array[$key])) { $array[$key][] = $val; } else { $temp = $array[$key]; $array[$key] = []; $array[$key][] = $temp; $array[$key][] = $val; } } else { $array[$key] = $val; } } return $this; } public function getArray($array,$key=null,$default=null,$exists=false) { if(is_null($key)) { if($exists) { return !empty($array) ? true : false; } else { return !empty($array) ? $array : $default; } } if(strpos($key,$this->GetSetSeparator) !== false) { $uniqueid = uniqid("getArray",true); if(($check = dhGlobal::getDot($array,$key,$uniqueid,$this->GetSetSeparator)) !== $uniqueid) { return $exists ? true : $check; }; } if($exists) { return isset($array[$key]); } else { return isset($array[$key]) ? $array[$key] : $default; } } public function existsArray($array,$key) { return $this->getArray($array,$key,null,true); } /** * Get the value of GetSetSeparator */ public function getGetSetSeparator() { return $this->GetSetSeparator; } /** * Set the value of GetSetSeparator * * @return self */ public function setGetSetSeparator($GetSetSeparator) { $this->GetSetSeparator = $GetSetSeparator; return $this; } /** * Get the value of GetSetMainArray */ public function getGetSetMainArray() { return $this->GetSetMainArray; } /** * Set the value of GetSetMainArray * * @return self */ public function setGetSetMainArray($GetSetMainArray) { $this->GetSetMainArray = $GetSetMainArray; return $this; } }src/traits/GlobalDotParse.php000064400000007444144761607140012237 0ustar00['subkey'=>'value']],'key.subkey') -- returns 'value' * * @param array $arr the array to get the element from * @param string $dotString the key to find * @param mixed $default a default value if key isn't found * @return mixed the value if found, $defualt if not */ public static function getDot($arr=[],$dotString,$default=null,$separator=".") { $pieces = explode($separator,$dotString); $pointer = $arr; for($i=0;$idefaults * @param string $keySeparator (default='.') string to split for 'dot search' * @param boolean $single (default=false) if true, returns the first matching value in order of $keyDefault key definitions * @return mixed if $single==false array of values for each of the keyDefault pairs. Otherwise the first matching value */ public static function getMultiVal(array $arr,array $keyValueArray,$single=false,$keySeparator=".") { $values = []; foreach($keyValueArray as $keyString=>$default) { $value = static::getVal($arr,$keyString,$default,$keySeparator); if($single && $value!==$default) { return $value; } $values[] = $value; } return $values; } public static function parseDots(&$array,$separator='.') { foreach($array as $k=>$v) { if(is_array($v)) { $array[$k] = static::parseDots($v,$separator); } if(strpos($k,$separator) !== false) { static::dotAssign($array,$k,$v,$separator); unset($array[$k]); } } } /** * Explodes dot notation and assigns a value based on the key * * Example: * * $arr = ['key'=>['subkey'=>'value']]; * * dhGlobal::dotAssign($arr,'key.subkey2','value2) * * //['key'=>['subkey'=>'value','subkey2'=>'value2']] * * @param array $arr the array to get the element from * @param string $path the dotNotated key * @param mixed $value the value to assign * @param string $separator defaults to '.' * @return void */ public static function dotAssign(&$arr, $path, $value=null, $separator='.') { $keys = explode($separator, $path); foreach ($keys as $key) { $arr = &$arr[$key]; } $arr = $value; } public static function dotDelete(&$arr, $path, $separator='.') { $keys = explode($separator, $path); $end = array_pop($keys); foreach ($keys as $key) { $arr = &$arr[$key]; } unset($arr[$end]); } }src/traits/GlobalFilesys.php000064400000007036144761607140012131 0ustar00$pathString]); } /** * Checkes to see if the provided Path exists as a Directory. * Returns a \boru\dhutils\filesys\Directory object if is a directory and exists, otherwise false * * Note, will return false if the path is a File or Symlink. */ public static function dirIfExists($pathString) { if(!file_exists($pathString) || !is_dir($pathString)) { return false; } return new \boru\dhutils\filesys\Directory(["path"=>$pathString]); } public static function getFileHashAndSize($data, $offset = 0, $partSize = null) { if (!$partSize) { if (is_resource($data)) { // We need to calculate the file's hash incrementally from the stream. $context = hash_init('sha1'); hash_update_stream($context, $data); $hash = hash_final($context); // Similarly, we have to use fstat to get the size of the stream. $size = fstat($data)['size']; // Rewind the stream before passing it to the HTTP client. rewind($data); } else { // We've been given a simple string body, it's super simple to calculate the hash and size. $hash = sha1($data); $size = mb_strlen($data, '8bit'); } } else { $dataPart = static::getPartOfFile($data, $offset, $partSize); $hash = sha1($dataPart); $size = mb_strlen($dataPart, '8bit'); } return array("hash"=>$hash, "size"=>$size); } /** * Return selected part of file * * @param $data * @param int $offset * @param int $partSize * @return bool|string */ public static function getPartOfFile($data, int $offset, int $partSize) { // Get size and hash of one data chunk if (is_resource($data)) { // Get data chunk fseek($data, $offset); $dataPart = fread($data, $partSize); // Rewind the stream before passing it to the HTTP client. rewind($data); } else { $dataPart = substr($data, $offset, $partSize); } return $dataPart; } /** * Return a santized relative path * * Used to make sure the path is within the defined root. * * @param string $path The path to test * @param string $root default=current directory * @param boolean $relative return relative path to $path if true, otherwise full path * @return mixed sanitized path if within root, false if not */ public static function sanitizePath($path,$root=null,$relative=true) { $bp = new \boru\dhutils\filesys\BasePath($path); if(is_null($root)) { $root = "."; } $rpath = $bp->relative($root); if($rpath === false) { return false; } return $relative ? $rpath : $bp->fullPath(); } }src/traits/GlobalLogHandler.php000064400000004743144761607140012534 0ustar00log(...$args); } public static function trace(...$args) { return static::logHandler()->trace(...$args); } public static function debug(...$args) { return static::logHandler()->debug(...$args); } public static function info(...$args) { return static::logHandler()->info(...$args); } public static function warn(...$args) { return static::logHandler()->warn(...$args); } public static function error(...$args) { return static::logHandler()->error(...$args); } public static function logger($name,$levels=dhGlobal::LOG_ERROR,$stdOut=true,$file=false,$lineSeperator=PHP_EOL) { return static::logHandler()->logger($name,$levels,$stdOut,$file,$lineSeperator); } /** * Add a level to the logger. * * Example: * * dhGlobal::addLogLevel("query","QUERY","debug") -- adds a 'query' level to the debug log display * * @param string $name the name of the level used for logging (eg: $logger->log($name,stuff,to,print)) * @param string $level level to add the new level to, ['trace','debug','info','warn','error'] * @param string $prefix optional prefix used if different from the name. 5 characters * @return boolean true if successful, false if failed */ public static function addLogLevel($name,$level,$prefix=null) { return static::logHandler()->defineLogLevel($name,$level,$prefix); } public static function defineLogLevel($name,$level,$prefix=null) { return static::logHandler()->defineLogLevel($name,$level,$prefix); } }src/traits/GlobalOut.php000064400000000777144761607140011267 0ustar00start($command,$meta,$options); } /** * collect all current running threads from the global threadPool instance * @param mixed $collectType constant that defines the output of the collect() call valid options are: * * dhThreads::COLLECT_FULL -- each completed Thread object * * dhThreads::COLLECT_ARRAY -- array containing just the command output (if a valid dhCache instance is available to the environment (Memcached)) * * dhThreads::COLLECT_NONE -- no output * @return array|true */ public static function threadCollect($collectType=null) { return static::threadPool("threadPool")->collect($collectType); } /** * Full-service wrapper for threading. * * @param array $commands array of commands to execute in the thread pool. (command is either a string or an array of ["exec","data","meta","options"]) * @param array $options options to apply to all commands executed {@see \boru\dhutils\dhThreads->start()} * @param int $numThreads number of threads to run * @param float $throttleDelay delay between waiting for available thread space * @return array array of Thread objects after completion * * @see \boru\dhutils\dhThreads->start() */ public static function threadMultiExec($commands=[],$options=[],$numThreads=4,$throttleDelay=0.1) { $pool = static::threadPool("threadPool",$numThreads,$throttleDelay); $collectOpts=[]; $collectOpts["collectType"] = dhGlobal::getVal($options,"collectType",dhThreads::COLLECT_FULL); if(!is_array($commands)) { $commands = [$commands]; } foreach($commands as $command) { $cmd = ""; $meta = []; $opts = $options; if(is_array($command)) { if(($cmd = dhGlobal::getMultiVal($command,["command"=>false,"cmd"=>false,"exec"=>false],true)) !== false) { $data = dhGlobal::getVal($command,"data",false); $meta = dhGlobal::getVal($command,"meta",[]); if($data !== false) { $meta["data"] = $data; } foreach(dhGlobal::getVal($command,"options",[]) as $k=>$v) { $opts[$k] = $v; } } else { $cmd = $command; } } $pool->start($cmd,$meta,$opts); } return $pool->collect($collectOpts); } }src/traits/GlobalUtils.php000064400000014406144761607140011612 0ustar001]) -- returns true * * @param array $array the array to test * @return boolean true if is assoc, false if not */ public static function isAssoc($array) { if(!is_array($array)) return false; return (bool)count(array_filter(array_keys($array), 'is_string')); } public static function exec($cmd,$array=true) { if(!$array) { ob_start(); passthru($cmd); $data = ob_get_contents(); ob_end_clean(); return $data; } else { $data = []; exec($cmd,$data); return $data; } } /** * Pad a $string to $len length using $padstring * * Balances the $string's length to match an even pad if $padstring is more than 1 char */ public static function pad($string,$len,$padstring=". ",$padStyle=STR_PAD_RIGHT) { if(strlen($padstring)>1) { $mod = strlen($string) % strlen($padstring); if($mod !== 0) { $diff = strlen($padstring)-$mod; $string = str_pad($string,strlen($string)+$diff," ",$padStyle); } } return str_pad($string,$len,$padstring,$padStyle); } /** * Used to limit the number of concurrent exec() calls for a given 'tag' * * Output: (int) number of running instances when < $concurrent * * Inputs * * * $tag (string) - identifier that should be included in the exec() command * * * $concurrent (int) - maximum concurrent instances of $tag that can exist * * * $seconds (float) - time to sleep in seconds between checks until < $concurrent * * * $callback (lambda) - callback function to run on each loop after checking */ public static function throttle($tag,$concurrent=5,$seconds=1,$callback=null) { $check_command = 'ps aux | grep "'.$tag.'" | grep -v grep | wc -l'; $data = exec($check_command); if(!is_null($callback)) { $callback(); } while($data>=$concurrent && $data>0) { usleep($seconds*1000000); $data = exec($check_command); if(!is_null($callback)) { $callback(); } } return $data; } /** * Trim a specific string off the beginning, end or both. * * @param string $needle the string to trim off * @param string $haystack the string to trim $needle from * @param int $flag (default=both) dhGlobal::TRIM_BOTH, dhGlobal::TRIM_START, dhGlobal::TRIM_END * @param int $limit (default=0) Number of times to trim (0=unlimited) * @return string */ public static function trimString($needle,$haystack,$flag=dhGlobal::TRIM_BOTH,$limit=0) { $needleLen = strlen($needle); if($flag == dhGlobal::TRIM_BOTH || $flag == dhGlobal::TRIM_START) { $cycles=0; while(strlen($haystack)>=$needleLen && substr($haystack,0,$needleLen) == $needle) { $haystack = substr($haystack,$needleLen); $cycles++; if($limit>0 && $cycles>=$limit) { break; } } } if($flag == dhGlobal::TRIM_BOTH || $flag == dhGlobal::TRIM_END) { $cycles=0; while(strlen($haystack)>=$needleLen && substr($haystack,-$needleLen) == $needle) { $haystack = substr($haystack,0,-$needleLen); $cycles++; if($limit>0 && $cycles>=$limit) { break; } } } return $haystack; } /** * Trim a specific string ($needle) off the beginning and end of $haystack, wrapper for dhGlobal::trimString() * * @param string $needle the string to trim off * @param string $haystack the string to trim $needle from * @param int $limit (default=0) Number of times to trim (0=unlimited) * @return string */ public static function btrimString($needle,$haystack,$limit=0) { return static::trimString($needle,$haystack,dhGlobal::TRIM_BOTH,$limit); } /** * Trim a specific string ($needle) off the beginning of $haystack, wrapper for dhGlobal::trimString() * * @param string $needle the string to trim off * @param string $haystack the string to trim $needle from * @param int $limit (default=0) Number of times to trim (0=unlimited) * @return string */ public static function ltrimString($needle,$haystack,$limit=0) { return static::trimString($needle,$haystack,dhGlobal::TRIM_START,$limit); } /** * Trim a specific string ($needle) off the end of $haystack, wrapper for dhGlobal::trimString() * * @param string $needle the string to trim off * @param string $haystack the string to trim $needle from * @param int $limit (default=0) Number of times to trim (0=unlimited) * @return string */ public static function rtrimString($needle,$haystack,$limit=0) { return static::trimString($needle,$haystack,dhGlobal::TRIM_END,$limit); } /** * Convert bytes into B/KB/MB/GB/TB * * @param mixed $bytes bytes to convert * @param int $precision (2) * @param null|string $forceUnit 'B', 'KB', 'MB', 'GB', 'TB' * @param boolean $space (false) space between value and unit * @return string */ public static function formatBytes($bytes,$format="%01.2f %s",$forceUnit=null) { $units = array('B', 'KB', 'MB', 'GB', 'TB'); $bytes = max($bytes, 0); if(($pow = array_search((string) $forceUnit,$units)) === false) { $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); $pow = min($pow, count($units) - 1); } // Uncomment one of the following alternatives $bytes /= pow(1024, $pow); // $bytes /= (1 << (10 * $pow)); return sprintf($format, $bytes,$units[$pow]); } }