Map-based autoloader across php and phar resources

⌈⌋ branch:  Canonic Autoloader


Check-in [35d87d3c07]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Introduce addPhar(), fix "const" subarray, keep static list of $instances.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:35d87d3c071545357df3eadf95aa0f717d5d2df3
User & Date: mario 2015-01-22 19:33:12
Context
2015-01-22
19:34
Typos in manpage. check-in: c956af642c user: mario tags: trunk
19:33
Introduce addPhar(), fix "const" subarray, keep static list of $instances. check-in: 35d87d3c07 user: mario tags: trunk
2014-09-10
22:57
Add php -d update example. check-in: a546e623ed user: mario tags: trunk
Changes

Changes to stub.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
165
166
167
168
169
170
171
172
173
174



175
176
177
178
179
180
181
...
201
202
203
204
205
206
207




















208
209
210
211
212
213
214
<?php
/**
 * api: php
 * title: Canonic Autoloader / shared.phar
 * description: Map-based autoloader across .php and .phar resources.
 * version: 0.3.3-18
 * depends: php:phar | php >= 5.3
 * category: cli
 * license: Public Domain
 *
 *
 * Self-contained autoloader which provides .php and .phar class
 * loading based on a map. Loader and map are also contained in a
 * phar.
 *
 * It's meant for /usr/share/php handling, but can also be utilized

 * for per-project autoloading. It's indifferent to PSR-0/PSR-4 or
 * custom directory schemes. Because of the filename map, identifier
 * names are handled in compliance to PHP semantics (unlike PSR-x);
 * and non-namespaced code works as well. Additionally it prepares
 * future rfc:function_autoloading support.
 *
 * Using the autoloader is as simple as:
 *
 *   include_once("shared.phar");
 *
 * Invoke it from the commandline to update the internal classmap:
 *
 *   php ./shared.phar
 *
 * For development (non-deployment) setups, configure auto-updates
 * in your .htaccess with:
 *
 *   SetEnv AUTOLOADER_UPDATE 1
 *
 * The phar could also be split up into separate autoload, map and
 * update includes.
 *
 */



// Declared just once for relocatable instantation
if (!class_exists("Canonic_Autoloader")) {
    class Canonic_Autoloader extends ArrayObject {


        // Support for rfc:function_autoloading identifier typing.
        public $types = array(1=>"class", 2=>"function", 4=>"constant");

        // Base directory for relative paths or phar:// paths in map.
        public $basedir = "";
        public $basefn = "";
        
        // Try to rebuild map on missing identifiers.
        public $auto_update = 0;
................................................................................

                    // Relative directory, if no phar: prefix
                    if (strncmp($path, "phar://", 7)) {
                        $path = "$this->basedir/$path";
                    }

                    // If non-absolute phar:// url, inject basedir
                    elseif ($path[7] != "/") {
                        $path = "phar://$this->basedir/" . substr($path, 7);
                    }
                }

                return include_once($path);
            }

................................................................................

        /**
         * Create instance and register it.
         *
         */
        public static function hookup($basefn) {
            spl_autoload_register(
                new Canonic_Autoloader( include(self::pharBase($basefn) . self::MAP_FILE), $basefn )
            );
        }




     
        /**
         * Recreate classmap within the phar / Or as separate autoload.map.php file.
         *
         */
        public static function update($basefn, $fp=NULL) {
................................................................................
            }
            // use its surrounding directory if plain .php file
            else {
                return dirname($basefn) . "/";
            }
        }






















    }
}



// Register loader with phar-contained indentifier map.





|






|
<

<
>
|
|
|
|
|





|



|
|



|
|











|







 







|







 







|


>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13

14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
<?php
/**
 * api: php
 * title: Canonic Autoloader / shared.phar
 * description: Map-based autoloader across .php and .phar resources.
 * version: 0.3.4
 * depends: php:phar | php >= 5.3
 * category: cli
 * license: Public Domain
 *
 *
 * Self-contained autoloader which provides .php and .phar class
 * loading based on a map.

 *

 * Usable for per-project classpath and /usr/share/php handling.
 * It's indifferent to PSR-0/PSR-4 or custom directory schemes.
 * Because of the filename map, identifier names are handled in
 * compliance to PHP semantics (unlike PSR-x); and still allows
 * non-namespaced code to work. Additionally it prepares future
 * rfc:function_autoloading support.
 *
 * Using the autoloader is as simple as:
 *
 *   include_once("shared.phar");
 *
 * Invoke it from the commandline to update the internal map:
 *
 *   php ./shared.phar
 *
 * For development (non-deployment) setups, configure automatic
 * updates per environment setting, e.g. via .htaccess:
 *
 *   SetEnv AUTOLOADER_UPDATE 1
 *
 * The phar could also be split up into separate autoload, map
 * and update includes.
 *
 */



// Declared just once for relocatable instantation
if (!class_exists("Canonic_Autoloader")) {
    class Canonic_Autoloader extends ArrayObject {


        // Support for rfc:function_autoloading identifier typing.
        public $types = array(1=>"class", 2=>"function", 4=>"const");

        // Base directory for relative paths or phar:// paths in map.
        public $basedir = "";
        public $basefn = "";
        
        // Try to rebuild map on missing identifiers.
        public $auto_update = 0;
................................................................................

                    // Relative directory, if no phar: prefix
                    if (strncmp($path, "phar://", 7)) {
                        $path = "$this->basedir/$path";
                    }

                    // If non-absolute phar:// url, inject basedir
                    elseif ($path[7] !== "/") {
                        $path = "phar://$this->basedir/" . substr($path, 7);
                    }
                }

                return include_once($path);
            }

................................................................................

        /**
         * Create instance and register it.
         *
         */
        public static function hookup($basefn) {
            spl_autoload_register(
                self::instances[] = new Canonic_Autoloader( include(self::pharBase($basefn) . self::MAP_FILE), $basefn )
            );
        }
        
        // keep a reference
        static $instances = array();

     
        /**
         * Recreate classmap within the phar / Or as separate autoload.map.php file.
         *
         */
        public static function update($basefn, $fp=NULL) {
................................................................................
            }
            // use its surrounding directory if plain .php file
            else {
                return dirname($basefn) . "/";
            }
        }


        /**
         * Loads meta data `map` from fpm/xpm-generated .phar/composer packages.
         * The map[] has the same structure as shared.phars` itself.
         *
         */
        public static function addPhar($phar_fn) {

            // open and scan for metadata
            if ($main = reset(self::$instances) and $p = new Phar($phar_fn, 0, NULL)
            and $p->hasMetadata() and $meta = $p->getMetadata() and !empty($meta["map"]))
            {
                // add to instance classmap by prepending phar location and scheme
                foreach ($main->types as $type) {
                    foreach (array_change_key_case($meta["map"][$type]) as $id=>$fn) {
                        $main[$type][$id] = "phar://$phar_fn/$fn";
                    }
                }
            }
        }

    }
}



// Register loader with phar-contained indentifier map.