GithubHelp home page GithubHelp logo

Glob support about core HOT 5 CLOSED

thekid avatar thekid commented on July 28, 2024
Glob support

from core.

Comments (5)

thekid avatar thekid commented on July 28, 2024 1

Alternatively, move this to a separate library, which also supersedes https://github.com/xp-framework/io-collections in Sequence-style interface:

Files::in($folder)
  ->matching('thumb*.webp')
  ->toMap(fn($file) => yield $file->name => $file->size())
;

from core.

thekid avatar thekid commented on July 28, 2024

Implementation:

diff --git a/src/main/php/io/FolderEntries.class.php b/src/main/php/io/FolderEntries.class.php
index c1718b3a3..3b0d77abd 100755
--- a/src/main/php/io/FolderEntries.class.php
+++ b/src/main/php/io/FolderEntries.class.php
@@ -31,6 +31,17 @@ class FolderEntries implements IteratorAggregate {
     return new Path($this->base, $name);
   }
 
+  /**
+   * Iterates over all entries matching a given pattern
+   *
+   * @see  https://www.php.net/glob
+   */
+  public function matching(string $pattern): iterable {
+    foreach (glob(rtrim($this->base, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$pattern, GLOB_NOSORT | GLOB_BRACE) as $match) {
+      yield basename($match) => new Path($match);
+    }
+  }
+
   /** Iterate over all entries */
   public function getIterator(): Traversable {
     if (null === $this->handle) {
diff --git a/src/test/php/net/xp_framework/unittest/io/FolderEntriesTest.class.php b/src/test/php/net/xp_framework/unittest/io/FolderEntriesTest.class.php
index 3a2dea37d..36c332023 100755
--- a/src/test/php/net/xp_framework/unittest/io/FolderEntriesTest.class.php
+++ b/src/test/php/net/xp_framework/unittest/io/FolderEntriesTest.class.php
@@ -105,4 +105,41 @@ class FolderEntriesTest extends \unittest\TestCase {
   public function named_dot() {
     $this->assertEquals(new Path($this->folder), (new FolderEntries($this->folder))->named('.'));
   }
+
+  #[Test]
+  public function entries_matching() {
+    (new File($this->folder, 'a.txt'))->touch();
+    (new File($this->folder, 'b.txt'))->touch();
+    (new File($this->folder, 'not-found'))->touch();
+
+    $this->assertEquals(
+      ['a.txt' => new Path($this->folder, 'a.txt'), 'b.txt' => new Path($this->folder, 'b.txt')],
+      iterator_to_array((new FolderEntries($this->folder))->matching('*.txt'))
+    );
+  }
+
+  #[Test]
+  public function entries_matching_ignores_hidden_files() {
+    (new File($this->folder, '.hidden.txt'))->touch();
+
+    $this->assertEquals([], iterator_to_array((new FolderEntries($this->folder))->matching('*.txt')));
+  }
+
+  #[Test]
+  public function entries_matching_is_case_sensitive() {
+    (new File($this->folder, 'C.TXT'))->touch();
+
+    $this->assertEquals([], iterator_to_array((new FolderEntries($this->folder))->matching('*.txt')));
+  }
+
+  #[Test]
+  public function entries_matching_supports_braces() {
+    (new File($this->folder, 'a.txt'))->touch();
+    (new File($this->folder, 'C.TXT'))->touch();
+
+    $this->assertEquals(
+      ['a.txt' => new Path($this->folder, 'a.txt'), 'C.TXT' => new Path($this->folder, 'C.TXT')],
+      iterator_to_array((new FolderEntries($this->folder))->matching('*.{txt,TXT}'))
+    );
+  }
 }
\ No newline at end of file

from core.

thekid avatar thekid commented on July 28, 2024

https://gist.github.com/thekid/795c35bec603c0f217cb5445cc901ded could be simplified if this was implemented:

- class Glob implements IteratorAggregate {
-
-   public function __construct(private Path $base, private string $pattern) { }
-
-   public function getIterator(): Traversable {
-     foreach (glob($this->base.$this->pattern, GLOB_NOSORT | GLOB_BRACE) as $file) {
-       yield new Path($file);
-     }
-   }
- }
@@ ... @@
- foreach ($p->isFile() ? [$p] : new Glob($p, 'thumb*.webp') as $entry) { ... }
+ foreach ($p->isFile() ? [$p] : $p->entries()->matching('thumb*.webp') as $entry) { ... }

from core.

thekid avatar thekid commented on July 28, 2024

Should there also be io.Path::match() which uses https://www.php.net/fnmatch? - including a replacement for non-POSIX compliant systems except Windows where this function is not available.

from core.

thekid avatar thekid commented on July 28, 2024

Should there also be io.Path::match() which uses https://www.php.net/fnmatch? - including a replacement for non-POSIX compliant systems except Windows where this function is not available.

Using fnmatch() means an inconsistency with glob(), the first doesn't support braces. Here's a replacement:

class Path {

  // ...

  public function matches($pattern): bool {
    $regex= '';
    $o= 0;
    $l= strlen($pattern);
    do {
      $s= strcspn($pattern, '.*?[]{}\\', $o);
      $regex.= substr($pattern, $o, $s);
      $o+= $s;
      switch ($pattern[$o] ?? null) {
        case null: break;
        case '.': $regex.= '\\.'; break;
        case '*': $regex.= '.*'; break;
        case '\\': $regex.= '\\'.$pattern[++$o]; break;
        case '{':
          $s= strcspn($pattern, '}', $o);
          $regex.= '('.strtr(substr($pattern, $o + 1, $s - 1), ',', '|').')';
          $o+= $s;
          break;
        case '[':
          $s= strcspn($pattern, ']', $o);
          $regex.= '['.('!' === $pattern[$o + 1] ? '^' : $pattern[$o + 1]).substr($pattern, $o + 2, $s - 2).']';
          $o+= $s;
          break;
      }
    } while (++$o < $l);

    return preg_match('~'.$regex.'$~', $this->path);
  }
}

from core.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.