From 142b4b19b58cdccfb157787ec92f69947e29115d Mon Sep 17 00:00:00 2001
From: jgmdev <jgmdev@gmail.com>
Date: Thu, 26 Sep 2019 16:54:08 -0400
Subject: [PATCH] Added php implementation of fnmatch for platforms not
 supporting it.

---
 buildPHAR.php | 82 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 75 insertions(+), 7 deletions(-)

diff --git a/buildPHAR.php b/buildPHAR.php
index 37e5764..670413f 100644
--- a/buildPHAR.php
+++ b/buildPHAR.php
@@ -1,21 +1,89 @@
 <?php
+// fnmatch implementation taken from:
+// https://www.php.net/manual/en/function.fnmatch.php#100207
+if (!function_exists('fnmatch'))
+    define('FNM_PATHNAME', 1);
+    define('FNM_NOESCAPE', 2);
+    define('FNM_PERIOD', 4);
+    define('FNM_CASEFOLD', 16);
+
+    function fnmatch($pattern, $string, $flags=0)
+    {
+        return pcre_fnmatch($pattern, $string, $flags);
+    }
+}
+
+function pcre_fnmatch($pattern, $string, $flags = 0)
+{
+    $modifiers = null;
+    $transforms = array(
+        '\*' => '.*',
+        '\?' => '.',
+        '\[\!' => '[^',
+        '\[' => '[',
+        '\]' => ']',
+        '\.' => '\.',
+        '\\' => '\\\\'
+    );
+
+    // Forward slash in string must be in pattern:
+    if ($flags & FNM_PATHNAME) {
+        $transforms['\*'] = '[^/]*';
+    }
+
+    // Back slash should not be escaped:
+    if ($flags & FNM_NOESCAPE) {
+        unset($transforms['\\']);
+    }
+
+    // Perform case insensitive match:
+    if ($flags & FNM_CASEFOLD) {
+        $modifiers .= 'i';
+    }
+
+    // Period at start must be the same as pattern:
+    if ($flags & FNM_PERIOD) {
+        if (strpos($string, '.') === 0 && strpos($pattern, '.') !== 0) {
+            return false;
+        }
+    }
+
+    $pattern = '#^'
+        . strtr(preg_quote($pattern, '#'), $transforms)
+        . '$#'
+        . $modifiers
+    ;
+
+    return (boolean)preg_match($pattern, $string);
+}
 
 $phar = new Phar('build/phpctags.phar', 0, 'phpctags.phar');
 
 if (version_compare(PHP_VERSION, '5.4.0') < 0) {
-    class RecursiveCallbackFilterIterator extends RecursiveFilterIterator {
-        public function __construct ( RecursiveIterator $iterator, $callback ) {
+    class RecursiveCallbackFilterIterator extends RecursiveFilterIterator
+    {
+        public function __construct(RecursiveIterator $iterator, $callback)
+        {
             $this->callback = $callback;
             parent::__construct($iterator);
         }
 
-        public function accept () {
+        public function accept()
+        {
             $callback = $this->callback;
-            return $callback(parent::current(), parent::key(), parent::getInnerIterator());
+            return $callback(
+                parent::current(),
+                parent::key(),
+                parent::getInnerIterator()
+            );
         }
 
-        public function getChildren () {
-            return new self($this->getInnerIterator()->getChildren(), $this->callback);
+        public function getChildren()
+        {
+            return new self(
+                $this->getInnerIterator()->getChildren(),
+                $this->callback
+            );
         }
     }
 }
@@ -38,7 +106,7 @@ function ($current) {
                     'buildPHAR.php',
                 );
 
-                foreach($excludes as $exclude) {
+                foreach ($excludes as $exclude) {
                     if (fnmatch(getcwd().'/'.$exclude, $current->getPathName())) {
                         return false;
                     }