├── .editorconfig ├── .gitignore ├── .scrutinizer.yml ├── .travis.yml ├── README.markdown ├── app ├── .htaccess ├── app.cache ├── bootstrap-responsive.min.css ├── bootstrap.min.css ├── config.php ├── favicon.ico ├── img │ ├── glyphicons-halflings-white.png │ └── glyphicons-halflings.png └── index.php ├── bootstrap.php ├── composer.json ├── composer.lock ├── make-million.php ├── phpunit.xml ├── src ├── Cache.php ├── Capsule.php ├── Pack.php └── Sweep.php ├── tests ├── CacheDefaultTest.php ├── DummyFixtures.php ├── Handlers │ ├── CdbReadTest.php │ ├── CdbWriteTest.php │ ├── Db4Test.php │ ├── FlatfileTest.php │ ├── GdbmTest.php │ ├── InifileTest.php │ ├── QdbmTest.php │ └── TestCase.php ├── PackTest.php ├── SweepTest.php └── _drafts │ └── test-cache-cdb2.cdb └── vendor ├── autoload.php └── composer ├── ClassLoader.php ├── LICENSE ├── autoload_classmap.php ├── autoload_namespaces.php ├── autoload_psr4.php ├── autoload_real.php └── installed.json /.editorconfig: -------------------------------------------------------------------------------- 1 | ; top-most EditorConfig file 2 | root = true 3 | 4 | ; Unix-style newlines 5 | [*] 6 | end_of_line = LF 7 | 8 | [*.php] 9 | indent_style = space 10 | indent_size = 4 11 | 12 | [*.test] 13 | indent_style = space 14 | indent_size = 4 15 | 16 | [*.rst] 17 | indent_style = space 18 | indent_size = 4 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | *.pyc 10 | 11 | # Logs and databases # 12 | ###################### 13 | *.log 14 | 15 | # OS generated files # 16 | ###################### 17 | .DS_Store* 18 | ehthumbs.db 19 | Icon? 20 | Thumbs.db 21 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - php 3 | 4 | tools: 5 | 6 | # Code Coverage 7 | external_code_coverage: 8 | enabled: false 9 | filter: 10 | excluded_paths: 11 | - 'tests/*' 12 | 13 | # Copy/Paste Detector 14 | php_cpd: 15 | enabled: true 16 | command: phpcpd 17 | excluded_dirs: 18 | - tests 19 | 20 | # Analyzes the size and structure of a PHP project. 21 | php_loc: 22 | enabled: true 23 | command: phploc 24 | excluded_dirs: 25 | - tests 26 | 27 | 28 | # PHP Mess Detector (http://phpmd.org). 29 | php_mess_detector: 30 | enabled: true 31 | command: phpmd 32 | config: 33 | rulesets: 34 | - codesize 35 | - unusedcode 36 | - naming 37 | - design 38 | filter: 39 | excluded_paths: 40 | - 'tests/*' 41 | 42 | 43 | # Analyzes the size and structure of a PHP project. 44 | php_pdepend: 45 | enabled: true 46 | command: pdepend 47 | excluded_dirs: 48 | - tests 49 | 50 | # Runs Scrutinizer's PHP Analyzer Tool 51 | php_analyzer: 52 | enabled: true 53 | filter: 54 | excluded_paths: 55 | - 'tests/*' 56 | 57 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.4 5 | - 5.5 6 | - 5.6 7 | - 7.0 8 | - 7.1 9 | - 7.2 10 | 11 | sudo: false 12 | 13 | matrix: 14 | include: 15 | - php: 5.5.9 16 | env: setup=lowest 17 | - php: 5.5.9 18 | env: setup=stable 19 | - php: 7.0 20 | env: setup=stable 21 | allow_failures: 22 | - php: 5.6 23 | - php: 7.0 24 | - php: 7.1 25 | - php: 7.2 26 | fast_finish: true 27 | 28 | before_script: 29 | - phpenv rehash 30 | 31 | script: 32 | - phpunit --configuration phpunit.xml --coverage-clover=coverage.clover 33 | - wget https://scrutinizer-ci.com/ocular.phar 34 | - php ocular.phar code-coverage:upload --format=php-clover coverage.clover 35 | 36 | notifications: 37 | email: 38 | - gjero@krsteski.de 39 | 40 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | The php-dba-cache uses the database (dbm-style) abstraction layer to cache/store your PHP objects, 5 | strings, integers or arrays. Even instances of SimpleXMLElement can be put to the cache. You don`t 6 | have to matter about the size of the cache-file. It depends on the free space of your disk. 7 | 8 | [![Build Status](https://travis-ci.org/gjerokrsteski/php-dba-cache.png?branch=master)](https://travis-ci.org/gjerokrsteski/php-dba-cache) 9 | [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/gjerokrsteski/php-dba-cache/badges/quality-score.png?s=05c35e93b4026539019555e034a9996839a3c658)](https://scrutinizer-ci.com/g/gjerokrsteski/php-dba-cache/) 10 | [![Dependency Status](https://www.versioneye.com/php/gjerokrsteski:php-dba-cache/dev-master/badge.png)](https://www.versioneye.com/php/gjerokrsteski:php-dba-cache/dev-master) 11 | 12 | Sample for Oracle Berkeley DB 4 with persistent connection 13 | ---------------------------------------------------------- 14 | 15 | ```php 16 | $cache = new Cache( 17 | '/your/path/to/the/cahe-file/cache.db4', 'db4' 18 | ); 19 | 20 | $yorObject = new ObjectYouWantToPutInCache(); 21 | $yourObjectIdentifier = 'your:cool:object:identifier'; 22 | 23 | // check if your object is in the cache. 24 | // you also can ignore it, and let the CacheDba do it for you. 25 | if (true === $cache->has($yourObjectIdentifier)) { 26 | $cache->delete($yourObjectIdentifier); 27 | } 28 | 29 | $cache->put($yourObjectIdentifier, $yorObject); 30 | 31 | // than somewhere at your project. 32 | $cache->get($yourObjectIdentifier); 33 | 34 | // for the garbage collection 35 | // you can create an cron-job starting once a day. 36 | $sweep = new Sweep($cache); 37 | $sweep->all(); 38 | 39 | // or clean all objects older than given expiration since now. 40 | $sweep->old(); 41 | ``` 42 | 43 | Saving SimpleXMLElement instances into DB 4 with persistent connection 44 | ---------------------------------------------------------------------- 45 | 46 | ```php 47 | $string = " 48 | 49 | Let us cache 50 | Joe 51 | Jane 52 | Some content here 53 | "; 54 | 55 | $simplexml = simplexml_load_string( 56 | $string, 57 | 'SimpleXMLElement', 58 | LIBXML_NOERROR|LIBXML_NOWARNING|LIBXML_NONET 59 | ); 60 | 61 | $identifier = md5('simplexml_identifier'); 62 | 63 | $path = dirname(__FILE__).'/simple-xml-test-cache.db4'; 64 | $cache = new Cache($path, 'db4'); 65 | 66 | $cache->put($identifier, $simplexml); 67 | 68 | $getObject = $cache->get($identifier); 69 | 70 | error_log(' - PUT IN CACHE : '.print_r($simplexml, true)); 71 | error_log(' - GET FROM CACHE : '.print_r($getObject, true)); 72 | 73 | error_log(' - IS SAME OBJECT : '. 74 | print_r(($simplexml->asXml() === $getObject->asXml()) 75 | ? 'true' : 'false', true)); 76 | ``` 77 | 78 | PHP DBA Cache Monitor 79 | --------------------- 80 | Responsive web-interface that provides a comprehensive, easy to use and of course good looking GUI. It not only gives 81 | access to statistical parameters of DBA Cache, it also makes it easier to administer a web-server running DBA by 82 | providing comfortable features for optimizing the cache and deleting entries from the cache. 83 | 84 | ![PHP DBA cache Monitor 2014](http://farm9.staticflickr.com/8528/8547311457_9e4a7ca45d.jpg "PHP DBA Cache Monitor") 85 | 86 | 87 | 88 | Available options 89 | =========================== 90 | 91 | Cache 92 | - Open a given dba database 93 | - Insert a new record with a given key (persistently or with a given expiration time) 94 | - Get a record with a given key 95 | - Replace the value of a record with a given key 96 | - Delete the record with a given key 97 | - Return metadata for the given key: expire timestamp & timestamp of last modification time 98 | - Get all keys from cache 99 | 100 | Sweep - CacheGarbageCollector (optional) 101 | - Clean all entries 102 | - Clean expired entries 103 | - Flush the cache file 104 | - Optimizes the database file automatically after cleaning process 105 | 106 | 107 | Installation 108 | ============ 109 | 110 | "By using the --enable-dba=shared configuration option you can build a dynamic loadable module 111 | to enable PHP for basic support of dbm-style databases. You also have to add support for at 112 | least one of the following handlers by specifying the --with-XXXX configure switch 113 | to your PHP configure line." 114 | 115 | More about installation: http://www.php.net/manual/en/dba.installation.php 116 | 117 | 118 | DBA handlers 119 | ============ 120 | 121 | The behaviour of various aspects for the caching depends on the implementation of yor 122 | installed dba-type database. I have tested it with several database-handlers like db4, flatfile, 123 | cdb, cdb_make, gdbm. The cdb & cdb_make family is the fastest, but you have to create 124 | you own garbage-collection-cleaner or you can delete it manually. Take a look at the tests 125 | (https://github.com/gjerokrsteski/php-dba-cache/tree/master/tests) to better understand 126 | how to use the cache. 127 | 128 | cdb = Tiny Constant Database - for reading 129 | Cdb is "a fast, reliable, lightweight package for creating and reading constant databases. 130 | " It is from the author of qmail and can be found at http://cr.yp.to/cdb.html. Since it is 131 | constant, we support only reading operations. And since PHP 4.3.0 we support writing 132 | (not updating) through the internal cdb library. 133 | 134 | cdb_make = Tiny Constant Database - for writing 135 | Since PHP 4.3.0 we support creation of cdb files when the bundled cdb library is used. 136 | 137 | db4 = Oracle Berkeley DB 4 - for reading and writing 138 | DB4 is Sleepycat Software's DB4. This is available since PHP 4.3.2. 139 | 140 | gdbm = GNU Database Manager - for reading and writing 141 | Gdbm is the GNU database manager. 142 | 143 | flatfile = default dba extension - for reading and writing 144 | This is available since PHP 4.3.0 for compatibility with the deprecated dbm extension only 145 | and should be avoided. However you may use this where files were created in this format. 146 | That happens when configure could not find any external library. 147 | 148 | More about requirements: http://www.php.net/manual/en/dba.requirements.php 149 | 150 | Nice to know 151 | ------------ 152 | 153 | Not all of the DBA-style databases can replace key-value pairs, like the CDB. The CDB database 154 | can handle only with fixed key-value pairs. The best and fastest handlers for DBA-style caching 155 | are: QDBM, Berkeley DB (DB4), NDBM and least the Flatfile. 156 | Most problematic are dbm and ndbm which conflict with many installations. The reason for this is 157 | that on several systems these libraries are part of more than one other library. The configuration 158 | test only prevents you from configuring malfaunctioning single handlers but not combinations. 159 | 160 | Benchmark Test of DBM Brothers 161 | ------------------------------ 162 | 163 | This benchmark test is to calculate processing time (real time) 164 | and file size of database. Writing test is to store 1,000,000 records. Reading test is 165 | to fetch all of its records. Both of the key and the value of each record are such 8-byte 166 | strings as `00000001', `00000002', `00000003'... Tuning parameters of each DBM are set to 167 | display its best performance. Platform: Linux 2.4.31 kernel, EXT2 file system, 168 | Pentium4 1.7GHz CPU, 1024MB RAM, ThinkPad T42 Compilation: gcc 3.3.2 (using -O3), glibc 2.3.3 169 | 170 | Result 171 | ```cli 172 | NAME DESCRIPTION WRITE TIME READ TIME FILE SIZE 173 | QDBM Quick Database Manager 1.8.74 1.89 1.58 55257 174 | NDBM New Database Manager 5.1 8.07 7.79 814457 175 | SDBM Substitute Database Manager 1.0.2 11.32 0.00 606720 176 | GDBM GNU Database Manager 1.8.3 14.01 5.36 82788 177 | TDB Trivial Database 1.0.6 9.64 2.22 51056 178 | CDB Tiny Constant Database 0.75 0.87 0.80 39065 179 | BDB Berkeley DB 4.4.20 9.62 5.62 40956 180 | QDBM-BT-ASC B+ tree API of QDBM (ascending order) 2.37 1.78 24304 181 | QDBM-BT-RND B+ tree API of QDBM (at random) 10.90 4.82 15362 182 | BDB-BT-ASC B+ tree API of BDB (ascending order) 3.04 3.06 27520 183 | BDB-BT-RND B+ tree API of BDB (at random) 10.03 4.15 29120 184 | ``` 185 | 186 | Unit of time is seconds. Unit of size is kilo bytes. Read time of SDBM can not be calculated 187 | because its database is broken when more than 100000 records. 188 | -------------------------------------------------------------------------------- /app/.htaccess: -------------------------------------------------------------------------------- 1 | # Apache configuration file 2 | # http://httpd.apache.org/docs/2.2/mod/quickreference.html 3 | 4 | # Note: ".htaccess" files are an overhead for each request. This logic should 5 | # be placed in your Apache config whenever possible. 6 | # http://httpd.apache.org/docs/2.2/howto/htaccess.html 7 | 8 | # For all files not found in the file system, reroute the request to the 9 | # "index.php" front controller, keeping the query string intact 10 | 11 | 12 | RewriteCond %{REQUEST_FILENAME} !-f 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteRule ^(.*)$ index.php/$1 [L] 15 | 16 | 17 | 18 | order allow,deny 19 | deny from all 20 | -------------------------------------------------------------------------------- /app/app.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gjerokrsteski/php-dba-cache/c54311733c9e0129be1a769fdb684d6b0a1d4a18/app/app.cache -------------------------------------------------------------------------------- /app/bootstrap-responsive.min.css: -------------------------------------------------------------------------------- 1 | /* generated by BootTheme (http://www.boottheme.com) */ 2 | .clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0;} 3 | .clearfix:after{clear:both;} 4 | .hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;} 5 | .input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} 6 | @-ms-viewport{width:device-width;}.hidden{display:none;visibility:hidden;} 7 | .visible-phone{display:none !important;} 8 | .visible-tablet{display:none !important;} 9 | .hidden-desktop{display:none !important;} 10 | .visible-desktop{display:inherit !important;} 11 | @media (min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit !important;} .visible-desktop{display:none !important ;} .visible-tablet{display:inherit !important;} .hidden-tablet{display:none !important;}}@media (max-width:767px){.hidden-desktop{display:inherit !important;} .visible-desktop{display:none !important;} .visible-phone{display:inherit !important;} .hidden-phone{display:none !important;}}.visible-print{display:none !important;} 12 | @media print{.visible-print{display:inherit !important;} .hidden-print{display:none !important;}}@media (min-width:1200px){.row{margin-left:-30px;*zoom:1;}.row:before,.row:after{display:table;content:"";line-height:0;} .row:after{clear:both;} [class*="span"]{float:left;min-height:1px;margin-left:30px;} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px;} .span12{width:1170px;} .span11{width:1070px;} .span10{width:970px;} .span9{width:870px;} .span8{width:770px;} .span7{width:670px;} .span6{width:570px;} .span5{width:470px;} .span4{width:370px;} .span3{width:270px;} .span2{width:170px;} .span1{width:70px;} .offset12{margin-left:1230px;} .offset11{margin-left:1130px;} .offset10{margin-left:1030px;} .offset9{margin-left:930px;} .offset8{margin-left:830px;} .offset7{margin-left:730px;} .offset6{margin-left:630px;} .offset5{margin-left:530px;} .offset4{margin-left:430px;} .offset3{margin-left:330px;} .offset2{margin-left:230px;} .offset1{margin-left:130px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0;} .row-fluid:after{clear:both;} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;} .row-fluid [class*="span"]:first-child{margin-left:0;} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%;} .row-fluid .span12{width:100%;*width:99.94680851063829%;} .row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%;} .row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%;} .row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%;} .row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%;} .row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%;} .row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%;} .row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%;} .row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%;} .row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%;} .row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%;} .row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%;} .row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%;} .row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%;} .row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%;} .row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%;} .row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%;} .row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%;} .row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%;} .row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%;} .row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%;} .row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%;} .row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%;} .row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%;} .row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%;} .row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%;} .row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%;} .row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%;} .row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%;} .row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%;} .row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%;} .row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%;} .row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%;} .row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%;} .row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%;} .row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%;} input,textarea,.uneditable-input{margin-left:0;} .controls-row [class*="span"]+[class*="span"]{margin-left:30px;} input.span12,textarea.span12,.uneditable-input.span12{width:1156px;} input.span11,textarea.span11,.uneditable-input.span11{width:1056px;} input.span10,textarea.span10,.uneditable-input.span10{width:956px;} input.span9,textarea.span9,.uneditable-input.span9{width:856px;} input.span8,textarea.span8,.uneditable-input.span8{width:756px;} input.span7,textarea.span7,.uneditable-input.span7{width:656px;} input.span6,textarea.span6,.uneditable-input.span6{width:556px;} input.span5,textarea.span5,.uneditable-input.span5{width:456px;} input.span4,textarea.span4,.uneditable-input.span4{width:356px;} input.span3,textarea.span3,.uneditable-input.span3{width:256px;} input.span2,textarea.span2,.uneditable-input.span2{width:156px;} input.span1,textarea.span1,.uneditable-input.span1{width:56px;} .thumbnails{margin-left:-30px;} .thumbnails>li{margin-left:30px;} .row-fluid .thumbnails{margin-left:0;}}@media (min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";line-height:0;} .row:after{clear:both;} [class*="span"]{float:left;min-height:1px;margin-left:20px;} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px;} .span12{width:724px;} .span11{width:662px;} .span10{width:600px;} .span9{width:538px;} .span8{width:476px;} .span7{width:414px;} .span6{width:352px;} .span5{width:290px;} .span4{width:228px;} .span3{width:166px;} .span2{width:104px;} .span1{width:42px;} .offset12{margin-left:764px;} .offset11{margin-left:702px;} .offset10{margin-left:640px;} .offset9{margin-left:578px;} .offset8{margin-left:516px;} .offset7{margin-left:454px;} .offset6{margin-left:392px;} .offset5{margin-left:330px;} .offset4{margin-left:268px;} .offset3{margin-left:206px;} .offset2{margin-left:144px;} .offset1{margin-left:82px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0;} .row-fluid:after{clear:both;} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;} .row-fluid [class*="span"]:first-child{margin-left:0;} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%;} .row-fluid .span12{width:100%;*width:99.94680851063829%;} .row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%;} .row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%;} .row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%;} .row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%;} .row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%;} .row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%;} .row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%;} .row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%;} .row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%;} .row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%;} .row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%;} .row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%;} .row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%;} .row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%;} .row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%;} .row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%;} .row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%;} .row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%;} .row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%;} .row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%;} .row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%;} .row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%;} .row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%;} .row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%;} .row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%;} .row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%;} .row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%;} .row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%;} .row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%;} .row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%;} .row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%;} .row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%;} .row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%;} .row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%;} .row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%;} input,textarea,.uneditable-input{margin-left:0;} .controls-row [class*="span"]+[class*="span"]{margin-left:20px;} input.span12,textarea.span12,.uneditable-input.span12{width:710px;} input.span11,textarea.span11,.uneditable-input.span11{width:648px;} input.span10,textarea.span10,.uneditable-input.span10{width:586px;} input.span9,textarea.span9,.uneditable-input.span9{width:524px;} input.span8,textarea.span8,.uneditable-input.span8{width:462px;} input.span7,textarea.span7,.uneditable-input.span7{width:400px;} input.span6,textarea.span6,.uneditable-input.span6{width:338px;} input.span5,textarea.span5,.uneditable-input.span5{width:276px;} input.span4,textarea.span4,.uneditable-input.span4{width:214px;} input.span3,textarea.span3,.uneditable-input.span3{width:152px;} input.span2,textarea.span2,.uneditable-input.span2{width:90px;} input.span1,textarea.span1,.uneditable-input.span1{width:28px;}}@media (max-width:767px){body{padding-left:20px;padding-right:20px;} .navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-left:-20px;margin-right:-20px;} .container-fluid{padding:0;} .dl-horizontal dt{float:none;clear:none;width:auto;text-align:left;} .dl-horizontal dd{margin-left:0;} .container{width:auto;} .row-fluid{width:100%;} .row,.thumbnails{margin-left:0;} .thumbnails>li{float:none;margin-left:0;} [class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{float:none;display:block;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .row-fluid [class*="offset"]:first-child{margin-left:0;} .input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto;} .controls-row [class*="span"]+[class*="span"]{margin-left:0;} .modal{position:fixed;top:20px;left:20px;right:20px;width:auto;margin:0;}.modal.fade{top:-100px;} .modal.fade.in{top:20px;}}@media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0, 0, 0);} .page-header h1 small{display:block;line-height:20px;} input[type="checkbox"],input[type="radio"]{border:1px solid #ccc;} .form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left;} .form-horizontal .controls{margin-left:0;} .form-horizontal .control-list{padding-top:0;} .form-horizontal .form-actions{padding-left:10px;padding-right:10px;} .media .pull-left,.media .pull-right{float:none;display:block;margin-bottom:10px;} .media-object{margin-right:0;margin-left:0;} .modal{top:10px;left:10px;right:10px;} .modal-header .close{padding:10px;margin:-10px;} .carousel-caption{position:static;}}@media (max-width:979px){body{padding-top:0;} .navbar-fixed-top,.navbar-fixed-bottom{position:static;} .navbar-fixed-top{margin-bottom:20px;} .navbar-fixed-bottom{margin-top:20px;} .navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px;} .navbar .container{width:auto;padding:0;} .navbar .brand{padding-left:10px;padding-right:10px;margin:0 0 0 -5px;} .nav-collapse{clear:both;} .nav-collapse .nav{float:none;margin:0 0 10px;} .nav-collapse .nav>li{float:none;} .nav-collapse .nav>li>a{margin-bottom:2px;} .nav-collapse .nav>.divider-vertical{display:none;} .nav-collapse .nav .nav-header{color:#777777;text-shadow:none;} .nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .nav-collapse .dropdown-menu li+li a{margin-bottom:2px;} .nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2;} .navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999999;} .navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111111;} .nav-collapse.in .btn-group{margin-top:5px;padding:0;} .nav-collapse .dropdown-menu{position:static;top:auto;left:auto;float:none;display:none;max-width:none;margin:0 15px;padding:0;background-color:transparent;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} .nav-collapse .open>.dropdown-menu{display:block;} .nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none;} .nav-collapse .dropdown-menu .divider{display:none;} .nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none;} .nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);} .navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111111;border-bottom-color:#111111;} .navbar .nav-collapse .nav.pull-right{float:none;margin-left:0;} .nav-collapse,.nav-collapse.collapse{overflow:hidden;height:0;} .navbar .btn-navbar{display:block;} .navbar-static .navbar-inner{padding-left:10px;padding-right:10px;}}@media (min-width:980px){.nav-collapse.collapse{height:auto !important;overflow:visible !important;}} -------------------------------------------------------------------------------- /app/config.php: -------------------------------------------------------------------------------- 1 | dirname(__FILE__) . DIRECTORY_SEPARATOR . 'app.flatfile', 8 | 9 | /* 10 | * You have to install one of this handlers before use. 11 | * 12 | * cdb = Tiny Constant Database - for reading. 13 | * cdb_make = Tiny Constant Database - for writing. 14 | * db4 = Oracle Berkeley DB 4 - for reading and writing. 15 | * qdbm = Quick Database Manager - for reading and writing. 16 | * gdbm = GNU Database Manager - for reading and writing. 17 | * inifile = Ini File - for reading and writing. 18 | * flatfile = default dba extension - for reading and writing. 19 | * 20 | * Use flatfile-handler only when you cannot install one, 21 | * of the libraries required by the other handlers, 22 | * and when you cannot use bundled cdb handler. 23 | */ 24 | 'handler' => 'flatfile', 25 | 26 | /* 27 | * The mode for read/write access, database creation if it doesn't currently exist. 28 | * 29 | * r = for read access 30 | * w = for read/write access to an already existing database 31 | * c = for read/write access and database creation if it doesn't currently exist 32 | * n = for create, truncate and read/write access 33 | * 34 | * When you are absolutely sure that you do not require database locking you can use "-" as suffix. 35 | */ 36 | 'mode' => 'c-', 37 | 38 | /* 39 | * Open the database persistently 40 | */ 41 | 'persistently' => false, 42 | 43 | /* 44 | * The date for mat for the view. 45 | */ 46 | 'date_format' => 'Y-m-d H:i:s', 47 | 48 | /* 49 | * Please define the authentication data for using the super-user options. 50 | */ 51 | 'authentication' => array( 52 | 'username' => 'admin', 53 | 'password' => 'dba', 54 | ), 55 | 56 | ); 57 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gjerokrsteski/php-dba-cache/c54311733c9e0129be1a769fdb684d6b0a1d4a18/app/favicon.ico -------------------------------------------------------------------------------- /app/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gjerokrsteski/php-dba-cache/c54311733c9e0129be1a769fdb684d6b0a1d4a18/app/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /app/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gjerokrsteski/php-dba-cache/c54311733c9e0129be1a769fdb684d6b0a1d4a18/app/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /app/index.php: -------------------------------------------------------------------------------- 1 | put(uniqid('test_'), (object)array(rand(1, 100)), 2); 30 | } 31 | 32 | /** 33 | * pretty printer for byte values. 34 | * 35 | * @param $size 36 | * 37 | * @return string 38 | */ 39 | function bsize($size) 40 | { 41 | $bytes = ''; 42 | 43 | foreach (array('', 'K', 'M', 'G') as $bytes) { 44 | if ($size < 1024) { 45 | break; 46 | } 47 | $size /= 1024; 48 | } 49 | 50 | return sprintf("%5.1f %sBytes", $size, $bytes); 51 | } 52 | 53 | /** 54 | * @param $check 55 | * @param $msg 56 | */ 57 | function flash_msg(&$check, $msg) 58 | { 59 | if (isset($check) && $check === true) { 60 | echo '
' . $msg . '
'; 61 | } elseif (isset($check) && $check === false) { 62 | echo '
NO! ' . $msg . '
'; 63 | } 64 | } 65 | 66 | // retrieve an cache and a cache-sweeper. 67 | try { 68 | list($cache, $sweep) = factory($config); 69 | } catch (Exception $exception) { 70 | die($exception->getMessage()); 71 | } 72 | 73 | // load the configuration at the global namespace. 74 | extract($config); 75 | 76 | // make a list of all the available handlers. 77 | $available_handlers = $handler_in_use = ''; 78 | foreach (dba_handlers(true) as $handler_name => $handler_version) { 79 | $handler_version = str_replace('$', '', $handler_version); 80 | if ($handler == $handler_name) { 81 | $handler_in_use = "$handler_name: $handler_version
"; 82 | continue; 83 | } 84 | $available_handlers .= "$handler_name: $handler_version
"; 85 | } 86 | 87 | // compute the user authentication. 88 | $authenticated = false; 89 | if (isset($_POST['login']) || isset($_SERVER['PHP_AUTH_USER'])) { 90 | if (!isset($_SERVER['PHP_AUTH_USER']) || 91 | !isset($_SERVER['PHP_AUTH_PW']) || 92 | $_SERVER['PHP_AUTH_USER'] != $authentication['username'] || 93 | $_SERVER['PHP_AUTH_PW'] != $authentication['password'] 94 | ) { 95 | header("WWW-Authenticate: Basic realm=\"PHP DBA Cache Login\""); 96 | header("HTTP/1.0 401 Unauthorized"); 97 | exit; 98 | } 99 | $authenticated = true; 100 | } 101 | 102 | 103 | if (isset($_POST['create-test-entry'])) { 104 | $create_test_entry = put($cache); 105 | } 106 | 107 | if (isset($_POST['optimize'])) { 108 | $optimize = @dba_optimize($cache->getDba()); 109 | } 110 | 111 | if (isset($_POST['synchronize'])) { 112 | $synchronize = @dba_sync($cache->getDba()); 113 | } 114 | 115 | if ($authenticated && isset($_POST['delete-old'])) { 116 | $delete_old = true; 117 | $sweep->old(); 118 | } 119 | 120 | if ($authenticated && isset($_POST['delete-all'])) { 121 | try { 122 | $delete_all = $sweep->flush(); 123 | } catch (\RuntimeException $re) { 124 | $delete_all = false; 125 | } 126 | 127 | list($cache, $sweep) = factory($config); 128 | put($cache); 129 | } 130 | 131 | // find the host-name 132 | $host = php_uname('n'); 133 | if ($host) { 134 | $host = '(' . $host . ')'; 135 | } 136 | if (isset($_SERVER['SERVER_ADDR'])) { 137 | $host .= ' (' . $_SERVER['SERVER_ADDR'] . ')'; 138 | } 139 | 140 | clearstatcache(); 141 | $file_info = new \SplFileInfo($file); 142 | ?> 143 | 144 | 145 | 146 | 147 | PHP DBA Cache Monitor by Gjero Krsteski 148 | 149 | 150 | 151 | 152 | 158 | 159 | 160 | 163 | 164 | 165 | 166 | 167 | 168 | 199 |
200 | 201 |

The php-dba-cache uses the database (dbm-style) abstraction layer to store your PHP data. It depends on 202 | the free space of your disk.

203 | 204 |
205 | 206 | 207 |

General Information

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 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 |
DBA Handler In Use
Available DBA Handlers
DBA Cache FilegetStorage() ?>
PHP Version
DBA Host
Server Software
Start TimegetCTime()) ?>
Last Modified TimegetMTime()) ?>
251 |
252 | 253 |
254 | 255 | 256 |

Memory Usage

257 | 258 |
259 |
260 |
261 |

getSize()) ?>

262 | 263 |

Cache file in use size

264 |
265 |
266 |
267 |
268 |

getPath())) ?>

269 | 270 |

Cache directory free size

271 |
272 |
273 |
274 |
275 |

getPath())) ?>

276 | 277 |

Cache directory total size

278 |
279 |
280 |
281 | 282 |
283 | 284 |
285 | 286 | 287 |

Tune Cache

288 | 289 | 293 | 294 |

If you add-remove-substitute keys with data having different content length, 295 | the db continues to grow, wasting space. Sometimes it is necessary, to optimize or synchronize the db in 296 | order to remove unused data from the db itself. 297 |

298 | 299 | 300 | 301 | 302 |
303 | 304 | 305 | 306 | 307 | 310 | 314 | 315 | 316 | 317 | 320 | 326 | 327 | 328 | 329 |
308 | 309 | 311 |

Optimize a database, which usually consists of eliminating gaps between records 312 | created by deletes.

313 |
318 | 319 |

Synchronize the view of the database in memory and its image 321 | on the disk. 322 | As you insert records, they may be cached in memory by the underlying engine. 323 | Other processes reading from the database will not see these new records until 324 | synchronization.

325 |
330 | 331 |
332 | 333 |
334 | 335 |
336 | 337 | 338 |

Cache Entries

339 | 340 | 345 | 346 |

Sometimes it is necessary to sweep the cache from old entries or to flush it.

347 | 348 |
349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | erasable()) : ?> 357 | 358 | 359 | 360 | 361 | 362 | 363 |
364 | 365 |
366 | 367 |

368 | Having trouble with PHP DBA Cache Monitor? Please contact gjero@krsteski.de and we’ll help you to sort it out. 370 | Because this GUI development and source control is done through GitHub, anyone is able to make contributions to 371 | it. 372 | Anyone can fix bugs and add features. Fork 373 | it here! 374 |

375 | 376 |
377 | 378 | 379 | 380 | 381 | -------------------------------------------------------------------------------- /bootstrap.php: -------------------------------------------------------------------------------- 1 | '/Cache.php', 21 | 'PhpDbaCache\\Pack' => '/Pack.php', 22 | 'PhpDbaCache\\Sweep' => '/Sweep.php', 23 | 'PhpDbaCache\\Capsule' => '/Capsule.php', 24 | ); 25 | 26 | if (isset($classes[$class])) { 27 | require BASE_PATH . '/src' . $classes[$class]; 28 | } 29 | 30 | return false; 31 | } 32 | ); 33 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "gjerokrsteski/php-dba-cache", 3 | "description" : "Create a caching with the PHP Database (dbm-style) Abstraction Layer to cache your objects, strings, integers or arrays", 4 | "type" : "library", 5 | "license" : "BSD", 6 | "homepage" : "http://gjerokrsteski.github.io/php-dba-cache/", 7 | "keywords" : ["dba", "cache", "storage", "php", "caching"], 8 | "support" : { 9 | "email" : "gjero@krsteski.de", 10 | "source" : "https://github.com/gjerokrsteski/php-dba-cache" 11 | }, 12 | "authors" : [ 13 | { 14 | "name" : "Gjero Krsteski", 15 | "email" : "gjero@krsteski.de", 16 | "homepage" : "http://krsteski.de/", 17 | "role" : "Main Developer" 18 | } 19 | ], 20 | "require" : { 21 | "php" : ">=5.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "e9416d2df2a41d5ba9edc05c4e772190", 8 | "content-hash": "b4d44f3760755f1d8e6e06855a360b08", 9 | "packages": [], 10 | "packages-dev": [], 11 | "aliases": [], 12 | "minimum-stability": "stable", 13 | "stability-flags": [], 14 | "prefer-stable": false, 15 | "prefer-lowest": false, 16 | "platform": { 17 | "php": ">=5.4" 18 | }, 19 | "platform-dev": [] 20 | } 21 | -------------------------------------------------------------------------------- /make-million.php: -------------------------------------------------------------------------------- 1 | put($key, $value, rand(1, 21600)) . PHP_EOL; 31 | } 32 | 33 | $cache->closeDba(); 34 | 35 | die('END'); 36 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | ./tests 22 | 23 | 24 | 25 | 26 | 27 | ./src 28 | 29 | bootstrap.core.php 30 | 31 | 32 | 33 | 34 | 35 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/Cache.php: -------------------------------------------------------------------------------- 1 | dba = (true === $persistently) 78 | ? @dba_popen($file, $mode, $handler) 79 | : @dba_open($file, $mode, $handler); 80 | 81 | if ($this->dba === false) { 82 | $err = error_get_last(); 83 | throw new \RuntimeException($err['message']); 84 | } 85 | 86 | $this->storage = $file; 87 | $this->handler = $handler; 88 | } 89 | 90 | /** 91 | * Closes an open dba resource 92 | * 93 | * @return void 94 | */ 95 | public function __destruct() 96 | { 97 | $this->closeDba(); 98 | } 99 | 100 | /** 101 | * @param string $key 102 | * @param mixed $value 103 | * @param int|bool $ltime Lifetime in seconds otherwise cache forever. 104 | * 105 | * @return bool 106 | */ 107 | public function put($key, $value, $ltime = false) 108 | { 109 | try { 110 | $value = Pack::wrap($value, $ltime); 111 | } catch (\RuntimeException $ret) { 112 | return false; 113 | } 114 | 115 | if (true === $this->has($key)) { 116 | return dba_replace($key, $value, $this->dba); 117 | } 118 | 119 | return dba_insert($key, $value, $this->dba); 120 | } 121 | 122 | /** 123 | * @param string $key 124 | * @param mixed $value 125 | * 126 | * @return bool 127 | */ 128 | public function forever($key, $value) 129 | { 130 | return $this->put($key, $value, false); 131 | } 132 | 133 | /** 134 | * @param string $key 135 | * 136 | * @return bool|object 137 | */ 138 | public function get($key) 139 | { 140 | $res = $this->fetch($key); 141 | 142 | if (false === $res) { 143 | return false; 144 | } 145 | 146 | if (false === $res->ltime || (microtime(true) - $res->mtime) < $res->ltime) { 147 | return $res->object; 148 | } 149 | 150 | $this->delete($key); 151 | 152 | return false; 153 | } 154 | 155 | /** 156 | * @return string 157 | */ 158 | public function getStorage() 159 | { 160 | return $this->storage; 161 | } 162 | 163 | /** 164 | * @param string $key 165 | * 166 | * @return Capsule|boolean 167 | */ 168 | public function fetch($key) 169 | { 170 | $fetched = dba_fetch($key, $this->dba); 171 | 172 | if (false === $fetched) { 173 | return false; 174 | } 175 | 176 | try { 177 | return Pack::unwrap($fetched); 178 | } catch (\RuntimeException $ret) { 179 | return false; 180 | } 181 | } 182 | 183 | /** 184 | * @param string $key 185 | * 186 | * @return boolean 187 | */ 188 | public function delete($key) 189 | { 190 | if (false === is_resource($this->dba)) { 191 | return false; 192 | } 193 | 194 | if ($this->erasable()) { 195 | return dba_delete($key, $this->dba); 196 | } 197 | 198 | return true; 199 | } 200 | 201 | /** 202 | * @param string $key 203 | * 204 | * @return boolean 205 | */ 206 | public function has($key) 207 | { 208 | return dba_exists($key, $this->dba); 209 | } 210 | 211 | /** 212 | * Close the handler. 213 | */ 214 | public function closeDba() 215 | { 216 | if ($this->dba) { 217 | dba_close($this->dba); 218 | $this->dba = null; 219 | } 220 | } 221 | 222 | /** 223 | * @return resource 224 | */ 225 | public function getDba() 226 | { 227 | return $this->dba; 228 | } 229 | 230 | /** 231 | * @return \ArrayObject of stored cache ids (string). 232 | */ 233 | public function getIds() 234 | { 235 | $ids = new \ArrayObject(); 236 | $dba = $this->getDba(); 237 | $key = dba_firstkey($dba); 238 | 239 | while ($key !== false && $key !== null) { 240 | $ids->offsetSet(null, $key); 241 | $key = dba_nextkey($dba); 242 | } 243 | 244 | return $ids; 245 | } 246 | 247 | /** 248 | * Return an array of metadata for the given cache id. 249 | * 250 | * - expire = the expire timestamp 251 | * - mtime = timestamp of last modification time 252 | * 253 | * @param string $key cache id 254 | * 255 | * @return array|boolean 256 | */ 257 | public function getMetaData($key) 258 | { 259 | $res = $this->fetch($key); 260 | 261 | if ($res instanceof Capsule) { 262 | return array( 263 | 'expire' => $res->mtime + $res->ltime, 264 | 'mtime' => $res->mtime, 265 | ); 266 | } 267 | 268 | return false; 269 | } 270 | 271 | /** 272 | * Ensures if a single cache-item can be deleted. 273 | * 274 | * @param null|string $handler 275 | * 276 | * @return bool 277 | */ 278 | public function erasable($handler = null) 279 | { 280 | $handler = (!$handler) ? $this->handler : $handler; 281 | 282 | return in_array($handler, array('inifile', 'gdbm', 'qdbm', 'db4'), true); 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /src/Capsule.php: -------------------------------------------------------------------------------- 1 | fake = $fake; 54 | $this->ltime = $ltime; 55 | $this->mtime = microtime(true); 56 | $this->object = $object; 57 | $this->type = get_class($object); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Pack.php: -------------------------------------------------------------------------------- 1 | object = $object->asXml(); 32 | } 33 | 34 | if (false === ($res = @serialize($capsule))) { 35 | $err = error_get_last(); 36 | throw new \RuntimeException($err['message']); 37 | } 38 | 39 | return $res; 40 | } 41 | 42 | /** 43 | * @param $object 44 | * 45 | * @return Capsule 46 | * @throws \RuntimeException If problems on un-serializing 47 | */ 48 | public static function unwrap($object) 49 | { 50 | $serialized = (false !== ($capsule = @unserialize(trim($object)))); 51 | 52 | if (!$serialized) { 53 | $err = error_get_last(); 54 | throw new \RuntimeException($err['message']); 55 | } 56 | 57 | if (true === $capsule->fake) { 58 | if (isset($capsule->object->scalar)) { 59 | $capsule->object = $capsule->object->scalar; 60 | } else { 61 | $capsule->object = (array)$capsule->object; 62 | } 63 | } 64 | 65 | if ($capsule->type == 'SimpleXMLElement') { 66 | $capsule->object = simplexml_load_string($capsule->object); 67 | } 68 | 69 | return $capsule; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Sweep.php: -------------------------------------------------------------------------------- 1 | cache = $cache; 23 | } 24 | 25 | /** 26 | * Remove all cache entries. 27 | * 28 | * @return void 29 | */ 30 | public function all() 31 | { 32 | $this->process(); 33 | } 34 | 35 | /** 36 | * Remove too old cache entries. 37 | * 38 | * @return void 39 | */ 40 | public function old() 41 | { 42 | $this->process(false); 43 | } 44 | 45 | /** 46 | * Internal cleaning process. 47 | * 48 | * @param boolean $cleanAll 49 | * 50 | * @return void 51 | */ 52 | protected function process($cleanAll = true) 53 | { 54 | $key = dba_firstkey($this->cache->getDba()); 55 | 56 | while ($key !== false && $key !== null) { 57 | if (true === $cleanAll) { 58 | $this->cache->delete($key); 59 | } else { 60 | $this->cache->get($key); 61 | } 62 | 63 | $key = dba_nextkey($this->cache->getDba()); 64 | } 65 | 66 | dba_optimize($this->cache->getDba()); 67 | } 68 | 69 | /** 70 | * Flush the whole storage. 71 | * 72 | * @throws \RuntimeException If can not flush file. 73 | * @return bool 74 | */ 75 | public function flush() 76 | { 77 | $file = $this->cache->getStorage(); 78 | 79 | if (file_exists($file)) { 80 | // close the dba file before delete 81 | // and reopen on next use 82 | $this->cache->closeDba(); 83 | 84 | if (!@unlink($file)) { 85 | throw new \RuntimeException("can not flush file '$file'"); 86 | } 87 | } 88 | 89 | return true; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /tests/CacheDefaultTest.php: -------------------------------------------------------------------------------- 1 | generalCacheFile = dirname(__FILE__) . '/_drafts/test-cache.flatfile'; 13 | $this->generalHandler = 'flatfile'; 14 | $this->generalMode = 'c-'; 15 | } 16 | 17 | public function testWriteAndReadWithoutPersistentConnection() 18 | { 19 | try { 20 | $cache = new \PhpDbaCache\Cache( 21 | dirname(__FILE__) . '/_drafts/test-cache-pers.flatfile', 'flatfile', 'c-', false 22 | ); 23 | } catch (\RuntimeException $e) { 24 | $this->markTestSkipped($e->getMessage()); 25 | } 26 | 27 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cache); 28 | 29 | $cache->put($this->identifier, array('rambo' => 123)); 30 | $cache->get($this->identifier); 31 | 32 | $res = $cache->get($this->identifier); 33 | 34 | $this->assertInternalType('array', $res); 35 | $this->assertEquals($res, array('rambo' => 123)); 36 | } 37 | 38 | public function testHandlingWithSimpleXMLElementIntoFlatfileHandler() 39 | { 40 | $identifier = md5(uniqid()); 41 | 42 | // make a xml-file of 1000 nodes. 43 | $string = " 44 | "; 45 | for ($i = 1; $i <= 100; $i++) { 46 | $string .= " 47 | Let us cache 48 | Joe 49 | Jane 50 | Some content here 51 | "; 52 | } 53 | $string .= ""; 54 | 55 | $simplexml = simplexml_load_string( 56 | $string, 'SimpleXMLElement', LIBXML_NOERROR | LIBXML_NOWARNING | LIBXML_NONET 57 | ); 58 | 59 | $path = dirname(__FILE__) . '/_drafts/test-cache-with-simplexml.flatfile'; 60 | 61 | try { 62 | $cache = new \PhpDbaCache\Cache($path); 63 | } catch (\RuntimeException $e) { 64 | $this->markTestSkipped($e->getMessage()); 65 | } 66 | 67 | $cache->put($identifier, $simplexml); 68 | $object_from_cache = $cache->get($identifier); 69 | $cache->closeDba(); 70 | 71 | $this->assertEquals($simplexml->asXML(), $object_from_cache->asXML()); 72 | 73 | @unlink($path); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/DummyFixtures.php: -------------------------------------------------------------------------------- 1 | moo = new Dummy1(); 24 | } 25 | } -------------------------------------------------------------------------------- /tests/Handlers/CdbReadTest.php: -------------------------------------------------------------------------------- 1 | generalCacheFile = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache-serialised.cdb'; 13 | $this->generalHandler = 'cdb'; 14 | $this->generalMode = 'r'; 15 | $this->identifier = md5('test123'); 16 | } 17 | 18 | public function testPuttingForever() 19 | { 20 | $this->markTestSkipped('sorry - this handler is not able to write'); 21 | } 22 | 23 | 24 | public function testIfNoDatabaseExists() 25 | { 26 | $path = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/simple-xml-test-cache-on-cdb.db'; 27 | try { 28 | new \PhpDbaCache\Cache( 29 | $path, "cdb", "n" 30 | ); 31 | @unlink($path); 32 | } catch (\RuntimeException $e) { 33 | $this->markTestSkipped($e->getMessage()); 34 | } 35 | } 36 | 37 | public function testWithPersistentConnection() 38 | { 39 | $path = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache-serialised.cdb'; 40 | 41 | // create handler to read. 42 | try { 43 | $cacheRead = new \PhpDbaCache\Cache($path, 'cdb', 'r'); 44 | } catch (\RuntimeException $e) { 45 | $this->markTestSkipped($e->getMessage()); 46 | } 47 | 48 | $this->assertTrue($cacheRead->has(md5('test123'))); 49 | 50 | $this->assertInstanceOf('\stdClass', $cacheRead->get(md5('test123'))); 51 | 52 | $cacheRead->closeDba(); 53 | } 54 | 55 | public function testSameIdentifierTwiceTime() 56 | { 57 | $path = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache-keyed.cdb'; 58 | 59 | try { 60 | $cacheRead = new \PhpDbaCache\Cache($path, 'cdb', 'r'); 61 | } catch (\RuntimeException $e) { 62 | $this->markTestSkipped($e->getMessage()); 63 | } 64 | 65 | //check if data replaced. 66 | $this->assertEquals('data', $cacheRead->get('key')); 67 | 68 | $cacheRead->closeDba(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/Handlers/CdbWriteTest.php: -------------------------------------------------------------------------------- 1 | markTestSkipped('sorry - this handler is not able to read'); 12 | } 13 | 14 | public function testFetchingMetaData() 15 | { 16 | $this->markTestSkipped('sorry - this handler is not able to read'); 17 | } 18 | 19 | public function testWithPersistentConnection() 20 | { 21 | $path = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache-serialised.cdb'; 22 | 23 | // create handler to write. 24 | try { 25 | $cacheMake = new \PhpDbaCache\Cache($path, 'cdb_make', 'n'); 26 | } catch (\RuntimeException $e) { 27 | $this->markTestSkipped($e->getMessage()); 28 | } 29 | 30 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cacheMake); 31 | 32 | $this->assertTrue($cacheMake->put(md5('test123'), $this->testObject)); 33 | 34 | // for read we close the handler. 35 | $cacheMake->closeDba(); 36 | } 37 | 38 | public function testPutSameIdentifierTwiceTime() 39 | { 40 | $path = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache-keyed.cdb'; 41 | 42 | try { 43 | $cacheMake = new \PhpDbaCache\Cache($path, 'cdb_make', 'n'); 44 | } catch (\RuntimeException $e) { 45 | $this->markTestSkipped($e->getMessage()); 46 | } 47 | 48 | // first insert. 49 | $this->assertTrue($cacheMake->put('key', 'data')); 50 | 51 | // replace instead of insert. 52 | $this->assertTrue($cacheMake->put('key', 'data-2')); 53 | 54 | // for read we close the handler. 55 | $cacheMake->closeDba(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tests/Handlers/Db4Test.php: -------------------------------------------------------------------------------- 1 | generalCacheFile = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache.db4'; 14 | $this->generalHandler = 'db4'; 15 | } 16 | 17 | public function testWithoutPersistentConnection() 18 | { 19 | try { 20 | $cache = new \PhpDbaCache\Cache($this->generalCacheFile, $this->generalHandler, 'c', false); 21 | } catch (\RuntimeException $e) { 22 | $this->markTestSkipped($e->getMessage()); 23 | } 24 | 25 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cache); 26 | 27 | $cache->put($this->identifier, $this->testObject); 28 | 29 | $this->assertInstanceOf('\stdClass', $cache->get($this->identifier)); 30 | 31 | $cache->closeDba(); 32 | } 33 | 34 | /** 35 | * @depends Db4Test::testWithoutPersistentConnection 36 | */ 37 | public function testOracleBerkeleyDb4HandlerBeSupportedWithPersistantConnection() 38 | { 39 | try { 40 | $cache = new \PhpDbaCache\Cache($this->generalCacheFile, $this->generalHandler); 41 | } catch (\RuntimeException $e) { 42 | $this->markTestSkipped($e->getMessage()); 43 | } 44 | 45 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cache); 46 | 47 | $cache->put($this->identifier, $this->testObject); 48 | 49 | $this->assertInstanceOf('\stdClass', $cache->get($this->identifier)); 50 | 51 | $cache->closeDba(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/Handlers/FlatfileTest.php: -------------------------------------------------------------------------------- 1 | generalCacheFile = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache.flatfile'; 14 | $this->generalHandler = 'flatfile'; 15 | $this->generalMode = 'c-'; 16 | } 17 | 18 | public function testWriteAndReadWithoutPersistentConnection() 19 | { 20 | try { 21 | $cache = new \PhpDbaCache\Cache( 22 | dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache-pers.flatfile', 'flatfile', 'c-', false 23 | ); 24 | } catch (\RuntimeException $e) { 25 | $this->markTestSkipped($e->getMessage()); 26 | } 27 | 28 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cache); 29 | 30 | $cache->put($this->identifier, array('rambo' => 123)); 31 | 32 | $res = $cache->get($this->identifier); 33 | 34 | $this->assertInternalType('array', $res); 35 | $this->assertEquals($res, array('rambo' => 123)); 36 | } 37 | 38 | public function testHandlingWithSimpleXMLElementIntoFlatfileHandler() 39 | { 40 | $identifier = md5(uniqid()); 41 | 42 | // make a xml-file of 1000 nodes. 43 | $string = " 44 | "; 45 | for ($i = 1; $i <= 100; $i++) { 46 | $string .= " 47 | Let us cache 48 | Joe 49 | Jane 50 | Some content here 51 | "; 52 | } 53 | $string .= ""; 54 | 55 | $simplexml = simplexml_load_string( 56 | $string, 'SimpleXMLElement', LIBXML_NOERROR | LIBXML_NOWARNING | LIBXML_NONET 57 | ); 58 | 59 | $path = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache-with-simplexml.flatfile'; 60 | 61 | try { 62 | $cache = new \PhpDbaCache\Cache($path); 63 | } catch (\RuntimeException $e) { 64 | $this->markTestSkipped($e->getMessage()); 65 | } 66 | 67 | $cache->put($identifier, $simplexml); 68 | $object_from_cache = $cache->get($identifier); 69 | $cache->closeDba(); 70 | 71 | $this->assertEquals($simplexml->asXML(), $object_from_cache->asXML()); 72 | 73 | @unlink($path); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/Handlers/GdbmTest.php: -------------------------------------------------------------------------------- 1 | generalCacheFile = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache.gdbm'; 13 | $this->generalHandler = 'gdbm'; 14 | } 15 | 16 | public function testWriteAndReadWithoutPersistentConnection() 17 | { 18 | try { 19 | $cache = new \PhpDbaCache\Cache( 20 | dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache.gdbm', 'gdbm', 'c', false 21 | ); 22 | } catch (\RuntimeException $e) { 23 | $this->markTestSkipped($e->getMessage()); 24 | } 25 | 26 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cache); 27 | 28 | $cache->put($this->identifier, $this->testObject); 29 | 30 | $this->assertInstanceOf('\stdClass', $cache->get($this->identifier)); 31 | } 32 | 33 | /** 34 | * @depends CacheHandlersTest::testSupportWithoutPersistentConnection 35 | */ 36 | public function testWriteAndReaddWithPersistentConnection() 37 | { 38 | try { 39 | $cache = new \PhpDbaCache\Cache(dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache.gdbm', 'gdbm'); 40 | } catch (\RuntimeException $e) { 41 | $this->markTestSkipped($e->getMessage()); 42 | } 43 | 44 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cache); 45 | 46 | $cache->put($this->identifier, $this->testObject); 47 | 48 | $this->assertInstanceOf('\stdClass', $cache->get($this->identifier)); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /tests/Handlers/InifileTest.php: -------------------------------------------------------------------------------- 1 | generalCacheFile = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache.inifile'; 13 | $this->generalHandler = 'inifile'; 14 | } 15 | 16 | public function testWriteAndReadWithoutPersistentConnection() 17 | { 18 | try { 19 | $cache = new \PhpDbaCache\Cache( 20 | dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache.inifile', 'inifile', 'c', false 21 | ); 22 | } catch (\RuntimeException $e) { 23 | $this->markTestSkipped($e->getMessage()); 24 | } 25 | 26 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cache); 27 | 28 | $cache->put($this->identifier, array('rambo' => 123)); 29 | 30 | $res = $cache->get($this->identifier); 31 | 32 | $this->assertInternalType('array', $res); 33 | $this->assertEquals($res, array('rambo' => 123)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/Handlers/QdbmTest.php: -------------------------------------------------------------------------------- 1 | generalCacheFile = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache.qdbm'; 15 | $this->generalHandler = 'qdbm'; 16 | } 17 | 18 | public function testWriteAndReadWithoutPersistentConnection() 19 | { 20 | try { 21 | $cache = new \PhpDbaCache\Cache( 22 | dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache.qdbm', 'qdbm', 'c', false 23 | ); 24 | } catch (\RuntimeException $e) { 25 | $this->markTestSkipped($e->getMessage()); 26 | } 27 | 28 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cache); 29 | 30 | $cache->put($this->identifier, $this->testObject); 31 | 32 | $this->assertInstanceOf('\stdClass', $cache->get($this->identifier)); 33 | } 34 | 35 | /** 36 | * @depends CacheHandlersTest::testSupportWithoutPersistentConnection 37 | */ 38 | public function testWriteAndReaddWithPersistentConnection() 39 | { 40 | try { 41 | $cache = new \PhpDbaCache\Cache(dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/test-cache.qdbm', 'qdbm'); 42 | } catch (\RuntimeException $e) { 43 | $this->markTestSkipped($e->getMessage()); 44 | } 45 | 46 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cache); 47 | 48 | $cache->put($this->identifier, $this->testObject); 49 | 50 | $this->assertInstanceOf('\stdClass', $cache->get($this->identifier)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/Handlers/TestCase.php: -------------------------------------------------------------------------------- 1 | title = 'Zweiundvierz'; 42 | $stdClass->from = 'Joe'; 43 | $stdClass->to = 'Jane'; 44 | $stdClass->body = new \Fixtures\Dummy(); 45 | 46 | $this->testObject = $stdClass; 47 | $this->identifier = md5('stdClass' . time()); 48 | $this->generalCacheFile = dirname(dirname(dirname(__FILE__))) . '/tests/_drafts/flatfile.db'; 49 | } 50 | 51 | /** 52 | * Cleans up the environment after running a test. 53 | */ 54 | protected function tearDown() 55 | { 56 | unset($this->testObject, $this->identifier); 57 | parent::tearDown(); 58 | } 59 | 60 | public function testPuttingForever() 61 | { 62 | try { 63 | $cache = new \PhpDbaCache\Cache($this->generalCacheFile, $this->generalHandler, $this->generalMode); 64 | } catch (\RuntimeException $e) { 65 | $this->markTestSkipped($e->getMessage()); 66 | } 67 | 68 | $cache->forever('forever', array('forever' => 123)); 69 | 70 | $res = $cache->getIds(); 71 | 72 | $this->assertInstanceOf('\ArrayObject', $res, 'no instance of ArrayObject'); 73 | $this->assertNotEmpty($res->getArrayCopy()); 74 | 75 | $cache->closeDba(); 76 | } 77 | 78 | public function badHandlersProvider() 79 | { 80 | return array( 81 | array('bad-bad-handler'), 82 | array(123), 83 | array(1), 84 | array('0'), 85 | array(' '), 86 | array(null), 87 | array(true), 88 | array(false), 89 | ); 90 | } 91 | 92 | /** 93 | * @expectedException \RuntimeException 94 | * @dataProvider badHandlersProvider 95 | */ 96 | public function testIfBadHandlerGiven() 97 | { 98 | new \PhpDbaCache\Cache($this->generalCacheFile, 'bad-bad-handler'); 99 | } 100 | 101 | /** 102 | * @expectedException \RuntimeException 103 | */ 104 | public function testIfBadDbFileGiven() 105 | { 106 | new \PhpDbaCache\Cache('/path/to/bad-bad-file.db', $this->generalHandler, 'r'); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /tests/PackTest.php: -------------------------------------------------------------------------------- 1 | assertNotNull(new \PhpDbaCache\Pack()); 12 | } 13 | 14 | public function objectsProvider() 15 | { 16 | $stdClass = new \stdClass(); 17 | $stdClass->title = 'Zweiundvierz'; 18 | $stdClass->from = 'Joe'; 19 | $stdClass->to = 'Jane'; 20 | $stdClass->body = new \Fixtures\Dummy2(); 21 | 22 | return array( 23 | array(new \Fixtures\Dummy2()), 24 | array($stdClass), 25 | array(new \ZipArchive()), 26 | array(new \XMLReader()), 27 | array('i am a string'), 28 | array(123456789), 29 | array( 30 | array( 31 | 'boo' => 1, 32 | 'foo' => 2, 33 | 'laa' => 3 34 | ) 35 | ) 36 | ); 37 | } 38 | 39 | /** 40 | * @depends PackTest::testCreatingNewObject 41 | * @dataProvider objectsProvider 42 | */ 43 | public function testSerializingSomeObjects($object) 44 | { 45 | \PhpDbaCache\Pack::wrap($object); 46 | } 47 | 48 | /** 49 | * @depends PackTest::testCreatingNewObject 50 | * @depends PackTest::testSerializingSomeObjects 51 | * @dataProvider objectsProvider 52 | */ 53 | public function testUnserializingSomeObjectsAndCompareThemEachOther($object) 54 | { 55 | $serialized = \PhpDbaCache\Pack::wrap($object); 56 | 57 | $userItem = \PhpDbaCache\Pack::unwrap($serialized); 58 | 59 | $this->assertEquals($object, $userItem->object); 60 | } 61 | 62 | public static function provideSerializedTestData() 63 | { 64 | return array( 65 | array(array(21.123, 21.124, 2, 0)), 66 | array((object)array('eee' => 21.123, 'asdfasdf' => 21.124)), 67 | array(new \Fixtures\Dummy2()), 68 | array(new \Fixtures\Dummy1()), 69 | array(new \Fixtures\Dummy()), 70 | ); 71 | } 72 | 73 | /** 74 | * @dataProvider provideSerializedTestData 75 | */ 76 | public function testIfCanBePackedIn($data) 77 | { 78 | $this->assertInternalType( 79 | 80 | 'string', 81 | 82 | \PhpDbaCache\Pack::wrap($data), 83 | 84 | 'problem on asserting that ' . print_r($data, true) . ' can be serialized' 85 | 86 | ); 87 | } 88 | 89 | public static function provideNotAndBadSerializedTestData() 90 | { 91 | return array( 92 | array(null), 93 | array(''), 94 | array(' '), 95 | array('0'), 96 | array(0), 97 | array(true), 98 | array('O:7:"Capsule":5:1 :4:"type";'), 99 | array('{s:7:"forever";i:123;'), 100 | array(array('eee' => 21.123, 'asdfasdf' => 21.124)), 101 | array(array('eee' => 21.123, 'asdfasdf' => 21.124)), 102 | ); 103 | } 104 | 105 | /** 106 | * @dataProvider provideNotAndBadSerializedTestData 107 | * @expectedException RuntimeException 108 | */ 109 | public function testFailsIfCanNotBePackedOut($data) 110 | { 111 | \PhpDbaCache\Pack::unwrap($data); 112 | } 113 | } 114 | 115 | -------------------------------------------------------------------------------- /tests/SweepTest.php: -------------------------------------------------------------------------------- 1 | cache = new \PhpDbaCache\Cache($path, 'gdbm'); 23 | } catch (\RuntimeException $e) { 24 | $this->markTestSkipped($e->getMessage()); 25 | } 26 | } 27 | 28 | /** 29 | * Cleans up the environment after running a test. 30 | */ 31 | protected function tearDown() 32 | { 33 | if ($this->cache) { 34 | $this->cache->closeDba(); 35 | } 36 | parent::tearDown(); 37 | } 38 | 39 | 40 | #tests 41 | 42 | 43 | public function testCreatingNewObject() 44 | { 45 | $sweep = new \PhpDbaCache\Sweep($this->cache); 46 | 47 | $this->assertInstanceOf('\PhpDbaCache\Sweep', $sweep); 48 | } 49 | 50 | /** 51 | * @depends SweepTest::testCreatingNewObject 52 | */ 53 | public function testCleanAllFromTheGarbageCollection() 54 | { 55 | // prepare data. 56 | $stdClass = new \stdClass(); 57 | $stdClass->title = 'Hi firend, i am cached.'; 58 | $stdClass->from = 'Joe'; 59 | $stdClass->to = 'Hover'; 60 | $stdClass->body = 'Yes, it works!'; 61 | 62 | // put some data to the cache. 63 | $this->cache->put(md5('stdClass'), $stdClass, 1); 64 | $this->cache->put(md5('ZipArchive'), new \ZipArchive(), 1); 65 | $this->cache->put(md5('XMLReader'), new \XMLReader(), 1); 66 | 67 | sleep(1); 68 | 69 | $sweep = new \PhpDbaCache\Sweep($this->cache); 70 | $sweep->all(); 71 | 72 | $this->assertFalse($this->cache->get(md5('stdClass'))); 73 | 74 | $this->assertFalse($this->cache->get(md5('ZipArchive'))); 75 | 76 | $this->assertFalse($this->cache->get(md5('XMLReader'))); 77 | } 78 | 79 | /** 80 | * @depends SweepTest::testCreatingNewObject 81 | */ 82 | public function testCleanTheGarbageCollectionByNotSuitableExpirationTime() 83 | { 84 | // prepare data. 85 | $stdClass = new \stdClass(); 86 | $stdClass->title = 'I am cached.'; 87 | $stdClass->from = 'Mike'; 88 | $stdClass->to = 'Gates'; 89 | $stdClass->body = 'Yes, it works fine!'; 90 | 91 | // put some data to the cache. 92 | $this->cache->put(md5('stdClass'), $stdClass); 93 | $this->cache->put(md5('ZipArchive'), new \ZipArchive()); 94 | $this->cache->put(md5('XMLReader'), new \XMLReader()); 95 | 96 | // wait one second to force the expiration-time-calculation. 97 | sleep(1); 98 | 99 | $sweep = new \Sweep($this->cache); 100 | $sweep->old(); 101 | 102 | $this->assertInstanceOf('\PhpDbaCache\stdClass', $this->cache->get(md5('stdClass'))); 103 | $this->assertInstanceOf('\PhpDbaCache\ZipArchive', $this->cache->get(md5('ZipArchive'))); 104 | $this->assertInstanceOf('\PhpDbaCache\XMLReader', $this->cache->get(md5('XMLReader'))); 105 | } 106 | 107 | /** 108 | * Tests support for CDB - Tiny Constant Database. 109 | * CDB can not be deleted - clear garbage manually. 110 | */ 111 | public function testCleanGarbageCollectionOnCdbHandler() 112 | { 113 | $path = dirname(dirname(__FILE__)) . '/tests/_drafts/test-cache-cdb2.cdb'; 114 | 115 | // create cdb-handler to write. 116 | try { 117 | $cacheMake = new \Cache($path, 'cdb_make', 'n'); 118 | } catch (\RuntimeException $e) { 119 | $this->markTestSkipped($e->getMessage()); 120 | } 121 | 122 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cacheMake); 123 | 124 | $testIdentifier1 = md5('ZipArchive' . time()); 125 | $testIdentifier2 = md5('XMLReader' . time()); 126 | 127 | $this->assertTrue($cacheMake->put($testIdentifier1, new \ZipArchive())); 128 | $this->assertTrue($cacheMake->put($testIdentifier2, new \XMLReader())); 129 | 130 | // CacheGarbageCollector has no effect. 131 | $sweep = new \PhpDbaCache\Sweep($cacheMake); 132 | $sweep->all(); 133 | 134 | // deleting has no effect. 135 | $cacheMake->delete($testIdentifier1); 136 | $cacheMake->delete($testIdentifier2); 137 | 138 | // for read we close the handler. 139 | $cacheMake->closeDba(); 140 | 141 | // create cdb-handler to read. 142 | try { 143 | $cacheRead = new \PhpDbaCache\Cache($path, 'cdb', 'r'); 144 | } catch (\RuntimeException $e) { 145 | $this->markTestSkipped($e->getMessage()); 146 | } 147 | 148 | $this->assertTrue($cacheRead->has($testIdentifier1)); 149 | $this->assertTrue($cacheRead->has($testIdentifier2)); 150 | 151 | $this->assertInstanceOf('\PhpDbaCache\ZipArchive', $cacheRead->get($testIdentifier1)); 152 | $this->assertInstanceOf('\PhpDbaCache\XMLReader', $cacheRead->get($testIdentifier2)); 153 | 154 | $cacheRead->closeDba(); 155 | } 156 | 157 | /** 158 | * Tests support for DB4 - Oracle Berkeley DB 4. 159 | */ 160 | public function testCleanTheGarbageCollectionOnDb4Handler() 161 | { 162 | $path = dirname(dirname(__FILE__)) . '/tests/_drafts/test-cache.db4'; 163 | 164 | try { 165 | $cache = new \PhpDbaCache\Cache($path, 'db4', 'c', false); 166 | } catch (\RuntimeException $e) { 167 | $this->markTestSkipped($e->getMessage()); 168 | } 169 | 170 | $this->assertInstanceOf('\PhpDbaCache\Cache', $cache); 171 | 172 | $cache->put(md5('ZipArchive'), new \ZipArchive()); 173 | $cache->put(md5('XMLReader'), new \XMLReader()); 174 | 175 | $this->assertInstanceOf('\PhpDbaCache\ZipArchive', $cache->get(md5('ZipArchive'))); 176 | $this->assertInstanceOf('\PhpDbaCache\XMLReader', $cache->get(md5('XMLReader'))); 177 | 178 | $sweep = new \PhpDbaCache\Sweep($cache); 179 | $sweep->all(); 180 | 181 | $this->assertFalse($cache->get(md5('ZipArchive'))); 182 | $this->assertFalse($cache->get(md5('XMLReader'))); 183 | 184 | $cache->closeDba(); 185 | 186 | @unlink($path); 187 | } 188 | 189 | public function testUtilMethods() 190 | { 191 | $sweep = new \PhpDbaCache\Sweep($this->cache); 192 | 193 | $this->assertTrue($sweep->flush()); 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /tests/_drafts/test-cache-cdb2.cdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gjerokrsteski/php-dba-cache/c54311733c9e0129be1a769fdb684d6b0a1d4a18/tests/_drafts/test-cache-cdb2.cdb -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. 17 | * 18 | * $loader = new \Composer\Autoload\ClassLoader(); 19 | * 20 | * // register classes with namespaces 21 | * $loader->add('Symfony\Component', __DIR__.'/component'); 22 | * $loader->add('Symfony', __DIR__.'/framework'); 23 | * 24 | * // activate the autoloader 25 | * $loader->register(); 26 | * 27 | * // to enable searching the include path (eg. for PEAR packages) 28 | * $loader->setUseIncludePath(true); 29 | * 30 | * In this example, if you try to use a class in the Symfony\Component 31 | * namespace or one of its children (Symfony\Component\Console for instance), 32 | * the autoloader will first look for the class under the component/ 33 | * directory, and it will then fallback to the framework/ directory if not 34 | * found before giving up. 35 | * 36 | * This class is loosely based on the Symfony UniversalClassLoader. 37 | * 38 | * @author Fabien Potencier 39 | * @author Jordi Boggiano 40 | * @see http://www.php-fig.org/psr/psr-0/ 41 | * @see http://www.php-fig.org/psr/psr-4/ 42 | */ 43 | class ClassLoader 44 | { 45 | // PSR-4 46 | private $prefixLengthsPsr4 = array(); 47 | private $prefixDirsPsr4 = array(); 48 | private $fallbackDirsPsr4 = array(); 49 | 50 | // PSR-0 51 | private $prefixesPsr0 = array(); 52 | private $fallbackDirsPsr0 = array(); 53 | 54 | private $useIncludePath = false; 55 | private $classMap = array(); 56 | 57 | private $classMapAuthoritative = false; 58 | 59 | public function getPrefixes() 60 | { 61 | if (!empty($this->prefixesPsr0)) { 62 | return call_user_func_array('array_merge', $this->prefixesPsr0); 63 | } 64 | 65 | return array(); 66 | } 67 | 68 | public function getPrefixesPsr4() 69 | { 70 | return $this->prefixDirsPsr4; 71 | } 72 | 73 | public function getFallbackDirs() 74 | { 75 | return $this->fallbackDirsPsr0; 76 | } 77 | 78 | public function getFallbackDirsPsr4() 79 | { 80 | return $this->fallbackDirsPsr4; 81 | } 82 | 83 | public function getClassMap() 84 | { 85 | return $this->classMap; 86 | } 87 | 88 | /** 89 | * @param array $classMap Class to filename map 90 | */ 91 | public function addClassMap(array $classMap) 92 | { 93 | if ($this->classMap) { 94 | $this->classMap = array_merge($this->classMap, $classMap); 95 | } else { 96 | $this->classMap = $classMap; 97 | } 98 | } 99 | 100 | /** 101 | * Registers a set of PSR-0 directories for a given prefix, either 102 | * appending or prepending to the ones previously set for this prefix. 103 | * 104 | * @param string $prefix The prefix 105 | * @param array|string $paths The PSR-0 root directories 106 | * @param bool $prepend Whether to prepend the directories 107 | */ 108 | public function add($prefix, $paths, $prepend = false) 109 | { 110 | if (!$prefix) { 111 | if ($prepend) { 112 | $this->fallbackDirsPsr0 = array_merge( 113 | (array) $paths, 114 | $this->fallbackDirsPsr0 115 | ); 116 | } else { 117 | $this->fallbackDirsPsr0 = array_merge( 118 | $this->fallbackDirsPsr0, 119 | (array) $paths 120 | ); 121 | } 122 | 123 | return; 124 | } 125 | 126 | $first = $prefix[0]; 127 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 128 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 129 | 130 | return; 131 | } 132 | if ($prepend) { 133 | $this->prefixesPsr0[$first][$prefix] = array_merge( 134 | (array) $paths, 135 | $this->prefixesPsr0[$first][$prefix] 136 | ); 137 | } else { 138 | $this->prefixesPsr0[$first][$prefix] = array_merge( 139 | $this->prefixesPsr0[$first][$prefix], 140 | (array) $paths 141 | ); 142 | } 143 | } 144 | 145 | /** 146 | * Registers a set of PSR-4 directories for a given namespace, either 147 | * appending or prepending to the ones previously set for this namespace. 148 | * 149 | * @param string $prefix The prefix/namespace, with trailing '\\' 150 | * @param array|string $paths The PSR-4 base directories 151 | * @param bool $prepend Whether to prepend the directories 152 | * 153 | * @throws \InvalidArgumentException 154 | */ 155 | public function addPsr4($prefix, $paths, $prepend = false) 156 | { 157 | if (!$prefix) { 158 | // Register directories for the root namespace. 159 | if ($prepend) { 160 | $this->fallbackDirsPsr4 = array_merge( 161 | (array) $paths, 162 | $this->fallbackDirsPsr4 163 | ); 164 | } else { 165 | $this->fallbackDirsPsr4 = array_merge( 166 | $this->fallbackDirsPsr4, 167 | (array) $paths 168 | ); 169 | } 170 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 171 | // Register directories for a new namespace. 172 | $length = strlen($prefix); 173 | if ('\\' !== $prefix[$length - 1]) { 174 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 175 | } 176 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 177 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 178 | } elseif ($prepend) { 179 | // Prepend directories for an already registered namespace. 180 | $this->prefixDirsPsr4[$prefix] = array_merge( 181 | (array) $paths, 182 | $this->prefixDirsPsr4[$prefix] 183 | ); 184 | } else { 185 | // Append directories for an already registered namespace. 186 | $this->prefixDirsPsr4[$prefix] = array_merge( 187 | $this->prefixDirsPsr4[$prefix], 188 | (array) $paths 189 | ); 190 | } 191 | } 192 | 193 | /** 194 | * Registers a set of PSR-0 directories for a given prefix, 195 | * replacing any others previously set for this prefix. 196 | * 197 | * @param string $prefix The prefix 198 | * @param array|string $paths The PSR-0 base directories 199 | */ 200 | public function set($prefix, $paths) 201 | { 202 | if (!$prefix) { 203 | $this->fallbackDirsPsr0 = (array) $paths; 204 | } else { 205 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 206 | } 207 | } 208 | 209 | /** 210 | * Registers a set of PSR-4 directories for a given namespace, 211 | * replacing any others previously set for this namespace. 212 | * 213 | * @param string $prefix The prefix/namespace, with trailing '\\' 214 | * @param array|string $paths The PSR-4 base directories 215 | * 216 | * @throws \InvalidArgumentException 217 | */ 218 | public function setPsr4($prefix, $paths) 219 | { 220 | if (!$prefix) { 221 | $this->fallbackDirsPsr4 = (array) $paths; 222 | } else { 223 | $length = strlen($prefix); 224 | if ('\\' !== $prefix[$length - 1]) { 225 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 226 | } 227 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 228 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 229 | } 230 | } 231 | 232 | /** 233 | * Turns on searching the include path for class files. 234 | * 235 | * @param bool $useIncludePath 236 | */ 237 | public function setUseIncludePath($useIncludePath) 238 | { 239 | $this->useIncludePath = $useIncludePath; 240 | } 241 | 242 | /** 243 | * Can be used to check if the autoloader uses the include path to check 244 | * for classes. 245 | * 246 | * @return bool 247 | */ 248 | public function getUseIncludePath() 249 | { 250 | return $this->useIncludePath; 251 | } 252 | 253 | /** 254 | * Turns off searching the prefix and fallback directories for classes 255 | * that have not been registered with the class map. 256 | * 257 | * @param bool $classMapAuthoritative 258 | */ 259 | public function setClassMapAuthoritative($classMapAuthoritative) 260 | { 261 | $this->classMapAuthoritative = $classMapAuthoritative; 262 | } 263 | 264 | /** 265 | * Should class lookup fail if not found in the current class map? 266 | * 267 | * @return bool 268 | */ 269 | public function isClassMapAuthoritative() 270 | { 271 | return $this->classMapAuthoritative; 272 | } 273 | 274 | /** 275 | * Registers this instance as an autoloader. 276 | * 277 | * @param bool $prepend Whether to prepend the autoloader or not 278 | */ 279 | public function register($prepend = false) 280 | { 281 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 282 | } 283 | 284 | /** 285 | * Unregisters this instance as an autoloader. 286 | */ 287 | public function unregister() 288 | { 289 | spl_autoload_unregister(array($this, 'loadClass')); 290 | } 291 | 292 | /** 293 | * Loads the given class or interface. 294 | * 295 | * @param string $class The name of the class 296 | * @return bool|null True if loaded, null otherwise 297 | */ 298 | public function loadClass($class) 299 | { 300 | if ($file = $this->findFile($class)) { 301 | includeFile($file); 302 | 303 | return true; 304 | } 305 | } 306 | 307 | /** 308 | * Finds the path to the file where the class is defined. 309 | * 310 | * @param string $class The name of the class 311 | * 312 | * @return string|false The path if found, false otherwise 313 | */ 314 | public function findFile($class) 315 | { 316 | // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 317 | if ('\\' == $class[0]) { 318 | $class = substr($class, 1); 319 | } 320 | 321 | // class map lookup 322 | if (isset($this->classMap[$class])) { 323 | return $this->classMap[$class]; 324 | } 325 | if ($this->classMapAuthoritative) { 326 | return false; 327 | } 328 | 329 | $file = $this->findFileWithExtension($class, '.php'); 330 | 331 | // Search for Hack files if we are running on HHVM 332 | if ($file === null && defined('HHVM_VERSION')) { 333 | $file = $this->findFileWithExtension($class, '.hh'); 334 | } 335 | 336 | if ($file === null) { 337 | // Remember that this class does not exist. 338 | return $this->classMap[$class] = false; 339 | } 340 | 341 | return $file; 342 | } 343 | 344 | private function findFileWithExtension($class, $ext) 345 | { 346 | // PSR-4 lookup 347 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 348 | 349 | $first = $class[0]; 350 | if (isset($this->prefixLengthsPsr4[$first])) { 351 | foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { 352 | if (0 === strpos($class, $prefix)) { 353 | foreach ($this->prefixDirsPsr4[$prefix] as $dir) { 354 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { 355 | return $file; 356 | } 357 | } 358 | } 359 | } 360 | } 361 | 362 | // PSR-4 fallback dirs 363 | foreach ($this->fallbackDirsPsr4 as $dir) { 364 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 365 | return $file; 366 | } 367 | } 368 | 369 | // PSR-0 lookup 370 | if (false !== $pos = strrpos($class, '\\')) { 371 | // namespaced class name 372 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 373 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 374 | } else { 375 | // PEAR-like class name 376 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 377 | } 378 | 379 | if (isset($this->prefixesPsr0[$first])) { 380 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 381 | if (0 === strpos($class, $prefix)) { 382 | foreach ($dirs as $dir) { 383 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 384 | return $file; 385 | } 386 | } 387 | } 388 | } 389 | } 390 | 391 | // PSR-0 fallback dirs 392 | foreach ($this->fallbackDirsPsr0 as $dir) { 393 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 394 | return $file; 395 | } 396 | } 397 | 398 | // PSR-0 include paths. 399 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 400 | return $file; 401 | } 402 | } 403 | } 404 | 405 | /** 406 | * Scope isolated include. 407 | * 408 | * Prevents access to $this/self from included files. 409 | */ 410 | function includeFile($file) 411 | { 412 | include $file; 413 | } 414 | -------------------------------------------------------------------------------- /vendor/composer/LICENSE: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: Composer 3 | Upstream-Contact: Jordi Boggiano 4 | Source: https://github.com/composer/composer 5 | 6 | Files: * 7 | Copyright: 2016, Nils Adermann 8 | 2016, Jordi Boggiano 9 | License: Expat 10 | 11 | Files: res/cacert.pem 12 | Copyright: 2015, Mozilla Foundation 13 | License: MPL-2.0 14 | 15 | Files: src/Composer/Util/RemoteFilesystem.php 16 | src/Composer/Util/TlsHelper.php 17 | Copyright: 2016, Nils Adermann 18 | 2016, Jordi Boggiano 19 | 2013, Evan Coury 20 | License: Expat and BSD-2-Clause 21 | 22 | License: BSD-2-Clause 23 | Redistribution and use in source and binary forms, with or without modification, 24 | are permitted provided that the following conditions are met: 25 | . 26 | * Redistributions of source code must retain the above copyright notice, 27 | this list of conditions and the following disclaimer. 28 | . 29 | * Redistributions in binary form must reproduce the above copyright notice, 30 | this list of conditions and the following disclaimer in the documentation 31 | and/or other materials provided with the distribution. 32 | . 33 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 34 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 35 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 36 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 37 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 38 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 39 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 40 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 41 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 42 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 | 44 | License: Expat 45 | Permission is hereby granted, free of charge, to any person obtaining a copy 46 | of this software and associated documentation files (the "Software"), to deal 47 | in the Software without restriction, including without limitation the rights 48 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 49 | copies of the Software, and to permit persons to whom the Software is furnished 50 | to do so, subject to the following conditions: 51 | . 52 | The above copyright notice and this permission notice shall be included in all 53 | copies or substantial portions of the Software. 54 | . 55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 56 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 57 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 58 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 59 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 60 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 61 | THE SOFTWARE. 62 | 63 | License: MPL-2.0 64 | 1. Definitions 65 | -------------- 66 | . 67 | 1.1. "Contributor" 68 | means each individual or legal entity that creates, contributes to 69 | the creation of, or owns Covered Software. 70 | . 71 | 1.2. "Contributor Version" 72 | means the combination of the Contributions of others (if any) used 73 | by a Contributor and that particular Contributor's Contribution. 74 | . 75 | 1.3. "Contribution" 76 | means Covered Software of a particular Contributor. 77 | . 78 | 1.4. "Covered Software" 79 | means Source Code Form to which the initial Contributor has attached 80 | the notice in Exhibit A, the Executable Form of such Source Code 81 | Form, and Modifications of such Source Code Form, in each case 82 | including portions thereof. 83 | . 84 | 1.5. "Incompatible With Secondary Licenses" 85 | means 86 | . 87 | (a) that the initial Contributor has attached the notice described 88 | in Exhibit B to the Covered Software; or 89 | . 90 | (b) that the Covered Software was made available under the terms of 91 | version 1.1 or earlier of the License, but not also under the 92 | terms of a Secondary License. 93 | . 94 | 1.6. "Executable Form" 95 | means any form of the work other than Source Code Form. 96 | . 97 | 1.7. "Larger Work" 98 | means a work that combines Covered Software with other material, in 99 | a separate file or files, that is not Covered Software. 100 | . 101 | 1.8. "License" 102 | means this document. 103 | . 104 | 1.9. "Licensable" 105 | means having the right to grant, to the maximum extent possible, 106 | whether at the time of the initial grant or subsequently, any and 107 | all of the rights conveyed by this License. 108 | . 109 | 1.10. "Modifications" 110 | means any of the following: 111 | . 112 | (a) any file in Source Code Form that results from an addition to, 113 | deletion from, or modification of the contents of Covered 114 | Software; or 115 | . 116 | (b) any new file in Source Code Form that contains any Covered 117 | Software. 118 | . 119 | 1.11. "Patent Claims" of a Contributor 120 | means any patent claim(s), including without limitation, method, 121 | process, and apparatus claims, in any patent Licensable by such 122 | Contributor that would be infringed, but for the grant of the 123 | License, by the making, using, selling, offering for sale, having 124 | made, import, or transfer of either its Contributions or its 125 | Contributor Version. 126 | . 127 | 1.12. "Secondary License" 128 | means either the GNU General Public License, Version 2.0, the GNU 129 | Lesser General Public License, Version 2.1, the GNU Affero General 130 | Public License, Version 3.0, or any later versions of those 131 | licenses. 132 | . 133 | 1.13. "Source Code Form" 134 | means the form of the work preferred for making modifications. 135 | . 136 | 1.14. "You" (or "Your") 137 | means an individual or a legal entity exercising rights under this 138 | License. For legal entities, "You" includes any entity that 139 | controls, is controlled by, or is under common control with You. For 140 | purposes of this definition, "control" means (a) the power, direct 141 | or indirect, to cause the direction or management of such entity, 142 | whether by contract or otherwise, or (b) ownership of more than 143 | fifty percent (50%) of the outstanding shares or beneficial 144 | ownership of such entity. 145 | . 146 | 2. License Grants and Conditions 147 | -------------------------------- 148 | . 149 | 2.1. Grants 150 | . 151 | Each Contributor hereby grants You a world-wide, royalty-free, 152 | non-exclusive license: 153 | . 154 | (a) under intellectual property rights (other than patent or trademark) 155 | Licensable by such Contributor to use, reproduce, make available, 156 | modify, display, perform, distribute, and otherwise exploit its 157 | Contributions, either on an unmodified basis, with Modifications, or 158 | as part of a Larger Work; and 159 | . 160 | (b) under Patent Claims of such Contributor to make, use, sell, offer 161 | for sale, have made, import, and otherwise transfer either its 162 | Contributions or its Contributor Version. 163 | . 164 | 2.2. Effective Date 165 | . 166 | The licenses granted in Section 2.1 with respect to any Contribution 167 | become effective for each Contribution on the date the Contributor first 168 | distributes such Contribution. 169 | . 170 | 2.3. Limitations on Grant Scope 171 | . 172 | The licenses granted in this Section 2 are the only rights granted under 173 | this License. No additional rights or licenses will be implied from the 174 | distribution or licensing of Covered Software under this License. 175 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 176 | Contributor: 177 | . 178 | (a) for any code that a Contributor has removed from Covered Software; 179 | or 180 | . 181 | (b) for infringements caused by: (i) Your and any other third party's 182 | modifications of Covered Software, or (ii) the combination of its 183 | Contributions with other software (except as part of its Contributor 184 | Version); or 185 | . 186 | (c) under Patent Claims infringed by Covered Software in the absence of 187 | its Contributions. 188 | . 189 | This License does not grant any rights in the trademarks, service marks, 190 | or logos of any Contributor (except as may be necessary to comply with 191 | the notice requirements in Section 3.4). 192 | . 193 | 2.4. Subsequent Licenses 194 | . 195 | No Contributor makes additional grants as a result of Your choice to 196 | distribute the Covered Software under a subsequent version of this 197 | License (see Section 10.2) or under the terms of a Secondary License (if 198 | permitted under the terms of Section 3.3). 199 | . 200 | 2.5. Representation 201 | . 202 | Each Contributor represents that the Contributor believes its 203 | Contributions are its original creation(s) or it has sufficient rights 204 | to grant the rights to its Contributions conveyed by this License. 205 | . 206 | 2.6. Fair Use 207 | . 208 | This License is not intended to limit any rights You have under 209 | applicable copyright doctrines of fair use, fair dealing, or other 210 | equivalents. 211 | . 212 | 2.7. Conditions 213 | . 214 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 215 | in Section 2.1. 216 | . 217 | 3. Responsibilities 218 | ------------------- 219 | . 220 | 3.1. Distribution of Source Form 221 | . 222 | All distribution of Covered Software in Source Code Form, including any 223 | Modifications that You create or to which You contribute, must be under 224 | the terms of this License. You must inform recipients that the Source 225 | Code Form of the Covered Software is governed by the terms of this 226 | License, and how they can obtain a copy of this License. You may not 227 | attempt to alter or restrict the recipients' rights in the Source Code 228 | Form. 229 | . 230 | 3.2. Distribution of Executable Form 231 | . 232 | If You distribute Covered Software in Executable Form then: 233 | . 234 | (a) such Covered Software must also be made available in Source Code 235 | Form, as described in Section 3.1, and You must inform recipients of 236 | the Executable Form how they can obtain a copy of such Source Code 237 | Form by reasonable means in a timely manner, at a charge no more 238 | than the cost of distribution to the recipient; and 239 | . 240 | (b) You may distribute such Executable Form under the terms of this 241 | License, or sublicense it under different terms, provided that the 242 | license for the Executable Form does not attempt to limit or alter 243 | the recipients' rights in the Source Code Form under this License. 244 | . 245 | 3.3. Distribution of a Larger Work 246 | . 247 | You may create and distribute a Larger Work under terms of Your choice, 248 | provided that You also comply with the requirements of this License for 249 | the Covered Software. If the Larger Work is a combination of Covered 250 | Software with a work governed by one or more Secondary Licenses, and the 251 | Covered Software is not Incompatible With Secondary Licenses, this 252 | License permits You to additionally distribute such Covered Software 253 | under the terms of such Secondary License(s), so that the recipient of 254 | the Larger Work may, at their option, further distribute the Covered 255 | Software under the terms of either this License or such Secondary 256 | License(s). 257 | . 258 | 3.4. Notices 259 | . 260 | You may not remove or alter the substance of any license notices 261 | (including copyright notices, patent notices, disclaimers of warranty, 262 | or limitations of liability) contained within the Source Code Form of 263 | the Covered Software, except that You may alter any license notices to 264 | the extent required to remedy known factual inaccuracies. 265 | . 266 | 3.5. Application of Additional Terms 267 | . 268 | You may choose to offer, and to charge a fee for, warranty, support, 269 | indemnity or liability obligations to one or more recipients of Covered 270 | Software. However, You may do so only on Your own behalf, and not on 271 | behalf of any Contributor. You must make it absolutely clear that any 272 | such warranty, support, indemnity, or liability obligation is offered by 273 | You alone, and You hereby agree to indemnify every Contributor for any 274 | liability incurred by such Contributor as a result of warranty, support, 275 | indemnity or liability terms You offer. You may include additional 276 | disclaimers of warranty and limitations of liability specific to any 277 | jurisdiction. 278 | . 279 | 4. Inability to Comply Due to Statute or Regulation 280 | --------------------------------------------------- 281 | . 282 | If it is impossible for You to comply with any of the terms of this 283 | License with respect to some or all of the Covered Software due to 284 | statute, judicial order, or regulation then You must: (a) comply with 285 | the terms of this License to the maximum extent possible; and (b) 286 | describe the limitations and the code they affect. Such description must 287 | be placed in a text file included with all distributions of the Covered 288 | Software under this License. Except to the extent prohibited by statute 289 | or regulation, such description must be sufficiently detailed for a 290 | recipient of ordinary skill to be able to understand it. 291 | . 292 | 5. Termination 293 | -------------- 294 | . 295 | 5.1. The rights granted under this License will terminate automatically 296 | if You fail to comply with any of its terms. However, if You become 297 | compliant, then the rights granted under this License from a particular 298 | Contributor are reinstated (a) provisionally, unless and until such 299 | Contributor explicitly and finally terminates Your grants, and (b) on an 300 | ongoing basis, if such Contributor fails to notify You of the 301 | non-compliance by some reasonable means prior to 60 days after You have 302 | come back into compliance. Moreover, Your grants from a particular 303 | Contributor are reinstated on an ongoing basis if such Contributor 304 | notifies You of the non-compliance by some reasonable means, this is the 305 | first time You have received notice of non-compliance with this License 306 | from such Contributor, and You become compliant prior to 30 days after 307 | Your receipt of the notice. 308 | . 309 | 5.2. If You initiate litigation against any entity by asserting a patent 310 | infringement claim (excluding declaratory judgment actions, 311 | counter-claims, and cross-claims) alleging that a Contributor Version 312 | directly or indirectly infringes any patent, then the rights granted to 313 | You by any and all Contributors for the Covered Software under Section 314 | 2.1 of this License shall terminate. 315 | . 316 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 317 | end user license agreements (excluding distributors and resellers) which 318 | have been validly granted by You or Your distributors under this License 319 | prior to termination shall survive termination. 320 | . 321 | ************************************************************************ 322 | * * 323 | * 6. Disclaimer of Warranty * 324 | * ------------------------- * 325 | * * 326 | * Covered Software is provided under this License on an "as is" * 327 | * basis, without warranty of any kind, either expressed, implied, or * 328 | * statutory, including, without limitation, warranties that the * 329 | * Covered Software is free of defects, merchantable, fit for a * 330 | * particular purpose or non-infringing. The entire risk as to the * 331 | * quality and performance of the Covered Software is with You. * 332 | * Should any Covered Software prove defective in any respect, You * 333 | * (not any Contributor) assume the cost of any necessary servicing, * 334 | * repair, or correction. This disclaimer of warranty constitutes an * 335 | * essential part of this License. No use of any Covered Software is * 336 | * authorized under this License except under this disclaimer. * 337 | * * 338 | ************************************************************************ 339 | . 340 | ************************************************************************ 341 | * * 342 | * 7. Limitation of Liability * 343 | * -------------------------- * 344 | * * 345 | * Under no circumstances and under no legal theory, whether tort * 346 | * (including negligence), contract, or otherwise, shall any * 347 | * Contributor, or anyone who distributes Covered Software as * 348 | * permitted above, be liable to You for any direct, indirect, * 349 | * special, incidental, or consequential damages of any character * 350 | * including, without limitation, damages for lost profits, loss of * 351 | * goodwill, work stoppage, computer failure or malfunction, or any * 352 | * and all other commercial damages or losses, even if such party * 353 | * shall have been informed of the possibility of such damages. This * 354 | * limitation of liability shall not apply to liability for death or * 355 | * personal injury resulting from such party's negligence to the * 356 | * extent applicable law prohibits such limitation. Some * 357 | * jurisdictions do not allow the exclusion or limitation of * 358 | * incidental or consequential damages, so this exclusion and * 359 | * limitation may not apply to You. * 360 | * * 361 | ************************************************************************ 362 | . 363 | 8. Litigation 364 | ------------- 365 | . 366 | Any litigation relating to this License may be brought only in the 367 | courts of a jurisdiction where the defendant maintains its principal 368 | place of business and such litigation shall be governed by laws of that 369 | jurisdiction, without reference to its conflict-of-law provisions. 370 | Nothing in this Section shall prevent a party's ability to bring 371 | cross-claims or counter-claims. 372 | . 373 | 9. Miscellaneous 374 | ---------------- 375 | . 376 | This License represents the complete agreement concerning the subject 377 | matter hereof. If any provision of this License is held to be 378 | unenforceable, such provision shall be reformed only to the extent 379 | necessary to make it enforceable. Any law or regulation which provides 380 | that the language of a contract shall be construed against the drafter 381 | shall not be used to construe this License against a Contributor. 382 | . 383 | 10. Versions of the License 384 | --------------------------- 385 | . 386 | 10.1. New Versions 387 | . 388 | Mozilla Foundation is the license steward. Except as provided in Section 389 | 10.3, no one other than the license steward has the right to modify or 390 | publish new versions of this License. Each version will be given a 391 | distinguishing version number. 392 | . 393 | 10.2. Effect of New Versions 394 | . 395 | You may distribute the Covered Software under the terms of the version 396 | of the License under which You originally received the Covered Software, 397 | or under the terms of any subsequent version published by the license 398 | steward. 399 | . 400 | 10.3. Modified Versions 401 | . 402 | If you create software not governed by this License, and you want to 403 | create a new license for such software, you may create and use a 404 | modified version of this License if you rename the license and remove 405 | any references to the name of the license steward (except to note that 406 | such modified license differs from this License). 407 | . 408 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 409 | Licenses 410 | . 411 | If You choose to distribute Source Code Form that is Incompatible With 412 | Secondary Licenses under the terms of this version of the License, the 413 | notice described in Exhibit B of this License must be attached. 414 | . 415 | Exhibit A - Source Code Form License Notice 416 | ------------------------------------------- 417 | . 418 | This Source Code Form is subject to the terms of the Mozilla Public 419 | License, v. 2.0. If a copy of the MPL was not distributed with this 420 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 421 | . 422 | If it is not possible or desirable to put the notice in a particular 423 | file, then You may include the notice in a location (such as a LICENSE 424 | file in a relevant directory) where a recipient would be likely to look 425 | for such a notice. 426 | . 427 | You may add additional accurate notices of copyright ownership. 428 | . 429 | Exhibit B - "Incompatible With Secondary Licenses" Notice 430 | --------------------------------------------------------- 431 | . 432 | This Source Code Form is "Incompatible With Secondary Licenses", as 433 | defined by the Mozilla Public License, v. 2.0. 434 | -------------------------------------------------------------------------------- /vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | $path) { 28 | $loader->set($namespace, $path); 29 | } 30 | 31 | $map = require __DIR__ . '/autoload_psr4.php'; 32 | foreach ($map as $namespace => $path) { 33 | $loader->setPsr4($namespace, $path); 34 | } 35 | 36 | $classMap = require __DIR__ . '/autoload_classmap.php'; 37 | if ($classMap) { 38 | $loader->addClassMap($classMap); 39 | } 40 | 41 | $loader->register(true); 42 | 43 | return $loader; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | [] 2 | --------------------------------------------------------------------------------