Joins two file or directory paths.
If the left path is null, returns the right path, making the
left path optional (see {@see https://stackoverflow.com/q/1091107}).
@param string|null $lhs
@param string $rhs
@return string
552335
public static function join($lhs, $rhs) {
        if ($lhs === null)
            return $rhs;
        return rtrim($lhs, '/') . '/' . ltrim($rhs, '/');
    }
426591
private static function getRelativePath($from, $to)
    {
        $from = explode('/', $from);
        $to = explode('/', $to);
        $relPath = $to;

        foreach ($from as $depth => $dir) {
            // find first non-matching dir
            if (isset($to[$depth]) && $dir === $to[$depth]) {
                // ignore this directory
                array_shift($relPath);
            } else {
                // get number of remaining dirs to $from
                $remaining = count($from) - $depth;
                if ($remaining > 1) {
                    // add traversals up to first matching dir
                    $padLength = (count($relPath) + $remaining - 1) * -1;
                    $relPath = array_pad($relPath, $padLength, '..');
                    break;
                } else {
                    $relPath[0] = './'.$relPath[0];
                }
            }
        }

        return implode('/', $relPath);
    }
1205474
public static function path(...$args)
    {
        static $dsds = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
        $result = implode(DIRECTORY_SEPARATOR, $args);
        $offset = strpos($result, '://');
        if(false === $offset)
        {
            $offset = 0;
        }
        else
        {
            $offset += 3;
        }
        while(false !== strpos($result, $dsds, $offset))
        {
            $result = str_replace($dsds, DIRECTORY_SEPARATOR, $result);
        }
        return $result;
    }
349737
public static function pathJoin($dir, $file) {
        if (empty($dir) || empty($file)) {
            return self::getRelativePath($dir . $file);
        }
        return self::getRelativePath($dir . '/' . $file);
    }
332181
public function getCriteriaClause($lhs = true, $operand = true, $rhs = true, $rhs1 = false, $rhs2 = false, $add_del = true)
    {

        $cls = "";

        if ($this->_use == "SHOW/HIDE-and-GROUPBY") {
            $add_del = false;
        }

        if ($this->column_value == "(ALL)") {
            return $cls;
        }

        if ($this->column_value == "(NOTFOUND)") {
            $cls = " AND 1 = 0";
            return $cls;
        }

        if (!$this->column_value) {
            return ($cls);
        }

        $del = '';

        switch ($this->criteria_type) {

            case "ANY":
            case "ANYCHAR":
            case "TEXTFIELD":
                if ($add_del) {
                    $del = $this->getValueDelimiter();
                }

                $extract = explode(',', $this->column_value);
                if (is_array($extract)) {
                    $ct = 0;
                    foreach ($extract as $col) {
                        if (is_string($col)) {
                            $col = trim($col);
                        }

                        if (!$col) {
                            continue;
                        }

                        if ($col == "(ALL)") {
                            continue;
                        }

                        if ($ct == 0) {
                            if ($lhs) {
                                //$cls .= " XX".$this->table_name.".".$this->column_name;
                                $cls .= " AND " . $this->column_name;
                            }
                            if ($rhs) {
                                if ($operand) {
                                    $cls .= " IN (";
                                }

                                $cls .= $del . $col . $del;
                            }
                        } else
                        if ($rhs) {
                            $cls .= "," . $del . $col . $del;
                        }

                        $ct++;
                    }

                    if ($ct > 0 && $rhs) {
                        if ($operand) {
                            $cls .= " )";
                        }
                    }

                } else {
                    if ($lhs) {
                        if ($this->table_name && $this->column_name) {
                            $cls .= " AND " . $this->table_name . "." . $this->column_name;
                        } else
                        if ($this->column_name) {
                            $cls .= " AND " . $this->column_name;
                        }

                    }
                    if ($rhs) {
                        if ($operand) {
                            $cls .= " =" . $del . $this->column_value . $del;
                        } else {
                            $cls .= $del . $this->column_value . $del;
                        }
                    }

                }
                break;

            case "LIST":
                if ($add_del) {
                    $del = $this->getValueDelimiter();
                }

                if (!is_array($this->column_value)) {
                    $this->column_value = explode(',', $this->column_value);
                }

                if (is_array($this->column_value)) {
                    $ct = 0;
                    foreach ($this->column_value as $col) {
                        if (is_string($col)) {
                            $col = trim($col);
                        }

                        if ($col == "(ALL)") {
                            continue;
                        }

                        if ($ct == 0) {
                            if ($lhs) {
                                if ($this->table_name && $this->column_name) {
                                    $cls .= " AND " . $this->table_name . "." . $this->column_name;
                                } else
                                if ($this->column_name) {
                                    $cls .= " AND " . $this->column_name;
                                }

                            }
                            if ($rhs) {
                                if ($operand) {
                                    $cls .= " IN (";
                                }

                                $cls .= $del . $col . $del;
                            }
                        } else
                        if ($rhs) {
                            $cls .= "," . $del . $col . $del;
                        }

                        $ct++;
                    }

                    if ($ct > 0) {
                        if ($operand) {
                            $cls .= " )";
                        }
                    }

                } else {
                    if ($lhs) {
                        if ($this->table_name && $this->column_name) {
                            $cls .= " AND " . $this->table_name . "." . $this->column_name;
                        } else
                        if ($this->column_name) {
                            $cls .= " AND " . $this->column_name;
                        }

                    }
                    if ($rhs) {
                        if ($operand) {
                            $cls .= " =" . $del . $this->column_value . $del;
                        } else {
                            $cls .= $del . $this->column_value . $del;
                        }

                    }
                }
                break;

            case "DATE":
                $cls = "";
                if ($this->column_value) {
                    $val1 = ReporticoLocale::parseDate($this->column_value, false, ReporticoApp::getConfig("prep_dateformat"));
                    $val1 = ReporticoLocale::convertYMDtoLocal($val1, ReporticoApp::getConfig("prep_dateformat"), ReporticoApp::getConfig("db_dateformat"));
                    if ($lhs) {
                        if ($this->table_name && $this->column_name) {
                            $cls .= " AND " . $this->table_name . "." . $this->column_name;
                        } else
                        if ($this->column_name) {
                            $cls .= " AND " . $this->column_name;
                        }

                    }
                    if ($add_del) {
                        $del = $this->getValueDelimiter();
                    }

                    if ($rhs) {
                        if ($operand) {
                            $cls .= " = ";
                        }

                        $cls .= $del . $val1 . $del;
                    }
                }
                break;

            case "DATERANGE":
                $cls = "";
                if ($this->column_value) {
                    // If daterange value here is a range in a single value then its been
                    // run directly from command line and needs splitting up using "-"

                    $val1 = ReporticoLocale::parseDate($this->column_value, false, ReporticoApp::getConfig("prep_dateformat"));
                    $val2 = ReporticoLocale::parseDate($this->column_value2, false, ReporticoApp::getConfig("prep_dateformat"));
                    $val1 = ReporticoLocale::convertYMDtoLocal($val1, ReporticoApp::getConfig("prep_dateformat"), ReporticoApp::getConfig("db_dateformat"));
                    $val2 = ReporticoLocale::convertYMDtoLocal($val2, ReporticoApp::getConfig("prep_dateformat"), ReporticoApp::getConfig("db_dateformat"));
                    if ($lhs) {
                        if ($this->table_name && $this->column_name) {
                            $cls .= " AND " . $this->table_name . "." . $this->column_name;
                        } else
                        if ($this->column_name) {
                            $cls .= " AND " . $this->column_name;
                        }

                    }

                    if ($add_del) {
                        $del = $this->getValueDelimiter();
                    }

                    if ($rhs) {
                        $cls .= " BETWEEN ";
                        //$cls .= $del.$this->column_value.$del;
                        $cls .= $del . $val1 . $del;
                        $cls .= " AND ";
                        //$cls .= $del.$this->column_value2.$del;
                        $cls .= $del . $val2 . $del;
                    }
                    if ($rhs1) {
                        $cls = $del . $val1 . $del;
                    }
                    if ($rhs2) {
                        $cls = $del . $val2 . $del;
                    }
                }
                break;

            case "LOOKUP":
                if ($add_del) {
                    $del = $this->getValueDelimiter();
                }

                if (!is_array($this->column_value)) {
                    $this->column_value = explode(',', $this->column_value);
                }

                if (is_array($this->column_value)) {
                    $ct = 0;
                    foreach ($this->column_value as $col) {
                        if (is_string($col)) {
                            $col = trim($col);
                        }

                        if ($col == "(ALL)") {
                            continue;
                        }

                        if ($ct == 0) {
                            if ($lhs) {
                                if ($this->table_name && $this->column_name) {
                                    $cls .= " AND " . $this->table_name . "." . $this->column_name;
                                } else
                                if ($this->column_name) {
                                    $cls .= " AND " . $this->column_name;
                                }

                            }
                            if ($rhs) {
                                if ($operand) {
                                    $cls .= " IN (";
                                }

                                $cls .= $del . $col . $del;
                            }
                        } else
                        if ($rhs) {
                            $cls .= "," . $del . $col . $del;
                        }

                        $ct++;
                    }

                    if ($ct > 0) {
                        if ($operand) {
                            $cls .= " )";
                        }
                    }

                } else {
                    if ($lhs) {
                        if ($this->table_name && $this->column_name) {
                            $cls .= " AND " . $this->table_name . "." . $this->column_name;
                        } else
                        if ($this->column_name) {
                            $cls .= " AND " . $this->column_name;
                        }

                    }
                    if ($rhs) {
                        if ($operand) {
                            $cls .= " =" . $del . $this->column_value . $del;
                        } else {
                            $cls .= $del . $this->column_value . $del;
                        }

                    }
                }
                break;

            default:
                break;
        }

        return ($cls);
    }
202208
public function getPath(string ...$dirs): string
    {
        if (empty($dirs)) {
            return $this->path;
        }

        return self::canonicalize($this->path, ...$dirs);
    }
1368154
public function concat($paths)
    {
        if (is_array($paths))
            $paths = implode('/', $paths);
        return $this->fullPath() . '/' . $paths;
    }
14105
protected function getPath(string $hash, ?string $cacheContext = null, bool $confirmed = true, string $ds = '/'): string
    {
        $folderName = $this->getBaseUrl();

        if (!$confirmed) {
            $folderName .= $ds . 'uploads';
        }

        //isolate cached files
        if ($cacheContext) {
            $folderName .= $ds . 'cache' . $ds . $cacheContext;
        }

        //in order to avoid a folder with a to big number of files in
        if ($confirmed) {
            $folderName .= $ds . substr($hash, 0, 3);
        }

        //create folder if missing
        if (!file_exists($folderName)) {
            mkdir($folderName, 0777, true);
        }

        return $folderName . $ds . $hash;
    }
696932
public static function joinPaths(...$parts)
    {
        $combined = null;
        $parts = array_filter($parts);
        array_walk_recursive($parts, function ($part) use (&$combined) {
            // Normalise path
            $part = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $part);
            $combined = $combined
                ? (rtrim($combined, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $part)
                : $part;
        });
        return $combined;
    }
1291609
private function buildCondition($lookup, $lhs, $rhs)
    {
        $lookup = (array) $lookup;
        $lookup = $lhs->getLookup($lookup[0]);
        /* @var $lookup LookupInterface */
        return $lookup::createObject($lhs, $rhs);
    }
344565
public JoinDescription nested(EntityPath<?>... paths) {
        for (EntityPath<?> path : paths) {
            nested(J.left(path));
        }

        return this;
    }
711
private function getPaths(&$s, $r = "#")
    {
        $this->paths[$r] = &$s;
        if (is_array($s) || is_object($s)) {
            foreach ($s as $k => &$v) {
                if ($k !== "\$ref") {
                    $this->getPaths($v, $r == "#" ? "#{$k}" : "{$r}.{$k}");
                }
            }
        }
    }
163741
public function ls($dir = null)
    {
        $dir = $this->_getAbsoluteRemotePath(null === $dir ? $this->_remotepath : $dir);
        if (false === $ls = @scandir($dir)) {
            return $this->_trigger_error(sprintf('Unable to list files of remote directory %s.', $dir));
        }

        return $ls;
    }
65596
public static function rpath(String $file = NULL) : String
    {
        $config = Config::get('Filesystem', 'file', self::$access);

        self::$access = NULL;

        if( $config['parentDirectoryAccess'] === false )
        {
            $file = str_replace('../', '', $file);
        }

        if( $config['realPath'] === true )
        {
            $file = Base::prefix(self::originpath($file), REAL_BASE_DIR);
        }

        return $file;
    }
884779
public function path($path = null)
    {
        if ($path !== null) {
            $this->path = $path;
        }

        return (string) $this->path;
    }
554953
protected function _findPath($path)
    {
        $path = $this->_unifyPath($path);
        $dirs = $this->_dirs;

        $file = null;

        foreach ($dirs as $dir) {
            if (is_readable(realpath($dir.DS.$path))) {
                $file = $dir.DS.$path;
                break;
            }
        }

        return $file;
    }
771180
public static function join_paths($part = null)
    {
        $args = func_get_args();
        if (count($args) === 1 && is_array($args[0])) {
            $args = $args[0];
        }

        $parts = array();
        foreach ($args as $arg) {
            $part = trim($arg, ' \\/');
            if ($part) {
                $parts[] = $part;
            }
        }

        return implode('/', $parts);
    }