code: protected function removeRecursive( $path, $pattern, Logger $logger )
      {
          // Check if source file exists at all.
          if ( !is_file( $path ) && !is_dir( $path ) )
          {
              $logger->log( "$path is not a valid source.", Logger::WARNING );
              return;
          }
  
          // Skip non readable files in src directory
          if ( !is_readable( $path ) )
          {
              $logger->log( "$path is not readable, skipping.", Logger::WARNING );
              return;
          }
  
          // Skip non writeable parent directories
          if ( !is_writeable( $parent = dirname( $path ) ) )
          {
              $logger->log( "$parent is not writable, skipping.", Logger::WARNING );
              return;
          }
  
          $matchesPattern = (
              ( $pattern === null ) ||
              ( preg_match( $pattern, basename( $path ) ) )
          );
  
          // Handle files
          if ( is_file( $path ) )
          {
              if ( $matchesPattern )
              {
                  unlink( $path );
              }
              return;
          }
  
          // Handle directory contents
          $dh = opendir( $path );
          while ( ( $file = readdir( $dh ) ) !== false )
          {
              if ( ( $file === '.' ) ||
                  ( $file === '..' ) )
              {
                  continue;
              }
  
              $this->removeRecursive(
                  $path . '/' . $file,
                  ( $matchesPattern ? null : $pattern ),
                  $logger
              );
          }
  
          if ( $matchesPattern )
          {
              rmdir( $path );
          }
      }
docs: Remove files and directories recursively
  
  Remove files and directories recursively. I one operation fails, a
  warning will be issued and the operation will be continued.
  
  You may optionally specify a pattern and only files and directories
  matching that pattern will be removed. If a directory matches the
  pattern all descendents will also be removed.
  
  @param string $path
  @param mixed $pattern
  @param Logger $logger
  @return void