src/php/Arbit/Periodic/Command/FileSystem/Copy.php
protected function copyRecursive( $src, $dst, $depth, Logger $logger )
    {
        if ( $depth == 0 )
        {
            return;
        }

        // Check if source file exists at all.
        if ( !is_file( $src ) && !is_dir( $src ) )
        {
            $logger->log( "$src is not a valid source.", Logger::WARNING );
            return;
        }

        // Skip non readable files in src directory
        if ( !is_readable( $src ) )
        {
            $logger->log( "$src is not readable, skipping.", Logger::WARNING );
            return;
        }

        // Destination file should not exist
        if ( is_file( $dst ) || is_dir( $dst ) )
        {
            $logger->log( "$dst already exists, and cannot be overwritten.", Logger::WARNING );
            return;
        }

        // Actually copy
        if ( is_dir( $src ) )
        {
            mkdir( $dst );
        }
        elseif ( is_file( $src ) )
        {
            copy( $src, $dst );
            return;
        }

        // Recurse into directory
        $dh = opendir( $src );
        while ( ( $file = readdir( $dh ) ) !== false )
        {
            if ( ( $file === '.' ) ||
                ( $file === '..' ) )
            {
                continue;
            }

            $this->copyRecursive(
                $src . '/' . $file,
                $dst . '/' . $file,
                $depth - 1,
                $logger
            );
        }
    }
protected function copyRecursive( $src, $dst, $depth, Logger $logger )
    {
        if ( $depth == 0 )
        {
            return;
        }

        // Check if source file exists at all.
        if ( !is_file( $src ) && !is_dir( $src ) )
        {
            $logger->log( "$src is not a valid source.", Logger::WARNING );
            return;
        }

        // Skip non readable files in src directory
        if ( !is_readable( $src ) )
        {
            $logger->log( "$src is not readable, skipping.", Logger::WARNING );
            return;
        }

        // Destination file should not exist
        if ( is_file( $dst ) || is_dir( $dst ) )
        {
            $logger->log( "$dst already exists, and cannot be overwritten.", Logger::WARNING );
            return;
        }

        // Actually copy
        if ( is_dir( $src ) )
        {
            mkdir( $dst );
        }
        elseif ( is_file( $src ) )
        {
            copy( $src, $dst );
            return;
        }

        // Recurse into directory
        $dh = opendir( $src );
        while ( ( $file = readdir( $dh ) ) !== false )
        {
            if ( ( $file === '.' ) ||
                ( $file === '..' ) )
            {
                continue;
            }

            $this->copyRecursive(
                $src . '/' . $file,
                $dst . '/' . $file,
                $depth - 1,
                $logger
            );
        }
    }
Copy files and directories recursively

Copy files and directories recursively. I fone operation fails, a
warning will be issued and the operation will be continued.

A negative depth means infinite recursion. A depth of 1 means that the
current files and directories are created, but no recursion is applied.

@param string $src
@param string $dst
@param int $depth
@param Logger $logger
@return void