From bc0249f2193ca094f048c8de5c2ea99f4a383b0b Mon Sep 17 00:00:00 2001 From: Michael Henning Date: Fri, 19 May 2017 11:54:19 +0200 Subject: [PATCH] init --- .gitignore | 21 + Procfile | 1 + README.md | 26 + app.json | 6 + app/api.php | 13 + app/controller.php | 63 + app/index.php | 16 + app/model/sample.php | 17 + app/rake.php | 25 + app/user.php | 71 + composer.json | 10 + composer.lock | 67 + config/config.dev.ini | 8 + config/config.local.ini.sample | 17 + config/config.production.ini | 8 + config/config.staging.ini | 8 + config/config.testing.ini | 8 + config/routes.ini | 22 + config/settings.ini | 11 + config/sql/.gitkeep | 1 + lib/colors/colors.php | 491 + lib/f3/api/annotated.html | 85 + lib/f3/api/bc_s.png | Bin 0 -> 624 bytes lib/f3/api/bdwn.png | Bin 0 -> 139 bytes lib/f3/api/classAudit-members.html | 58 + lib/f3/api/classAudit.html | 412 + lib/f3/api/classAudit.png | Bin 0 -> 340 bytes lib/f3/api/classAuth-members.html | 53 + lib/f3/api/classAuth.html | 431 + lib/f3/api/classBase-members.html | 165 + lib/f3/api/classBase.html | 2218 +++ lib/f3/api/classBase.png | Bin 0 -> 338 bytes lib/f3/api/classBasket-members.html | 62 + lib/f3/api/classBasket.html | 534 + lib/f3/api/classBcrypt-members.html | 48 + lib/f3/api/classBcrypt.html | 204 + lib/f3/api/classBcrypt.png | Bin 0 -> 364 bytes lib/f3/api/classCache-members.html | 52 + lib/f3/api/classCache.html | 314 + lib/f3/api/classCache.png | Bin 0 -> 352 bytes lib/f3/api/classDB_1_1Cursor-members.html | 84 + lib/f3/api/classDB_1_1Cursor.html | 785 + lib/f3/api/classDB_1_1Cursor.png | Bin 0 -> 2201 bytes lib/f3/api/classDB_1_1Jig-members.html | 59 + lib/f3/api/classDB_1_1Jig.html | 291 + .../api/classDB_1_1Jig_1_1Mapper-members.html | 94 + lib/f3/api/classDB_1_1Jig_1_1Mapper.html | 717 + lib/f3/api/classDB_1_1Jig_1_1Mapper.png | Bin 0 -> 1083 bytes .../classDB_1_1Jig_1_1Session-members.html | 104 + lib/f3/api/classDB_1_1Jig_1_1Session.html | 531 + lib/f3/api/classDB_1_1Jig_1_1Session.png | Bin 0 -> 1078 bytes lib/f3/api/classDB_1_1Mongo-members.html | 53 + lib/f3/api/classDB_1_1Mongo.html | 204 + lib/f3/api/classDB_1_1Mongo.png | Bin 0 -> 419 bytes .../classDB_1_1Mongo_1_1Mapper-members.html | 94 + lib/f3/api/classDB_1_1Mongo_1_1Mapper.html | 743 + lib/f3/api/classDB_1_1Mongo_1_1Mapper.png | Bin 0 -> 1137 bytes .../classDB_1_1Mongo_1_1Session-members.html | 104 + lib/f3/api/classDB_1_1Mongo_1_1Session.html | 533 + lib/f3/api/classDB_1_1Mongo_1_1Session.png | Bin 0 -> 1127 bytes lib/f3/api/classDB_1_1SQL-members.html | 66 + lib/f3/api/classDB_1_1SQL.html | 502 + lib/f3/api/classDB_1_1SQL.png | Bin 0 -> 327 bytes .../api/classDB_1_1SQL_1_1Mapper-members.html | 100 + lib/f3/api/classDB_1_1SQL_1_1Mapper.html | 842 + lib/f3/api/classDB_1_1SQL_1_1Mapper.png | Bin 0 -> 1087 bytes .../classDB_1_1SQL_1_1Session-members.html | 111 + lib/f3/api/classDB_1_1SQL_1_1Session.html | 552 + lib/f3/api/classDB_1_1SQL_1_1Session.png | Bin 0 -> 1084 bytes lib/f3/api/classF3-members.html | 43 + lib/f3/api/classF3.html | 107 + lib/f3/api/classISO-members.html | 377 + lib/f3/api/classISO.html | 1148 ++ lib/f3/api/classISO.png | Bin 0 -> 330 bytes lib/f3/api/classImage-members.html | 82 + lib/f3/api/classImage.html | 898 + lib/f3/api/classLog-members.html | 45 + lib/f3/api/classLog.html | 144 + lib/f3/api/classMagic-members.html | 53 + lib/f3/api/classMagic.html | 450 + lib/f3/api/classMagic.png | Bin 0 -> 2601 bytes lib/f3/api/classMarkdown-members.html | 63 + lib/f3/api/classMarkdown.html | 739 + lib/f3/api/classMarkdown.png | Bin 0 -> 403 bytes lib/f3/api/classMatrix-members.html | 47 + lib/f3/api/classMatrix.html | 259 + lib/f3/api/classMatrix.png | Bin 0 -> 350 bytes lib/f3/api/classPrefab-members.html | 42 + lib/f3/api/classPrefab.html | 103 + lib/f3/api/classPrefab.png | Bin 0 -> 2714 bytes lib/f3/api/classPreview-members.html | 51 + lib/f3/api/classPreview.html | 248 + lib/f3/api/classPreview.png | Bin 0 -> 619 bytes lib/f3/api/classRegistry-members.html | 45 + lib/f3/api/classRegistry.html | 201 + lib/f3/api/classSMTP-members.html | 70 + lib/f3/api/classSMTP.html | 474 + lib/f3/api/classSMTP.png | Bin 0 -> 544 bytes lib/f3/api/classSession-members.html | 52 + lib/f3/api/classSession.html | 349 + lib/f3/api/classTemplate-members.html | 70 + lib/f3/api/classTemplate.html | 681 + lib/f3/api/classTemplate.png | Bin 0 -> 618 bytes lib/f3/api/classTest-members.html | 48 + lib/f3/api/classTest.html | 176 + lib/f3/api/classUTF-members.html | 56 + lib/f3/api/classUTF.html | 543 + lib/f3/api/classUTF.png | Bin 0 -> 316 bytes lib/f3/api/classView-members.html | 47 + lib/f3/api/classView.html | 222 + lib/f3/api/classView.png | Bin 0 -> 623 bytes lib/f3/api/classWeb-members.html | 59 + lib/f3/api/classWeb.html | 692 + lib/f3/api/classWeb.png | Bin 0 -> 340 bytes lib/f3/api/classWeb_1_1Geo-members.html | 49 + lib/f3/api/classWeb_1_1Geo.html | 164 + lib/f3/api/classWeb_1_1Geo.png | Bin 0 -> 370 bytes ...assWeb_1_1Google_1_1StaticMap-members.html | 49 + .../api/classWeb_1_1Google_1_1StaticMap.html | 130 + lib/f3/api/classWeb_1_1OpenID-members.html | 63 + lib/f3/api/classWeb_1_1OpenID.html | 352 + lib/f3/api/classWeb_1_1OpenID.png | Bin 0 -> 595 bytes lib/f3/api/classWeb_1_1Pingback-members.html | 51 + lib/f3/api/classWeb_1_1Pingback.html | 215 + lib/f3/api/classWeb_1_1Pingback.png | Bin 0 -> 466 bytes lib/f3/api/classes.html | 131 + lib/f3/api/closed.png | Bin 0 -> 125 bytes .../dir_3a960e52dd9a2c9686c19ff6ef19d5fb.html | 48 + .../dir_562abdcd8625d4bf7bad2fe6fe01354c.html | 57 + .../dir_60985a986063d10a97c0bb7f42d76d6f.html | 50 + .../dir_826b1e4cd13f4e7f528ca52e638927e5.html | 50 + .../dir_9d4753e6cb22f68b75f0462ac2496f38.html | 50 + .../dir_ce5981f09099a3fa6071b9eb8fe67a2c.html | 63 + lib/f3/api/doxygen.css | 1382 ++ lib/f3/api/doxygen.png | Bin 0 -> 3529 bytes lib/f3/api/doxygen_8h_source.html | 39 + lib/f3/api/dynsections.js | 97 + lib/f3/api/ftv2blank.png | Bin 0 -> 86 bytes lib/f3/api/ftv2cl.png | Bin 0 -> 416 bytes lib/f3/api/ftv2doc.png | Bin 0 -> 652 bytes lib/f3/api/ftv2folderclosed.png | Bin 0 -> 493 bytes lib/f3/api/ftv2folderopen.png | Bin 0 -> 505 bytes lib/f3/api/ftv2lastnode.png | Bin 0 -> 86 bytes lib/f3/api/ftv2link.png | Bin 0 -> 652 bytes lib/f3/api/ftv2mlastnode.png | Bin 0 -> 241 bytes lib/f3/api/ftv2mnode.png | Bin 0 -> 241 bytes lib/f3/api/ftv2mo.png | Bin 0 -> 373 bytes lib/f3/api/ftv2node.png | Bin 0 -> 86 bytes lib/f3/api/ftv2ns.png | Bin 0 -> 370 bytes lib/f3/api/ftv2plastnode.png | Bin 0 -> 227 bytes lib/f3/api/ftv2pnode.png | Bin 0 -> 227 bytes lib/f3/api/ftv2splitbar.png | Bin 0 -> 282 bytes lib/f3/api/ftv2vertline.png | Bin 0 -> 86 bytes lib/f3/api/functions.html | 207 + lib/f3/api/functions_0x5f.html | 183 + lib/f3/api/functions_0x61.html | 56 + lib/f3/api/functions_0x62.html | 65 + lib/f3/api/functions_0x63.html | 158 + lib/f3/api/functions_0x64.html | 82 + lib/f3/api/functions_0x65.html | 95 + lib/f3/api/functions_0x66.html | 77 + lib/f3/api/functions_0x67.html | 56 + lib/f3/api/functions_0x68.html | 54 + lib/f3/api/functions_0x69.html | 87 + lib/f3/api/functions_0x6a.html | 41 + lib/f3/api/functions_0x6c.html | 75 + lib/f3/api/functions_0x6d.html | 68 + lib/f3/api/functions_0x6e.html | 47 + lib/f3/api/functions_0x6f.html | 71 + lib/f3/api/functions_0x70.html | 63 + lib/f3/api/functions_0x71.html | 44 + lib/f3/api/functions_0x72.html | 116 + lib/f3/api/functions_0x73.html | 160 + lib/f3/api/functions_0x74.html | 55 + lib/f3/api/functions_0x75.html | 67 + lib/f3/api/functions_0x76.html | 56 + lib/f3/api/functions_0x77.html | 56 + lib/f3/api/functions_0x78.html | 44 + lib/f3/api/functions__.html | 184 + lib/f3/api/functions_a.html | 56 + lib/f3/api/functions_b.html | 65 + lib/f3/api/functions_c.html | 165 + lib/f3/api/functions_d.html | 82 + lib/f3/api/functions_e.html | 98 + lib/f3/api/functions_f.html | 77 + lib/f3/api/functions_func.html | 184 + lib/f3/api/functions_func_0x61.html | 56 + lib/f3/api/functions_func_0x62.html | 65 + lib/f3/api/functions_func_0x63.html | 152 + lib/f3/api/functions_func_0x64.html | 82 + lib/f3/api/functions_func_0x65.html | 95 + lib/f3/api/functions_func_0x66.html | 77 + lib/f3/api/functions_func_0x67.html | 53 + lib/f3/api/functions_func_0x68.html | 54 + lib/f3/api/functions_func_0x69.html | 87 + lib/f3/api/functions_func_0x6a.html | 41 + lib/f3/api/functions_func_0x6c.html | 75 + lib/f3/api/functions_func_0x6d.html | 65 + lib/f3/api/functions_func_0x6e.html | 47 + lib/f3/api/functions_func_0x6f.html | 71 + lib/f3/api/functions_func_0x70.html | 63 + lib/f3/api/functions_func_0x71.html | 44 + lib/f3/api/functions_func_0x72.html | 116 + lib/f3/api/functions_func_0x73.html | 160 + lib/f3/api/functions_func_0x74.html | 55 + lib/f3/api/functions_func_0x75.html | 64 + lib/f3/api/functions_func_0x76.html | 53 + lib/f3/api/functions_func_0x77.html | 56 + lib/f3/api/functions_func_0x78.html | 44 + lib/f3/api/functions_func_a.html | 56 + lib/f3/api/functions_func_b.html | 65 + lib/f3/api/functions_func_c.html | 159 + lib/f3/api/functions_func_d.html | 82 + lib/f3/api/functions_func_e.html | 98 + lib/f3/api/functions_func_f.html | 77 + lib/f3/api/functions_func_g.html | 53 + lib/f3/api/functions_func_h.html | 54 + lib/f3/api/functions_func_i.html | 86 + lib/f3/api/functions_func_j.html | 41 + lib/f3/api/functions_func_l.html | 75 + lib/f3/api/functions_func_m.html | 65 + lib/f3/api/functions_func_n.html | 47 + lib/f3/api/functions_func_o.html | 71 + lib/f3/api/functions_func_p.html | 63 + lib/f3/api/functions_func_q.html | 44 + lib/f3/api/functions_func_r.html | 119 + lib/f3/api/functions_func_s.html | 157 + lib/f3/api/functions_func_t.html | 58 + lib/f3/api/functions_func_u.html | 64 + lib/f3/api/functions_func_v.html | 53 + lib/f3/api/functions_func_w.html | 56 + lib/f3/api/functions_g.html | 56 + lib/f3/api/functions_h.html | 54 + lib/f3/api/functions_i.html | 86 + lib/f3/api/functions_j.html | 41 + lib/f3/api/functions_l.html | 75 + lib/f3/api/functions_m.html | 68 + lib/f3/api/functions_n.html | 47 + lib/f3/api/functions_o.html | 71 + lib/f3/api/functions_p.html | 63 + lib/f3/api/functions_q.html | 44 + lib/f3/api/functions_r.html | 119 + lib/f3/api/functions_s.html | 157 + lib/f3/api/functions_t.html | 58 + lib/f3/api/functions_u.html | 67 + lib/f3/api/functions_v.html | 56 + lib/f3/api/functions_vars.html | 245 + lib/f3/api/functions_w.html | 56 + lib/f3/api/hierarchy.html | 82 + lib/f3/api/index.html | 44 + lib/f3/api/jquery.js | 31 + lib/f3/api/nav_f.png | Bin 0 -> 136 bytes lib/f3/api/nav_g.png | Bin 0 -> 95 bytes lib/f3/api/nav_h.png | Bin 0 -> 93 bytes lib/f3/api/open.png | Bin 0 -> 115 bytes lib/f3/api/sync_off.png | Bin 0 -> 815 bytes lib/f3/api/sync_on.png | Bin 0 -> 809 bytes lib/f3/api/tab_a.png | Bin 0 -> 124 bytes lib/f3/api/tab_b.png | Bin 0 -> 149 bytes lib/f3/api/tab_h.png | Bin 0 -> 145 bytes lib/f3/api/tab_s.png | Bin 0 -> 156 bytes lib/f3/api/tabs.css | 60 + lib/f3/audit.php | 177 + lib/f3/auth.php | 234 + lib/f3/base.php | 3119 ++++ lib/f3/basket.php | 227 + lib/f3/bcrypt.php | 89 + lib/f3/changelog.txt | 376 + lib/f3/code.css | 1 + lib/f3/db/cortex.php | 2672 +++ lib/f3/db/cursor.php | 246 + lib/f3/db/jig.php | 133 + lib/f3/db/jig/mapper.php | 442 + lib/f3/db/jig/session.php | 184 + lib/f3/db/mongo.php | 92 + lib/f3/db/mongo/mapper.php | 328 + lib/f3/db/mongo/session.php | 184 + lib/f3/db/sql.php | 381 + lib/f3/db/sql/mapper.php | 534 + lib/f3/db/sql/schema.php | 1186 ++ lib/f3/db/sql/session.php | 201 + lib/f3/f3.php | 35 + lib/f3/image.php | 571 + lib/f3/license.txt | 621 + lib/f3/log.php | 60 + lib/f3/magic.php | 140 + lib/f3/markdown.php | 570 + lib/f3/matrix.php | 101 + lib/f3/pagination.php | 257 + lib/f3/session.php | 184 + lib/f3/smtp.php | 268 + lib/f3/template.php | 335 + lib/f3/test.php | 77 + lib/f3/utf.php | 192 + lib/f3/web.php | 838 + lib/f3/web/geo.php | 101 + lib/f3/web/google/staticmap.php | 58 + lib/f3/web/openid.php | 236 + lib/f3/web/pingback.php | 170 + lib/faker/.gitignore | 2 + lib/faker/.travis.yml | 21 + lib/faker/CHANGELOG.md | 295 + lib/faker/CONTRIBUTING.md | 22 + lib/faker/LICENSE | 22 + lib/faker/Makefile | 10 + lib/faker/composer.json | 35 + lib/faker/phpunit.xml.dist | 12 + lib/faker/readme.md | 1176 ++ lib/faker/src/Faker/Calculator/Iban.php | 68 + lib/faker/src/Faker/Calculator/Luhn.php | 55 + lib/faker/src/Faker/DefaultGenerator.php | 27 + lib/faker/src/Faker/Documentor.php | 60 + lib/faker/src/Faker/Factory.php | 52 + lib/faker/src/Faker/Generator.php | 240 + lib/faker/src/Faker/Guesser/Name.php | 153 + .../Faker/ORM/CakePHP/ColumnTypeGuesser.php | 64 + .../src/Faker/ORM/CakePHP/EntityPopulator.php | 152 + lib/faker/src/Faker/ORM/CakePHP/Populator.php | 84 + .../Faker/ORM/Doctrine/ColumnTypeGuesser.php | 68 + .../Faker/ORM/Doctrine/EntityPopulator.php | 197 + .../src/Faker/ORM/Doctrine/Populator.php | 78 + .../Faker/ORM/Mandango/ColumnTypeGuesser.php | 43 + .../Faker/ORM/Mandango/EntityPopulator.php | 110 + .../src/Faker/ORM/Mandango/Populator.php | 61 + .../Faker/ORM/Propel/ColumnTypeGuesser.php | 100 + .../src/Faker/ORM/Propel/EntityPopulator.php | 170 + lib/faker/src/Faker/ORM/Propel/Populator.php | 86 + lib/faker/src/Faker/Provider/Address.php | 123 + lib/faker/src/Faker/Provider/Barcode.php | 110 + lib/faker/src/Faker/Provider/Base.php | 545 + lib/faker/src/Faker/Provider/Biased.php | 64 + lib/faker/src/Faker/Provider/Color.php | 116 + lib/faker/src/Faker/Provider/Company.php | 30 + lib/faker/src/Faker/Provider/DateTime.php | 263 + lib/faker/src/Faker/Provider/File.php | 606 + lib/faker/src/Faker/Provider/Image.php | 88 + lib/faker/src/Faker/Provider/Internet.php | 335 + lib/faker/src/Faker/Provider/Lorem.php | 215 + .../src/Faker/Provider/Miscellaneous.php | 258 + lib/faker/src/Faker/Provider/Payment.php | 287 + lib/faker/src/Faker/Provider/Person.php | 126 + lib/faker/src/Faker/Provider/PhoneNumber.php | 16 + lib/faker/src/Faker/Provider/Text.php | 137 + lib/faker/src/Faker/Provider/UserAgent.php | 162 + lib/faker/src/Faker/Provider/Uuid.php | 57 + .../src/Faker/Provider/ar_JO/Address.php | 152 + .../src/Faker/Provider/ar_JO/Company.php | 63 + .../src/Faker/Provider/ar_JO/Internet.php | 55 + lib/faker/src/Faker/Provider/ar_JO/Person.php | 108 + lib/faker/src/Faker/Provider/ar_JO/Text.php | 271 + .../src/Faker/Provider/ar_SA/Address.php | 146 + .../src/Faker/Provider/ar_SA/Company.php | 63 + .../src/Faker/Provider/ar_SA/Internet.php | 55 + lib/faker/src/Faker/Provider/ar_SA/Person.php | 148 + lib/faker/src/Faker/Provider/ar_SA/Text.php | 271 + .../src/Faker/Provider/at_AT/Payment.php | 31 + .../src/Faker/Provider/be_BE/Payment.php | 31 + .../src/Faker/Provider/bg_BG/Internet.php | 9 + .../src/Faker/Provider/bg_BG/Payment.php | 43 + lib/faker/src/Faker/Provider/bg_BG/Person.php | 114 + .../src/Faker/Provider/bg_BG/PhoneNumber.php | 20 + .../src/Faker/Provider/bn_BD/Address.php | 58 + .../src/Faker/Provider/bn_BD/Company.php | 28 + lib/faker/src/Faker/Provider/bn_BD/Person.php | 36 + .../src/Faker/Provider/bn_BD/PhoneNumber.php | 14 + lib/faker/src/Faker/Provider/bn_BD/Utils.php | 14 + .../src/Faker/Provider/cs_CZ/Address.php | 149 + .../src/Faker/Provider/cs_CZ/Company.php | 120 + .../src/Faker/Provider/cs_CZ/DateTime.php | 61 + .../src/Faker/Provider/cs_CZ/Internet.php | 9 + .../src/Faker/Provider/cs_CZ/Payment.php | 19 + lib/faker/src/Faker/Provider/cs_CZ/Person.php | 535 + .../src/Faker/Provider/cs_CZ/PhoneNumber.php | 14 + lib/faker/src/Faker/Provider/cs_CZ/Text.php | 7185 +++++++ .../src/Faker/Provider/da_DK/Address.php | 287 + .../src/Faker/Provider/da_DK/Company.php | 70 + .../src/Faker/Provider/da_DK/Internet.php | 30 + .../src/Faker/Provider/da_DK/Payment.php | 19 + lib/faker/src/Faker/Provider/da_DK/Person.php | 195 + .../src/Faker/Provider/da_DK/PhoneNumber.php | 21 + .../src/Faker/Provider/de_AT/Address.php | 99 + .../src/Faker/Provider/de_AT/Company.php | 13 + .../src/Faker/Provider/de_AT/Internet.php | 9 + .../src/Faker/Provider/de_AT/Payment.php | 19 + lib/faker/src/Faker/Provider/de_AT/Person.php | 116 + .../src/Faker/Provider/de_AT/PhoneNumber.php | 19 + .../src/Faker/Provider/de_DE/Address.php | 90 + .../src/Faker/Provider/de_DE/Company.php | 15 + .../src/Faker/Provider/de_DE/Internet.php | 9 + .../src/Faker/Provider/de_DE/Payment.php | 19 + lib/faker/src/Faker/Provider/de_DE/Person.php | 124 + .../src/Faker/Provider/de_DE/PhoneNumber.php | 20 + lib/faker/src/Faker/Provider/de_DE/Text.php | 2036 ++ .../src/Faker/Provider/el_GR/Address.php | 61 + .../src/Faker/Provider/el_GR/Company.php | 84 + .../src/Faker/Provider/el_GR/Payment.php | 19 + lib/faker/src/Faker/Provider/el_GR/Person.php | 178 + .../src/Faker/Provider/el_GR/PhoneNumber.php | 19 + .../src/Faker/Provider/en_AU/Address.php | 83 + .../src/Faker/Provider/en_AU/Internet.php | 9 + .../src/Faker/Provider/en_AU/PhoneNumber.php | 56 + .../src/Faker/Provider/en_CA/Address.php | 64 + .../src/Faker/Provider/en_CA/PhoneNumber.php | 18 + .../src/Faker/Provider/en_GB/Address.php | 89 + .../src/Faker/Provider/en_GB/Internet.php | 9 + .../src/Faker/Provider/en_GB/Payment.php | 19 + lib/faker/src/Faker/Provider/en_GB/Person.php | 93 + .../src/Faker/Provider/en_GB/PhoneNumber.php | 39 + .../src/Faker/Provider/en_NZ/Address.php | 84 + .../src/Faker/Provider/en_NZ/Internet.php | 14 + .../src/Faker/Provider/en_NZ/PhoneNumber.php | 93 + .../src/Faker/Provider/en_PH/Address.php | 421 + .../src/Faker/Provider/en_PH/PhoneNumber.php | 51 + .../src/Faker/Provider/en_UG/Address.php | 129 + .../src/Faker/Provider/en_UG/Internet.php | 9 + lib/faker/src/Faker/Provider/en_UG/Person.php | 132 + .../src/Faker/Provider/en_UG/PhoneNumber.php | 17 + .../src/Faker/Provider/en_US/Address.php | 97 + .../src/Faker/Provider/en_US/Company.php | 64 + lib/faker/src/Faker/Provider/en_US/Person.php | 119 + .../src/Faker/Provider/en_US/PhoneNumber.php | 108 + lib/faker/src/Faker/Provider/en_US/Text.php | 3720 ++++ .../src/Faker/Provider/en_ZA/Address.php | 97 + .../src/Faker/Provider/en_ZA/Internet.php | 9 + lib/faker/src/Faker/Provider/en_ZA/Person.php | 126 + .../src/Faker/Provider/en_ZA/PhoneNumber.php | 17 + .../src/Faker/Provider/es_AR/Address.php | 95 + .../src/Faker/Provider/es_AR/Company.php | 66 + lib/faker/src/Faker/Provider/es_AR/Person.php | 90 + .../src/Faker/Provider/es_AR/PhoneNumber.php | 42 + .../src/Faker/Provider/es_ES/Address.php | 101 + .../src/Faker/Provider/es_ES/Company.php | 80 + .../src/Faker/Provider/es_ES/Internet.php | 9 + .../src/Faker/Provider/es_ES/Payment.php | 19 + lib/faker/src/Faker/Provider/es_ES/Person.php | 71 + .../src/Faker/Provider/es_ES/PhoneNumber.php | 29 + .../src/Faker/Provider/es_PE/Address.php | 91 + .../src/Faker/Provider/es_PE/Company.php | 66 + lib/faker/src/Faker/Provider/es_PE/Person.php | 90 + .../src/Faker/Provider/es_PE/PhoneNumber.php | 17 + .../src/Faker/Provider/es_VE/Address.php | 97 + .../src/Faker/Provider/es_VE/Company.php | 30 + .../src/Faker/Provider/es_VE/Internet.php | 9 + lib/faker/src/Faker/Provider/es_VE/Person.php | 157 + .../src/Faker/Provider/es_VE/PhoneNumber.php | 29 + .../src/Faker/Provider/fa_IR/Internet.php | 99 + lib/faker/src/Faker/Provider/fa_IR/Person.php | 137 + lib/faker/src/Faker/Provider/fa_IR/Text.php | 546 + .../src/Faker/Provider/fi_FI/Address.php | 85 + .../src/Faker/Provider/fi_FI/Company.php | 64 + .../src/Faker/Provider/fi_FI/Internet.php | 9 + lib/faker/src/Faker/Provider/fi_FI/Person.php | 88 + .../src/Faker/Provider/fi_FI/PhoneNumber.php | 20 + .../src/Faker/Provider/fr_BE/Address.php | 91 + .../src/Faker/Provider/fr_BE/Company.php | 13 + .../src/Faker/Provider/fr_BE/Internet.php | 9 + .../src/Faker/Provider/fr_BE/Payment.php | 19 + lib/faker/src/Faker/Provider/fr_BE/Person.php | 49 + .../src/Faker/Provider/fr_BE/PhoneNumber.php | 20 + .../src/Faker/Provider/fr_CA/Address.php | 156 + lib/faker/src/Faker/Provider/fr_CA/Person.php | 82 + .../src/Faker/Provider/fr_FR/Address.php | 137 + .../src/Faker/Provider/fr_FR/Company.php | 169 + .../src/Faker/Provider/fr_FR/Internet.php | 9 + .../src/Faker/Provider/fr_FR/Payment.php | 19 + lib/faker/src/Faker/Provider/fr_FR/Person.php | 70 + .../src/Faker/Provider/fr_FR/PhoneNumber.php | 70 + lib/faker/src/Faker/Provider/fr_FR/Text.php | 15531 ++++++++++++++++ .../src/Faker/Provider/he_IL/Address.php | 63 + .../src/Faker/Provider/he_IL/Company.php | 14 + lib/faker/src/Faker/Provider/he_IL/Person.php | 105 + .../src/Faker/Provider/he_IL/PhoneNumber.php | 14 + .../src/Faker/Provider/hu_HU/Address.php | 50 + .../src/Faker/Provider/hu_HU/Company.php | 13 + .../src/Faker/Provider/hu_HU/Payment.php | 19 + lib/faker/src/Faker/Provider/hu_HU/Person.php | 73 + .../src/Faker/Provider/hu_HU/PhoneNumber.php | 14 + lib/faker/src/Faker/Provider/hu_HU/Text.php | 3407 ++++ .../src/Faker/Provider/hy_AM/Address.php | 132 + .../src/Faker/Provider/hy_AM/Company.php | 54 + .../src/Faker/Provider/hy_AM/Internet.php | 8 + lib/faker/src/Faker/Provider/hy_AM/Person.php | 112 + .../src/Faker/Provider/hy_AM/PhoneNumber.php | 37 + .../src/Faker/Provider/id_ID/Address.php | 316 + .../src/Faker/Provider/id_ID/Company.php | 43 + .../src/Faker/Provider/id_ID/Internet.php | 25 + lib/faker/src/Faker/Provider/id_ID/Person.php | 256 + .../src/Faker/Provider/id_ID/PhoneNumber.php | 55 + .../src/Faker/Provider/is_IS/Address.php | 178 + .../src/Faker/Provider/is_IS/Company.php | 53 + .../src/Faker/Provider/is_IS/Internet.php | 23 + .../src/Faker/Provider/is_IS/Payment.php | 19 + lib/faker/src/Faker/Provider/is_IS/Person.php | 140 + .../src/Faker/Provider/is_IS/PhoneNumber.php | 20 + .../src/Faker/Provider/it_IT/Address.php | 97 + .../src/Faker/Provider/it_IT/Company.php | 64 + .../src/Faker/Provider/it_IT/Internet.php | 9 + .../src/Faker/Provider/it_IT/Payment.php | 19 + lib/faker/src/Faker/Provider/it_IT/Person.php | 88 + .../src/Faker/Provider/it_IT/PhoneNumber.php | 21 + lib/faker/src/Faker/Provider/it_IT/Text.php | 1994 ++ .../src/Faker/Provider/ja_JP/Address.php | 137 + .../src/Faker/Provider/ja_JP/Company.php | 17 + .../src/Faker/Provider/ja_JP/Internet.php | 57 + lib/faker/src/Faker/Provider/ja_JP/Person.php | 100 + .../src/Faker/Provider/ja_JP/PhoneNumber.php | 12 + .../src/Faker/Provider/ka_GE/Payment.php | 19 + lib/faker/src/Faker/Provider/ka_GE/Person.php | 59 + lib/faker/src/Faker/Provider/ka_GE/Text.php | 997 + .../src/Faker/Provider/kk_KZ/Address.php | 131 + lib/faker/src/Faker/Provider/kk_KZ/Color.php | 12 + .../src/Faker/Provider/kk_KZ/Company.php | 72 + .../src/Faker/Provider/kk_KZ/Internet.php | 9 + .../src/Faker/Provider/kk_KZ/Payment.php | 33 + lib/faker/src/Faker/Provider/kk_KZ/Person.php | 155 + .../src/Faker/Provider/kk_KZ/PhoneNumber.php | 16 + lib/faker/src/Faker/Provider/kk_KZ/Text.php | 490 + .../src/Faker/Provider/ko_KR/Address.php | 96 + .../src/Faker/Provider/ko_KR/Company.php | 31 + .../src/Faker/Provider/ko_KR/Internet.php | 86 + lib/faker/src/Faker/Provider/ko_KR/Person.php | 52 + .../src/Faker/Provider/ko_KR/PhoneNumber.php | 17 + .../src/Faker/Provider/lv_LV/Address.php | 114 + lib/faker/src/Faker/Provider/lv_LV/Color.php | 19 + .../src/Faker/Provider/lv_LV/Internet.php | 9 + .../src/Faker/Provider/lv_LV/Payment.php | 19 + lib/faker/src/Faker/Provider/lv_LV/Person.php | 83 + .../src/Faker/Provider/lv_LV/PhoneNumber.php | 13 + .../src/Faker/Provider/me_ME/Address.php | 127 + .../src/Faker/Provider/me_ME/Company.php | 49 + .../src/Faker/Provider/me_ME/Payment.php | 19 + lib/faker/src/Faker/Provider/me_ME/Person.php | 102 + .../src/Faker/Provider/me_ME/PhoneNumber.php | 15 + .../src/Faker/Provider/ne_NP/Address.php | 129 + .../src/Faker/Provider/ne_NP/Internet.php | 32 + lib/faker/src/Faker/Provider/ne_NP/Person.php | 121 + .../src/Faker/Provider/ne_NP/PhoneNumber.php | 19 + .../src/Faker/Provider/nl_BE/Address.php | 106 + .../src/Faker/Provider/nl_BE/Company.php | 13 + .../src/Faker/Provider/nl_BE/Internet.php | 9 + .../src/Faker/Provider/nl_BE/Payment.php | 19 + lib/faker/src/Faker/Provider/nl_BE/Person.php | 72 + .../src/Faker/Provider/nl_BE/PhoneNumber.php | 20 + .../src/Faker/Provider/nl_NL/Address.php | 112 + lib/faker/src/Faker/Provider/nl_NL/Color.php | 36 + .../src/Faker/Provider/nl_NL/Company.php | 15 + .../src/Faker/Provider/nl_NL/Internet.php | 9 + .../src/Faker/Provider/nl_NL/Payment.php | 19 + lib/faker/src/Faker/Provider/nl_NL/Person.php | 293 + .../src/Faker/Provider/nl_NL/PhoneNumber.php | 39 + .../src/Faker/Provider/no_NO/Address.php | 195 + .../src/Faker/Provider/no_NO/Company.php | 19 + .../src/Faker/Provider/no_NO/Payment.php | 19 + lib/faker/src/Faker/Provider/no_NO/Person.php | 326 + .../src/Faker/Provider/no_NO/PhoneNumber.php | 22 + .../src/Faker/Provider/pl_PL/Address.php | 108 + .../src/Faker/Provider/pl_PL/Company.php | 80 + .../src/Faker/Provider/pl_PL/Internet.php | 9 + .../src/Faker/Provider/pl_PL/Payment.php | 120 + lib/faker/src/Faker/Provider/pl_PL/Person.php | 226 + .../src/Faker/Provider/pl_PL/PhoneNumber.php | 18 + lib/faker/src/Faker/Provider/pl_PL/Text.php | 2866 +++ .../src/Faker/Provider/pt_BR/Address.php | 132 + .../src/Faker/Provider/pt_BR/Company.php | 33 + .../src/Faker/Provider/pt_BR/Internet.php | 9 + .../src/Faker/Provider/pt_BR/Payment.php | 72 + lib/faker/src/Faker/Provider/pt_BR/Person.php | 133 + .../src/Faker/Provider/pt_BR/PhoneNumber.php | 142 + .../src/Faker/Provider/pt_BR/check_digit.php | 35 + .../src/Faker/Provider/pt_PT/Address.php | 124 + .../src/Faker/Provider/pt_PT/Payment.php | 19 + lib/faker/src/Faker/Provider/pt_PT/Person.php | 146 + .../src/Faker/Provider/pt_PT/PhoneNumber.php | 50 + .../src/Faker/Provider/ro_MD/Address.php | 148 + .../src/Faker/Provider/ro_MD/Payment.php | 19 + lib/faker/src/Faker/Provider/ro_MD/Person.php | 90 + .../src/Faker/Provider/ro_MD/PhoneNumber.php | 33 + .../src/Faker/Provider/ro_RO/Address.php | 176 + .../src/Faker/Provider/ro_RO/Payment.php | 19 + lib/faker/src/Faker/Provider/ro_RO/Person.php | 202 + .../src/Faker/Provider/ro_RO/PhoneNumber.php | 67 + .../src/Faker/Provider/ru_RU/Address.php | 156 + lib/faker/src/Faker/Provider/ru_RU/Color.php | 23 + .../src/Faker/Provider/ru_RU/Company.php | 52 + .../src/Faker/Provider/ru_RU/Internet.php | 9 + .../src/Faker/Provider/ru_RU/Payment.php | 811 + lib/faker/src/Faker/Provider/ru_RU/Person.php | 135 + .../src/Faker/Provider/ru_RU/PhoneNumber.php | 14 + lib/faker/src/Faker/Provider/ru_RU/Text.php | 4544 +++++ .../src/Faker/Provider/sk_SK/Address.php | 344 + .../src/Faker/Provider/sk_SK/Company.php | 64 + .../src/Faker/Provider/sk_SK/Internet.php | 9 + .../src/Faker/Provider/sk_SK/Payment.php | 19 + lib/faker/src/Faker/Provider/sk_SK/Person.php | 168 + .../src/Faker/Provider/sk_SK/PhoneNumber.php | 15 + .../src/Faker/Provider/sl_SI/Address.php | 107 + .../src/Faker/Provider/sl_SI/Internet.php | 11 + .../src/Faker/Provider/sl_SI/Payment.php | 19 + lib/faker/src/Faker/Provider/sl_SI/Person.php | 149 + .../src/Faker/Provider/sl_SI/PhoneNumber.php | 18 + .../src/Faker/Provider/sr_Cyrl_RS/Address.php | 58 + .../src/Faker/Provider/sr_Cyrl_RS/Payment.php | 19 + .../src/Faker/Provider/sr_Cyrl_RS/Person.php | 242 + .../src/Faker/Provider/sr_Latn_RS/Address.php | 58 + .../src/Faker/Provider/sr_Latn_RS/Payment.php | 19 + .../src/Faker/Provider/sr_Latn_RS/Person.php | 213 + .../src/Faker/Provider/sr_RS/Address.php | 58 + .../src/Faker/Provider/sr_RS/Payment.php | 19 + lib/faker/src/Faker/Provider/sr_RS/Person.php | 247 + .../src/Faker/Provider/sv_SE/Address.php | 150 + .../src/Faker/Provider/sv_SE/Company.php | 19 + .../src/Faker/Provider/sv_SE/Payment.php | 19 + lib/faker/src/Faker/Provider/sv_SE/Person.php | 143 + .../src/Faker/Provider/sv_SE/PhoneNumber.php | 37 + .../src/Faker/Provider/tr_TR/Address.php | 92 + lib/faker/src/Faker/Provider/tr_TR/Color.php | 58 + .../src/Faker/Provider/tr_TR/DateTime.php | 46 + .../src/Faker/Provider/tr_TR/Internet.php | 9 + .../src/Faker/Provider/tr_TR/Payment.php | 19 + lib/faker/src/Faker/Provider/tr_TR/Person.php | 97 + .../src/Faker/Provider/tr_TR/PhoneNumber.php | 33 + .../src/Faker/Provider/uk_UA/Address.php | 345 + lib/faker/src/Faker/Provider/uk_UA/Color.php | 23 + .../src/Faker/Provider/uk_UA/Company.php | 44 + .../src/Faker/Provider/uk_UA/Internet.php | 9 + lib/faker/src/Faker/Provider/uk_UA/Person.php | 57 + .../src/Faker/Provider/uk_UA/PhoneNumber.php | 29 + lib/faker/src/Faker/Provider/uk_UA/Text.php | 4512 +++++ .../src/Faker/Provider/vi_VN/Address.php | 170 + lib/faker/src/Faker/Provider/vi_VN/Color.php | 36 + .../src/Faker/Provider/vi_VN/Internet.php | 8 + lib/faker/src/Faker/Provider/vi_VN/Person.php | 184 + .../src/Faker/Provider/vi_VN/PhoneNumber.php | 61 + .../src/Faker/Provider/zh_CN/Address.php | 43 + .../src/Faker/Provider/zh_CN/Company.php | 26 + .../src/Faker/Provider/zh_CN/Internet.php | 19 + lib/faker/src/Faker/Provider/zh_CN/Person.php | 79 + .../src/Faker/Provider/zh_CN/PhoneNumber.php | 21 + .../src/Faker/Provider/zh_TW/Address.php | 419 + lib/faker/src/Faker/Provider/zh_TW/Color.php | 66 + .../src/Faker/Provider/zh_TW/Company.php | 253 + .../src/Faker/Provider/zh_TW/DateTime.php | 46 + .../src/Faker/Provider/zh_TW/Internet.php | 16 + .../src/Faker/Provider/zh_TW/Payment.php | 11 + lib/faker/src/Faker/Provider/zh_TW/Person.php | 132 + .../src/Faker/Provider/zh_TW/PhoneNumber.php | 19 + lib/faker/src/Faker/Provider/zh_TW/Text.php | 124 + lib/faker/src/Faker/UniqueGenerator.php | 49 + lib/faker/src/autoload.php | 26 + lib/faker/test/Faker/Calculator/IbanTest.php | 305 + lib/faker/test/Faker/Calculator/LuhnTest.php | 62 + lib/faker/test/Faker/DefaultGeneratorTest.php | 27 + lib/faker/test/Faker/GeneratorTest.php | 147 + lib/faker/test/Faker/Provider/AddressTest.php | 34 + lib/faker/test/Faker/Provider/BarcodeTest.php | 45 + lib/faker/test/Faker/Provider/BaseTest.php | 467 + lib/faker/test/Faker/Provider/BiasedTest.php | 73 + lib/faker/test/Faker/Provider/ColorTest.php | 53 + .../test/Faker/Provider/DateTimeTest.php | 151 + lib/faker/test/Faker/Provider/ImageTest.php | 62 + .../test/Faker/Provider/InternetTest.php | 130 + .../test/Faker/Provider/LocalizationTest.php | 26 + lib/faker/test/Faker/Provider/LoremTest.php | 108 + .../test/Faker/Provider/MiscellaneousTest.php | 54 + lib/faker/test/Faker/Provider/PaymentTest.php | 206 + lib/faker/test/Faker/Provider/PersonTest.php | 86 + .../Faker/Provider/ProviderOverrideTest.php | 189 + lib/faker/test/Faker/Provider/TextTest.php | 54 + .../test/Faker/Provider/UserAgentTest.php | 38 + lib/faker/test/Faker/Provider/UuidTest.php | 26 + .../test/Faker/Provider/at_AT/PaymentTest.php | 30 + .../test/Faker/Provider/be_BE/PaymentTest.php | 30 + .../test/Faker/Provider/bg_BG/PaymentTest.php | 30 + .../test/Faker/Provider/cs_CZ/PersonTest.php | 46 + .../Faker/Provider/de_AT/InternetTest.php | 32 + .../Faker/Provider/de_AT/PhoneNumberTest.php | 28 + .../Faker/Provider/en_US/PhoneNumberTest.php | 84 + .../test/Faker/Provider/fr_FR/CompanyTest.php | 74 + .../test/Faker/Provider/id_ID/PersonTest.php | 40 + .../test/Faker/Provider/ja_JP/PersonTest.php | 36 + .../test/Faker/Provider/pt_BR/CompanyTest.php | 25 + .../test/Faker/Provider/pt_BR/PersonTest.php | 33 + .../test/Faker/Provider/pt_PT/AddressTest.php | 30 + .../test/Faker/Provider/pt_PT/PersonTest.php | 52 + .../Faker/Provider/pt_PT/PhoneNumberTest.php | 25 + .../test/Faker/Provider/ro_RO/PersonTest.php | 95 + .../Faker/Provider/ro_RO/PhoneNumberTest.php | 31 + .../test/Faker/Provider/sv_SE/PersonTest.php | 60 + .../test/Faker/Provider/uk_UA/AddressTest.php | 80 + .../Faker/Provider/uk_UA/PhoneNumberTest.php | 35 + lib/faker/test/documentor.php | 16 + lib/faker/test/test.php | 39 + lib/mobiledetect/index.php | 1447 ++ lib/simple_html_dom/simple_html_dom.php | 1742 ++ templates/elements/.gitkeep | 1 + templates/layouts/default.json | 6 + templates/layouts/default.php | 37 + templates/layouts/empty.php | 6 + templates/layouts/login.php | 42 + templates/views/index.php | 1 + templates/views/pages/terms.php | 43 + tmp/.gitkeep | 1 + vendor/autoload.php | 7 + vendor/bin/heroku-hhvm-apache2 | 1 + vendor/bin/heroku-hhvm-nginx | 1 + vendor/bin/heroku-php-apache2 | 1 + vendor/bin/heroku-php-nginx | 1 + vendor/composer/ClassLoader.php | 413 + vendor/composer/LICENSE | 21 + vendor/composer/autoload_classmap.php | 9 + vendor/composer/autoload_namespaces.php | 9 + vendor/composer/autoload_psr4.php | 9 + vendor/composer/autoload_real.php | 45 + vendor/composer/installed.json | 48 + vendor/heroku/heroku-buildpack-php/.gitignore | 3 + .../heroku/heroku-buildpack-php/.travis.yml | 2 + .../heroku/heroku-buildpack-php/CHANGELOG.md | 750 + vendor/heroku/heroku-buildpack-php/LICENSE | 19 + vendor/heroku/heroku-buildpack-php/README.md | 55 + .../heroku/heroku-buildpack-php/bin/compile | 302 + vendor/heroku/heroku-buildpack-php/bin/detect | 8 + .../bin/heroku-hhvm-apache2 | 374 + .../bin/heroku-hhvm-nginx | 374 + .../bin/heroku-php-apache2 | 405 + .../heroku-buildpack-php/bin/heroku-php-nginx | 406 + .../heroku/heroku-buildpack-php/bin/release | 9 + .../heroku-buildpack-php/bin/test-compile | 14 + .../bin/util/autotune.php | 79 + .../bin/util/blackfire.sh | 15 + .../heroku-buildpack-php/bin/util/common.sh | 66 + .../heroku-buildpack-php/bin/util/newrelic.sh | 25 + .../bin/util/platform.php | 172 + .../heroku/heroku-buildpack-php/composer.json | 20 + .../conf/apache2/default_include.conf | 1 + .../conf/apache2/heroku.conf | 70 + .../conf/hhvm/php.ini.php | 16 + .../conf/nginx/default_include.conf.php | 8 + .../conf/nginx/heroku.conf.php | 72 + .../conf/php/php-fpm.conf | 533 + .../heroku-buildpack-php/requirements.txt | 2 + .../support/build/README.md | 215 + .../support/build/_conf/apache2/httpd.conf | 527 + .../support/build/_conf/nginx/nginx.conf | 36 + .../_conf/php/conf.d/010-ext-zend_opcache.ini | 7 + .../support/build/_conf/php/php.ini | 1900 ++ .../support/build/_docker/README.md | 31 + .../support/build/_docker/cedar-14.Dockerfile | 13 + .../support/build/_docker/env.default | 8 + .../build/_docker/heroku-16.Dockerfile | 13 + .../support/build/_util/deploy.sh | 75 + .../support/build/_util/include/manifest.py | 23 + .../support/build/_util/include/manifest.sh | 13 + .../support/build/_util/mkrepo.sh | 102 + .../support/build/_util/remove.sh | 145 + .../support/build/_util/sync.sh | 287 + .../heroku-buildpack-php/support/build/apache | 72 + .../support/build/apache-2.4.20 | 4 + .../support/build/composer | 42 + .../support/build/composer-1.3.2 | 5 + .../extensions/no-debug-non-zts-20121212/apcu | 14 + .../no-debug-non-zts-20121212/apcu-4.0.11 | 5 + .../no-debug-non-zts-20121212/blackfire | 133 + .../blackfire-1.14.3 | 4 + .../no-debug-non-zts-20121212/cassandra | 45 + .../no-debug-non-zts-20121212/cassandra-1.2.2 | 5 + .../no-debug-non-zts-20121212/cassandra-bare | 55 + .../cassandra-bare-1.2.2 | 5 + .../extensions/no-debug-non-zts-20121212/ev | 5 + .../no-debug-non-zts-20121212/ev-1.0.4 | 5 + .../no-debug-non-zts-20121212/event | 5 + .../no-debug-non-zts-20121212/event-2.2.1 | 5 + .../no-debug-non-zts-20121212/imagick | 5 + .../no-debug-non-zts-20121212/imagick-3.4.3 | 5 + .../no-debug-non-zts-20121212/memcached | 51 + .../no-debug-non-zts-20121212/memcached-2.2.0 | 7 + .../no-debug-non-zts-20121212/memcached-bare | 84 + .../memcached-bare-2.2.0 | 5 + .../no-debug-non-zts-20121212/mongo | 5 + .../no-debug-non-zts-20121212/mongo-1.6.14 | 5 + .../no-debug-non-zts-20121212/mongodb | 5 + .../no-debug-non-zts-20121212/mongodb-1.2.5 | 5 + .../no-debug-non-zts-20121212/newrelic | 112 + .../newrelic-6.9.0.182 | 4 + .../no-debug-non-zts-20121212/oauth | 5 + .../no-debug-non-zts-20121212/oauth-1.2.3 | 5 + .../no-debug-non-zts-20121212/phalcon | 63 + .../no-debug-non-zts-20121212/phalcon-2.0.13 | 5 + .../no-debug-non-zts-20121212/phalcon-3.0.3 | 5 + .../extensions/no-debug-non-zts-20121212/pq | 24 + .../no-debug-non-zts-20121212/pq-1.1.1 | 5 + .../no-debug-non-zts-20121212/raphf | 5 + .../no-debug-non-zts-20121212/raphf-1.1.2 | 5 + .../no-debug-non-zts-20121212/rdkafka | 45 + .../no-debug-non-zts-20121212/rdkafka-3.0.1 | 5 + .../no-debug-non-zts-20121212/rdkafka-bare | 47 + .../rdkafka-bare-3.0.1 | 5 + .../no-debug-non-zts-20121212/redis | 5 + .../no-debug-non-zts-20121212/redis-3.1.1 | 5 + .../extensions/no-debug-non-zts-20131226/amqp | 20 + .../no-debug-non-zts-20131226/amqp-1.8.0 | 5 + .../no-debug-non-zts-20131226/apcu-4.0.11 | 6 + .../no-debug-non-zts-20131226/blackfire | 4 + .../blackfire-1.14.3 | 4 + .../no-debug-non-zts-20131226/cassandra-1.2.2 | 7 + .../cassandra-bare-1.2.2 | 5 + .../no-debug-non-zts-20131226/ev-1.0.4 | 6 + .../no-debug-non-zts-20131226/event-2.2.1 | 6 + .../no-debug-non-zts-20131226/imagick-3.4.3 | 6 + .../no-debug-non-zts-20131226/memcached-2.2.0 | 7 + .../memcached-bare-2.2.0 | 5 + .../no-debug-non-zts-20131226/mongo-1.6.14 | 6 + .../no-debug-non-zts-20131226/mongodb-1.2.5 | 6 + .../newrelic-6.9.0.182 | 4 + .../no-debug-non-zts-20131226/oauth-1.2.3 | 6 + .../no-debug-non-zts-20131226/phalcon-2.0.13 | 6 + .../no-debug-non-zts-20131226/phalcon-3.0.3 | 6 + .../no-debug-non-zts-20131226/pq-1.1.1 | 5 + .../no-debug-non-zts-20131226/raphf-1.1.2 | 6 + .../no-debug-non-zts-20131226/rdkafka-3.0.1 | 5 + .../rdkafka-bare-3.0.1 | 5 + .../no-debug-non-zts-20131226/redis-3.1.1 | 6 + .../no-debug-non-zts-20151012/amqp-1.8.0 | 5 + .../extensions/no-debug-non-zts-20151012/apcu | 78 + .../no-debug-non-zts-20151012/apcu-5.1.8 | 5 + .../no-debug-non-zts-20151012/blackfire | 4 + .../blackfire-1.14.3 | 4 + .../no-debug-non-zts-20151012/cassandra-1.2.2 | 7 + .../cassandra-bare-1.2.2 | 5 + .../no-debug-non-zts-20151012/ev-1.0.4 | 5 + .../no-debug-non-zts-20151012/event-2.2.1 | 5 + .../no-debug-non-zts-20151012/imagick-3.4.3 | 5 + .../no-debug-non-zts-20151012/memcached-3.0.3 | 7 + .../memcached-bare-3.0.3 | 5 + .../no-debug-non-zts-20151012/mongodb-1.2.5 | 5 + .../newrelic-6.9.0.182 | 4 + .../no-debug-non-zts-20151012/oauth-2.0.2 | 5 + .../no-debug-non-zts-20151012/phalcon-3.0.3 | 5 + .../no-debug-non-zts-20151012/pq-2.1.1 | 5 + .../no-debug-non-zts-20151012/raphf-2.0.0 | 5 + .../no-debug-non-zts-20151012/rdkafka-3.0.1 | 5 + .../rdkafka-bare-3.0.1 | 5 + .../no-debug-non-zts-20151012/redis-3.1.1 | 5 + .../no-debug-non-zts-20160303/amqp-1.8.0 | 5 + .../no-debug-non-zts-20160303/apcu-5.1.8 | 5 + .../no-debug-non-zts-20160303/blackfire | 4 + .../blackfire-1.14.3 | 4 + .../no-debug-non-zts-20160303/cassandra-1.2.2 | 7 + .../cassandra-bare-1.2.2 | 5 + .../no-debug-non-zts-20160303/ev-1.0.4 | 5 + .../no-debug-non-zts-20160303/event-2.2.1 | 5 + .../no-debug-non-zts-20160303/imagick-3.4.3 | 5 + .../no-debug-non-zts-20160303/memcached-3.0.3 | 7 + .../memcached-bare-3.0.3 | 5 + .../no-debug-non-zts-20160303/mongodb-1.2.5 | 5 + .../newrelic-6.9.0.182 | 4 + .../no-debug-non-zts-20160303/oauth-2.0.2 | 5 + .../no-debug-non-zts-20160303/pq-2.1.1 | 5 + .../no-debug-non-zts-20160303/raphf-2.0.0 | 5 + .../no-debug-non-zts-20160303/rdkafka-3.0.1 | 5 + .../rdkafka-bare-3.0.1 | 5 + .../no-debug-non-zts-20160303/redis-3.1.1 | 5 + .../support/build/extensions/pecl | 46 + .../heroku-buildpack-php/support/build/hhvm | 100 + .../support/build/hhvm-3.5.1 | 76 + .../support/build/libraries/libc-client | 46 + .../support/build/libraries/libc-client-2007f | 4 + .../support/build/libraries/libcassandra | 43 + .../build/libraries/libcassandra-2.4.2 | 4 + .../support/build/libraries/libmcrypt | 44 + .../support/build/libraries/libmcrypt-2.5.8 | 4 + .../support/build/libraries/libmemcached | 57 + .../build/libraries/libmemcached-1.0.18 | 4 + .../support/build/libraries/librdkafka | 42 + .../support/build/libraries/librdkafka-0.9.3 | 4 + .../heroku-buildpack-php/support/build/nginx | 70 + .../support/build/nginx-1.8.1 | 4 + .../heroku-buildpack-php/support/build/php | 199 + .../support/build/php-5.5.38 | 5 + .../support/build/php-5.6.30 | 5 + .../support/build/php-7.0.16 | 5 + .../support/build/php-7.1.2 | 5 + .../support/build/php-min | 67 + .../support/build/php-min-7.0.16 | 4 + .../support/installer/composer.json | 16 + .../installer/src/ComposerInstaller.php | 33 + .../installer/src/ComposerInstallerPlugin.php | 201 + .../support/installer/src/Downloader.php | 98 + webroot/_htaccess | 33 + webroot/assets/css/.gitkeep | 1 + webroot/assets/css/custom/.gitkeep | 1 + webroot/assets/icons/.gitkeep | 1 + webroot/assets/images/.gitkeep | 1 + webroot/assets/js/.gitkeep | 1 + webroot/assets/js/custom/.gitkeep | 1 + webroot/assets/vendor/.gitkeep | 1 + webroot/index.php | 26 + webroot/info.php | 1 + 897 files changed, 141768 insertions(+) create mode 100644 .gitignore create mode 100644 Procfile create mode 100644 README.md create mode 100644 app.json create mode 100644 app/api.php create mode 100644 app/controller.php create mode 100644 app/index.php create mode 100644 app/model/sample.php create mode 100644 app/rake.php create mode 100644 app/user.php create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 config/config.dev.ini create mode 100644 config/config.local.ini.sample create mode 100644 config/config.production.ini create mode 100644 config/config.staging.ini create mode 100644 config/config.testing.ini create mode 100644 config/routes.ini create mode 100644 config/settings.ini create mode 100644 config/sql/.gitkeep create mode 100644 lib/colors/colors.php create mode 100755 lib/f3/api/annotated.html create mode 100755 lib/f3/api/bc_s.png create mode 100755 lib/f3/api/bdwn.png create mode 100755 lib/f3/api/classAudit-members.html create mode 100755 lib/f3/api/classAudit.html create mode 100755 lib/f3/api/classAudit.png create mode 100755 lib/f3/api/classAuth-members.html create mode 100755 lib/f3/api/classAuth.html create mode 100755 lib/f3/api/classBase-members.html create mode 100755 lib/f3/api/classBase.html create mode 100755 lib/f3/api/classBase.png create mode 100755 lib/f3/api/classBasket-members.html create mode 100755 lib/f3/api/classBasket.html create mode 100755 lib/f3/api/classBcrypt-members.html create mode 100755 lib/f3/api/classBcrypt.html create mode 100755 lib/f3/api/classBcrypt.png create mode 100755 lib/f3/api/classCache-members.html create mode 100755 lib/f3/api/classCache.html create mode 100755 lib/f3/api/classCache.png create mode 100755 lib/f3/api/classDB_1_1Cursor-members.html create mode 100755 lib/f3/api/classDB_1_1Cursor.html create mode 100755 lib/f3/api/classDB_1_1Cursor.png create mode 100755 lib/f3/api/classDB_1_1Jig-members.html create mode 100755 lib/f3/api/classDB_1_1Jig.html create mode 100755 lib/f3/api/classDB_1_1Jig_1_1Mapper-members.html create mode 100755 lib/f3/api/classDB_1_1Jig_1_1Mapper.html create mode 100755 lib/f3/api/classDB_1_1Jig_1_1Mapper.png create mode 100755 lib/f3/api/classDB_1_1Jig_1_1Session-members.html create mode 100755 lib/f3/api/classDB_1_1Jig_1_1Session.html create mode 100755 lib/f3/api/classDB_1_1Jig_1_1Session.png create mode 100755 lib/f3/api/classDB_1_1Mongo-members.html create mode 100755 lib/f3/api/classDB_1_1Mongo.html create mode 100755 lib/f3/api/classDB_1_1Mongo.png create mode 100755 lib/f3/api/classDB_1_1Mongo_1_1Mapper-members.html create mode 100755 lib/f3/api/classDB_1_1Mongo_1_1Mapper.html create mode 100755 lib/f3/api/classDB_1_1Mongo_1_1Mapper.png create mode 100755 lib/f3/api/classDB_1_1Mongo_1_1Session-members.html create mode 100755 lib/f3/api/classDB_1_1Mongo_1_1Session.html create mode 100755 lib/f3/api/classDB_1_1Mongo_1_1Session.png create mode 100755 lib/f3/api/classDB_1_1SQL-members.html create mode 100755 lib/f3/api/classDB_1_1SQL.html create mode 100755 lib/f3/api/classDB_1_1SQL.png create mode 100755 lib/f3/api/classDB_1_1SQL_1_1Mapper-members.html create mode 100755 lib/f3/api/classDB_1_1SQL_1_1Mapper.html create mode 100755 lib/f3/api/classDB_1_1SQL_1_1Mapper.png create mode 100755 lib/f3/api/classDB_1_1SQL_1_1Session-members.html create mode 100755 lib/f3/api/classDB_1_1SQL_1_1Session.html create mode 100755 lib/f3/api/classDB_1_1SQL_1_1Session.png create mode 100755 lib/f3/api/classF3-members.html create mode 100755 lib/f3/api/classF3.html create mode 100755 lib/f3/api/classISO-members.html create mode 100755 lib/f3/api/classISO.html create mode 100755 lib/f3/api/classISO.png create mode 100755 lib/f3/api/classImage-members.html create mode 100755 lib/f3/api/classImage.html create mode 100755 lib/f3/api/classLog-members.html create mode 100755 lib/f3/api/classLog.html create mode 100755 lib/f3/api/classMagic-members.html create mode 100755 lib/f3/api/classMagic.html create mode 100755 lib/f3/api/classMagic.png create mode 100755 lib/f3/api/classMarkdown-members.html create mode 100755 lib/f3/api/classMarkdown.html create mode 100755 lib/f3/api/classMarkdown.png create mode 100755 lib/f3/api/classMatrix-members.html create mode 100755 lib/f3/api/classMatrix.html create mode 100755 lib/f3/api/classMatrix.png create mode 100755 lib/f3/api/classPrefab-members.html create mode 100755 lib/f3/api/classPrefab.html create mode 100755 lib/f3/api/classPrefab.png create mode 100755 lib/f3/api/classPreview-members.html create mode 100755 lib/f3/api/classPreview.html create mode 100755 lib/f3/api/classPreview.png create mode 100755 lib/f3/api/classRegistry-members.html create mode 100755 lib/f3/api/classRegistry.html create mode 100755 lib/f3/api/classSMTP-members.html create mode 100755 lib/f3/api/classSMTP.html create mode 100755 lib/f3/api/classSMTP.png create mode 100755 lib/f3/api/classSession-members.html create mode 100755 lib/f3/api/classSession.html create mode 100755 lib/f3/api/classTemplate-members.html create mode 100755 lib/f3/api/classTemplate.html create mode 100755 lib/f3/api/classTemplate.png create mode 100755 lib/f3/api/classTest-members.html create mode 100755 lib/f3/api/classTest.html create mode 100755 lib/f3/api/classUTF-members.html create mode 100755 lib/f3/api/classUTF.html create mode 100755 lib/f3/api/classUTF.png create mode 100755 lib/f3/api/classView-members.html create mode 100755 lib/f3/api/classView.html create mode 100755 lib/f3/api/classView.png create mode 100755 lib/f3/api/classWeb-members.html create mode 100755 lib/f3/api/classWeb.html create mode 100755 lib/f3/api/classWeb.png create mode 100755 lib/f3/api/classWeb_1_1Geo-members.html create mode 100755 lib/f3/api/classWeb_1_1Geo.html create mode 100755 lib/f3/api/classWeb_1_1Geo.png create mode 100755 lib/f3/api/classWeb_1_1Google_1_1StaticMap-members.html create mode 100755 lib/f3/api/classWeb_1_1Google_1_1StaticMap.html create mode 100755 lib/f3/api/classWeb_1_1OpenID-members.html create mode 100755 lib/f3/api/classWeb_1_1OpenID.html create mode 100755 lib/f3/api/classWeb_1_1OpenID.png create mode 100755 lib/f3/api/classWeb_1_1Pingback-members.html create mode 100755 lib/f3/api/classWeb_1_1Pingback.html create mode 100755 lib/f3/api/classWeb_1_1Pingback.png create mode 100755 lib/f3/api/classes.html create mode 100755 lib/f3/api/closed.png create mode 100755 lib/f3/api/dir_3a960e52dd9a2c9686c19ff6ef19d5fb.html create mode 100755 lib/f3/api/dir_562abdcd8625d4bf7bad2fe6fe01354c.html create mode 100755 lib/f3/api/dir_60985a986063d10a97c0bb7f42d76d6f.html create mode 100755 lib/f3/api/dir_826b1e4cd13f4e7f528ca52e638927e5.html create mode 100755 lib/f3/api/dir_9d4753e6cb22f68b75f0462ac2496f38.html create mode 100755 lib/f3/api/dir_ce5981f09099a3fa6071b9eb8fe67a2c.html create mode 100755 lib/f3/api/doxygen.css create mode 100755 lib/f3/api/doxygen.png create mode 100755 lib/f3/api/doxygen_8h_source.html create mode 100755 lib/f3/api/dynsections.js create mode 100755 lib/f3/api/ftv2blank.png create mode 100755 lib/f3/api/ftv2cl.png create mode 100755 lib/f3/api/ftv2doc.png create mode 100755 lib/f3/api/ftv2folderclosed.png create mode 100755 lib/f3/api/ftv2folderopen.png create mode 100755 lib/f3/api/ftv2lastnode.png create mode 100755 lib/f3/api/ftv2link.png create mode 100755 lib/f3/api/ftv2mlastnode.png create mode 100755 lib/f3/api/ftv2mnode.png create mode 100755 lib/f3/api/ftv2mo.png create mode 100755 lib/f3/api/ftv2node.png create mode 100755 lib/f3/api/ftv2ns.png create mode 100755 lib/f3/api/ftv2plastnode.png create mode 100755 lib/f3/api/ftv2pnode.png create mode 100755 lib/f3/api/ftv2splitbar.png create mode 100755 lib/f3/api/ftv2vertline.png create mode 100755 lib/f3/api/functions.html create mode 100755 lib/f3/api/functions_0x5f.html create mode 100755 lib/f3/api/functions_0x61.html create mode 100755 lib/f3/api/functions_0x62.html create mode 100755 lib/f3/api/functions_0x63.html create mode 100755 lib/f3/api/functions_0x64.html create mode 100755 lib/f3/api/functions_0x65.html create mode 100755 lib/f3/api/functions_0x66.html create mode 100755 lib/f3/api/functions_0x67.html create mode 100755 lib/f3/api/functions_0x68.html create mode 100755 lib/f3/api/functions_0x69.html create mode 100755 lib/f3/api/functions_0x6a.html create mode 100755 lib/f3/api/functions_0x6c.html create mode 100755 lib/f3/api/functions_0x6d.html create mode 100755 lib/f3/api/functions_0x6e.html create mode 100755 lib/f3/api/functions_0x6f.html create mode 100755 lib/f3/api/functions_0x70.html create mode 100755 lib/f3/api/functions_0x71.html create mode 100755 lib/f3/api/functions_0x72.html create mode 100755 lib/f3/api/functions_0x73.html create mode 100755 lib/f3/api/functions_0x74.html create mode 100755 lib/f3/api/functions_0x75.html create mode 100755 lib/f3/api/functions_0x76.html create mode 100755 lib/f3/api/functions_0x77.html create mode 100755 lib/f3/api/functions_0x78.html create mode 100755 lib/f3/api/functions__.html create mode 100755 lib/f3/api/functions_a.html create mode 100755 lib/f3/api/functions_b.html create mode 100755 lib/f3/api/functions_c.html create mode 100755 lib/f3/api/functions_d.html create mode 100755 lib/f3/api/functions_e.html create mode 100755 lib/f3/api/functions_f.html create mode 100755 lib/f3/api/functions_func.html create mode 100755 lib/f3/api/functions_func_0x61.html create mode 100755 lib/f3/api/functions_func_0x62.html create mode 100755 lib/f3/api/functions_func_0x63.html create mode 100755 lib/f3/api/functions_func_0x64.html create mode 100755 lib/f3/api/functions_func_0x65.html create mode 100755 lib/f3/api/functions_func_0x66.html create mode 100755 lib/f3/api/functions_func_0x67.html create mode 100755 lib/f3/api/functions_func_0x68.html create mode 100755 lib/f3/api/functions_func_0x69.html create mode 100755 lib/f3/api/functions_func_0x6a.html create mode 100755 lib/f3/api/functions_func_0x6c.html create mode 100755 lib/f3/api/functions_func_0x6d.html create mode 100755 lib/f3/api/functions_func_0x6e.html create mode 100755 lib/f3/api/functions_func_0x6f.html create mode 100755 lib/f3/api/functions_func_0x70.html create mode 100755 lib/f3/api/functions_func_0x71.html create mode 100755 lib/f3/api/functions_func_0x72.html create mode 100755 lib/f3/api/functions_func_0x73.html create mode 100755 lib/f3/api/functions_func_0x74.html create mode 100755 lib/f3/api/functions_func_0x75.html create mode 100755 lib/f3/api/functions_func_0x76.html create mode 100755 lib/f3/api/functions_func_0x77.html create mode 100755 lib/f3/api/functions_func_0x78.html create mode 100755 lib/f3/api/functions_func_a.html create mode 100755 lib/f3/api/functions_func_b.html create mode 100755 lib/f3/api/functions_func_c.html create mode 100755 lib/f3/api/functions_func_d.html create mode 100755 lib/f3/api/functions_func_e.html create mode 100755 lib/f3/api/functions_func_f.html create mode 100755 lib/f3/api/functions_func_g.html create mode 100755 lib/f3/api/functions_func_h.html create mode 100755 lib/f3/api/functions_func_i.html create mode 100755 lib/f3/api/functions_func_j.html create mode 100755 lib/f3/api/functions_func_l.html create mode 100755 lib/f3/api/functions_func_m.html create mode 100755 lib/f3/api/functions_func_n.html create mode 100755 lib/f3/api/functions_func_o.html create mode 100755 lib/f3/api/functions_func_p.html create mode 100755 lib/f3/api/functions_func_q.html create mode 100755 lib/f3/api/functions_func_r.html create mode 100755 lib/f3/api/functions_func_s.html create mode 100755 lib/f3/api/functions_func_t.html create mode 100755 lib/f3/api/functions_func_u.html create mode 100755 lib/f3/api/functions_func_v.html create mode 100755 lib/f3/api/functions_func_w.html create mode 100755 lib/f3/api/functions_g.html create mode 100755 lib/f3/api/functions_h.html create mode 100755 lib/f3/api/functions_i.html create mode 100755 lib/f3/api/functions_j.html create mode 100755 lib/f3/api/functions_l.html create mode 100755 lib/f3/api/functions_m.html create mode 100755 lib/f3/api/functions_n.html create mode 100755 lib/f3/api/functions_o.html create mode 100755 lib/f3/api/functions_p.html create mode 100755 lib/f3/api/functions_q.html create mode 100755 lib/f3/api/functions_r.html create mode 100755 lib/f3/api/functions_s.html create mode 100755 lib/f3/api/functions_t.html create mode 100755 lib/f3/api/functions_u.html create mode 100755 lib/f3/api/functions_v.html create mode 100755 lib/f3/api/functions_vars.html create mode 100755 lib/f3/api/functions_w.html create mode 100755 lib/f3/api/hierarchy.html create mode 100755 lib/f3/api/index.html create mode 100755 lib/f3/api/jquery.js create mode 100755 lib/f3/api/nav_f.png create mode 100755 lib/f3/api/nav_g.png create mode 100755 lib/f3/api/nav_h.png create mode 100755 lib/f3/api/open.png create mode 100755 lib/f3/api/sync_off.png create mode 100755 lib/f3/api/sync_on.png create mode 100755 lib/f3/api/tab_a.png create mode 100755 lib/f3/api/tab_b.png create mode 100755 lib/f3/api/tab_h.png create mode 100755 lib/f3/api/tab_s.png create mode 100755 lib/f3/api/tabs.css create mode 100755 lib/f3/audit.php create mode 100755 lib/f3/auth.php create mode 100755 lib/f3/base.php create mode 100755 lib/f3/basket.php create mode 100755 lib/f3/bcrypt.php create mode 100755 lib/f3/changelog.txt create mode 100755 lib/f3/code.css create mode 100644 lib/f3/db/cortex.php create mode 100755 lib/f3/db/cursor.php create mode 100755 lib/f3/db/jig.php create mode 100755 lib/f3/db/jig/mapper.php create mode 100755 lib/f3/db/jig/session.php create mode 100755 lib/f3/db/mongo.php create mode 100755 lib/f3/db/mongo/mapper.php create mode 100755 lib/f3/db/mongo/session.php create mode 100755 lib/f3/db/sql.php create mode 100755 lib/f3/db/sql/mapper.php create mode 100644 lib/f3/db/sql/schema.php create mode 100755 lib/f3/db/sql/session.php create mode 100755 lib/f3/f3.php create mode 100755 lib/f3/image.php create mode 100755 lib/f3/license.txt create mode 100755 lib/f3/log.php create mode 100755 lib/f3/magic.php create mode 100755 lib/f3/markdown.php create mode 100755 lib/f3/matrix.php create mode 100644 lib/f3/pagination.php create mode 100755 lib/f3/session.php create mode 100755 lib/f3/smtp.php create mode 100755 lib/f3/template.php create mode 100755 lib/f3/test.php create mode 100755 lib/f3/utf.php create mode 100755 lib/f3/web.php create mode 100755 lib/f3/web/geo.php create mode 100755 lib/f3/web/google/staticmap.php create mode 100755 lib/f3/web/openid.php create mode 100755 lib/f3/web/pingback.php create mode 100755 lib/faker/.gitignore create mode 100755 lib/faker/.travis.yml create mode 100755 lib/faker/CHANGELOG.md create mode 100755 lib/faker/CONTRIBUTING.md create mode 100755 lib/faker/LICENSE create mode 100755 lib/faker/Makefile create mode 100755 lib/faker/composer.json create mode 100755 lib/faker/phpunit.xml.dist create mode 100755 lib/faker/readme.md create mode 100755 lib/faker/src/Faker/Calculator/Iban.php create mode 100755 lib/faker/src/Faker/Calculator/Luhn.php create mode 100755 lib/faker/src/Faker/DefaultGenerator.php create mode 100755 lib/faker/src/Faker/Documentor.php create mode 100755 lib/faker/src/Faker/Factory.php create mode 100755 lib/faker/src/Faker/Generator.php create mode 100755 lib/faker/src/Faker/Guesser/Name.php create mode 100755 lib/faker/src/Faker/ORM/CakePHP/ColumnTypeGuesser.php create mode 100755 lib/faker/src/Faker/ORM/CakePHP/EntityPopulator.php create mode 100755 lib/faker/src/Faker/ORM/CakePHP/Populator.php create mode 100755 lib/faker/src/Faker/ORM/Doctrine/ColumnTypeGuesser.php create mode 100755 lib/faker/src/Faker/ORM/Doctrine/EntityPopulator.php create mode 100755 lib/faker/src/Faker/ORM/Doctrine/Populator.php create mode 100755 lib/faker/src/Faker/ORM/Mandango/ColumnTypeGuesser.php create mode 100755 lib/faker/src/Faker/ORM/Mandango/EntityPopulator.php create mode 100755 lib/faker/src/Faker/ORM/Mandango/Populator.php create mode 100755 lib/faker/src/Faker/ORM/Propel/ColumnTypeGuesser.php create mode 100755 lib/faker/src/Faker/ORM/Propel/EntityPopulator.php create mode 100755 lib/faker/src/Faker/ORM/Propel/Populator.php create mode 100755 lib/faker/src/Faker/Provider/Address.php create mode 100755 lib/faker/src/Faker/Provider/Barcode.php create mode 100755 lib/faker/src/Faker/Provider/Base.php create mode 100755 lib/faker/src/Faker/Provider/Biased.php create mode 100755 lib/faker/src/Faker/Provider/Color.php create mode 100755 lib/faker/src/Faker/Provider/Company.php create mode 100755 lib/faker/src/Faker/Provider/DateTime.php create mode 100755 lib/faker/src/Faker/Provider/File.php create mode 100755 lib/faker/src/Faker/Provider/Image.php create mode 100755 lib/faker/src/Faker/Provider/Internet.php create mode 100755 lib/faker/src/Faker/Provider/Lorem.php create mode 100755 lib/faker/src/Faker/Provider/Miscellaneous.php create mode 100755 lib/faker/src/Faker/Provider/Payment.php create mode 100755 lib/faker/src/Faker/Provider/Person.php create mode 100755 lib/faker/src/Faker/Provider/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/Text.php create mode 100755 lib/faker/src/Faker/Provider/UserAgent.php create mode 100755 lib/faker/src/Faker/Provider/Uuid.php create mode 100755 lib/faker/src/Faker/Provider/ar_JO/Address.php create mode 100755 lib/faker/src/Faker/Provider/ar_JO/Company.php create mode 100755 lib/faker/src/Faker/Provider/ar_JO/Internet.php create mode 100755 lib/faker/src/Faker/Provider/ar_JO/Person.php create mode 100755 lib/faker/src/Faker/Provider/ar_JO/Text.php create mode 100755 lib/faker/src/Faker/Provider/ar_SA/Address.php create mode 100755 lib/faker/src/Faker/Provider/ar_SA/Company.php create mode 100755 lib/faker/src/Faker/Provider/ar_SA/Internet.php create mode 100755 lib/faker/src/Faker/Provider/ar_SA/Person.php create mode 100755 lib/faker/src/Faker/Provider/ar_SA/Text.php create mode 100755 lib/faker/src/Faker/Provider/at_AT/Payment.php create mode 100755 lib/faker/src/Faker/Provider/be_BE/Payment.php create mode 100755 lib/faker/src/Faker/Provider/bg_BG/Internet.php create mode 100755 lib/faker/src/Faker/Provider/bg_BG/Payment.php create mode 100755 lib/faker/src/Faker/Provider/bg_BG/Person.php create mode 100755 lib/faker/src/Faker/Provider/bg_BG/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/bn_BD/Address.php create mode 100755 lib/faker/src/Faker/Provider/bn_BD/Company.php create mode 100755 lib/faker/src/Faker/Provider/bn_BD/Person.php create mode 100755 lib/faker/src/Faker/Provider/bn_BD/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/bn_BD/Utils.php create mode 100755 lib/faker/src/Faker/Provider/cs_CZ/Address.php create mode 100755 lib/faker/src/Faker/Provider/cs_CZ/Company.php create mode 100755 lib/faker/src/Faker/Provider/cs_CZ/DateTime.php create mode 100755 lib/faker/src/Faker/Provider/cs_CZ/Internet.php create mode 100755 lib/faker/src/Faker/Provider/cs_CZ/Payment.php create mode 100755 lib/faker/src/Faker/Provider/cs_CZ/Person.php create mode 100755 lib/faker/src/Faker/Provider/cs_CZ/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/cs_CZ/Text.php create mode 100755 lib/faker/src/Faker/Provider/da_DK/Address.php create mode 100755 lib/faker/src/Faker/Provider/da_DK/Company.php create mode 100755 lib/faker/src/Faker/Provider/da_DK/Internet.php create mode 100755 lib/faker/src/Faker/Provider/da_DK/Payment.php create mode 100755 lib/faker/src/Faker/Provider/da_DK/Person.php create mode 100755 lib/faker/src/Faker/Provider/da_DK/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/de_AT/Address.php create mode 100755 lib/faker/src/Faker/Provider/de_AT/Company.php create mode 100755 lib/faker/src/Faker/Provider/de_AT/Internet.php create mode 100755 lib/faker/src/Faker/Provider/de_AT/Payment.php create mode 100755 lib/faker/src/Faker/Provider/de_AT/Person.php create mode 100755 lib/faker/src/Faker/Provider/de_AT/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/de_DE/Address.php create mode 100755 lib/faker/src/Faker/Provider/de_DE/Company.php create mode 100755 lib/faker/src/Faker/Provider/de_DE/Internet.php create mode 100755 lib/faker/src/Faker/Provider/de_DE/Payment.php create mode 100755 lib/faker/src/Faker/Provider/de_DE/Person.php create mode 100755 lib/faker/src/Faker/Provider/de_DE/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/de_DE/Text.php create mode 100755 lib/faker/src/Faker/Provider/el_GR/Address.php create mode 100755 lib/faker/src/Faker/Provider/el_GR/Company.php create mode 100755 lib/faker/src/Faker/Provider/el_GR/Payment.php create mode 100755 lib/faker/src/Faker/Provider/el_GR/Person.php create mode 100755 lib/faker/src/Faker/Provider/el_GR/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/en_AU/Address.php create mode 100755 lib/faker/src/Faker/Provider/en_AU/Internet.php create mode 100755 lib/faker/src/Faker/Provider/en_AU/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/en_CA/Address.php create mode 100755 lib/faker/src/Faker/Provider/en_CA/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/en_GB/Address.php create mode 100755 lib/faker/src/Faker/Provider/en_GB/Internet.php create mode 100755 lib/faker/src/Faker/Provider/en_GB/Payment.php create mode 100755 lib/faker/src/Faker/Provider/en_GB/Person.php create mode 100755 lib/faker/src/Faker/Provider/en_GB/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/en_NZ/Address.php create mode 100755 lib/faker/src/Faker/Provider/en_NZ/Internet.php create mode 100755 lib/faker/src/Faker/Provider/en_NZ/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/en_PH/Address.php create mode 100755 lib/faker/src/Faker/Provider/en_PH/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/en_UG/Address.php create mode 100755 lib/faker/src/Faker/Provider/en_UG/Internet.php create mode 100755 lib/faker/src/Faker/Provider/en_UG/Person.php create mode 100755 lib/faker/src/Faker/Provider/en_UG/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/en_US/Address.php create mode 100755 lib/faker/src/Faker/Provider/en_US/Company.php create mode 100755 lib/faker/src/Faker/Provider/en_US/Person.php create mode 100755 lib/faker/src/Faker/Provider/en_US/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/en_US/Text.php create mode 100755 lib/faker/src/Faker/Provider/en_ZA/Address.php create mode 100755 lib/faker/src/Faker/Provider/en_ZA/Internet.php create mode 100755 lib/faker/src/Faker/Provider/en_ZA/Person.php create mode 100755 lib/faker/src/Faker/Provider/en_ZA/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/es_AR/Address.php create mode 100755 lib/faker/src/Faker/Provider/es_AR/Company.php create mode 100755 lib/faker/src/Faker/Provider/es_AR/Person.php create mode 100755 lib/faker/src/Faker/Provider/es_AR/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/es_ES/Address.php create mode 100755 lib/faker/src/Faker/Provider/es_ES/Company.php create mode 100755 lib/faker/src/Faker/Provider/es_ES/Internet.php create mode 100755 lib/faker/src/Faker/Provider/es_ES/Payment.php create mode 100755 lib/faker/src/Faker/Provider/es_ES/Person.php create mode 100755 lib/faker/src/Faker/Provider/es_ES/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/es_PE/Address.php create mode 100755 lib/faker/src/Faker/Provider/es_PE/Company.php create mode 100755 lib/faker/src/Faker/Provider/es_PE/Person.php create mode 100755 lib/faker/src/Faker/Provider/es_PE/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/es_VE/Address.php create mode 100755 lib/faker/src/Faker/Provider/es_VE/Company.php create mode 100755 lib/faker/src/Faker/Provider/es_VE/Internet.php create mode 100755 lib/faker/src/Faker/Provider/es_VE/Person.php create mode 100755 lib/faker/src/Faker/Provider/es_VE/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/fa_IR/Internet.php create mode 100755 lib/faker/src/Faker/Provider/fa_IR/Person.php create mode 100755 lib/faker/src/Faker/Provider/fa_IR/Text.php create mode 100755 lib/faker/src/Faker/Provider/fi_FI/Address.php create mode 100755 lib/faker/src/Faker/Provider/fi_FI/Company.php create mode 100755 lib/faker/src/Faker/Provider/fi_FI/Internet.php create mode 100755 lib/faker/src/Faker/Provider/fi_FI/Person.php create mode 100755 lib/faker/src/Faker/Provider/fi_FI/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/fr_BE/Address.php create mode 100755 lib/faker/src/Faker/Provider/fr_BE/Company.php create mode 100755 lib/faker/src/Faker/Provider/fr_BE/Internet.php create mode 100755 lib/faker/src/Faker/Provider/fr_BE/Payment.php create mode 100755 lib/faker/src/Faker/Provider/fr_BE/Person.php create mode 100755 lib/faker/src/Faker/Provider/fr_BE/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/fr_CA/Address.php create mode 100755 lib/faker/src/Faker/Provider/fr_CA/Person.php create mode 100755 lib/faker/src/Faker/Provider/fr_FR/Address.php create mode 100755 lib/faker/src/Faker/Provider/fr_FR/Company.php create mode 100755 lib/faker/src/Faker/Provider/fr_FR/Internet.php create mode 100755 lib/faker/src/Faker/Provider/fr_FR/Payment.php create mode 100755 lib/faker/src/Faker/Provider/fr_FR/Person.php create mode 100755 lib/faker/src/Faker/Provider/fr_FR/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/fr_FR/Text.php create mode 100755 lib/faker/src/Faker/Provider/he_IL/Address.php create mode 100755 lib/faker/src/Faker/Provider/he_IL/Company.php create mode 100755 lib/faker/src/Faker/Provider/he_IL/Person.php create mode 100755 lib/faker/src/Faker/Provider/he_IL/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/hu_HU/Address.php create mode 100755 lib/faker/src/Faker/Provider/hu_HU/Company.php create mode 100755 lib/faker/src/Faker/Provider/hu_HU/Payment.php create mode 100755 lib/faker/src/Faker/Provider/hu_HU/Person.php create mode 100755 lib/faker/src/Faker/Provider/hu_HU/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/hu_HU/Text.php create mode 100755 lib/faker/src/Faker/Provider/hy_AM/Address.php create mode 100755 lib/faker/src/Faker/Provider/hy_AM/Company.php create mode 100755 lib/faker/src/Faker/Provider/hy_AM/Internet.php create mode 100755 lib/faker/src/Faker/Provider/hy_AM/Person.php create mode 100755 lib/faker/src/Faker/Provider/hy_AM/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/id_ID/Address.php create mode 100755 lib/faker/src/Faker/Provider/id_ID/Company.php create mode 100755 lib/faker/src/Faker/Provider/id_ID/Internet.php create mode 100755 lib/faker/src/Faker/Provider/id_ID/Person.php create mode 100755 lib/faker/src/Faker/Provider/id_ID/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/is_IS/Address.php create mode 100755 lib/faker/src/Faker/Provider/is_IS/Company.php create mode 100755 lib/faker/src/Faker/Provider/is_IS/Internet.php create mode 100755 lib/faker/src/Faker/Provider/is_IS/Payment.php create mode 100755 lib/faker/src/Faker/Provider/is_IS/Person.php create mode 100755 lib/faker/src/Faker/Provider/is_IS/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/it_IT/Address.php create mode 100755 lib/faker/src/Faker/Provider/it_IT/Company.php create mode 100755 lib/faker/src/Faker/Provider/it_IT/Internet.php create mode 100755 lib/faker/src/Faker/Provider/it_IT/Payment.php create mode 100755 lib/faker/src/Faker/Provider/it_IT/Person.php create mode 100755 lib/faker/src/Faker/Provider/it_IT/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/it_IT/Text.php create mode 100755 lib/faker/src/Faker/Provider/ja_JP/Address.php create mode 100755 lib/faker/src/Faker/Provider/ja_JP/Company.php create mode 100755 lib/faker/src/Faker/Provider/ja_JP/Internet.php create mode 100755 lib/faker/src/Faker/Provider/ja_JP/Person.php create mode 100755 lib/faker/src/Faker/Provider/ja_JP/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/ka_GE/Payment.php create mode 100755 lib/faker/src/Faker/Provider/ka_GE/Person.php create mode 100755 lib/faker/src/Faker/Provider/ka_GE/Text.php create mode 100755 lib/faker/src/Faker/Provider/kk_KZ/Address.php create mode 100755 lib/faker/src/Faker/Provider/kk_KZ/Color.php create mode 100755 lib/faker/src/Faker/Provider/kk_KZ/Company.php create mode 100755 lib/faker/src/Faker/Provider/kk_KZ/Internet.php create mode 100755 lib/faker/src/Faker/Provider/kk_KZ/Payment.php create mode 100755 lib/faker/src/Faker/Provider/kk_KZ/Person.php create mode 100755 lib/faker/src/Faker/Provider/kk_KZ/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/kk_KZ/Text.php create mode 100755 lib/faker/src/Faker/Provider/ko_KR/Address.php create mode 100755 lib/faker/src/Faker/Provider/ko_KR/Company.php create mode 100755 lib/faker/src/Faker/Provider/ko_KR/Internet.php create mode 100755 lib/faker/src/Faker/Provider/ko_KR/Person.php create mode 100755 lib/faker/src/Faker/Provider/ko_KR/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/lv_LV/Address.php create mode 100755 lib/faker/src/Faker/Provider/lv_LV/Color.php create mode 100755 lib/faker/src/Faker/Provider/lv_LV/Internet.php create mode 100755 lib/faker/src/Faker/Provider/lv_LV/Payment.php create mode 100755 lib/faker/src/Faker/Provider/lv_LV/Person.php create mode 100755 lib/faker/src/Faker/Provider/lv_LV/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/me_ME/Address.php create mode 100755 lib/faker/src/Faker/Provider/me_ME/Company.php create mode 100755 lib/faker/src/Faker/Provider/me_ME/Payment.php create mode 100755 lib/faker/src/Faker/Provider/me_ME/Person.php create mode 100755 lib/faker/src/Faker/Provider/me_ME/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/ne_NP/Address.php create mode 100755 lib/faker/src/Faker/Provider/ne_NP/Internet.php create mode 100755 lib/faker/src/Faker/Provider/ne_NP/Person.php create mode 100755 lib/faker/src/Faker/Provider/ne_NP/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/nl_BE/Address.php create mode 100755 lib/faker/src/Faker/Provider/nl_BE/Company.php create mode 100755 lib/faker/src/Faker/Provider/nl_BE/Internet.php create mode 100755 lib/faker/src/Faker/Provider/nl_BE/Payment.php create mode 100755 lib/faker/src/Faker/Provider/nl_BE/Person.php create mode 100755 lib/faker/src/Faker/Provider/nl_BE/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/nl_NL/Address.php create mode 100755 lib/faker/src/Faker/Provider/nl_NL/Color.php create mode 100755 lib/faker/src/Faker/Provider/nl_NL/Company.php create mode 100755 lib/faker/src/Faker/Provider/nl_NL/Internet.php create mode 100755 lib/faker/src/Faker/Provider/nl_NL/Payment.php create mode 100755 lib/faker/src/Faker/Provider/nl_NL/Person.php create mode 100755 lib/faker/src/Faker/Provider/nl_NL/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/no_NO/Address.php create mode 100755 lib/faker/src/Faker/Provider/no_NO/Company.php create mode 100755 lib/faker/src/Faker/Provider/no_NO/Payment.php create mode 100755 lib/faker/src/Faker/Provider/no_NO/Person.php create mode 100755 lib/faker/src/Faker/Provider/no_NO/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/pl_PL/Address.php create mode 100755 lib/faker/src/Faker/Provider/pl_PL/Company.php create mode 100755 lib/faker/src/Faker/Provider/pl_PL/Internet.php create mode 100755 lib/faker/src/Faker/Provider/pl_PL/Payment.php create mode 100755 lib/faker/src/Faker/Provider/pl_PL/Person.php create mode 100755 lib/faker/src/Faker/Provider/pl_PL/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/pl_PL/Text.php create mode 100755 lib/faker/src/Faker/Provider/pt_BR/Address.php create mode 100755 lib/faker/src/Faker/Provider/pt_BR/Company.php create mode 100755 lib/faker/src/Faker/Provider/pt_BR/Internet.php create mode 100755 lib/faker/src/Faker/Provider/pt_BR/Payment.php create mode 100755 lib/faker/src/Faker/Provider/pt_BR/Person.php create mode 100755 lib/faker/src/Faker/Provider/pt_BR/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/pt_BR/check_digit.php create mode 100755 lib/faker/src/Faker/Provider/pt_PT/Address.php create mode 100755 lib/faker/src/Faker/Provider/pt_PT/Payment.php create mode 100755 lib/faker/src/Faker/Provider/pt_PT/Person.php create mode 100755 lib/faker/src/Faker/Provider/pt_PT/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/ro_MD/Address.php create mode 100755 lib/faker/src/Faker/Provider/ro_MD/Payment.php create mode 100755 lib/faker/src/Faker/Provider/ro_MD/Person.php create mode 100755 lib/faker/src/Faker/Provider/ro_MD/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/ro_RO/Address.php create mode 100755 lib/faker/src/Faker/Provider/ro_RO/Payment.php create mode 100755 lib/faker/src/Faker/Provider/ro_RO/Person.php create mode 100755 lib/faker/src/Faker/Provider/ro_RO/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/ru_RU/Address.php create mode 100755 lib/faker/src/Faker/Provider/ru_RU/Color.php create mode 100755 lib/faker/src/Faker/Provider/ru_RU/Company.php create mode 100755 lib/faker/src/Faker/Provider/ru_RU/Internet.php create mode 100755 lib/faker/src/Faker/Provider/ru_RU/Payment.php create mode 100755 lib/faker/src/Faker/Provider/ru_RU/Person.php create mode 100755 lib/faker/src/Faker/Provider/ru_RU/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/ru_RU/Text.php create mode 100755 lib/faker/src/Faker/Provider/sk_SK/Address.php create mode 100755 lib/faker/src/Faker/Provider/sk_SK/Company.php create mode 100755 lib/faker/src/Faker/Provider/sk_SK/Internet.php create mode 100755 lib/faker/src/Faker/Provider/sk_SK/Payment.php create mode 100755 lib/faker/src/Faker/Provider/sk_SK/Person.php create mode 100755 lib/faker/src/Faker/Provider/sk_SK/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/sl_SI/Address.php create mode 100755 lib/faker/src/Faker/Provider/sl_SI/Internet.php create mode 100755 lib/faker/src/Faker/Provider/sl_SI/Payment.php create mode 100755 lib/faker/src/Faker/Provider/sl_SI/Person.php create mode 100755 lib/faker/src/Faker/Provider/sl_SI/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/sr_Cyrl_RS/Address.php create mode 100755 lib/faker/src/Faker/Provider/sr_Cyrl_RS/Payment.php create mode 100755 lib/faker/src/Faker/Provider/sr_Cyrl_RS/Person.php create mode 100755 lib/faker/src/Faker/Provider/sr_Latn_RS/Address.php create mode 100755 lib/faker/src/Faker/Provider/sr_Latn_RS/Payment.php create mode 100755 lib/faker/src/Faker/Provider/sr_Latn_RS/Person.php create mode 100755 lib/faker/src/Faker/Provider/sr_RS/Address.php create mode 100755 lib/faker/src/Faker/Provider/sr_RS/Payment.php create mode 100755 lib/faker/src/Faker/Provider/sr_RS/Person.php create mode 100755 lib/faker/src/Faker/Provider/sv_SE/Address.php create mode 100755 lib/faker/src/Faker/Provider/sv_SE/Company.php create mode 100755 lib/faker/src/Faker/Provider/sv_SE/Payment.php create mode 100755 lib/faker/src/Faker/Provider/sv_SE/Person.php create mode 100755 lib/faker/src/Faker/Provider/sv_SE/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/tr_TR/Address.php create mode 100755 lib/faker/src/Faker/Provider/tr_TR/Color.php create mode 100755 lib/faker/src/Faker/Provider/tr_TR/DateTime.php create mode 100755 lib/faker/src/Faker/Provider/tr_TR/Internet.php create mode 100755 lib/faker/src/Faker/Provider/tr_TR/Payment.php create mode 100755 lib/faker/src/Faker/Provider/tr_TR/Person.php create mode 100755 lib/faker/src/Faker/Provider/tr_TR/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/uk_UA/Address.php create mode 100755 lib/faker/src/Faker/Provider/uk_UA/Color.php create mode 100755 lib/faker/src/Faker/Provider/uk_UA/Company.php create mode 100755 lib/faker/src/Faker/Provider/uk_UA/Internet.php create mode 100755 lib/faker/src/Faker/Provider/uk_UA/Person.php create mode 100755 lib/faker/src/Faker/Provider/uk_UA/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/uk_UA/Text.php create mode 100755 lib/faker/src/Faker/Provider/vi_VN/Address.php create mode 100755 lib/faker/src/Faker/Provider/vi_VN/Color.php create mode 100755 lib/faker/src/Faker/Provider/vi_VN/Internet.php create mode 100755 lib/faker/src/Faker/Provider/vi_VN/Person.php create mode 100755 lib/faker/src/Faker/Provider/vi_VN/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/zh_CN/Address.php create mode 100755 lib/faker/src/Faker/Provider/zh_CN/Company.php create mode 100755 lib/faker/src/Faker/Provider/zh_CN/Internet.php create mode 100755 lib/faker/src/Faker/Provider/zh_CN/Person.php create mode 100755 lib/faker/src/Faker/Provider/zh_CN/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/zh_TW/Address.php create mode 100755 lib/faker/src/Faker/Provider/zh_TW/Color.php create mode 100755 lib/faker/src/Faker/Provider/zh_TW/Company.php create mode 100755 lib/faker/src/Faker/Provider/zh_TW/DateTime.php create mode 100755 lib/faker/src/Faker/Provider/zh_TW/Internet.php create mode 100755 lib/faker/src/Faker/Provider/zh_TW/Payment.php create mode 100755 lib/faker/src/Faker/Provider/zh_TW/Person.php create mode 100755 lib/faker/src/Faker/Provider/zh_TW/PhoneNumber.php create mode 100755 lib/faker/src/Faker/Provider/zh_TW/Text.php create mode 100755 lib/faker/src/Faker/UniqueGenerator.php create mode 100755 lib/faker/src/autoload.php create mode 100755 lib/faker/test/Faker/Calculator/IbanTest.php create mode 100755 lib/faker/test/Faker/Calculator/LuhnTest.php create mode 100755 lib/faker/test/Faker/DefaultGeneratorTest.php create mode 100755 lib/faker/test/Faker/GeneratorTest.php create mode 100755 lib/faker/test/Faker/Provider/AddressTest.php create mode 100755 lib/faker/test/Faker/Provider/BarcodeTest.php create mode 100755 lib/faker/test/Faker/Provider/BaseTest.php create mode 100755 lib/faker/test/Faker/Provider/BiasedTest.php create mode 100755 lib/faker/test/Faker/Provider/ColorTest.php create mode 100755 lib/faker/test/Faker/Provider/DateTimeTest.php create mode 100755 lib/faker/test/Faker/Provider/ImageTest.php create mode 100755 lib/faker/test/Faker/Provider/InternetTest.php create mode 100755 lib/faker/test/Faker/Provider/LocalizationTest.php create mode 100755 lib/faker/test/Faker/Provider/LoremTest.php create mode 100755 lib/faker/test/Faker/Provider/MiscellaneousTest.php create mode 100755 lib/faker/test/Faker/Provider/PaymentTest.php create mode 100755 lib/faker/test/Faker/Provider/PersonTest.php create mode 100755 lib/faker/test/Faker/Provider/ProviderOverrideTest.php create mode 100755 lib/faker/test/Faker/Provider/TextTest.php create mode 100755 lib/faker/test/Faker/Provider/UserAgentTest.php create mode 100755 lib/faker/test/Faker/Provider/UuidTest.php create mode 100755 lib/faker/test/Faker/Provider/at_AT/PaymentTest.php create mode 100755 lib/faker/test/Faker/Provider/be_BE/PaymentTest.php create mode 100755 lib/faker/test/Faker/Provider/bg_BG/PaymentTest.php create mode 100755 lib/faker/test/Faker/Provider/cs_CZ/PersonTest.php create mode 100755 lib/faker/test/Faker/Provider/de_AT/InternetTest.php create mode 100755 lib/faker/test/Faker/Provider/de_AT/PhoneNumberTest.php create mode 100755 lib/faker/test/Faker/Provider/en_US/PhoneNumberTest.php create mode 100755 lib/faker/test/Faker/Provider/fr_FR/CompanyTest.php create mode 100755 lib/faker/test/Faker/Provider/id_ID/PersonTest.php create mode 100755 lib/faker/test/Faker/Provider/ja_JP/PersonTest.php create mode 100755 lib/faker/test/Faker/Provider/pt_BR/CompanyTest.php create mode 100755 lib/faker/test/Faker/Provider/pt_BR/PersonTest.php create mode 100755 lib/faker/test/Faker/Provider/pt_PT/AddressTest.php create mode 100755 lib/faker/test/Faker/Provider/pt_PT/PersonTest.php create mode 100755 lib/faker/test/Faker/Provider/pt_PT/PhoneNumberTest.php create mode 100755 lib/faker/test/Faker/Provider/ro_RO/PersonTest.php create mode 100755 lib/faker/test/Faker/Provider/ro_RO/PhoneNumberTest.php create mode 100755 lib/faker/test/Faker/Provider/sv_SE/PersonTest.php create mode 100755 lib/faker/test/Faker/Provider/uk_UA/AddressTest.php create mode 100755 lib/faker/test/Faker/Provider/uk_UA/PhoneNumberTest.php create mode 100755 lib/faker/test/documentor.php create mode 100755 lib/faker/test/test.php create mode 100644 lib/mobiledetect/index.php create mode 100644 lib/simple_html_dom/simple_html_dom.php create mode 100644 templates/elements/.gitkeep create mode 100644 templates/layouts/default.json create mode 100644 templates/layouts/default.php create mode 100644 templates/layouts/empty.php create mode 100644 templates/layouts/login.php create mode 100644 templates/views/index.php create mode 100644 templates/views/pages/terms.php create mode 100644 tmp/.gitkeep create mode 100644 vendor/autoload.php create mode 120000 vendor/bin/heroku-hhvm-apache2 create mode 120000 vendor/bin/heroku-hhvm-nginx create mode 120000 vendor/bin/heroku-php-apache2 create mode 120000 vendor/bin/heroku-php-nginx create mode 100644 vendor/composer/ClassLoader.php create mode 100644 vendor/composer/LICENSE create mode 100644 vendor/composer/autoload_classmap.php create mode 100644 vendor/composer/autoload_namespaces.php create mode 100644 vendor/composer/autoload_psr4.php create mode 100644 vendor/composer/autoload_real.php create mode 100644 vendor/composer/installed.json create mode 100644 vendor/heroku/heroku-buildpack-php/.gitignore create mode 100644 vendor/heroku/heroku-buildpack-php/.travis.yml create mode 100644 vendor/heroku/heroku-buildpack-php/CHANGELOG.md create mode 100644 vendor/heroku/heroku-buildpack-php/LICENSE create mode 100644 vendor/heroku/heroku-buildpack-php/README.md create mode 100755 vendor/heroku/heroku-buildpack-php/bin/compile create mode 100755 vendor/heroku/heroku-buildpack-php/bin/detect create mode 100755 vendor/heroku/heroku-buildpack-php/bin/heroku-hhvm-apache2 create mode 100755 vendor/heroku/heroku-buildpack-php/bin/heroku-hhvm-nginx create mode 100755 vendor/heroku/heroku-buildpack-php/bin/heroku-php-apache2 create mode 100755 vendor/heroku/heroku-buildpack-php/bin/heroku-php-nginx create mode 100755 vendor/heroku/heroku-buildpack-php/bin/release create mode 100755 vendor/heroku/heroku-buildpack-php/bin/test-compile create mode 100755 vendor/heroku/heroku-buildpack-php/bin/util/autotune.php create mode 100755 vendor/heroku/heroku-buildpack-php/bin/util/blackfire.sh create mode 100755 vendor/heroku/heroku-buildpack-php/bin/util/common.sh create mode 100755 vendor/heroku/heroku-buildpack-php/bin/util/newrelic.sh create mode 100755 vendor/heroku/heroku-buildpack-php/bin/util/platform.php create mode 100644 vendor/heroku/heroku-buildpack-php/composer.json create mode 100644 vendor/heroku/heroku-buildpack-php/conf/apache2/default_include.conf create mode 100644 vendor/heroku/heroku-buildpack-php/conf/apache2/heroku.conf create mode 100644 vendor/heroku/heroku-buildpack-php/conf/hhvm/php.ini.php create mode 100644 vendor/heroku/heroku-buildpack-php/conf/nginx/default_include.conf.php create mode 100644 vendor/heroku/heroku-buildpack-php/conf/nginx/heroku.conf.php create mode 100644 vendor/heroku/heroku-buildpack-php/conf/php/php-fpm.conf create mode 100644 vendor/heroku/heroku-buildpack-php/requirements.txt create mode 100644 vendor/heroku/heroku-buildpack-php/support/build/README.md create mode 100644 vendor/heroku/heroku-buildpack-php/support/build/_conf/apache2/httpd.conf create mode 100644 vendor/heroku/heroku-buildpack-php/support/build/_conf/nginx/nginx.conf create mode 100644 vendor/heroku/heroku-buildpack-php/support/build/_conf/php/conf.d/010-ext-zend_opcache.ini create mode 100644 vendor/heroku/heroku-buildpack-php/support/build/_conf/php/php.ini create mode 100644 vendor/heroku/heroku-buildpack-php/support/build/_docker/README.md create mode 100644 vendor/heroku/heroku-buildpack-php/support/build/_docker/cedar-14.Dockerfile create mode 100644 vendor/heroku/heroku-buildpack-php/support/build/_docker/env.default create mode 100644 vendor/heroku/heroku-buildpack-php/support/build/_docker/heroku-16.Dockerfile create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/_util/deploy.sh create mode 100644 vendor/heroku/heroku-buildpack-php/support/build/_util/include/manifest.py create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/_util/include/manifest.sh create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/_util/mkrepo.sh create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/_util/remove.sh create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/_util/sync.sh create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/apache create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/apache-2.4.20 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/composer create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/composer-1.3.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/apcu create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/apcu-4.0.11 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/blackfire create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/blackfire-1.14.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-1.2.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-bare create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-bare-1.2.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/ev create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/ev-1.0.4 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/event create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/event-2.2.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/imagick create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/imagick-3.4.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-2.2.0 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-bare create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-bare-2.2.0 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongo create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongo-1.6.14 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongodb create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongodb-1.2.5 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/newrelic create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/newrelic-6.9.0.182 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/oauth create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/oauth-1.2.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon-2.0.13 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon-3.0.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/pq create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/pq-1.1.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/raphf create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/raphf-1.1.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-3.0.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-bare create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-bare-3.0.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/redis create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/redis-3.1.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/amqp create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/amqp-1.8.0 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/apcu-4.0.11 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/blackfire create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/blackfire-1.14.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/cassandra-1.2.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/cassandra-bare-1.2.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/ev-1.0.4 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/event-2.2.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/imagick-3.4.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/memcached-2.2.0 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/memcached-bare-2.2.0 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/mongo-1.6.14 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/mongodb-1.2.5 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/newrelic-6.9.0.182 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/oauth-1.2.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/phalcon-2.0.13 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/phalcon-3.0.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/pq-1.1.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/raphf-1.1.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/rdkafka-3.0.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/rdkafka-bare-3.0.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/redis-3.1.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/amqp-1.8.0 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/apcu create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/apcu-5.1.8 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/blackfire create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/blackfire-1.14.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/cassandra-1.2.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/cassandra-bare-1.2.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/ev-1.0.4 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/event-2.2.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/imagick-3.4.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/memcached-3.0.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/memcached-bare-3.0.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/mongodb-1.2.5 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/newrelic-6.9.0.182 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/oauth-2.0.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/phalcon-3.0.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/pq-2.1.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/raphf-2.0.0 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/rdkafka-3.0.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/rdkafka-bare-3.0.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/redis-3.1.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/amqp-1.8.0 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/apcu-5.1.8 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/blackfire create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/blackfire-1.14.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/cassandra-1.2.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/cassandra-bare-1.2.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/ev-1.0.4 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/event-2.2.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/imagick-3.4.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/memcached-3.0.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/memcached-bare-3.0.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/mongodb-1.2.5 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/newrelic-6.9.0.182 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/oauth-2.0.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/pq-2.1.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/raphf-2.0.0 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/rdkafka-3.0.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/rdkafka-bare-3.0.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/redis-3.1.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/extensions/pecl create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/hhvm create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/hhvm-3.5.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/libraries/libc-client create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/libraries/libc-client-2007f create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/libraries/libcassandra create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/libraries/libcassandra-2.4.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/libraries/libmcrypt create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/libraries/libmcrypt-2.5.8 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/libraries/libmemcached create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/libraries/libmemcached-1.0.18 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/libraries/librdkafka create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/libraries/librdkafka-0.9.3 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/nginx create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/nginx-1.8.1 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/php create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/php-5.5.38 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/php-5.6.30 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/php-7.0.16 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/php-7.1.2 create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/php-min create mode 100755 vendor/heroku/heroku-buildpack-php/support/build/php-min-7.0.16 create mode 100644 vendor/heroku/heroku-buildpack-php/support/installer/composer.json create mode 100644 vendor/heroku/heroku-buildpack-php/support/installer/src/ComposerInstaller.php create mode 100644 vendor/heroku/heroku-buildpack-php/support/installer/src/ComposerInstallerPlugin.php create mode 100644 vendor/heroku/heroku-buildpack-php/support/installer/src/Downloader.php create mode 100644 webroot/_htaccess create mode 100644 webroot/assets/css/.gitkeep create mode 100644 webroot/assets/css/custom/.gitkeep create mode 100644 webroot/assets/icons/.gitkeep create mode 100644 webroot/assets/images/.gitkeep create mode 100644 webroot/assets/js/.gitkeep create mode 100644 webroot/assets/js/custom/.gitkeep create mode 100644 webroot/assets/vendor/.gitkeep create mode 100644 webroot/index.php create mode 100644 webroot/info.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea67272 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +#.htpasswd/.htaccess +.sshtunnel +.test.php + +# Test URI +# Ignore netbeans folder +nbproject/* + +# MAC +.DS_Store + +# Windows +Thumbs.db + +# Eclipse project files +/.cache +.project +.tmp +/.settings +.buildpath +/config/config.local.ini \ No newline at end of file diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..c022b78 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: vendor/bin/heroku-php-apache2 webroot/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d5ac5c3 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# Fat Free Framework - MVC Starter Kit +============================================ + +An early approach to a very lightweight F3 MVC Starter Kit. +It is currently based on an older F3 Version - updates will follow soon.... + +## System Requirements + +* PHP >= 5.3.3 +* PCRE PHP Module >= 8.02 +* mod_rewrite and mod_headers enabled +* cURL, sockets or stream extension + +## System Config + +* Create MySQL Databse +* Import SQL file(s) located in config/sql/* +* Copy config/config.local.ini.sample to config/config.local.ini and adapt to your settings +* Copy webroot/_htaccess to webroot/.htaccess +* Create Apache V-Host pointing to webroot/ and use "local.*" as hostname +* Modify your host-file + +## Basic File Structure + +To be updated..... + diff --git a/app.json b/app.json new file mode 100644 index 0000000..73dd325 --- /dev/null +++ b/app.json @@ -0,0 +1,6 @@ +{ + "name": "fatfree-mvc", + "description": "Fat Free Framework - MVC Starterkit", + "repository": "https://github.com/fivenp/fatfree-mvc", + "addons": [] +} \ No newline at end of file diff --git a/app/api.php b/app/api.php new file mode 100644 index 0000000..db193df --- /dev/null +++ b/app/api.php @@ -0,0 +1,13 @@ +render('layouts/default.json'); + } + + function sampleGet($f3){ + $f3->set('data',array('return'=>'sample')); + } + +} \ No newline at end of file diff --git a/app/controller.php b/app/controller.php new file mode 100644 index 0000000..3638119 --- /dev/null +++ b/app/controller.php @@ -0,0 +1,63 @@ +get('ENV.DATABASE_URL')){ + $dbUrl = $this->__multiexplode(array('@',':','/'),$f3->get('ENV.DATABASE_URL')); + $f3->set('db.dsn',"pgsql:host=".$dbUrl[5].";port=".$dbUrl[6].";dbname=".$dbUrl[7]); + $f3->set('db.user',$dbUrl[3]); + $f3->set('db.pass',$dbUrl[4]); + } + // $db = new \DB\SQL($f3->get('db.dsn'),$f3->get('db.user'),$f3->get('db.pass')); + // $f3->set('DB',$db); + } + + // HTTP route post-processor + function afterroute($f3) { + // Render appropriate layout + if($f3->get('layout')=="empty"){ + echo View::instance()->render('layouts/empty.php'); + } else if($f3->get('AJAX')){ + echo View::instance()->render('layouts/default.json'); + } else { + echo View::instance()->render('layouts/default.php'); + } + } + + // Instantiate class + function __construct() { + $f3=Base::instance(); + } + + // Some tiny helper classes + function __debug($d){ + print_r($d); + } + function __in_array_r($needle, $haystack, $strict = true) { + foreach ($haystack as $item) { + if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && $this->__in_array_r($needle, $item, $strict))) { + return true; + } + } + return false; + } + function __set_cache($f3,$secs=0){ + if ($secs) { + $time=microtime(TRUE); + header_remove('Pragma'); + header('Expires: '.gmdate('r',$time+$secs)); + header('Cache-Control: public, max-age='.$secs); + header('Last-Modified: '.gmdate('r')); + } else { + header('Cache-Control: no-cache, no-store, must-revalidate'); + } + } + function __multiexplode ($delimiters,$string) { + $ready = str_replace($delimiters, $delimiters[0], $string); + $launch = explode($delimiters[0], $ready); + return $launch; + } +} diff --git a/app/index.php b/app/index.php new file mode 100644 index 0000000..2b9d2d5 --- /dev/null +++ b/app/index.php @@ -0,0 +1,16 @@ +set('title',''); + $f3->set('classname','index'); + $f3->set('template','views/index.php'); + } + +} \ No newline at end of file diff --git a/app/model/sample.php b/app/model/sample.php new file mode 100644 index 0000000..a89ecba --- /dev/null +++ b/app/model/sample.php @@ -0,0 +1,17 @@ + array( + 'has-many' => array('\Model\SampleImages','images'), + ), + ), + $db = 'DB', // F3 hive key of a valid DB object + $table = 'samples', + // $fluid = true, // triggers the SQL Fluid Mode, default: false + $primary = 'id', // name of the primary key (auto-created), default: id + $ttl = 120, // caching time of field schema, default: 60 + $rel_ttl = 30; // caching time of all relations, default: 0 +} \ No newline at end of file diff --git a/app/rake.php b/app/rake.php new file mode 100644 index 0000000..29b5ede --- /dev/null +++ b/app/rake.php @@ -0,0 +1,25 @@ +get('db.dsn'),$f3->get('db.user'),$f3->get('db.pass')); + + $samples = new \DB\Cortex($db, 'samples'); + $samples = $samples->find(array('test = ? AND status = ?','test',1),array('order'=>'id ASC')); + + foreach($samples as $sample){ + // Do your stuff + } + + $f3->set('layout','empty'); + $f3->set('template','empty.php'); + + } + +} \ No newline at end of file diff --git a/app/user.php b/app/user.php new file mode 100644 index 0000000..dfc0a93 --- /dev/null +++ b/app/user.php @@ -0,0 +1,71 @@ +render('layouts/login.php'); + } + + /** + Display login form + **/ + function login($f3) { + // $crypt = \Bcrypt::instance(); + // die(print_r($crypt->hash('mypwd',$f3->get('md.salt')))); + $f3->clear('SESSION'); + $f3->set('title','BACKEND!'); + $f3->set('classname','login'); + $f3->set('template','views/user/login.php'); + } + + /** + Process login form + **/ + function auth($f3) { + $crypt = \Bcrypt::instance(); + $db = new \DB\SQL($f3->get('db.dsn'),$f3->get('db.user'),$f3->get('db.pass')); + $users = new \DB\Cortex($db, 'users'); + + if (!$f3->get('COOKIE.sent')){ + $f3->set('message_type','warning'); + $f3->set('message','Cookies must be enabled to enter this area'); + } else { + $user = $users->find(array('login=?',$f3->get('POST.username'))); + if($user){ + if($user[0]->password === $crypt->hash($f3->get('POST.password'),$f3->get('md.salt')) ){ + $f3->set('message_type','success'); + $f3->set('message','User / PW match'); + $f3->clear('COOKIE.sent'); + $f3->set('SESSION.admin_user',$user[0]->login); + $f3->set('SESSION.admin_isadmin',$user[0]->admin); + $f3->set('SESSION.admin_id',$user[0]->id); + $f3->set('SESSION.admin_lastseen',time()); + + $users->load(array('id = ?',$user[0]->id)); + $users->last_login = date('Y-m-d H:i:s'); + $users->last_login_remote_addr = ($f3->get('SERVER.HTTP_X_FORWARDED_FOR') ? $f3->get('SERVER.HTTP_X_FORWARDED_FOR') : $f3->get('SERVER.REMOTE_ADDR')); + $users->save(); + + $f3->reroute('/'); + } else { + $f3->set('message_type','danger'); + $f3->set('message','PW false'); + } + + } else { + $f3->set('message_type','danger'); + $f3->set('message','Please check your Username and Password'); + } + } + + $this->login($f3); + } + + /** + Terminate session + **/ + function logout($f3) { + $f3->clear('SESSION'); + $f3->reroute('/login'); + } +} \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..167f1e2 --- /dev/null +++ b/composer.json @@ -0,0 +1,10 @@ +{ + "require" : { + "php": "^5.5.0", + "ext-imagick": "*", + "ext-gd": "*" + }, + "require-dev": { + "heroku/heroku-buildpack-php": "*" + } +} \ No newline at end of file diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..e694375 --- /dev/null +++ b/composer.lock @@ -0,0 +1,67 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "196a5db0bb3e420ef7f1dc71a7171d84", + "content-hash": "b98c57ab17aea1420a86be605fbe9d04", + "packages": [], + "packages-dev": [ + { + "name": "heroku/heroku-buildpack-php", + "version": "v120", + "source": { + "type": "git", + "url": "https://github.com/heroku/heroku-buildpack-php.git", + "reference": "e0499a7fdffd56f46534a037a6c48d65cef4e645" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/heroku/heroku-buildpack-php/zipball/e0499a7fdffd56f46534a037a6c48d65cef4e645", + "reference": "e0499a7fdffd56f46534a037a6c48d65cef4e645", + "shasum": "" + }, + "bin": [ + "bin/heroku-hhvm-apache2", + "bin/heroku-hhvm-nginx", + "bin/heroku-php-apache2", + "bin/heroku-php-nginx" + ], + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David Zuelke", + "email": "dz@heroku.com" + } + ], + "description": "Toolkit for starting a PHP application locally, with or without foreman, using the same config for PHP/HHVM and Apache2/Nginx as on Heroku", + "homepage": "https://github.com/heroku/heroku-buildpack-php", + "keywords": [ + "apache", + "apache2", + "foreman", + "heroku", + "hhvm", + "nginx", + "php" + ], + "time": "2017-02-20 15:05:49" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^5.5.0", + "ext-imagick": "*", + "ext-gd": "*" + }, + "platform-dev": [] +} diff --git a/config/config.dev.ini b/config/config.dev.ini new file mode 100644 index 0000000..0311c85 --- /dev/null +++ b/config/config.dev.ini @@ -0,0 +1,8 @@ +# BASIC LOCAL ENVIRONMENT CONFIGURATION + +[globals] +DEBUG="3" +env = "dev" +asset_url = "/assets/" +asset_domain = "" +img_domain = "" diff --git a/config/config.local.ini.sample b/config/config.local.ini.sample new file mode 100644 index 0000000..1d8e5db --- /dev/null +++ b/config/config.local.ini.sample @@ -0,0 +1,17 @@ +# BASIC LOCAL ENVIRONMENT CONFIGURATION + +[globals] +DEBUG="3" +env = "dev" +asset_url = "/assets/" +asset_domain = "" +img_domain = "" + +# EITHER SET IT IN YOUR ENV VARS OR HERE + +db.dsn="pgsql:host=localhost;port=5432;dbname=test" +db.host="localhost" +db.port="5432" +db.user="user" +db.pass="pass" +db.db="test" \ No newline at end of file diff --git a/config/config.production.ini b/config/config.production.ini new file mode 100644 index 0000000..46167a6 --- /dev/null +++ b/config/config.production.ini @@ -0,0 +1,8 @@ +# BASIC LOCAL ENVIRONMENT CONFIGURATION + +[globals] +DEBUG="0" +env = "production" +asset_url = "/assets/" +asset_domain = "" +img_domain = "" diff --git a/config/config.staging.ini b/config/config.staging.ini new file mode 100644 index 0000000..5fa50d3 --- /dev/null +++ b/config/config.staging.ini @@ -0,0 +1,8 @@ +# BASIC LOCAL ENVIRONMENT CONFIGURATION + +[globals] +DEBUG="0" +env = "staging" +asset_url = "/assets/" +asset_domain = "" +img_domain = "" diff --git a/config/config.testing.ini b/config/config.testing.ini new file mode 100644 index 0000000..d128667 --- /dev/null +++ b/config/config.testing.ini @@ -0,0 +1,8 @@ +# BASIC LOCAL ENVIRONMENT CONFIGURATION + +[globals] +DEBUG="1" +env = "testing" +asset_url = "/assets/" +asset_domain = "" +img_domain = "" diff --git a/config/routes.ini b/config/routes.ini new file mode 100644 index 0000000..e74c119 --- /dev/null +++ b/config/routes.ini @@ -0,0 +1,22 @@ +[routes] + +# INDEX ROUTE +GET @home: /=Index->index + +# CONTROLLERS +GET /yourcontroller=YourController->index +GET /yourcontroller/@id=YourController->detail + +# LOGIN ROUTES +GET @login: /user/login=User->login +GET @logout: /user/logout=User->logout +POST /user/login=User->auth + +# API +POST /api/endpoint1=Api->endpoint1_create +GET /api/endpoint1=Api->endpoint1_read +PUT /api/endpoint1/@id=Api->endpoint1_updated +DELETE /api/endpoint1/@id=Api->endpoint1_delete + +# RAKE +GET /rake/task1=Rake->task1 diff --git a/config/settings.ini b/config/settings.ini new file mode 100644 index 0000000..e6406b5 --- /dev/null +++ b/config/settings.ini @@ -0,0 +1,11 @@ +# GENERAL SETTINGS + +[globals] + +UI="../templates/" +AUTOLOAD="../app/;../app/model/" +LOGS="../tmp/" +TEMP="../tmp/" + +template.desc="Template" + diff --git a/config/sql/.gitkeep b/config/sql/.gitkeep new file mode 100644 index 0000000..1ec6b8a --- /dev/null +++ b/config/sql/.gitkeep @@ -0,0 +1 @@ +EMPTY \ No newline at end of file diff --git a/lib/colors/colors.php b/lib/colors/colors.php new file mode 100644 index 0000000..df49fa1 --- /dev/null +++ b/lib/colors/colors.php @@ -0,0 +1,491 @@ + + * Info: http://mexitek.github.io/phpColors/ + * License: http://arlo.mit-license.org/ + */ + +#namespace phpColors; + +#use \Exception; + +/** + * A color utility that helps manipulate HEX colors + */ +class Color { + + private $_hex; + private $_hsl; + private $_rgb; + + /** + * Auto darkens/lightens by 10% for sexily-subtle gradients. + * Set this to FALSE to adjust automatic shade to be between given color + * and black (for darken) or white (for lighten) + */ + const DEFAULT_ADJUST = 10; + + /** + * Instantiates the class with a HEX value + * @param string $hex + */ + function __construct( $hex ) { + // Strip # sign is present + $color = str_replace("#", "", $hex); + + // Make sure it's 6 digits + if( strlen($color) === 3 ) { + $color = $color[0].$color[0].$color[1].$color[1].$color[2].$color[2]; + } else if( strlen($color) != 6 ) { + throw new Exception("HEX color needs to be 6 or 3 digits long"); + } + + $this->_hsl = self::hexToHsl( $color ); + $this->_hex = $color; + $this->_rgb = self::hexToRgb( $color ); + } + + // ==================== + // = Public Interface = + // ==================== + + /** + * Given a HEX string returns a HSL array equivalent. + * @param string $color + * @return array HSL associative array + */ + public static function hexToHsl( $color ){ + + // Sanity check + $color = self::_checkHex($color); + + // Convert HEX to DEC + $R = hexdec($color[0].$color[1]); + $G = hexdec($color[2].$color[3]); + $B = hexdec($color[4].$color[5]); + + $HSL = array(); + + $var_R = ($R / 255); + $var_G = ($G / 255); + $var_B = ($B / 255); + + $var_Min = min($var_R, $var_G, $var_B); + $var_Max = max($var_R, $var_G, $var_B); + $del_Max = $var_Max - $var_Min; + + $L = ($var_Max + $var_Min)/2; + + if ($del_Max == 0) + { + $H = 0; + $S = 0; + } + else + { + if ( $L < 0.5 ) $S = $del_Max / ( $var_Max + $var_Min ); + else $S = $del_Max / ( 2 - $var_Max - $var_Min ); + + $del_R = ( ( ( $var_Max - $var_R ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max; + $del_G = ( ( ( $var_Max - $var_G ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max; + $del_B = ( ( ( $var_Max - $var_B ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max; + + if ($var_R == $var_Max) $H = $del_B - $del_G; + else if ($var_G == $var_Max) $H = ( 1 / 3 ) + $del_R - $del_B; + else if ($var_B == $var_Max) $H = ( 2 / 3 ) + $del_G - $del_R; + + if ($H<0) $H++; + if ($H>1) $H--; + } + + $HSL['H'] = ($H*360); + $HSL['S'] = $S; + $HSL['L'] = $L; + + return $HSL; + } + + /** + * Given a HSL associative array returns the equivalent HEX string + * @param array $hsl + * @return string HEX string + * @throws Exception "Bad HSL Array" + */ + public static function hslToHex( $hsl = array() ){ + // Make sure it's HSL + if(empty($hsl) || !isset($hsl["H"]) || !isset($hsl["S"]) || !isset($hsl["L"]) ) { + throw new Exception("Param was not an HSL array"); + } + + list($H,$S,$L) = array( $hsl['H']/360,$hsl['S'],$hsl['L'] ); + + if( $S == 0 ) { + $r = $L * 255; + $g = $L * 255; + $b = $L * 255; + } else { + + if($L<0.5) { + $var_2 = $L*(1+$S); + } else { + $var_2 = ($L+$S) - ($S*$L); + } + + $var_1 = 2 * $L - $var_2; + + $r = round(255 * self::_huetorgb( $var_1, $var_2, $H + (1/3) )); + $g = round(255 * self::_huetorgb( $var_1, $var_2, $H )); + $b = round(255 * self::_huetorgb( $var_1, $var_2, $H - (1/3) )); + + } + + // Convert to hex + $r = dechex($r); + $g = dechex($g); + $b = dechex($b); + + // Make sure we get 2 digits for decimals + $r = (strlen("".$r)===1) ? "0".$r:$r; + $g = (strlen("".$g)===1) ? "0".$g:$g; + $b = (strlen("".$b)===1) ? "0".$b:$b; + + return $r.$g.$b; + } + + + /** + * Given a HEX string returns a RGB array equivalent. + * @param string $color + * @return array RGB associative array + */ + public static function hexToRgb( $color ){ + + // Sanity check + $color = self::_checkHex($color); + + // Convert HEX to DEC + $R = hexdec($color[0].$color[1]); + $G = hexdec($color[2].$color[3]); + $B = hexdec($color[4].$color[5]); + + $RGB['R'] = $R; + $RGB['G'] = $G; + $RGB['B'] = $B; + + return $RGB; + } + + + /** + * Given an RGB associative array returns the equivalent HEX string + * @param array $rgb + * @return string RGB string + * @throws Exception "Bad RGB Array" + */ + public static function rgbToHex( $rgb = array() ){ + // Make sure it's RGB + if(empty($rgb) || !isset($rgb["R"]) || !isset($rgb["G"]) || !isset($rgb["B"]) ) { + throw new Exception("Param was not an RGB array"); + } + + // Convert RGB to HEX + $hex[0] = dechex( $rgb['R'] ); + $hex[1] = dechex( $rgb['G'] ); + $hex[2] = dechex( $rgb['B'] ); + + return implode( '', $hex ); + + } + + + /** + * Given a HEX value, returns a darker color. If no desired amount provided, then the color halfway between + * given HEX and black will be returned. + * @param int $amount + * @return string Darker HEX value + */ + public function darken( $amount = self::DEFAULT_ADJUST ){ + // Darken + $darkerHSL = $this->_darken($this->_hsl, $amount); + // Return as HEX + return self::hslToHex($darkerHSL); + } + + /** + * Given a HEX value, returns a lighter color. If no desired amount provided, then the color halfway between + * given HEX and white will be returned. + * @param int $amount + * @return string Lighter HEX value + */ + public function lighten( $amount = self::DEFAULT_ADJUST ){ + // Lighten + $lighterHSL = $this->_lighten($this->_hsl, $amount); + // Return as HEX + return self::hslToHex($lighterHSL); + } + + /** + * Given a HEX value, returns a mixed color. If no desired amount provided, then the color mixed by this ratio + * @param int $amount = -100..0..+100 + * @return string mixed HEX value + */ + public function mix($hex2, $amount = 0){ + $rgb2 = self::hexToRgb($hex2); + $mixed = $this->_mix($this->_rgb, $rgb2, $amount); + // Return as HEX + return self::rgbToHex($mixed); + } + + /** + * Creates an array with two shades that can be used to make a gradient + * @param int $amount Optional percentage amount you want your contrast color + * @return array An array with a 'light' and 'dark' index + */ + public function makeGradient( $amount = self::DEFAULT_ADJUST ) { + // Decide which color needs to be made + if( $this->isLight() ) { + $lightColor = $this->_hex; + $darkColor = $this->darken($amount); + } else { + $lightColor = $this->lighten($amount); + $darkColor = $this->_hex; + } + + // Return our gradient array + return array( "light" => $lightColor, "dark" => $darkColor ); + } + + + /** + * Returns whether or not given color is considered "light" + * @param string|Boolean $color + * @return boolean + */ + public function isLight( $color = FALSE ){ + // Get our color + $color = ($color) ? $color : $this->_hex; + + // Calculate straight from rbg + $r = hexdec($color[0].$color[1]); + $g = hexdec($color[2].$color[3]); + $b = hexdec($color[4].$color[5]); + + return (( $r*299 + $g*587 + $b*114 )/1000 > 130); + } + + /** + * Returns whether or not a given color is considered "dark" + * @param string|Boolean $color + * @return boolean + */ + public function isDark( $color = FALSE ){ + // Get our color + $color = ($color) ? $color:$this->_hex; + + // Calculate straight from rbg + $r = hexdec($color[0].$color[1]); + $g = hexdec($color[2].$color[3]); + $b = hexdec($color[4].$color[5]); + + return (( $r*299 + $g*587 + $b*114 )/1000 <= 130); + } + + /** + * Returns the complimentary color + * @return string Complementary hex color + * + */ + public function complementary() { + // Get our HSL + $hsl = $this->_hsl; + + // Adjust Hue 180 degrees + $hsl['H'] += ($hsl['H']>180) ? -180:180; + + // Return the new value in HEX + return self::hslToHex($hsl); + } + + /** + * Returns your color's HSL array + */ + public function getHsl() { + return $this->_hsl; + } + /** + * Returns your original color + */ + public function getHex() { + return $this->_hex; + } + /** + * Returns your color's RGB array + */ + public function getRgb() { + return $this->_rgb; + } + + /** + * Returns the cross browser CSS3 gradient + * @param int Optional: percentage amount to light/darken the gradient + * @param boolean $vintageBrowsers Optional: include vendor prefixes for browsers that almost died out already + * @param string $prefix Optional: prefix for every lines + * @param string $suffix Optional: suffix for every lines + * @link http://caniuse.com/css-gradients Resource for the browser support + * @return string CSS3 gradient for chrome, safari, firefox, opera and IE10 + */ + public function getCssGradient( $amount = self::DEFAULT_ADJUST, $vintageBrowsers = FALSE, $suffix = "" , $prefix = "" ) { + + // Get the recommended gradient + $g = $this->makeGradient($amount); + + $css = ""; + /* fallback/image non-cover color */ + $css .= "{$prefix}background-color: #".$this->_hex.";{$suffix}"; + + /* IE Browsers */ + $css .= "{$prefix}filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#".$g['light']."', endColorstr='#".$g['dark']."');{$suffix}"; + + /* Safari 4+, Chrome 1-9 */ + if ( $vintageBrowsers ) { + $css .= "{$prefix}background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#".$g['light']."), to(#".$g['dark']."));{$suffix}"; + } + + /* Safari 5.1+, Mobile Safari, Chrome 10+ */ + $css .= "{$prefix}background-image: -webkit-linear-gradient(top, #".$g['light'].", #".$g['dark'].");{$suffix}"; + + /* Firefox 3.6+ */ + if ( $vintageBrowsers ) { + $css .= "{$prefix}background-image: -moz-linear-gradient(top, #".$g['light'].", #".$g['dark'].");{$suffix}"; + } + + /* Opera 11.10+ */ + if ( $vintageBrowsers ) { + $css .= "{$prefix}background-image: -o-linear-gradient(top, #".$g['light'].", #".$g['dark'].");{$suffix}"; + } + + /* Unprefixed version (standards): FF 16+, IE10+, Chrome 26+, Safari 7+, Opera 12.1+ */ + $css .= "{$prefix}background-image: linear-gradient(to bottom, #".$g['light'].", #".$g['dark'].");{$suffix}"; + + // Return our CSS + return $css; + } + + // =========================== + // = Private Functions Below = + // =========================== + + + /** + * Darkens a given HSL array + * @param array $hsl + * @param int $amount + * @return array $hsl + */ + private function _darken( $hsl, $amount = self::DEFAULT_ADJUST){ + // Check if we were provided a number + if( $amount ) { + $hsl['L'] = ($hsl['L'] * 100) - $amount; + $hsl['L'] = ($hsl['L'] < 0) ? 0:$hsl['L']/100; + } else { + // We need to find out how much to darken + $hsl['L'] = $hsl['L']/2 ; + } + + return $hsl; + } + + /** + * Lightens a given HSL array + * @param array $hsl + * @param int $amount + * @return array $hsl + */ + private function _lighten( $hsl, $amount = self::DEFAULT_ADJUST){ + // Check if we were provided a number + if( $amount ) { + $hsl['L'] = ($hsl['L'] * 100) + $amount; + $hsl['L'] = ($hsl['L'] > 100) ? 1:$hsl['L']/100; + } else { + // We need to find out how much to lighten + $hsl['L'] += (1-$hsl['L'])/2; + } + + return $hsl; + } + + /** + * Mix 2 rgb colors and return an rgb color + * @param array $rgb1 + * @param array $rgb2 + * @param int $amount ranged -100..0..+100 + * @return array $rgb + * + * ported from http://phpxref.pagelines.com/nav.html?includes/class.colors.php.source.html + */ + private function _mix($rgb1, $rgb2, $amount = 0) { + + $r1 = ($amount + 100) / 100; + $r2 = 2 - $r1; + + $rmix = (($rgb1['R'] * $r1) + ($rgb2['R'] * $r2)) / 2; + $gmix = (($rgb1['G'] * $r1) + ($rgb2['G'] * $r2)) / 2; + $bmix = (($rgb1['B'] * $r1) + ($rgb2['B'] * $r2)) / 2; + + return array('R' => $rmix, 'G' => $gmix, 'B' => $bmix); + } + + /** + * Given a Hue, returns corresponding RGB value + * @param type $v1 + * @param type $v2 + * @param type $vH + * @return int + */ + private static function _huetorgb( $v1,$v2,$vH ) { + if( $vH < 0 ) { + $vH += 1; + } + + if( $vH > 1 ) { + $vH -= 1; + } + + if( (6*$vH) < 1 ) { + return ($v1 + ($v2 - $v1) * 6 * $vH); + } + + if( (2*$vH) < 1 ) { + return $v2; + } + + if( (3*$vH) < 2 ) { + return ($v1 + ($v2-$v1) * ( (2/3)-$vH ) * 6); + } + + return $v1; + + } + + /** + * You need to check if you were given a good hex string + * @param string $hex + * @return string Color + * @throws Exception "Bad color format" + */ + private static function _checkHex( $hex ) { + // Strip # sign is present + $color = str_replace("#", "", $hex); + + // Make sure it's 6 digits + if( strlen($color) == 3 ) { + $color = $color[0].$color[0].$color[1].$color[1].$color[2].$color[2]; + } else if( strlen($color) != 6 ) { + throw new Exception("HEX color needs to be 6 or 3 digits long"); + } + + return $color; + } + +} \ No newline at end of file diff --git a/lib/f3/api/annotated.html b/lib/f3/api/annotated.html new file mode 100755 index 0000000..0b451ab --- /dev/null +++ b/lib/f3/api/annotated.html @@ -0,0 +1,85 @@ + + + + + + + +Fat-Free Framework: Class List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Class List
+
+
+
Here are the classes, structs, unions and interfaces with brief descriptions:
+
[detail level 123]
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
oNDB
|oNJig
||oCMapperFlat-file DB mapper
||\CSessionJig-managed session handler
|oNMongo
||oCMapperMongoDB mapper
||\CSessionMongoDB-managed session handler
|oNSQL
||oCMapperSQL data mapper
||\CSessionSQL-managed session handler
|oCCursorSimple cursor implementation
|oCJigFlat-file DB wrapper
|oCMongoMongoDB wrapper
|\CSQLPDO wrapper
oNWeb
|oNGoogle
||\CStaticMapGoogle Static Maps API v2 plug-in
|oCGeoGeo plug-in
|oCOpenIDOpenID consumer
|\CPingbackPingback 1.0 protocol (client and server) implementation
oCAuditData validator
oCAuthAuthorization/authentication plug-in
oCBaseBase structure
oCBasketSession-based pseudo-mapper
oCBcryptLightweight password hashing library
oCCacheCache engine
oCF3Legacy mode enabler
oCImageImage manipulation tools
oCISOISO language/country codes
oCLogCustom logger
oCMagicPHP magic wrapper
oCMarkdownMarkdown-to-HTML converter
oCMatrixGeneric array utilities
oCPrefabFactory class for single-instance objects
oCPreviewLightweight template engine
oCRegistryContainer for singular object instances
oCSessionCache-based session handler
oCSMTPSMTP plug-in
oCTemplateXML-style template engine
oCTestUnit test kit
oCUTFUnicode string manager
oCViewView handler
\CWebWrapper for various HTTP utilities
+
+
diff --git a/lib/f3/api/bc_s.png b/lib/f3/api/bc_s.png new file mode 100755 index 0000000000000000000000000000000000000000..fd162ea76db92647e51fbcd742f46c016f9f633d GIT binary patch literal 624 zcmV-$0+0QPP)P1xSY#5Gv_zwo_qMFXPr)G77B$3>uj&r`%Xlh z3F&nDoK~w9)oQgknM@9eh%?r1w=ZZkn&&>B?-!oWbi3W(9I&^yC;3Ca-)}*c2LN8I z0^&bknNFuWcDwy9Vh&)fR!j04#@H|z3<~gJH2Y}@G@DH&-gP(}myAZ^5rBJ3pwVb3 z@hL$NJ_iDUKZpZ>W-?H(*H@3+_jo*;I-RZw;IRzUYPD4$jO0_d+kM>c_c#9sNb3V; zastO~4+evmtXi!S5ocQ_lj)AlW*eZ&RaU7~h={Wdl}a^66*$#-RxX!`h}QQb3@vOh z7!FveR3ai;-&gc{{e7p?ITBK-6cN$-erUB?gQ6(DX2oKWh&VebjU5A%H6kRFNh0Fx z7H$!O1l|va!xk$P3Pi-&N3YjwMERQlUa@>WznZ)Vbv<*rTtAVNCn+QniB(|NVzKBk z#pY}_dn*fOu~;ZcD+Y5JXA|DFmG?qC9#??dXwHu#jz*(Vd#Q(9E~ms_(A);f-vIDt zDf?I~Cixh?yoS*pBe}!<7tv@`Zq95rOJ6^k&*$$r(Ppz*2b%i^B}vbx$K&x2u0kXd z*+z42bbo;4J`r)oGMUU*NKA+F*8#|P=PKZuTWIbFk{KeR_5Bz9%d?zJLgcXk0000< KMNUMnLSTZcL=TGq literal 0 HcmV?d00001 diff --git a/lib/f3/api/bdwn.png b/lib/f3/api/bdwn.png new file mode 100755 index 0000000000000000000000000000000000000000..7c943f0178f06cc641b5e069ca6ec290369c8023 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)H!3HEvS)PKZAWs*^kP61PbGdmN40v4bACM5r zTIh9bN{H5*6Afvc5igd$|7FR0AX>06Wj{mB%ley(%NinQz21C|{qXgxXSx!;y!{sI n`ypo8^JnkEb(nZRITbK9bxE6Z3Lmion$FgTe~DWM4fu|YD- literal 0 HcmV?d00001 diff --git a/lib/f3/api/classAudit-members.html b/lib/f3/api/classAudit-members.html new file mode 100755 index 0000000..581b3b0 --- /dev/null +++ b/lib/f3/api/classAudit-members.html @@ -0,0 +1,58 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Audit Member List
+
+
+ +

This is the complete list of members for Audit, including all inherited members.

+ + + + + + + + + + + + + + + + + + +
card($id)Audit
email($str, $mx=TRUE)Audit
entropy($str)Audit
instance()Prefabstatic
ipv4($addr)Audit
ipv6($addr)Audit
isbot()Audit
isdesktop()Audit
ismobile()Audit
isprivate($addr)Audit
ispublic($addr)Audit
isreserved($addr)Audit
mod10($id)Audit
UA_Bot (defined in Audit)Audit
UA_Desktop (defined in Audit)Audit
UA_Mobile (defined in Audit)Audit
url($str)Audit
diff --git a/lib/f3/api/classAudit.html b/lib/f3/api/classAudit.html new file mode 100755 index 0000000..5ee2034 --- /dev/null +++ b/lib/f3/api/classAudit.html @@ -0,0 +1,412 @@ + + + + + + + +Fat-Free Framework: Audit Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+ +
+
Audit Class Reference
+
+
+ +

Data validator. + More...

+
+ + Inheritance diagram for Audit:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 url ($str)
 
 email ($str, $mx=TRUE)
 
 ipv4 ($addr)
 
 ipv6 ($addr)
 
 isprivate ($addr)
 
 isreserved ($addr)
 
 ispublic ($addr)
 
 isdesktop ()
 
 ismobile ()
 
 isbot ()
 
 mod10 ($id)
 
 card ($id)
 
 entropy ($str)
 
+ + + + + + + + +

+Public Attributes

+const UA_Mobile ='android|blackberry|iphone|ipod|palm|windows\s+ce'
 
+const UA_Desktop ='bsd|linux|os\s+[x9]|solaris|windows'
 
+const UA_Bot ='bot|crawl|slurp|spider'
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

Data validator.

+

Member Function Documentation

+ +
+
+ + + + + + + + +
Audit::card ( $id)
+
+

Return credit card type if number is valid

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Audit::email ( $str,
 $mx = TRUE 
)
+
+

Return TRUE if string is a valid e-mail address; Check DNS MX records if specified

+
Returns
bool
+
Parameters
+ + + +
$strstring
$mxboolean
+
+
+ +
+
+ +
+
+ + + + + + + + +
Audit::entropy ( $str)
+
+

Return entropy estimate of a password (NIST 800-63)

+
Returns
int|float
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Audit::ipv4 ( $addr)
+
+

Return TRUE if string is a valid IPV4 address

+
Returns
bool
+
Parameters
+ + +
$addrstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Audit::ipv6 ( $addr)
+
+

Return TRUE if string is a valid IPV6 address

+
Returns
bool
+
Parameters
+ + +
$addrstring
+
+
+ +
+
+ +
+
+ + + + + + + +
Audit::isbot ()
+
+

Return TRUE if user agent is a Web bot

+
Returns
bool
+ +
+
+ +
+
+ + + + + + + +
Audit::isdesktop ()
+
+

Return TRUE if user agent is a desktop browser

+
Returns
bool
+ +
+
+ +
+
+ + + + + + + +
Audit::ismobile ()
+
+

Return TRUE if user agent is a mobile device

+
Returns
bool
+ +
+
+ +
+
+ + + + + + + + +
Audit::isprivate ( $addr)
+
+

Return TRUE if IP address is within private range

+
Returns
bool
+
Parameters
+ + +
$addrstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Audit::ispublic ( $addr)
+
+

Return TRUE if IP address is neither private nor reserved

+
Returns
bool
+
Parameters
+ + +
$addrstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Audit::isreserved ( $addr)
+
+

Return TRUE if IP address is within reserved range

+
Returns
bool
+
Parameters
+ + +
$addrstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Audit::mod10 ( $id)
+
+

Return TRUE if specified ID has a valid (Luhn) Mod-10 check digit

+
Returns
bool
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Audit::url ( $str)
+
+

Return TRUE if string is a valid URL

+
Returns
bool
+
Parameters
+ + +
$strstring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • audit.php
  • +
+
diff --git a/lib/f3/api/classAudit.png b/lib/f3/api/classAudit.png new file mode 100755 index 0000000000000000000000000000000000000000..f2bb9eb12d86f0b86050b63c8f2eacd13d765e0c GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^MnD|E!3-pG?q0hDq$C1-LR|m<{|{uod-rb6oH-MK zEHFNB;J^pRRC^$oqa?^Lm;tB=1g@S60U7ex)5S5Qg7NL#hm)EWc-YKO_PqapLR}%~ zXqa97ojYGLVp&o+Pkvx(8H6^s7LsE<|UmWfJG^t-6m| zCy7n}_f4z%&BR|Zao4v7U%jd4)g9s&_FXEl?`~kK!gOcL?3vs0{*{Xsm&+$>0S!Ap zrGtaBAzO@rH#So2=EbR31Lm@y(htqiVh{>u44A>ya43X9&%pTd0S1wMkuS|6)K7i( zd)Ykg + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Auth Member List
+
+
+ +

This is the complete list of members for Auth, including all inherited members.

+ + + + + + + + + + + + + +
$argsAuth
$mapperAuth
__construct($storage, array $args=NULL)Auth
_jig($id, $pw, $realm)Authprotected
_ldap($id, $pw)Authprotected
_mongo($id, $pw, $realm)Authprotected
_smtp($id, $pw)Authprotected
_sql($id, $pw, $realm)Authprotected
basic($func=NULL)Auth
E_LDAP (defined in Auth)Auth
E_SMTP (defined in Auth)Auth
login($id, $pw, $realm=NULL)Auth
diff --git a/lib/f3/api/classAuth.html b/lib/f3/api/classAuth.html new file mode 100755 index 0000000..d562044 --- /dev/null +++ b/lib/f3/api/classAuth.html @@ -0,0 +1,431 @@ + + + + + + + +Fat-Free Framework: Auth Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

Authorization/authentication plug-in. + More...

+ + + + + + + + +

+Public Member Functions

 login ($id, $pw, $realm=NULL)
 
 basic ($func=NULL)
 
 __construct ($storage, array $args=NULL)
 
+ + + + + + + + + + + + +

+Public Attributes

$mapper
 Mapper object.
 
$args
 Storage options.
 
+const E_LDAP ='LDAP connection failure'
 
+const E_SMTP ='SMTP connection failure'
 
+ + + + + + + + + + + +

+Protected Member Functions

 _jig ($id, $pw, $realm)
 
 _mongo ($id, $pw, $realm)
 
 _sql ($id, $pw, $realm)
 
 _ldap ($id, $pw)
 
 _smtp ($id, $pw)
 
+

Detailed Description

+

Authorization/authentication plug-in.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
Auth::__construct ( $storage,
array $args = NULL 
)
+
+

Instantiate class

+
Returns
object
+
Parameters
+ + + +
$storagestring|object
$argsarray
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
Auth::_jig ( $id,
 $pw,
 $realm 
)
+
+protected
+
+

Jig storage handler

+
Returns
bool
+
Parameters
+ + + + +
$idstring
$pwstring
$realmstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Auth::_ldap ( $id,
 $pw 
)
+
+protected
+
+

LDAP storage handler

+
Returns
bool
+
Parameters
+ + + +
$idstring
$pwstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
Auth::_mongo ( $id,
 $pw,
 $realm 
)
+
+protected
+
+

MongoDB storage handler

+
Returns
bool
+
Parameters
+ + + + +
$idstring
$pwstring
$realmstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Auth::_smtp ( $id,
 $pw 
)
+
+protected
+
+

SMTP storage handler

+
Returns
bool
+
Parameters
+ + + +
$idstring
$pwstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
Auth::_sql ( $id,
 $pw,
 $realm 
)
+
+protected
+
+

SQL storage handler

+
Returns
bool
+
Parameters
+ + + + +
$idstring
$pwstring
$realmstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Auth::basic ( $func = NULL)
+
+

HTTP basic auth mechanism

+
Returns
bool
+
Parameters
+ + +
$funccallback
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Auth::login ( $id,
 $pw,
 $realm = NULL 
)
+
+

Login auth mechanism

+
Returns
bool
+
Parameters
+ + + + +
$idstring
$pwstring
$realmstring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • auth.php
  • +
+
diff --git a/lib/f3/api/classBase-members.html b/lib/f3/api/classBase-members.html new file mode 100755 index 0000000..293e354 --- /dev/null +++ b/lib/f3/api/classBase-members.html @@ -0,0 +1,165 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Base Member List
+
+
+ +

This is the complete list of members for Base, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$fallbackBase
$initBase
$languagesBase
$localesBase
$nullBase
__construct()Base
autoload($class)Baseprotected
base64($data, $mime)Base
blacklisted($ip)Base
build($url)Base
call($func, $args=NULL, $hooks='')Base
camelcase($str)Base
chain($funcs, $args=NULL)Base
clean($arg, $tags=NULL)Base
clear($key)Base
compile($str)Base
concat($key, $val)Base
config($file)Base
copy($src, $dst)Base
CSSBase
csv(array $args)Base
decode($str)Base
devoid($key)Base
dump($expr)Base
dupe($arg)Base
E_Class (defined in Base)Base
E_Fatal (defined in Base)Base
E_Hive (defined in Base)Base
E_Method (defined in Base)Base
E_Named (defined in Base)Base
E_Open (defined in Base)Base
E_Pattern (defined in Base)Base
E_Routes (defined in Base)Base
encode($str)Base
error($code, $text='', array $trace=NULL)Base
exists($key, &$val=NULL)Base
expire($secs=0)Base
fixslashes($str)Base
flip($key)Base
format()Base
get($key, $args=NULL)Base
GLOBALSBase
hash($str)Base
highlight($text)Base
hive()Base
HTTP_100 (defined in Base)Base
HTTP_101 (defined in Base)Base
HTTP_200 (defined in Base)Base
HTTP_201 (defined in Base)Base
HTTP_202 (defined in Base)Base
HTTP_203 (defined in Base)Base
HTTP_204 (defined in Base)Base
HTTP_205 (defined in Base)Base
HTTP_206 (defined in Base)Base
HTTP_300 (defined in Base)Base
HTTP_301 (defined in Base)Base
HTTP_302 (defined in Base)Base
HTTP_303 (defined in Base)Base
HTTP_304 (defined in Base)Base
HTTP_305 (defined in Base)Base
HTTP_307 (defined in Base)Base
HTTP_400 (defined in Base)Base
HTTP_401 (defined in Base)Base
HTTP_402 (defined in Base)Base
HTTP_403 (defined in Base)Base
HTTP_404 (defined in Base)Base
HTTP_405 (defined in Base)Base
HTTP_406 (defined in Base)Base
HTTP_407 (defined in Base)Base
HTTP_408 (defined in Base)Base
HTTP_409 (defined in Base)Base
HTTP_410 (defined in Base)Base
HTTP_411 (defined in Base)Base
HTTP_412 (defined in Base)Base
HTTP_413 (defined in Base)Base
HTTP_414 (defined in Base)Base
HTTP_415 (defined in Base)Base
HTTP_416 (defined in Base)Base
HTTP_417 (defined in Base)Base
HTTP_500 (defined in Base)Base
HTTP_501 (defined in Base)Base
HTTP_502 (defined in Base)Base
HTTP_503 (defined in Base)Base
HTTP_504 (defined in Base)Base
HTTP_505 (defined in Base)Base
instance()Prefabstatic
language($code)Base
lexicon($path)Base
map($url, $class, $ttl=0, $kbps=0)Base
merge($key, $src)Base
mock($pattern, array $args=NULL, array $headers=NULL, $body=NULL)Base
MODEBase
mset(array $vars, $prefix='', $ttl=0)Base
mutex($id, $func, $args=NULL)Base
PACKAGE (defined in Base)Base
parse($str)Base
pop($key)Base
push($key, $val)Base
read($file, $lf=FALSE)Base
recursive($arg, $func)Base
ref($key, $add=TRUE)Base
rel($url)Base
relay($funcs, $args=NULL)Base
REQ_AJAX (defined in Base)Base
REQ_SYNC (defined in Base)Base
reroute($url, $permanent=FALSE)Base
route($pattern, $handler, $ttl=0, $kbps=0)Base
run()Base
scrub(&$var, $tags=NULL)Base
serialize($arg)Base
set($key, $val, $ttl=0)Base
shift($key)Base
sign($num)Base
snakecase($str)Base
split($str)Base
status($code)Base
stringify($arg, array $stack=NULL)Base
sync($key)Base
unload($cwd)Base
unserialize($arg)Base
unshift($key, $val)Base
VERBSBase
VERSION (defined in Base)Base
write($file, $data, $append=FALSE)Base
diff --git a/lib/f3/api/classBase.html b/lib/f3/api/classBase.html new file mode 100755 index 0000000..d0ff86b --- /dev/null +++ b/lib/f3/api/classBase.html @@ -0,0 +1,2218 @@ + + + + + + + +Fat-Free Framework: Base Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

Base structure. + More...

+
+ + Inheritance diagram for Base:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 sync ($key)
 
 build ($url)
 
 parse ($str)
 
 compile ($str)
 
ref ($key, $add=TRUE)
 
 exists ($key, &$val=NULL)
 
 devoid ($key)
 
 set ($key, $val, $ttl=0)
 
 get ($key, $args=NULL)
 
 clear ($key)
 
 mset (array $vars, $prefix='', $ttl=0)
 
 hive ()
 
 copy ($src, $dst)
 
 concat ($key, $val)
 
 flip ($key)
 
 push ($key, $val)
 
 pop ($key)
 
 unshift ($key, $val)
 
 shift ($key)
 
 merge ($key, $src)
 
 fixslashes ($str)
 
 split ($str)
 
 stringify ($arg, array $stack=NULL)
 
 csv (array $args)
 
 camelcase ($str)
 
 snakecase ($str)
 
 sign ($num)
 
 hash ($str)
 
 base64 ($data, $mime)
 
 encode ($str)
 
 decode ($str)
 
 dupe ($arg)
 
 recursive ($arg, $func)
 
 clean ($arg, $tags=NULL)
 
 scrub (&$var, $tags=NULL)
 
 format ()
 
 language ($code)
 
 lexicon ($path)
 
 serialize ($arg)
 
 unserialize ($arg)
 
 status ($code)
 
 expire ($secs=0)
 
 error ($code, $text='', array $trace=NULL)
 
 mock ($pattern, array $args=NULL, array $headers=NULL, $body=NULL)
 
 route ($pattern, $handler, $ttl=0, $kbps=0)
 
 reroute ($url, $permanent=FALSE)
 
 map ($url, $class, $ttl=0, $kbps=0)
 
 blacklisted ($ip)
 
 run ()
 
 call ($func, $args=NULL, $hooks='')
 
 chain ($funcs, $args=NULL)
 
 relay ($funcs, $args=NULL)
 
 config ($file)
 
 mutex ($id, $func, $args=NULL)
 
 read ($file, $lf=FALSE)
 
 write ($file, $data, $append=FALSE)
 
 highlight ($text)
 
 dump ($expr)
 
 rel ($url)
 
 unload ($cwd)
 
__construct ()
 Bootstrap.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Attributes

+const GLOBALS ='GET|POST|COOKIE|REQUEST|SESSION|FILES|SERVER|ENV'
 Mapped PHP globals.
 
+const VERBS ='GET|HEAD|POST|PUT|PATCH|DELETE|CONNECT'
 HTTP verbs.
 
+const MODE =0755
 Default directory permissions.
 
+const CSS ='code.css'
 Syntax highlighting stylesheet.
 
$init
 Initial settings.
 
$languages
 Language lookup sequence.
 
$locales
 Equivalent Locales.
 
$fallback ='en'
 Default fallback language.
 
$null =NULL
 NULL reference.
 
+const PACKAGE ='Fat-Free Framework'
 
+const VERSION ='3.2.1-Release'
 
+const HTTP_100 ='Continue'
 
+const HTTP_101 ='Switching Protocols'
 
+const HTTP_200 ='OK'
 
+const HTTP_201 ='Created'
 
+const HTTP_202 ='Accepted'
 
+const HTTP_203 ='Non-Authorative Information'
 
+const HTTP_204 ='No Content'
 
+const HTTP_205 ='Reset Content'
 
+const HTTP_206 ='Partial Content'
 
+const HTTP_300 ='Multiple Choices'
 
+const HTTP_301 ='Moved Permanently'
 
+const HTTP_302 ='Found'
 
+const HTTP_303 ='See Other'
 
+const HTTP_304 ='Not Modified'
 
+const HTTP_305 ='Use Proxy'
 
+const HTTP_307 ='Temporary Redirect'
 
+const HTTP_400 ='Bad Request'
 
+const HTTP_401 ='Unauthorized'
 
+const HTTP_402 ='Payment Required'
 
+const HTTP_403 ='Forbidden'
 
+const HTTP_404 ='Not Found'
 
+const HTTP_405 ='Method Not Allowed'
 
+const HTTP_406 ='Not Acceptable'
 
+const HTTP_407 ='Proxy Authentication Required'
 
+const HTTP_408 ='Request Timeout'
 
+const HTTP_409 ='Conflict'
 
+const HTTP_410 ='Gone'
 
+const HTTP_411 ='Length Required'
 
+const HTTP_412 ='Precondition Failed'
 
+const HTTP_413 ='Request Entity Too Large'
 
+const HTTP_414 ='Request-URI Too Long'
 
+const HTTP_415 ='Unsupported Media Type'
 
+const HTTP_416 ='Requested Range Not Satisfiable'
 
+const HTTP_417 ='Expectation Failed'
 
+const HTTP_500 ='Internal Server Error'
 
+const HTTP_501 ='Not Implemented'
 
+const HTTP_502 ='Bad Gateway'
 
+const HTTP_503 ='Service Unavailable'
 
+const HTTP_504 ='Gateway Timeout'
 
+const HTTP_505 ='HTTP Version Not Supported'
 
+const REQ_SYNC =1
 
+const REQ_AJAX =2
 
+const E_Pattern ='Invalid routing pattern: %s'
 
+const E_Named ='Named route does not exist: %s'
 
+const E_Fatal ='Fatal error: %s'
 
+const E_Open ='Unable to open %s'
 
+const E_Routes ='No routes specified'
 
+const E_Class ='Invalid class %s'
 
+const E_Method ='Invalid method %s'
 
+const E_Hive ='Invalid hive key %s'
 
+ + + +

+Protected Member Functions

 autoload ($class)
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

Base structure.

+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + +
Base::autoload ( $class)
+
+protected
+
+

Namespace-aware class autoloader

+
Returns
mixed
+
Parameters
+ + +
$classstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::base64 ( $data,
 $mime 
)
+
+

Return Base64-encoded equivalent

+
Returns
string
+
Parameters
+ + + +
$datastring
$mimestring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::blacklisted ( $ip)
+
+

Return TRUE if IPv4 address exists in DNSBL

+
Returns
bool
+
Parameters
+ + +
$ipstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::build ( $url)
+
+

Replace tokenized URL with current route's token values

+
Returns
string
+
Parameters
+ + +
$urlarray|string
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Base::call ( $func,
 $args = NULL,
 $hooks = '' 
)
+
+

Execute callback/hooks (supports 'class->method' format)

+
Returns
mixed|FALSE
+
Parameters
+ + + + +
$funccallback
$argsmixed
$hooksstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::camelcase ( $str)
+
+

Convert snakecase string to camelcase

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::chain ( $funcs,
 $args = NULL 
)
+
+

Execute specified callbacks in succession; Apply same arguments to all callbacks

+
Returns
array
+
Parameters
+ + + +
$funcsarray|string
$argsmixed
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::clean ( $arg,
 $tags = NULL 
)
+
+

Remove HTML tags (except those enumerated) and non-printable characters to mitigate XSS/code injection attacks

+
Returns
mixed
+
Parameters
+ + + +
$argmixed
$tagsstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::clear ( $key)
+
+

Unset hive key

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::compile ( $str)
+
+

Convert JS-style token to PHP expression

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::concat ( $key,
 $val 
)
+
+

Concatenate string to hive string variable

+
Returns
string
+
Parameters
+ + + +
$keystring
$valstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::config ( $file)
+
+

Configure framework according to .ini-style file settings

+
Returns
NULL
+
Parameters
+ + +
$filestring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::copy ( $src,
 $dst 
)
+
+

Copy contents of hive variable to another

+
Returns
mixed
+
Parameters
+ + + +
$srcstring
$dststring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::csv (array $args)
+
+

Flatten array values and return as CSV string

+
Returns
string
+
Parameters
+ + +
$argsarray
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::decode ( $str)
+
+

Convert HTML entities back to characters

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::devoid ( $key)
+
+

Return TRUE if hive key is empty and not cached

+
Returns
bool
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::dump ( $expr)
+
+

Dump expression with syntax highlighting

+
Returns
NULL
+
Parameters
+ + +
$exprmixed
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::dupe ( $arg)
+
+

Attempt to clone object

+
Returns
object
+
+$arg object
+ +
+
+ +
+
+ + + + + + + + +
Base::encode ( $str)
+
+

Convert special characters to HTML entities

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Base::error ( $code,
 $text = '',
array $trace = NULL 
)
+
+

Log error; Execute ONERROR handler if defined, else display default error page (HTML for synchronous requests, JSON string for AJAX requests)

+
Returns
NULL
+
Parameters
+ + + + +
$codeint
$textstring
$tracearray
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::exists ( $key,
$val = NULL 
)
+
+

Return TRUE if hive key is not set (or return timestamp and TTL if cached)

+
Returns
bool
+
Parameters
+ + + +
$keystring
$valmixed
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::expire ( $secs = 0)
+
+

Send cache metadata to HTTP client

+
Returns
NULL
+
Parameters
+ + +
$secsint
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::fixslashes ( $str)
+
+

Convert backslashes to slashes

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::flip ( $key)
+
+

Swap keys and values of hive array variable

+
Returns
array
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + +
Base::format ()
+
+

Return locale-aware formatted string

+
Returns
string
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::get ( $key,
 $args = NULL 
)
+
+

Retrieve contents of hive key

+
Returns
mixed
+
Parameters
+ + + +
$keystring
$argsstring|array
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::hash ( $str)
+
+

Generate 64bit/base36 hash

+
Returns
string
+
Parameters
+ + +
$str
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::highlight ( $text)
+
+

Apply syntax highlighting

+
Returns
string
+
Parameters
+ + +
$textstring
+
+
+ +
+
+ +
+
+ + + + + + + +
Base::hive ()
+
+

Publish hive contents

+
Returns
array
+ +
+
+ +
+
+ + + + + + + + +
Base::language ( $code)
+
+

Assign/auto-detect language

+
Returns
string
+
Parameters
+ + +
$codestring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::lexicon ( $path)
+
+

Transfer lexicon entries to hive

+
Returns
array
+
Parameters
+ + +
$pathstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Base::map ( $url,
 $class,
 $ttl = 0,
 $kbps = 0 
)
+
+

Provide ReST interface by mapping HTTP verb to class method

+
Returns
NULL
+
Parameters
+ + + + + +
$urlstring
$classstring
$ttlint
$kbpsint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::merge ( $key,
 $src 
)
+
+

Merge array with hive array variable

+
Returns
array
+
Parameters
+ + + +
$keystring
$srcarray
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Base::mock ( $pattern,
array $args = NULL,
array $headers = NULL,
 $body = NULL 
)
+
+

Mock HTTP request

+
Returns
NULL
+
Parameters
+ + + + + +
$patternstring
$argsarray
$headersarray
$bodystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Base::mset (array $vars,
 $prefix = '',
 $ttl = 0 
)
+
+

Multi-variable assignment using associative array

+
Returns
NULL
+
Parameters
+ + + + +
$varsarray
$prefixstring
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Base::mutex ( $id,
 $func,
 $args = NULL 
)
+
+

Create mutex, invoke callback then drop ownership when done

+
Returns
mixed
+
Parameters
+ + + + +
$idstring
$funccallback
$argsmixed
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::parse ( $str)
+
+

Parse string containing key-value pairs and use as routing tokens

+
Returns
NULL
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::pop ( $key)
+
+

Remove last element of hive array variable

+
Returns
mixed
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::push ( $key,
 $val 
)
+
+

Add element to the end of hive array variable

+
Returns
mixed
+
Parameters
+ + + +
$keystring
$valmixed
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::read ( $file,
 $lf = FALSE 
)
+
+

Read file (with option to apply Unix LF as standard line ending)

+
Returns
string
+
Parameters
+ + + +
$filestring
$lfbool
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::recursive ( $arg,
 $func 
)
+
+

Invoke callback recursively for all data types

+
Returns
mixed
+
Parameters
+ + + +
$argmixed
$funccallback
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
& Base::ref ( $key,
 $add = TRUE 
)
+
+

Get hive key reference/contents; Add non-existent hive keys, array elements, and object properties by default

+
Returns
mixed
+
Parameters
+ + + +
$keystring
$addbool
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::rel ( $url)
+
+

Return path relative to the base directory

+
Returns
string
+
Parameters
+ + +
$urlstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::relay ( $funcs,
 $args = NULL 
)
+
+

Execute specified callbacks in succession; Relay result of previous callback as argument to the next callback

+
Returns
array
+
Parameters
+ + + +
$funcsarray|string
$argsmixed
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::reroute ( $url,
 $permanent = FALSE 
)
+
+

Reroute to specified URI

+
Returns
NULL
+
Parameters
+ + + +
$urlstring
$permanentbool
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Base::route ( $pattern,
 $handler,
 $ttl = 0,
 $kbps = 0 
)
+
+

Bind handler to route pattern

+
Returns
NULL
+
Parameters
+ + + + + +
$patternstring|array
$handlercallback
$ttlint
$kbpsint
+
+
+ +
+
+ +
+
+ + + + + + + +
Base::run ()
+
+

Match routes against incoming URI

+
Returns
NULL
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::scrub ($var,
 $tags = NULL 
)
+
+

Similar to clean(), except that variable is passed by reference

+
Returns
mixed
+
Parameters
+ + + +
$varmixed
$tagsstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::serialize ( $arg)
+
+

Return string representation of PHP value

+
Returns
string
+
Parameters
+ + +
$argmixed
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Base::set ( $key,
 $val,
 $ttl = 0 
)
+
+

Bind value to hive key

+
Returns
mixed
+
Parameters
+ + + + +
$keystring
$valmixed
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::shift ( $key)
+
+

Remove first element of hive array variable

+
Returns
mixed
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::sign ( $num)
+
+

Return -1 if specified number is negative, 0 if zero, or 1 if the number is positive

+
Returns
int
+
Parameters
+ + +
$nummixed
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::snakecase ( $str)
+
+

Convert camelcase string to snakecase

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::split ( $str)
+
+

Split comma-, semi-colon, or pipe-separated string

+
Returns
array
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::status ( $code)
+
+

Send HTTP/1.1 status header; Return text equivalent of status code

+
Returns
string
+
Parameters
+ + +
$codeint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::stringify ( $arg,
array $stack = NULL 
)
+
+

Convert PHP expression/value to compressed exportable string

+
Returns
string
+
Parameters
+ + + +
$argmixed
$stackarray
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::sync ( $key)
+
+

Sync PHP global with corresponding hive key

+
Returns
array
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::unload ( $cwd)
+
+

Execute framework/application shutdown sequence

+
Returns
NULL
+
Parameters
+ + +
$cwdstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Base::unserialize ( $arg)
+
+

Return PHP value derived from string

+
Returns
string
+
Parameters
+ + +
$argmixed
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Base::unshift ( $key,
 $val 
)
+
+

Add element to the beginning of hive array variable

+
Returns
mixed
+
Parameters
+ + + +
$keystring
$valmixed
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Base::write ( $file,
 $data,
 $append = FALSE 
)
+
+

Exclusive file write

+
Returns
int|FALSE
+
Parameters
+ + + + +
$filestring
$datamixed
$appendbool
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • base.php
  • +
+
diff --git a/lib/f3/api/classBase.png b/lib/f3/api/classBase.png new file mode 100755 index 0000000000000000000000000000000000000000..8b95990b5130288c975a1eb78f7e2cde470e8949 GIT binary patch literal 338 zcmeAS@N?(olHy`uVBq!ia0vp^MnD|E!3-pG?q0hDq$C1-LR|m<{|{uod-rb6oH-MK zEHFNB;J^pRRC^$oqa?^Lm;tB=1g@S60U7ep)5S5Qg7NL#yL`-9` zaO$ia@wT(gKGi=K++$Uz>Vc~T_droI>m(iuNI44-!N?T@MJAC}5#)W5nB!Vu%bdf;#fgN+aCg6576ewG7=tEXNNXyBGg zm1pp?2uzBQS{?f9RGMgba7o#;h?> + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Basket Member List
+
+
+ +

This is the complete list of members for Basket, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + +
$idBasket
$itemBasket
$keyBasketprotected
__construct($key='basket')Basket
checkout()Basket
clear($key)Basket
copyfrom($key)Basket
copyto($key)Basket
count()Basket
drop()Basket
dry()Basket
E_Field (defined in Basket)Basket
erase($key, $val)Basket
exists($key)Basket
find($key, $val)Basket
findone($key, $val)Basket
get($key)Basket
load($key, $val)Basket
reset()Basket
save()Basket
set($key, $val)Basket
diff --git a/lib/f3/api/classBasket.html b/lib/f3/api/classBasket.html new file mode 100755 index 0000000..667c85b --- /dev/null +++ b/lib/f3/api/classBasket.html @@ -0,0 +1,534 @@ + + + + + + + +Fat-Free Framework: Basket Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

Session-based pseudo-mapper. + More...

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 find ($key, $val)
 
 findone ($key, $val)
 
 load ($key, $val)
 
 dry ()
 
 count ()
 
 save ()
 
 erase ($key, $val)
 
 reset ()
 
 drop ()
 
 copyfrom ($key)
 
 copyto ($key)
 
 checkout ()
 
 __construct ($key='basket')
 
+ + + + + + + + + + +

+Public Attributes

$id
 Current item identifier.
 
$item =array()
 Current item contents.
 
+const E_Field ='Undefined field %s'
 
+ + + + +

+Protected Attributes

$key
 Session key.
 
+

Detailed Description

+

Session-based pseudo-mapper.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
Basket::__construct ( $key = 'basket')
+
+

Instantiate class

+
Returns
void
+
Parameters
+ + +
$keystring
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + +
Basket::checkout ()
+
+

Check out basket contents

+
Returns
array
+ +
+
+ +
+
+ + + + + + + + +
Basket::clear ( $key)
+
+

Delete field

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Basket::copyfrom ( $key)
+
+

Hydrate item using hive array variable

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Basket::copyto ( $key)
+
+

Populate hive array variable with item contents

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + +
Basket::count ()
+
+

Return number of items in basket

+
Returns
int
+ +
+
+ +
+
+ + + + + + + +
Basket::drop ()
+
+

Empty basket

+
Returns
NULL
+ +
+
+ +
+
+ + + + + + + +
Basket::dry ()
+
+

Return TRUE if current item is empty/undefined

+
Returns
bool
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Basket::erase ( $key,
 $val 
)
+
+

Erase item matching key/value pair

+
Returns
bool
+
Parameters
+ + + +
$keystring
$valmixed
+
+
+ +
+
+ +
+
+ + + + + + + + +
Basket::exists ( $key)
+
+

Return TRUE if field is defined

+
Returns
bool
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Basket::find ( $key,
 $val 
)
+
+

Return items that match key/value pair

+
Returns
array|FALSE
+
Parameters
+ + + +
$keystring
$valmixed
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Basket::findone ( $key,
 $val 
)
+
+

Return first item that matches key/value pair

+
Returns
object|FALSE
+
Parameters
+ + + +
$keystring
$valmixed
+
+
+ +
+
+ +
+
+ + + + + + + + +
Basket::get ( $key)
+
+

Retrieve value of field

+
Returns
scalar|FALSE
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Basket::load ( $key,
 $val 
)
+
+

Map current item to matching key/value pair

+
Returns
array
+
Parameters
+ + + +
$keystring
$valmixed
+
+
+ +
+
+ +
+
+ + + + + + + +
Basket::reset ()
+
+

Reset cursor

+
Returns
NULL
+ +
+
+ +
+
+ + + + + + + +
Basket::save ()
+
+

Save current item

+
Returns
array
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Basket::set ( $key,
 $val 
)
+
+

Assign value to field

+
Returns
scalar|FALSE
+
Parameters
+ + + +
$keystring
$valscalar
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • basket.php
  • +
+
diff --git a/lib/f3/api/classBcrypt-members.html b/lib/f3/api/classBcrypt-members.html new file mode 100755 index 0000000..5f3cac6 --- /dev/null +++ b/lib/f3/api/classBcrypt-members.html @@ -0,0 +1,48 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Bcrypt Member List
+
+
+ +

This is the complete list of members for Bcrypt, including all inherited members.

+ + + + + + + + +
COSTBcrypt
E_CostArg (defined in Bcrypt)Bcrypt
E_SaltArg (defined in Bcrypt)Bcrypt
hash($pw, $salt=NULL, $cost=self::COST)Bcrypt
instance()Prefabstatic
needs_rehash($hash, $cost=self::COST)Bcrypt
verify($pw, $hash)Bcrypt
diff --git a/lib/f3/api/classBcrypt.html b/lib/f3/api/classBcrypt.html new file mode 100755 index 0000000..46ac5f9 --- /dev/null +++ b/lib/f3/api/classBcrypt.html @@ -0,0 +1,204 @@ + + + + + + + +Fat-Free Framework: Bcrypt Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+ +
+
Bcrypt Class Reference
+
+
+ +

Lightweight password hashing library. + More...

+
+ + Inheritance diagram for Bcrypt:
+
+
+ + + + + + + + + +

+Public Member Functions

 hash ($pw, $salt=NULL, $cost=self::COST)
 
 needs_rehash ($hash, $cost=self::COST)
 
 verify ($pw, $hash)
 
+ + + + + + + + + +

+Public Attributes

+const COST =10
 Default cost.
 
+const E_CostArg ='Invalid cost parameter'
 
+const E_SaltArg ='Salt must be at least 22 alphanumeric characters'
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

Lightweight password hashing library.

+

Member Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Bcrypt::hash ( $pw,
 $salt = NULL,
 $cost = self::COST 
)
+
+

Generate bcrypt hash of string

+
Returns
string|FALSE
+
Parameters
+ + + + +
$pwstring
$saltstring
$costint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Bcrypt::needs_rehash ( $hash,
 $cost = self::COST 
)
+
+

Check if password is still strong enough

+
Returns
bool
+
Parameters
+ + + +
$hashstring
$costint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Bcrypt::verify ( $pw,
 $hash 
)
+
+

Verify password against hash using timing attack resistant approach

+
Returns
bool
+
Parameters
+ + + +
$pwstring
$hashstring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • bcrypt.php
  • +
+
diff --git a/lib/f3/api/classBcrypt.png b/lib/f3/api/classBcrypt.png new file mode 100755 index 0000000000000000000000000000000000000000..caea9bec3fe53bad2b5593f4509485ed17f4417b GIT binary patch literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^MnD|E!3-pG?q0hDq$C1-LR|m<{|{uod-rb6oH-MK zEHFNB;J^pRRC^$oqa?^Lm;tB=1g@S60U7e!)5S5Qg7NL#gPWQacwGG_N&f#o`M&dk z1qrILB@ZuD84C4HZz=4b8R;`)RhG+o7nQ#uUrT=aOfGsdX@^ani%ReAX3`f&$__P($_ zaz;m`VWU~Yj7KN7wa&Eo!?psu>HG z&njIqm-R(SzsTk(H{`z?^p*FVdQ&MBb@ E0Cs7ifB*mh literal 0 HcmV?d00001 diff --git a/lib/f3/api/classCache-members.html b/lib/f3/api/classCache-members.html new file mode 100755 index 0000000..3f4b2f2 --- /dev/null +++ b/lib/f3/api/classCache-members.html @@ -0,0 +1,52 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Cache Member List
+
+
+ +

This is the complete list of members for Cache, including all inherited members.

+ + + + + + + + + + + + +
$dsnCacheprotected
$prefixCache
$refCache
__construct($dsn=FALSE)Cache
clear($key)Cache
exists($key, &$val=NULL)Cache
get($key)Cache
instance()Prefabstatic
load($dsn)Cache
reset($suffix=NULL, $lifetime=0)Cache
set($key, $val, $ttl=0)Cache
diff --git a/lib/f3/api/classCache.html b/lib/f3/api/classCache.html new file mode 100755 index 0000000..997967f --- /dev/null +++ b/lib/f3/api/classCache.html @@ -0,0 +1,314 @@ + + + + + + + +Fat-Free Framework: Cache Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

Cache engine. + More...

+
+ + Inheritance diagram for Cache:
+
+
+ + + + + + + + + + + + + + + + + +

+Public Member Functions

 exists ($key, &$val=NULL)
 
 set ($key, $val, $ttl=0)
 
 get ($key)
 
 clear ($key)
 
 reset ($suffix=NULL, $lifetime=0)
 
 load ($dsn)
 
 __construct ($dsn=FALSE)
 
+ + + + + + + +

+Public Attributes

$prefix
 Prefix for cache entries.
 
$ref
 MemCache object.
 
+ + + + +

+Protected Attributes

$dsn
 Cache DSN.
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

Cache engine.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
Cache::__construct ( $dsn = FALSE)
+
+

Class constructor

+
Returns
object
+
Parameters
+ + +
$dsnbool|string
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
Cache::clear ( $key)
+
+

Delete cache entry

+
Returns
bool
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Cache::exists ( $key,
$val = NULL 
)
+
+

Return timestamp and TTL of cache entry or FALSE if not found

+
Returns
array|FALSE
+
Parameters
+ + + +
$keystring
$valmixed
+
+
+ +
+
+ +
+
+ + + + + + + + +
Cache::get ( $key)
+
+

Retrieve value of cache entry

+
Returns
mixed|FALSE
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Cache::load ( $dsn)
+
+

Load/auto-detect cache backend

+
Returns
string
+
Parameters
+ + +
$dsnbool|string
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Cache::reset ( $suffix = NULL,
 $lifetime = 0 
)
+
+

Clear contents of cache backend

+
Returns
bool
+
Parameters
+ + + +
$suffixstring
$lifetimeint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Cache::set ( $key,
 $val,
 $ttl = 0 
)
+
+

Store value in cache

+
Returns
mixed|FALSE
+
Parameters
+ + + + +
$keystring
$valmixed
$ttlint
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • base.php
  • +
+
diff --git a/lib/f3/api/classCache.png b/lib/f3/api/classCache.png new file mode 100755 index 0000000000000000000000000000000000000000..4093d229535da4c5abb83528a3540214a743e6d2 GIT binary patch literal 352 zcmeAS@N?(olHy`uVBq!ia0vp^MnD|E!3-pG?q0hDq$C1-LR|m<{|{uod-rb6oH-MK zEHFNB;J^pRRC^$oqa?^Lm;tB=1g@S60U7e%)5S5Qg7NKKN1yZu_eLxty$Duy#>k`9H0Dp#p0{q_%CeR}?!X)-%?VwO3(e5+nHwM9@=drT>v$f(h%gdh3a(wkr$Ea}HsdI;y8TtG_W*B + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
DB\Cursor Member List
+
+
+ +

This is the complete list of members for DB\Cursor, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$ptrDB\Cursor
$queryDB\Cursorprotected
$triggerDB\Cursor
__get($key)Magic
__isset($key)Magic
__set($key, $val)Magic
__unset($key)Magic
cast($obj=NULL)DB\Cursor
clear($key)Magic
copyfrom($key, $func=NULL)DB\Cursor
copyto($key)DB\Cursor
count($filter=NULL, $ttl=0)DB\Cursor
dry()DB\Cursor
E_Field (defined in DB\Cursor)DB\Cursor
erase()DB\Cursor
exists($key)Magic
find($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
findone($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
first()DB\Cursor
get($key)Magic
insert()DB\Cursor
last()DB\Cursor
load($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
next()DB\Cursor
offsetexists($key)Magic
offsetget($key)Magic
offsetset($key, $val)Magic
offsetunset($key)Magic
onerase($func)DB\Cursor
oninsert($func)DB\Cursor
onload($func)DB\Cursor
onupdate($func)DB\Cursor
paginate($pos=0, $size=10, $filter=NULL, array $options=NULL)DB\Cursor
prev()DB\Cursor
reset()DB\Cursor
save()DB\Cursor
set($key, $val)Magic
skip($ofs=1)DB\Cursor
update()DB\Cursor
diff --git a/lib/f3/api/classDB_1_1Cursor.html b/lib/f3/api/classDB_1_1Cursor.html new file mode 100755 index 0000000..8eec72a --- /dev/null +++ b/lib/f3/api/classDB_1_1Cursor.html @@ -0,0 +1,785 @@ + + + + + + + +Fat-Free Framework: DB\Cursor Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+ +
+ +

Simple cursor implementation. + More...

+
+ + Inheritance diagram for DB\Cursor:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 cast ($obj=NULL)
 
 find ($filter=NULL, array $options=NULL, $ttl=0)
 
 count ($filter=NULL, $ttl=0)
 
 insert ()
 
 update ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 dry ()
 
 findone ($filter=NULL, array $options=NULL, $ttl=0)
 
 paginate ($pos=0, $size=10, $filter=NULL, array $options=NULL)
 
 load ($filter=NULL, array $options=NULL, $ttl=0)
 
 first ()
 
 last ()
 
 skip ($ofs=1)
 
 next ()
 
 prev ()
 
 save ()
 
 erase ()
 
 onload ($func)
 
 oninsert ($func)
 
 onupdate ($func)
 
 onerase ($func)
 
 reset ()
 
- Public Member Functions inherited from Magic
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 offsetexists ($key)
 
 __isset ($key)
 
 offsetset ($key, $val)
 
 __set ($key, $val)
 
 offsetget ($key)
 
 __get ($key)
 
 offsetunset ($key)
 
 __unset ($key)
 
+ + + + + + + + + + +

+Public Attributes

$ptr =0
 Current position.
 
$trigger =array()
 Event listeners.
 
+const E_Field ='Undefined field %s'
 
+ + + + +

+Protected Attributes

$query =array()
 Query results.
 
+

Detailed Description

+

Simple cursor implementation.

+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + +
DB\Cursor::cast ( $obj = NULL)
+
+abstract
+
+

Return fields of mapper object as an associative array

+
Returns
array
+
Parameters
+ + +
$objobject
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
DB\Cursor::copyfrom ( $key,
 $func = NULL 
)
+
+abstract
+
+

Hydrate mapper object using hive array variable

+
Returns
NULL
+
Parameters
+ + + +
$keystring
$funccallback
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
DB\Cursor::copyto ( $key)
+
+abstract
+
+

Populate hive array variable with mapper fields

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
DB\Cursor::count ( $filter = NULL,
 $ttl = 0 
)
+
+abstract
+
+

Count records that match criteria

+
Returns
int
+
Parameters
+ + + +
$filterarray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Cursor::dry ()
+
+

Return TRUE if current cursor position is not mapped to any record

+
Returns
bool
+ +
+
+ +
+
+ + + + + + + +
DB\Cursor::erase ()
+
+

Delete current record

+
Returns
int|bool
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
DB\Cursor::find ( $filter = NULL,
array $options = NULL,
 $ttl = 0 
)
+
+abstract
+
+

Return records (array of mapper objects) that match criteria

+
Returns
array
+
Parameters
+ + + + +
$filterstring|array
$optionsarray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
DB\Cursor::findone ( $filter = NULL,
array $options = NULL,
 $ttl = 0 
)
+
+

Return first record (mapper object) that matches criteria

+
Returns
object|FALSE
+
Parameters
+ + + + +
$filterstring|array
$optionsarray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Cursor::first ()
+
+

Map to first record in cursor

+
Returns
mixed
+ +
+
+ +
+
+ + + + + +
+ + + + + + + +
DB\Cursor::insert ()
+
+abstract
+
+

Insert new record

+
Returns
array
+ +
+
+ +
+
+ + + + + + + +
DB\Cursor::last ()
+
+

Map to last record in cursor

+
Returns
mixed
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
DB\Cursor::load ( $filter = NULL,
array $options = NULL,
 $ttl = 0 
)
+
+

Map to first record that matches criteria

+
Returns
array|FALSE
+
Parameters
+ + + + +
$filterstring|array
$optionsarray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Cursor::next ()
+
+

Map next record

+
Returns
mixed
+ +
+
+ +
+
+ + + + + + + + +
DB\Cursor::onerase ( $func)
+
+

Define onerase trigger

+
Returns
closure
+ +
+
+ +
+
+ + + + + + + + +
DB\Cursor::oninsert ( $func)
+
+

Define oninsert trigger

+
Returns
closure
+ +
+
+ +
+
+ + + + + + + + +
DB\Cursor::onload ( $func)
+
+

Define onload trigger

+
Returns
closure
+ +
+
+ +
+
+ + + + + + + + +
DB\Cursor::onupdate ( $func)
+
+

Define onupdate trigger

+
Returns
closure
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DB\Cursor::paginate ( $pos = 0,
 $size = 10,
 $filter = NULL,
array $options = NULL 
)
+
+

Return array containing subset of records matching criteria, total number of records in superset, specified limit, number of subsets available, and actual subset position

+
Returns
array
+
Parameters
+ + + + + +
$posint
$sizeint
$filterstring|array
$optionsarray
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Cursor::prev ()
+
+

Map previous record

+
Returns
mixed
+ +
+
+ +
+
+ + + + + + + +
DB\Cursor::reset ()
+
+

Reset cursor

+
Returns
NULL
+ +
+
+ +
+
+ + + + + + + +
DB\Cursor::save ()
+
+

Save mapped record

+
Returns
mixed
+ +
+
+ +
+
+ + + + + + + + +
DB\Cursor::skip ( $ofs = 1)
+
+

Map to nth record relative to current cursor position

+
Returns
mixed
+
Parameters
+ + +
$ofsint
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + +
DB\Cursor::update ()
+
+abstract
+
+

Update current record

+
Returns
array
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • db/cursor.php
  • +
+
diff --git a/lib/f3/api/classDB_1_1Cursor.png b/lib/f3/api/classDB_1_1Cursor.png new file mode 100755 index 0000000000000000000000000000000000000000..858faba1c7e4e205ba65360e06c820c1c6720cc5 GIT binary patch literal 2201 zcmb`J3s4hx9>;^Rf;|j4$c0BK)TUsSf)E8%NPNIyP(UKqwgM>?$%$aNhL;ku5g#eT z^AHG;NAOP6)(KDL)sSQk2rW}pWn{roC*ux_O`>@C=_ZN>3AR+g)(Cx8nQqmag@f-MlN=zPDTd7FpS8Bg@ww> z$|6L)KE-0O?#Klqa%+)74m*uPHfvGU6+naFsl*HU3!4aO5 zeL0tghbH;yefrw0q@U4x85?f$@(#3j!(wS>GZ$wDhAaz zYZl6Xj#x^CCVWa<;Pk_)=w6)SImwg9i9x&oI?l3 zF<1>Jt*lG_+4V+}y|c?M6?*dp2CF9T|9t3CLJrw(W;7JzCVuJf%gxNzjHpf*k~!Y= zsnKdt=R%sdhc_|xR~7{TA^s3<_PB)DsS%XAEet1R__eRuiJX8>W}CH#i^JlKOW1Kn zsTV<9JEo(is?ht=Frq&#?02r=`xs?S_@~2jML4HH$PN79;)MLIUWj-DNNe;W6iw7s z8QidrDztolvFUx1`j>vymXHHcn3_g&7P^h7LU%7`eB$ha+Ypai35Np_Ec%y!RfB$} z?TzosqtUX|4ZpH?3Lnv^r`LdRyLI?+mxm$Ly-3lOH}u9RA(b7{SHL0$kOjY>MNXEt2}MxW?vg8hx~z z7q+BHarWVzA2=ti;Vn%W$g6ub10t~})F0~`Y!~k}?@#1r8Ak&9Y?422S3YII9ijL; z3+%0!`aG-YzkjCl4gQY$!#*w@vPrfT4aPc)q9)^whH~}Y+}rmU5BWDUA$db-*O||TZY8Y#(e&|AF$W+`M;ngI9B{DNi%t1`DKHuR|7;z<9xum zUSihT^2-bC-KGrRM0YWkw$|rPn%fOMiG6@ByEk~pwK<UqA*mV^{Xgf6;qQAKDjPpjq)5KIX>r?>h&ic0>y7?`+^Ro9DdKWlwH zSUmH$2%|x0Y|~tKbfaU4@UkuQ&s_v&yP%Y}pP$xK)8Fn1>}2bjWA{KKR#qoB!u&?D{B>15A z^0*z7EbYmBH;JhpI%9HSCXE`=eT9zk5ktCxxE8Rr0En6(9>a3(yRsdGxU7r$ACjnJ z{wbt`qfb6Hc3a}U?%ZNr + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
DB\Jig Member List
+
+
+ +

This is the complete list of members for DB\Jig, including all inherited members.

+ + + + + + + + + + + + + + + +
$dirDB\Jig
$formatDB\Jig
$logDB\Jig
$uuidDB\Jigprotected
__construct($dir, $format=self::FORMAT_JSON)DB\Jig
dir()DB\Jig
drop()DB\Jig
FORMAT_JSON (defined in DB\Jig)DB\Jig
FORMAT_Serialized (defined in DB\Jig)DB\Jig
jot($frame)DB\Jig
log()DB\Jig
read($file)DB\Jig
uuid()DB\Jig
write($file, array $data=NULL)DB\Jig
diff --git a/lib/f3/api/classDB_1_1Jig.html b/lib/f3/api/classDB_1_1Jig.html new file mode 100755 index 0000000..f9d909d --- /dev/null +++ b/lib/f3/api/classDB_1_1Jig.html @@ -0,0 +1,291 @@ + + + + + + + +Fat-Free Framework: DB\Jig Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+ +
+ +

Flat-file DB wrapper. + More...

+ + + + + + + + + + + + + + + + + + +

+Public Member Functions

 read ($file)
 
 write ($file, array $data=NULL)
 
 dir ()
 
 uuid ()
 
 log ()
 
 jot ($frame)
 
 drop ()
 
 __construct ($dir, $format=self::FORMAT_JSON)
 
+ + + + + + + + + + + + + + + +

+Public Attributes

$dir
 Storage location.
 
$format
 Current storage format.
 
$log
 Jig log.
 
+const FORMAT_JSON =0
 
+const FORMAT_Serialized =1
 
+ + + + +

+Protected Attributes

$uuid
 UUID.
 
+

Detailed Description

+

Flat-file DB wrapper.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Jig::__construct ( $dir,
 $format = self::FORMAT_JSON 
)
+
+

Instantiate class

+
Parameters
+ + + +
$dirstring
$formatint
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + +
DB\Jig::dir ()
+
+

Return directory

+
Returns
string
+ +
+
+ +
+
+ + + + + + + +
DB\Jig::drop ()
+
+

Clean storage

+
Returns
NULL
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig::jot ( $frame)
+
+

Jot down log entry

+
Returns
NULL
+
Parameters
+ + +
$framestring
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Jig::log ()
+
+

Return SQL profiler results

+
Returns
string
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig::read ( $file)
+
+

Read data from file

+
Returns
array
+
Parameters
+ + +
$filestring
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Jig::uuid ()
+
+

Return UUID

+
Returns
string
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Jig::write ( $file,
array $data = NULL 
)
+
+

Write data to file

+
Returns
int
+
Parameters
+ + + +
$filestring
$dataarray
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • db/jig.php
  • +
+
diff --git a/lib/f3/api/classDB_1_1Jig_1_1Mapper-members.html b/lib/f3/api/classDB_1_1Jig_1_1Mapper-members.html new file mode 100755 index 0000000..01ba498 --- /dev/null +++ b/lib/f3/api/classDB_1_1Jig_1_1Mapper-members.html @@ -0,0 +1,94 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
DB\Jig\Mapper Member List
+
+
+ +

This is the complete list of members for DB\Jig\Mapper, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$dbDB\Jig\Mapperprotected
$documentDB\Jig\Mapper
$fileDB\Jig\Mapper
$idDB\Jig\Mapper
$ptrDB\Cursor
$queryDB\Cursorprotected
$triggerDB\Cursor
__construct(\DB\Jig $db, $file)DB\Jig\Mapper
__get($key)Magic
__isset($key)Magic
__set($key, $val)Magic
__unset($key)Magic
cast($obj=NULL)DB\Jig\Mapper
clear($key)DB\Jig\Mapper
copyfrom($key, $func=NULL)DB\Jig\Mapper
copyto($key)DB\Jig\Mapper
count($filter=NULL, $ttl=0)DB\Jig\Mapper
dry()DB\Cursor
E_Field (defined in DB\Cursor)DB\Cursor
erase($filter=NULL)DB\Jig\Mapper
DB::Cursor::erase()DB\Cursor
exists($key)DB\Jig\Mapper
factory($id, $row)DB\Jig\Mapperprotected
fields()DB\Jig\Mapper
find($filter=NULL, array $options=NULL, $ttl=0, $log=TRUE)DB\Jig\Mapper
DB::Cursor::find($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
findone($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
first()DB\Cursor
get($key)DB\Jig\Mapper
insert()DB\Jig\Mapper
last()DB\Cursor
load($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
next()DB\Cursor
offsetexists($key)Magic
offsetget($key)Magic
offsetset($key, $val)Magic
offsetunset($key)Magic
onerase($func)DB\Cursor
oninsert($func)DB\Cursor
onload($func)DB\Cursor
onupdate($func)DB\Cursor
paginate($pos=0, $size=10, $filter=NULL, array $options=NULL)DB\Cursor
prev()DB\Cursor
reset()DB\Jig\Mapper
save()DB\Cursor
set($key, $val)DB\Jig\Mapper
skip($ofs=1)DB\Jig\Mapper
token($str)DB\Jig\Mapper
update()DB\Jig\Mapper
diff --git a/lib/f3/api/classDB_1_1Jig_1_1Mapper.html b/lib/f3/api/classDB_1_1Jig_1_1Mapper.html new file mode 100755 index 0000000..50d32c9 --- /dev/null +++ b/lib/f3/api/classDB_1_1Jig_1_1Mapper.html @@ -0,0 +1,717 @@ + + + + + + + +Fat-Free Framework: DB\Jig\Mapper Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+ +
+ +

Flat-file DB mapper. + More...

+
+ + Inheritance diagram for DB\Jig\Mapper:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 cast ($obj=NULL)
 
 token ($str)
 
 find ($filter=NULL, array $options=NULL, $ttl=0, $log=TRUE)
 
 count ($filter=NULL, $ttl=0)
 
 skip ($ofs=1)
 
 insert ()
 
 update ()
 
 erase ($filter=NULL)
 
 reset ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 fields ()
 
 __construct (\DB\Jig $db, $file)
 
- Public Member Functions inherited from DB\Cursor
 cast ($obj=NULL)
 
 find ($filter=NULL, array $options=NULL, $ttl=0)
 
 count ($filter=NULL, $ttl=0)
 
 insert ()
 
 update ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 dry ()
 
 findone ($filter=NULL, array $options=NULL, $ttl=0)
 
 paginate ($pos=0, $size=10, $filter=NULL, array $options=NULL)
 
 load ($filter=NULL, array $options=NULL, $ttl=0)
 
 first ()
 
 last ()
 
 skip ($ofs=1)
 
 next ()
 
 prev ()
 
 save ()
 
 erase ()
 
 onload ($func)
 
 oninsert ($func)
 
 onupdate ($func)
 
 onerase ($func)
 
 reset ()
 
- Public Member Functions inherited from Magic
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 offsetexists ($key)
 
 __isset ($key)
 
 offsetset ($key, $val)
 
 __set ($key, $val)
 
 offsetget ($key)
 
 __get ($key)
 
 offsetunset ($key)
 
 __unset ($key)
 
+ + + + + + + + + + + + + + + + + + + +

+Public Attributes

$file
 Data file.
 
$id
 Document identifier.
 
$document =array()
 Document contents.
 
- Public Attributes inherited from DB\Cursor
$ptr =0
 Current position.
 
$trigger =array()
 Event listeners.
 
+const E_Field ='Undefined field %s'
 
+ + + +

+Protected Member Functions

 factory ($id, $row)
 
+ + + + + + + + +

+Protected Attributes

$db
 Flat-file DB wrapper.
 
- Protected Attributes inherited from DB\Cursor
$query =array()
 Query results.
 
+

Detailed Description

+

Flat-file DB mapper.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Jig\Mapper::__construct (\DB\Jig $db,
 $file 
)
+
+

Instantiate class

+
Returns
void
+
Parameters
+ + + +
$dbobject
$filestring
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
DB\Jig\Mapper::cast ( $obj = NULL)
+
+

Return fields of mapper object as an associative array

+
Returns
array
+
Parameters
+ + +
$objobject
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Mapper::clear ( $key)
+
+

Delete field

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Jig\Mapper::copyfrom ( $key,
 $func = NULL 
)
+
+

Hydrate mapper object using hive array variable

+
Returns
NULL
+
Parameters
+ + + +
$keystring
$funccallback
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Mapper::copyto ( $key)
+
+

Populate hive array variable with mapper fields

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Jig\Mapper::count ( $filter = NULL,
 $ttl = 0 
)
+
+

Count records that match criteria

+
Returns
int
+
Parameters
+ + + +
$filterarray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Mapper::erase ( $filter = NULL)
+
+

Delete current record

+
Returns
bool
+
Parameters
+ + +
$filterarray
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Mapper::exists ( $key)
+
+

Return TRUE if field is defined

+
Returns
bool
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
DB\Jig\Mapper::factory ( $id,
 $row 
)
+
+protected
+
+

Convert array to mapper object

+
Returns
object
+
Parameters
+ + + +
$idstring
$rowarray
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Jig\Mapper::fields ()
+
+

Return field names

+
Returns
array
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DB\Jig\Mapper::find ( $filter = NULL,
array $options = NULL,
 $ttl = 0,
 $log = TRUE 
)
+
+

Return records that match criteria

+
Returns
array|FALSE
+
Parameters
+ + + + + +
$filterarray
$optionsarray
$ttlint
$logbool
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Mapper::get ( $key)
+
+

Retrieve value of field

+
Returns
scalar|FALSE
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Jig\Mapper::insert ()
+
+

Insert new record

+
Returns
array
+ +
+
+ +
+
+ + + + + + + +
DB\Jig\Mapper::reset ()
+
+

Reset cursor

+
Returns
NULL
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Jig\Mapper::set ( $key,
 $val 
)
+
+

Assign value to field

+
Returns
scalar|FALSE
+
Parameters
+ + + +
$keystring
$valscalar
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Mapper::skip ( $ofs = 1)
+
+

Return record at specified offset using criteria of previous load() call and make it active

+
Returns
array
+
Parameters
+ + +
$ofsint
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Mapper::token ( $str)
+
+

Convert tokens in string expression to variable names

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Jig\Mapper::update ()
+
+

Update current record

+
Returns
array
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • db/jig/mapper.php
  • +
+
diff --git a/lib/f3/api/classDB_1_1Jig_1_1Mapper.png b/lib/f3/api/classDB_1_1Jig_1_1Mapper.png new file mode 100755 index 0000000000000000000000000000000000000000..b428aa13de96992aeeda9a8c79dee1d1ae1daafc GIT binary patch literal 1083 zcmeAS@N?(olHy`uVBq!ia0vp^NkIIAgBeIFv>lcNQW60^A+G=b{|7SPy?Zxj&YTHA z78oBmaNvVusy&d)Q4-`A%m7pb0#{Fk7%?y~pYn8Z45?szJNNaZ)d~V^v-`Cw|C`%& zitEKadeQb~<(rgT$CBle5`TR;6u-1i2=cNmboJ7d{K0#4<;PD`u5}fNJ^Io(B`C`x zsON17*ZGO9pAJ~;$vpMbBT%V#Z=kVIke7ANtQrZCubbpGZmGG)=|743_-AWZW(wy9 zn+-uai=T6cE}JOYDzsC_^|p!Ny+u2=id%PWjJP%N<)=K?rBg03Zr{(8cJ%N2p3slY z`ZMd#1bdx4a9zWRW1%*~bqR)Fm*Ne1?#liZ<#*0M&Mp!k6u6FI!vih`=5-7PsMLpW zQNv?5#22Z2Jt8_O<-z`dmeAch6+PD*XeRx^599oZC+yhf(P z>e;bPannUU^M$B+S{>eU_v@~buqik4!`~dK`y3Z?X6u({U6YpRir<@L&2{9B{T9uwwGW3=rhqg)x7)F$ucqXO%@?O!tYmSh6v$Oi#BliS^Xg;~LqBv^W`9&+5-)WXD-@k6h;jUF;dvA4TeW=kt zcdvU+$;~}$llIvEdmDD;>-OItPNuD8lv>keRou|_U1QoCMzcMhj0ODR3=%(jlv)IK zF%|SOF3|rgdicWKi}4=~zLeECd{h;E%EiEqkxD>mran|Kxo5gWQqM;&7tdFnpkPuL zefV>=RdW5Fyx*UNCv8bB-=Q(>@}0=mSlcb~K9ja>>9Tp6^{V*0;m4)ZTfJ}nw6V4L zTC^F&CvrSh_c`~9K0{2rg3JSNE&i?z%1 jdRBGTpHYRy;(vxIQl-*;_cvJqb2@{ktDnm{r-UW|m~Zq% literal 0 HcmV?d00001 diff --git a/lib/f3/api/classDB_1_1Jig_1_1Session-members.html b/lib/f3/api/classDB_1_1Jig_1_1Session-members.html new file mode 100755 index 0000000..2c27ece --- /dev/null +++ b/lib/f3/api/classDB_1_1Jig_1_1Session-members.html @@ -0,0 +1,104 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
DB\Jig\Session Member List
+
+
+ +

This is the complete list of members for DB\Jig\Session, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$dbDB\Jig\Mapperprotected
$documentDB\Jig\Mapper
$fileDB\Jig\Mapper
$idDB\Jig\Mapper
$ptrDB\Cursor
$queryDB\Cursorprotected
$triggerDB\Cursor
__construct(\DB\Jig $db, $table='sessions')DB\Jig\Session
__get($key)Magic
__isset($key)Magic
__set($key, $val)Magic
__unset($key)Magic
agent($id=NULL)DB\Jig\Session
cast($obj=NULL)DB\Jig\Mapper
cleanup($max)DB\Jig\Session
clear($key)DB\Jig\Mapper
close()DB\Jig\Session
copyfrom($key, $func=NULL)DB\Jig\Mapper
copyto($key)DB\Jig\Mapper
count($filter=NULL, $ttl=0)DB\Jig\Mapper
csrf($id=NULL)DB\Jig\Session
destroy($id)DB\Jig\Session
dry()DB\Cursor
E_Field (defined in DB\Cursor)DB\Cursor
erase($filter=NULL)DB\Jig\Mapper
DB::Cursor::erase()DB\Cursor
exists($key)DB\Jig\Mapper
factory($id, $row)DB\Jig\Mapperprotected
fields()DB\Jig\Mapper
find($filter=NULL, array $options=NULL, $ttl=0, $log=TRUE)DB\Jig\Mapper
DB::Cursor::find($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
findone($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
first()DB\Cursor
get($key)DB\Jig\Mapper
insert()DB\Jig\Mapper
ip($id=NULL)DB\Jig\Session
last()DB\Cursor
load($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
next()DB\Cursor
offsetexists($key)Magic
offsetget($key)Magic
offsetset($key, $val)Magic
offsetunset($key)Magic
onerase($func)DB\Cursor
oninsert($func)DB\Cursor
onload($func)DB\Cursor
onupdate($func)DB\Cursor
open($path, $name)DB\Jig\Session
paginate($pos=0, $size=10, $filter=NULL, array $options=NULL)DB\Cursor
prev()DB\Cursor
read($id)DB\Jig\Session
reset()DB\Jig\Mapper
save()DB\Cursor
set($key, $val)DB\Jig\Mapper
skip($ofs=1)DB\Jig\Mapper
stamp($id=NULL)DB\Jig\Session
token($str)DB\Jig\Mapper
update()DB\Jig\Mapper
write($id, $data)DB\Jig\Session
diff --git a/lib/f3/api/classDB_1_1Jig_1_1Session.html b/lib/f3/api/classDB_1_1Jig_1_1Session.html new file mode 100755 index 0000000..bce7108 --- /dev/null +++ b/lib/f3/api/classDB_1_1Jig_1_1Session.html @@ -0,0 +1,531 @@ + + + + + + + +Fat-Free Framework: DB\Jig\Session Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+ +
+
DB\Jig\Session Class Reference
+
+
+ +

Jig-managed session handler. + More...

+
+ + Inheritance diagram for DB\Jig\Session:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 open ($path, $name)
 
 close ()
 
 read ($id)
 
 write ($id, $data)
 
 destroy ($id)
 
 cleanup ($max)
 
 csrf ($id=NULL)
 
 ip ($id=NULL)
 
 stamp ($id=NULL)
 
 agent ($id=NULL)
 
 __construct (\DB\Jig $db, $table='sessions')
 
- Public Member Functions inherited from DB\Jig\Mapper
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 cast ($obj=NULL)
 
 token ($str)
 
 find ($filter=NULL, array $options=NULL, $ttl=0, $log=TRUE)
 
 count ($filter=NULL, $ttl=0)
 
 skip ($ofs=1)
 
 insert ()
 
 update ()
 
 erase ($filter=NULL)
 
 reset ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 fields ()
 
 __construct (\DB\Jig $db, $file)
 
- Public Member Functions inherited from DB\Cursor
 cast ($obj=NULL)
 
 find ($filter=NULL, array $options=NULL, $ttl=0)
 
 count ($filter=NULL, $ttl=0)
 
 insert ()
 
 update ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 dry ()
 
 findone ($filter=NULL, array $options=NULL, $ttl=0)
 
 paginate ($pos=0, $size=10, $filter=NULL, array $options=NULL)
 
 load ($filter=NULL, array $options=NULL, $ttl=0)
 
 first ()
 
 last ()
 
 skip ($ofs=1)
 
 next ()
 
 prev ()
 
 save ()
 
 erase ()
 
 onload ($func)
 
 oninsert ($func)
 
 onupdate ($func)
 
 onerase ($func)
 
 reset ()
 
- Public Member Functions inherited from Magic
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 offsetexists ($key)
 
 __isset ($key)
 
 offsetset ($key, $val)
 
 __set ($key, $val)
 
 offsetget ($key)
 
 __get ($key)
 
 offsetunset ($key)
 
 __unset ($key)
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Public Attributes inherited from DB\Jig\Mapper
$file
 Data file.
 
$id
 Document identifier.
 
$document =array()
 Document contents.
 
- Public Attributes inherited from DB\Cursor
$ptr =0
 Current position.
 
$trigger =array()
 Event listeners.
 
+const E_Field ='Undefined field %s'
 
- Protected Member Functions inherited from DB\Jig\Mapper
 factory ($id, $row)
 
- Protected Attributes inherited from DB\Jig\Mapper
$db
 Flat-file DB wrapper.
 
- Protected Attributes inherited from DB\Cursor
$query =array()
 Query results.
 
+

Detailed Description

+

Jig-managed session handler.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Jig\Session::__construct (\DB\Jig $db,
 $table = 'sessions' 
)
+
+

Instantiate class

+
Parameters
+ + + +
$dbobject
$tablestring
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
DB\Jig\Session::agent ( $id = NULL)
+
+

Return HTTP user agent associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Session::cleanup ( $max)
+
+

Garbage collector

+
Returns
TRUE
+
Parameters
+ + +
$maxint
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Jig\Session::close ()
+
+

Close session

+
Returns
TRUE
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Session::csrf ( $id = NULL)
+
+

Return anti-CSRF tokan associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Session::destroy ( $id)
+
+

Destroy session

+
Returns
TRUE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Session::ip ( $id = NULL)
+
+

Return IP address associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Jig\Session::open ( $path,
 $name 
)
+
+

Open session

+
Returns
TRUE
+
Parameters
+ + + +
$pathstring
$namestring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Session::read ( $id)
+
+

Return session data in serialized format

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Jig\Session::stamp ( $id = NULL)
+
+

Return Unix timestamp associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Jig\Session::write ( $id,
 $data 
)
+
+

Write session data

+
Returns
TRUE
+
Parameters
+ + + +
$idstring
$datastring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • db/jig/session.php
  • +
+
diff --git a/lib/f3/api/classDB_1_1Jig_1_1Session.png b/lib/f3/api/classDB_1_1Jig_1_1Session.png new file mode 100755 index 0000000000000000000000000000000000000000..47ea9513447dfd4255fc70a73829ac0c91a67a6d GIT binary patch literal 1078 zcmeAS@N?(olHy`uVBq!ia0vp^NkIIAgBeIFv>lcNQW60^A+G=b{|7SPy?Zxj&YTHA z78oBmaNvVusy&d)Q4-`A%m7pb0#{Fk7%?y~AN6!`45?szJNNaZ%{l^Xv)i?H{&VlFDM48l z!Dqe(wWObSlQbxQzba^+rq`04rrBvuUN0MBr|LH^iu)$)8vXRdU#D+f&)0|Q*hV+x zIxN3YwO)LckFqwGYEfj@wk)MTU60o8wFo%VzVvNm-hJCZ&7~!WZpSlje)RW!Pw2;H z{h9S=g1t^2xUS*Ek*LA&eFnoZqc}s~!?KS>`449tXBUYtS`@>Wa8Q(i4M-h8p&qQ) zO6n=paq*Pu)K)op;J=gLuBz`2lj0HsbQWIonv_@MFF0+s`_C1t`8=(TZVD(~BU7^T z+Nn)(+eKdUg{XP%I<)2P*IhheQ*P{EXVLNZbamjyc}wH%0w-;Gek}S^-=Qrw_Gb=l zviWB?eMxjpuhKDzcBX=U&IFyuqL)qX7{+}x=qaml_^7IWN|Zqi!)+j!{#ymqblhpm zl8HNe!vQcPcOC)VtP3NP9oHqwQH1r!nuTnCa`R?`zK8yf%4a$U1q= zY3x@YA1>V!^u*Wl%p$3q=N|Ry_=%oAa$M_H>!c-ew>xj;`q+Lq7rk3OvAp>8Td`Gh zG(2B@$e*GjSWpft>Jxh-2EzGIu2Jd6X#e_D91bZ@($p3_3fQ4m4;p z@SswELV=q4S~WbC3qeLKQL?EIP0l<2J$Lt=r*WQDj)6HxZ)F@d>sp$=R^_GXS|$IT zvwq#GanV`3Cc>!RX4R^##{QRARm9C+G$s4m>&a_xO-t@ASa4$YCC#D(ULmPB!z=rq zNA3v-(R{Kv@c91>4hH2y)`muZt!aDpdvo61dd<;b+kV$| zqiFVG?%TY(CReXM5xj2MKC|hM=RV(%wmD>H44dBCIV(dy?)h}sX4-*+S9$D0p7_2L z3FS&Xb=5vh(){JT^p9Q_&n%5yvAZixcUI>0=WBl6*LE#k^l5XN{wMn{|L(@gXzu#1 zr0-^@p;{*S^O4J2Q3mlnKV>&)%@Sui&}Z3wxu5NT_n&0Gga_FoiY*3H{xdYMDEYSE TaD@aglQVd_`njxgN@xNAA@}f2 literal 0 HcmV?d00001 diff --git a/lib/f3/api/classDB_1_1Mongo-members.html b/lib/f3/api/classDB_1_1Mongo-members.html new file mode 100755 index 0000000..38739cf --- /dev/null +++ b/lib/f3/api/classDB_1_1Mongo-members.html @@ -0,0 +1,53 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
DB\Mongo Member List
+
+
+ +

This is the complete list of members for DB\Mongo, including all inherited members.

+ + + + + + + + + +
$dsnDB\Mongo
$logDB\Mongo
__construct($dsn, $dbname, array $options=NULL)DB\Mongo
drop()DB\Mongo
dsn()DB\Mongo
E_Profiler (defined in DB\Mongo)DB\Mongo
log()DB\Mongo
uuid()DB\Mongo
diff --git a/lib/f3/api/classDB_1_1Mongo.html b/lib/f3/api/classDB_1_1Mongo.html new file mode 100755 index 0000000..26d2337 --- /dev/null +++ b/lib/f3/api/classDB_1_1Mongo.html @@ -0,0 +1,204 @@ + + + + + + + +Fat-Free Framework: DB\Mongo Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+ +
+
DB\Mongo Class Reference
+
+
+ +

MongoDB wrapper. + More...

+
+ + Inheritance diagram for DB\Mongo:
+
+
+ + + + + + + + + + + + + +

+Public Member Functions

 dsn ()
 
 uuid ()
 
 log ()
 
 drop ()
 
 __construct ($dsn, $dbname, array $options=NULL)
 
+ + + + + + + + + + +

+Public Attributes

$dsn
 Data source name.
 
$log
 MongoDB log.
 
+const E_Profiler ='MongoDB profiler is disabled'
 
+

Detailed Description

+

MongoDB wrapper.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
DB\Mongo::__construct ( $dsn,
 $dbname,
array $options = NULL 
)
+
+

Instantiate class

+
Parameters
+ + + + +
$dsnstring
$dbnamestring
$optionsarray
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + +
DB\Mongo::drop ()
+
+

Intercept native call to re-enable profiler

+
Returns
int
+ +
+
+ +
+
+ + + + + + + +
DB\Mongo::dsn ()
+
+

Return data source name

+
Returns
string
+ +
+
+ +
+
+ + + + + + + +
DB\Mongo::log ()
+
+

Return MongoDB profiler results

+
Returns
string
+ +
+
+ +
+
+ + + + + + + +
DB\Mongo::uuid ()
+
+

Return UUID

+
Returns
string
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • db/mongo.php
  • +
+
diff --git a/lib/f3/api/classDB_1_1Mongo.png b/lib/f3/api/classDB_1_1Mongo.png new file mode 100755 index 0000000000000000000000000000000000000000..f16e7b6e94fb1f76721779190373f5603715073f GIT binary patch literal 419 zcmeAS@N?(olHy`uVBq!ia0vp^9zYzx!3-pOw;gTjfZhDuB=CRIe503oNx~NtmJoUt1P0xIhPJX4p zo2Oshxb*9wmPGd}yV7%;wG;bq{qlERyzZ2{<*RAgi#~RKayh*8x6IMd&s&(L#@BuL zBI|i+!sW5 z%yi!pzYxAXXX3ZNXcl+byS9Dp_IH8t|JAZiT8YS(e(b!~8~tB&;_6waFKkSlvG}g_ zt?sC+QMT-%%s+bG9*Xa}GdFMEiu;*${S0~&HI0nDAF#XM(wtv#aEd1|L>W9?{an^L HB{Ts54lTRf literal 0 HcmV?d00001 diff --git a/lib/f3/api/classDB_1_1Mongo_1_1Mapper-members.html b/lib/f3/api/classDB_1_1Mongo_1_1Mapper-members.html new file mode 100755 index 0000000..d006033 --- /dev/null +++ b/lib/f3/api/classDB_1_1Mongo_1_1Mapper-members.html @@ -0,0 +1,94 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
DB\Mongo\Mapper Member List
+
+
+ +

This is the complete list of members for DB\Mongo\Mapper, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$collectionDB\Mongo\Mapper
$cursorDB\Mongo\Mapper
$dbDB\Mongo\Mapperprotected
$documentDB\Mongo\Mapper
$ptrDB\Cursor
$queryDB\Cursorprotected
$triggerDB\Cursor
__construct(\DB\Mongo $db, $collection)DB\Mongo\Mapper
__get($key)Magic
__isset($key)Magic
__set($key, $val)Magic
__unset($key)Magic
cast($obj=NULL)DB\Mongo\Mapper
clear($key)DB\Mongo\Mapper
copyfrom($key, $func=NULL)DB\Mongo\Mapper
copyto($key)DB\Mongo\Mapper
count($filter=NULL, $ttl=0)DB\Mongo\Mapper
cursor()DB\Mongo\Mapper
dry()DB\Cursor
E_Field (defined in DB\Cursor)DB\Cursor
erase($filter=NULL)DB\Mongo\Mapper
DB::Cursor::erase()DB\Cursor
exists($key)DB\Mongo\Mapper
factory($row)DB\Mongo\Mapperprotected
fields()DB\Mongo\Mapper
find($filter=NULL, array $options=NULL, $ttl=0)DB\Mongo\Mapper
findone($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
first()DB\Cursor
get($key)DB\Mongo\Mapper
insert()DB\Mongo\Mapper
last()DB\Cursor
load($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
next()DB\Cursor
offsetexists($key)Magic
offsetget($key)Magic
offsetset($key, $val)Magic
offsetunset($key)Magic
onerase($func)DB\Cursor
oninsert($func)DB\Cursor
onload($func)DB\Cursor
onupdate($func)DB\Cursor
paginate($pos=0, $size=10, $filter=NULL, array $options=NULL)DB\Cursor
prev()DB\Cursor
reset()DB\Mongo\Mapper
save()DB\Cursor
select($fields=NULL, $filter=NULL, array $options=NULL, $ttl=0)DB\Mongo\Mapper
set($key, $val)DB\Mongo\Mapper
skip($ofs=1)DB\Mongo\Mapper
update()DB\Mongo\Mapper
diff --git a/lib/f3/api/classDB_1_1Mongo_1_1Mapper.html b/lib/f3/api/classDB_1_1Mongo_1_1Mapper.html new file mode 100755 index 0000000..aba8143 --- /dev/null +++ b/lib/f3/api/classDB_1_1Mongo_1_1Mapper.html @@ -0,0 +1,743 @@ + + + + + + + +Fat-Free Framework: DB\Mongo\Mapper Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+ +
+ +

MongoDB mapper. + More...

+
+ + Inheritance diagram for DB\Mongo\Mapper:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 cast ($obj=NULL)
 
 select ($fields=NULL, $filter=NULL, array $options=NULL, $ttl=0)
 
 find ($filter=NULL, array $options=NULL, $ttl=0)
 
 count ($filter=NULL, $ttl=0)
 
 skip ($ofs=1)
 
 insert ()
 
 update ()
 
 erase ($filter=NULL)
 
 reset ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 fields ()
 
 cursor ()
 
 __construct (\DB\Mongo $db, $collection)
 
- Public Member Functions inherited from DB\Cursor
 cast ($obj=NULL)
 
 find ($filter=NULL, array $options=NULL, $ttl=0)
 
 count ($filter=NULL, $ttl=0)
 
 insert ()
 
 update ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 dry ()
 
 findone ($filter=NULL, array $options=NULL, $ttl=0)
 
 paginate ($pos=0, $size=10, $filter=NULL, array $options=NULL)
 
 load ($filter=NULL, array $options=NULL, $ttl=0)
 
 first ()
 
 last ()
 
 skip ($ofs=1)
 
 next ()
 
 prev ()
 
 save ()
 
 erase ()
 
 onload ($func)
 
 oninsert ($func)
 
 onupdate ($func)
 
 onerase ($func)
 
 reset ()
 
- Public Member Functions inherited from Magic
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 offsetexists ($key)
 
 __isset ($key)
 
 offsetset ($key, $val)
 
 __set ($key, $val)
 
 offsetget ($key)
 
 __get ($key)
 
 offsetunset ($key)
 
 __unset ($key)
 
+ + + + + + + + + + + + + + + + + + + +

+Public Attributes

$collection
 Mongo collection.
 
$document =array()
 Mongo document.
 
$cursor
 Mongo cursor.
 
- Public Attributes inherited from DB\Cursor
$ptr =0
 Current position.
 
$trigger =array()
 Event listeners.
 
+const E_Field ='Undefined field %s'
 
+ + + +

+Protected Member Functions

 factory ($row)
 
+ + + + + + + + +

+Protected Attributes

$db
 MongoDB wrapper.
 
- Protected Attributes inherited from DB\Cursor
$query =array()
 Query results.
 
+

Detailed Description

+

MongoDB mapper.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Mongo\Mapper::__construct (\DB\Mongo $db,
 $collection 
)
+
+

Instantiate class

+
Returns
void
+
Parameters
+ + + +
$dbobject
$collectionstring
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
DB\Mongo\Mapper::cast ( $obj = NULL)
+
+

Return fields of mapper object as an associative array

+
Returns
array
+
Parameters
+ + +
$objobject
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Mapper::clear ( $key)
+
+

Delete field

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Mongo\Mapper::copyfrom ( $key,
 $func = NULL 
)
+
+

Hydrate mapper object using hive array variable

+
Returns
NULL
+
Parameters
+ + + +
$keystring
$funccallback
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Mapper::copyto ( $key)
+
+

Populate hive array variable with mapper fields

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Mongo\Mapper::count ( $filter = NULL,
 $ttl = 0 
)
+
+

Count records that match criteria

+
Returns
int
+
Parameters
+ + + +
$filterarray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Mongo\Mapper::cursor ()
+
+

Return the cursor from last query

+
Returns
object|NULL
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Mapper::erase ( $filter = NULL)
+
+

Delete current record

+
Returns
bool
+
Parameters
+ + +
$filterarray
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Mapper::exists ( $key)
+
+

Return TRUE if field is defined

+
Returns
bool
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
DB\Mongo\Mapper::factory ( $row)
+
+protected
+
+

Convert array to mapper object

+
Returns
object
+
Parameters
+ + +
$rowarray
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Mongo\Mapper::fields ()
+
+

Return field names

+
Returns
array
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
DB\Mongo\Mapper::find ( $filter = NULL,
array $options = NULL,
 $ttl = 0 
)
+
+

Return records that match criteria

+
Returns
array
+
Parameters
+ + + + +
$filterarray
$optionsarray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Mapper::get ( $key)
+
+

Retrieve value of field

+
Returns
scalar|FALSE
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Mongo\Mapper::insert ()
+
+

Insert new record

+
Returns
array
+ +
+
+ +
+
+ + + + + + + +
DB\Mongo\Mapper::reset ()
+
+

Reset cursor

+
Returns
NULL
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DB\Mongo\Mapper::select ( $fields = NULL,
 $filter = NULL,
array $options = NULL,
 $ttl = 0 
)
+
+

Build query and execute

+
Returns
array
+
Parameters
+ + + + + +
$fieldsstring
$filterarray
$optionsarray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Mongo\Mapper::set ( $key,
 $val 
)
+
+

Assign value to field

+
Returns
scalar|FALSE
+
Parameters
+ + + +
$keystring
$valscalar
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Mapper::skip ( $ofs = 1)
+
+

Return record at specified offset using criteria of previous load() call and make it active

+
Returns
array
+
Parameters
+ + +
$ofsint
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Mongo\Mapper::update ()
+
+

Update current record

+
Returns
array
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • db/mongo/mapper.php
  • +
+
diff --git a/lib/f3/api/classDB_1_1Mongo_1_1Mapper.png b/lib/f3/api/classDB_1_1Mongo_1_1Mapper.png new file mode 100755 index 0000000000000000000000000000000000000000..6282b76c205f09a5245e8dc15049fb8e3317e303 GIT binary patch literal 1137 zcmeAS@N?(olHy`uVBq!ia0vp^6+rxhgBeH)a9y$hQW60^A+G=b{|7SPy?Zxj&YTHA z78oBmaNvVusy&d)Q4-`A%m7pb0#{Fk7%?!gFnGE+hEy=Vo%?#yD+K|z+5M|N{L8N~ z5m%Tv^NM1m4TP!^)ZWEAaV%tSnG&?=_)*QJDTn5Z$hUo&JmY@H;fsgbg@e2@ z`-LBEoImTso=pL2J=5cNU0OEf(zM#b$a4>n z)wNq1-Lt$$ z`fIYpnQuHuVi1nuNoeY3^eHfG;M8L?ICzvnZHL4I6T@RSm=~$se4ONI^zgqxyYK%` zttxY$%&HJNGgsyA^KBMB@^Wt%uh;XqB&jF&HRHspm$v2N{(sh0oXdGSeF=Ar?z&$o zyF0osdfYLX^<+oVy7bAbrY#A7XM5FNB;NMH`L{nFG5)Ss_cVH@eH3UDW5aD82HO{^ za&3Ok;vThc@83E52lwh*M;Xj^NE~1hXP$xKP7B{2!*2~5p5JyvO!E1$`_YG*(B?v$ z+DS`p%XCjqlk?eC6FMoc(C<%6X`989XRJQ(@Qt@liuU{I%;zulRo|O$Z zzP`~jsQI<^JyHMJZxrL?x2o)YSQNTnWzW6m?nh@ox43?;sI>UX(p9RN^8ZgxQ4x;O z@l>l>YH>`$nxSAe;{x`*M-E>&dB^+Dhi``E!u5%vyCn{=VRJ4hSeJ7uw#W%EyeR|* z^xvbwOQ#+*Ik%bN+YW=Rs&TU_4cHCYSvQ<+U0MAoeYcANTi{wV*%QhC9<9{hH#6$p zitQyTdT(`RYz}Zc9{gFhv_ZGfudH}$*!G#by7m};O*nq~SW&&oI;JyEBj4{|@^t%= z-NDzd?hn2idh6EdklD9p-a7a3V)35XwR#V7L$@#Mt3SKy-$(uH7kgLBFs<34xsIQA z!O`^{pCy^!e6UVxkbekF6;)l%91EElwo5WpUGTQynR{mM5&nGnV)KvUVOzTyb5K$X zQWO=;l1ScjS|GW{T+wTit==>h;a}Z{KZo)z`)HH>QuXE3m$#qRc}88{6LZAdnE#o= zGgH;f=|YcxS57)rty{P4G*_~~)QVddlozQk`IYqa414&ynw`HRVs2HoT5_j`^Lp_=*TT6AuZ#8{2@MUG%#&U% zGky63jpMo>pIP4PGH2bh>Q&9L + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
DB\Mongo\Session Member List
+
+
+ +

This is the complete list of members for DB\Mongo\Session, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$collectionDB\Mongo\Mapper
$cursorDB\Mongo\Mapper
$dbDB\Mongo\Mapperprotected
$documentDB\Mongo\Mapper
$ptrDB\Cursor
$queryDB\Cursorprotected
$triggerDB\Cursor
__construct(\DB\Mongo $db, $table='sessions')DB\Mongo\Session
__get($key)Magic
__isset($key)Magic
__set($key, $val)Magic
__unset($key)Magic
agent($id=NULL)DB\Mongo\Session
cast($obj=NULL)DB\Mongo\Mapper
cleanup($max)DB\Mongo\Session
clear($key)DB\Mongo\Mapper
close()DB\Mongo\Session
copyfrom($key, $func=NULL)DB\Mongo\Mapper
copyto($key)DB\Mongo\Mapper
count($filter=NULL, $ttl=0)DB\Mongo\Mapper
csrf($id=NULL)DB\Mongo\Session
cursor()DB\Mongo\Mapper
destroy($id)DB\Mongo\Session
dry()DB\Cursor
E_Field (defined in DB\Cursor)DB\Cursor
erase($filter=NULL)DB\Mongo\Mapper
DB::Cursor::erase()DB\Cursor
exists($key)DB\Mongo\Mapper
factory($row)DB\Mongo\Mapperprotected
fields()DB\Mongo\Mapper
find($filter=NULL, array $options=NULL, $ttl=0)DB\Mongo\Mapper
findone($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
first()DB\Cursor
get($key)DB\Mongo\Mapper
insert()DB\Mongo\Mapper
ip($id=NULL)DB\Mongo\Session
last()DB\Cursor
load($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
next()DB\Cursor
offsetexists($key)Magic
offsetget($key)Magic
offsetset($key, $val)Magic
offsetunset($key)Magic
onerase($func)DB\Cursor
oninsert($func)DB\Cursor
onload($func)DB\Cursor
onupdate($func)DB\Cursor
open($path, $name)DB\Mongo\Session
paginate($pos=0, $size=10, $filter=NULL, array $options=NULL)DB\Cursor
prev()DB\Cursor
read($id)DB\Mongo\Session
reset()DB\Mongo\Mapper
save()DB\Cursor
select($fields=NULL, $filter=NULL, array $options=NULL, $ttl=0)DB\Mongo\Mapper
set($key, $val)DB\Mongo\Mapper
skip($ofs=1)DB\Mongo\Mapper
stamp($id=NULL)DB\Mongo\Session
update()DB\Mongo\Mapper
write($id, $data)DB\Mongo\Session
diff --git a/lib/f3/api/classDB_1_1Mongo_1_1Session.html b/lib/f3/api/classDB_1_1Mongo_1_1Session.html new file mode 100755 index 0000000..9c123f1 --- /dev/null +++ b/lib/f3/api/classDB_1_1Mongo_1_1Session.html @@ -0,0 +1,533 @@ + + + + + + + +Fat-Free Framework: DB\Mongo\Session Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+ +
+
DB\Mongo\Session Class Reference
+
+
+ +

MongoDB-managed session handler. + More...

+
+ + Inheritance diagram for DB\Mongo\Session:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 open ($path, $name)
 
 close ()
 
 read ($id)
 
 write ($id, $data)
 
 destroy ($id)
 
 cleanup ($max)
 
 csrf ($id=NULL)
 
 ip ($id=NULL)
 
 stamp ($id=NULL)
 
 agent ($id=NULL)
 
 __construct (\DB\Mongo $db, $table='sessions')
 
- Public Member Functions inherited from DB\Mongo\Mapper
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 cast ($obj=NULL)
 
 select ($fields=NULL, $filter=NULL, array $options=NULL, $ttl=0)
 
 find ($filter=NULL, array $options=NULL, $ttl=0)
 
 count ($filter=NULL, $ttl=0)
 
 skip ($ofs=1)
 
 insert ()
 
 update ()
 
 erase ($filter=NULL)
 
 reset ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 fields ()
 
 cursor ()
 
 __construct (\DB\Mongo $db, $collection)
 
- Public Member Functions inherited from DB\Cursor
 cast ($obj=NULL)
 
 find ($filter=NULL, array $options=NULL, $ttl=0)
 
 count ($filter=NULL, $ttl=0)
 
 insert ()
 
 update ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 dry ()
 
 findone ($filter=NULL, array $options=NULL, $ttl=0)
 
 paginate ($pos=0, $size=10, $filter=NULL, array $options=NULL)
 
 load ($filter=NULL, array $options=NULL, $ttl=0)
 
 first ()
 
 last ()
 
 skip ($ofs=1)
 
 next ()
 
 prev ()
 
 save ()
 
 erase ()
 
 onload ($func)
 
 oninsert ($func)
 
 onupdate ($func)
 
 onerase ($func)
 
 reset ()
 
- Public Member Functions inherited from Magic
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 offsetexists ($key)
 
 __isset ($key)
 
 offsetset ($key, $val)
 
 __set ($key, $val)
 
 offsetget ($key)
 
 __get ($key)
 
 offsetunset ($key)
 
 __unset ($key)
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Public Attributes inherited from DB\Mongo\Mapper
$collection
 Mongo collection.
 
$document =array()
 Mongo document.
 
$cursor
 Mongo cursor.
 
- Public Attributes inherited from DB\Cursor
$ptr =0
 Current position.
 
$trigger =array()
 Event listeners.
 
+const E_Field ='Undefined field %s'
 
- Protected Member Functions inherited from DB\Mongo\Mapper
 factory ($row)
 
- Protected Attributes inherited from DB\Mongo\Mapper
$db
 MongoDB wrapper.
 
- Protected Attributes inherited from DB\Cursor
$query =array()
 Query results.
 
+

Detailed Description

+

MongoDB-managed session handler.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Mongo\Session::__construct (\DB\Mongo $db,
 $table = 'sessions' 
)
+
+

Instantiate class

+
Parameters
+ + + +
$dbobject
$tablestring
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
DB\Mongo\Session::agent ( $id = NULL)
+
+

Return HTTP user agent associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Session::cleanup ( $max)
+
+

Garbage collector

+
Returns
TRUE
+
Parameters
+ + +
$maxint
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\Mongo\Session::close ()
+
+

Close session

+
Returns
TRUE
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Session::csrf ( $id = NULL)
+
+

Return anti-CSRF tokan associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Session::destroy ( $id)
+
+

Destroy session

+
Returns
TRUE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Session::ip ( $id = NULL)
+
+

Return IP address associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Mongo\Session::open ( $path,
 $name 
)
+
+

Open session

+
Returns
TRUE
+
Parameters
+ + + +
$pathstring
$namestring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Session::read ( $id)
+
+

Return session data in serialized format

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\Mongo\Session::stamp ( $id = NULL)
+
+

Return Unix timestamp associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\Mongo\Session::write ( $id,
 $data 
)
+
+

Write session data

+
Returns
TRUE
+
Parameters
+ + + +
$idstring
$datastring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • db/mongo/session.php
  • +
+
diff --git a/lib/f3/api/classDB_1_1Mongo_1_1Session.png b/lib/f3/api/classDB_1_1Mongo_1_1Session.png new file mode 100755 index 0000000000000000000000000000000000000000..0f5e194bfac7f63ee072804b193b877be7dd900a GIT binary patch literal 1127 zcmeAS@N?(olHy`uVBq!ia0vp^6+rxhgBeH)a9y$hQW60^A+G=b{|7SPy?Zxj&YTHA z78oBmaNvVusy&d)Q4-`A%m7pb0#{Fk7%?y~fAe&445?szJNNaaS6TwBvt2_g{+rv) z;-27f#&v(<{GuytE>8Rgo%NiGEph@uUMJvKbM_V6h&)&H%%yIn%_+8%*ZT_3mkKWtd`Fme;=@g$Io`oEWB@7SDm>u}5I@=dc-Z}lp!?(%r)cze@ zQ)bw}tH)+=@F;`Y4v7OS;>neWF*xgxgusW6}p}CvUr@*j*6WyH+mybv!^LI>2>F-uO*-{@aGjIJW!)?p+ zCzZ@j{up$o*K>Nc>PxZbN6r@&K2>c2&>aF%rAf>!x|LBnw>4x!h)>6lGKTeD=bp zT~(g$kAluM{S@(fU6HYG5#I*YbM1HMtPRa=Tc?!IV;k{t(}o!N&eaUXRo7nYAO95o z=+3&CVYPm6#PKL^7%V8Uwo_ek@yS8~?#K!$3c{d(7# z*JPH7gW|}tqtdS-)~iRnEMK>7+G(C-fvFWy7n1)71>KFb{CsSxcKkX!vFSzg675UYe-(qrB=EjG^UH2?lFY>(%I(6HyWcIRG&8y+yVtA27 + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
DB\SQL Member List
+
+
+ +

This is the complete list of members for DB\SQL, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + +
$dbnameDB\SQL
$dsnDB\SQL
$engineDB\SQL
$logDB\SQL
$rowsDB\SQL
$transDB\SQL
__construct($dsn, $user=NULL, $pw=NULL, array $options=NULL)DB\SQL
begin()DB\SQL
commit()DB\SQL
count()DB\SQL
driver()DB\SQL
exec($cmds, $args=NULL, $ttl=0, $log=TRUE)DB\SQL
log()DB\SQL
name()DB\SQL
quote($val, $type=\PDO::PARAM_STR)DB\SQL
quotekey($key)DB\SQL
rollback()DB\SQL
schema($table, $fields=NULL, $ttl=0)DB\SQL
type($val)DB\SQL
uuid()DB\SQL
version()DB\SQL
diff --git a/lib/f3/api/classDB_1_1SQL.html b/lib/f3/api/classDB_1_1SQL.html new file mode 100755 index 0000000..80b5c50 --- /dev/null +++ b/lib/f3/api/classDB_1_1SQL.html @@ -0,0 +1,502 @@ + + + + + + + +Fat-Free Framework: DB\SQL Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+ +
+
DB\SQL Class Reference
+
+
+ +

PDO wrapper. + More...

+
+ + Inheritance diagram for DB\SQL:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 begin ()
 
 rollback ()
 
 commit ()
 
 type ($val)
 
 exec ($cmds, $args=NULL, $ttl=0, $log=TRUE)
 
 count ()
 
 log ()
 
 schema ($table, $fields=NULL, $ttl=0)
 
 quote ($val, $type=\PDO::PARAM_STR)
 
 uuid ()
 
 driver ()
 
 version ()
 
 name ()
 
 quotekey ($key)
 
 __construct ($dsn, $user=NULL, $pw=NULL, array $options=NULL)
 
+ + + + + + + + + + + + + + + + + + + +

+Public Attributes

$dsn
 Data source name.
 
$engine
 Database engine.
 
$dbname
 Database name.
 
$trans =FALSE
 Transaction flag.
 
$rows =0
 Number of rows affected by query.
 
$log
 SQL log.
 
+

Detailed Description

+

PDO wrapper.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DB\SQL::__construct ( $dsn,
 $user = NULL,
 $pw = NULL,
array $options = NULL 
)
+
+

Instantiate class

+
Parameters
+ + + + + +
$dsnstring
$userstring
$pwstring
$optionsarray
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + +
DB\SQL::begin ()
+
+

Begin SQL transaction

+
Returns
bool
+ +
+
+ +
+
+ + + + + + + +
DB\SQL::commit ()
+
+

Commit SQL transaction

+
Returns
bool
+ +
+
+ +
+
+ + + + + + + +
DB\SQL::count ()
+
+

Return number of rows affected by last query

+
Returns
int
+ +
+
+ +
+
+ + + + + + + +
DB\SQL::driver ()
+
+

Return database engine

+
Returns
string
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DB\SQL::exec ( $cmds,
 $args = NULL,
 $ttl = 0,
 $log = TRUE 
)
+
+

Execute SQL statement(s)

+
Returns
array|int|FALSE
+
Parameters
+ + + + + +
$cmdsstring|array
$argsstring|array
$ttlint
$logbool
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\SQL::log ()
+
+

Return SQL profiler results

+
Returns
string
+ +
+
+ +
+
+ + + + + + + +
DB\SQL::name ()
+
+

Return database name

+
Returns
string
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\SQL::quote ( $val,
 $type = \PDO::PARAM_STR 
)
+
+

Quote string

+
Returns
string
+
Parameters
+ + + +
$valmixed
$typeint
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL::quotekey ( $key)
+
+

Return quoted identifier name

+
Returns
string
+
Parameters
+ + +
$key
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\SQL::rollback ()
+
+

Rollback SQL transaction

+
Returns
bool
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
DB\SQL::schema ( $table,
 $fields = NULL,
 $ttl = 0 
)
+
+

Retrieve schema of SQL table

+
Returns
array|FALSE
+
Parameters
+ + + + +
$tablestring
$fieldsarray|string
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL::type ( $val)
+
+

Map data type of argument to a PDO constant

+
Returns
int
+
Parameters
+ + +
$valscalar
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\SQL::uuid ()
+
+

Return UUID

+
Returns
string
+ +
+
+ +
+
+ + + + + + + +
DB\SQL::version ()
+
+

Return server version

+
Returns
string
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • db/sql.php
  • +
+
diff --git a/lib/f3/api/classDB_1_1SQL.png b/lib/f3/api/classDB_1_1SQL.png new file mode 100755 index 0000000000000000000000000000000000000000..6e2c0ce76720bed05e342bbad50a9b4d3618a08e GIT binary patch literal 327 zcmeAS@N?(olHy`uVBq!ia0vp^RzMuU!3-qpxu&TBDTx4|5ZC|z{{xxt-o2YMXU+s5 z3ycpOIPk$S)gH*@C<*clW&kPzfvcxNjDTX-JY5_^Dj46+y_nZ*Ai$Cyf8+oE#{maE zPE?bK*Ip>*Em^!VFQvNoi1wr@%s0#0s#kkgJlr{T+urBByLg{UvfuuCJs|tz-M_J0 z=a}w%wKYrW;hnv=zG=2)-S*WBR@G!ZkgnDsQ&~FeQeNELvul1ce_hnl&UGPe1%q!J z*M$@y^>3z@r)5UX9L9Ua-lb>Ph`lbEStFLXaMiR#?X2V(HUayOT@sbfKA%~7FMawh z`)fhv>!iwe|9u1ZU6uP literal 0 HcmV?d00001 diff --git a/lib/f3/api/classDB_1_1SQL_1_1Mapper-members.html b/lib/f3/api/classDB_1_1SQL_1_1Mapper-members.html new file mode 100755 index 0000000..e78f9b5 --- /dev/null +++ b/lib/f3/api/classDB_1_1SQL_1_1Mapper-members.html @@ -0,0 +1,100 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
DB\SQL\Mapper Member List
+
+
+ +

This is the complete list of members for DB\SQL\Mapper, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$_idDB\SQL\Mapper
$adhocDB\SQL\Mapper
$dbDB\SQL\Mapperprotected
$engineDB\SQL\Mapper
$fieldsDB\SQL\Mapper
$ptrDB\Cursor
$queryDB\Cursorprotected
$sourceDB\SQL\Mapper
$tableDB\SQL\Mapper
$triggerDB\Cursor
__construct(\DB\SQL $db, $table, $fields=NULL, $ttl=60)DB\SQL\Mapper
__get($key)Magic
__isset($key)Magic
__set($key, $val)Magic
__unset($key)Magic
cast($obj=NULL)DB\SQL\Mapper
clear($key)DB\SQL\Mapper
copyfrom($key, $func=NULL)DB\SQL\Mapper
copyto($key)DB\SQL\Mapper
count($filter=NULL, $ttl=0)DB\SQL\Mapper
dry()DB\Cursor
E_Adhoc (defined in DB\SQL\Mapper)DB\SQL\Mapper
E_Field (defined in DB\Cursor)DB\Cursor
erase($filter=NULL)DB\SQL\Mapper
DB::Cursor::erase()DB\Cursor
exists($key)DB\SQL\Mapper
factory($row)DB\SQL\Mapperprotected
fields($adhoc=TRUE)DB\SQL\Mapper
find($filter=NULL, array $options=NULL, $ttl=0)DB\SQL\Mapper
findone($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
first()DB\Cursor
get($key)DB\SQL\Mapper
insert()DB\SQL\Mapper
last()DB\Cursor
load($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
next()DB\Cursor
offsetexists($key)Magic
offsetget($key)Magic
offsetset($key, $val)Magic
offsetunset($key)Magic
onerase($func)DB\Cursor
oninsert($func)DB\Cursor
onload($func)DB\Cursor
onupdate($func)DB\Cursor
paginate($pos=0, $size=10, $filter=NULL, array $options=NULL)DB\Cursor
prev()DB\Cursor
reset()DB\SQL\Mapper
save()DB\Cursor
schema()DB\SQL\Mapper
select($fields, $filter=NULL, array $options=NULL, $ttl=0)DB\SQL\Mapper
set($key, $val)DB\SQL\Mapper
skip($ofs=1)DB\SQL\Mapper
type($pdo)DB\SQL\Mapper
update()DB\SQL\Mapper
value($type, $val)DB\SQL\Mapper
diff --git a/lib/f3/api/classDB_1_1SQL_1_1Mapper.html b/lib/f3/api/classDB_1_1SQL_1_1Mapper.html new file mode 100755 index 0000000..adc74ca --- /dev/null +++ b/lib/f3/api/classDB_1_1SQL_1_1Mapper.html @@ -0,0 +1,842 @@ + + + + + + + +Fat-Free Framework: DB\SQL\Mapper Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+ +
+ +

SQL data mapper. + More...

+
+ + Inheritance diagram for DB\SQL\Mapper:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 type ($pdo)
 
 value ($type, $val)
 
 cast ($obj=NULL)
 
 select ($fields, $filter=NULL, array $options=NULL, $ttl=0)
 
 find ($filter=NULL, array $options=NULL, $ttl=0)
 
 count ($filter=NULL, $ttl=0)
 
 skip ($ofs=1)
 
 insert ()
 
 update ()
 
 erase ($filter=NULL)
 
 reset ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 schema ()
 
 fields ($adhoc=TRUE)
 
 __construct (\DB\SQL $db, $table, $fields=NULL, $ttl=60)
 
- Public Member Functions inherited from DB\Cursor
 cast ($obj=NULL)
 
 find ($filter=NULL, array $options=NULL, $ttl=0)
 
 count ($filter=NULL, $ttl=0)
 
 insert ()
 
 update ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 dry ()
 
 findone ($filter=NULL, array $options=NULL, $ttl=0)
 
 paginate ($pos=0, $size=10, $filter=NULL, array $options=NULL)
 
 load ($filter=NULL, array $options=NULL, $ttl=0)
 
 first ()
 
 last ()
 
 skip ($ofs=1)
 
 next ()
 
 prev ()
 
 save ()
 
 erase ()
 
 onload ($func)
 
 oninsert ($func)
 
 onupdate ($func)
 
 onerase ($func)
 
 reset ()
 
- Public Member Functions inherited from Magic
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 offsetexists ($key)
 
 __isset ($key)
 
 offsetset ($key, $val)
 
 __set ($key, $val)
 
 offsetget ($key)
 
 __get ($key)
 
 offsetunset ($key)
 
 __unset ($key)
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Attributes

$engine
 Database engine.
 
$source
 SQL table.
 
$table
 SQL table (quoted)
 
$_id
 Last insert ID.
 
$fields
 Defined fields.
 
$adhoc =array()
 Adhoc fields.
 
+const E_Adhoc ='Unable to process ad hoc field %s'
 
- Public Attributes inherited from DB\Cursor
$ptr =0
 Current position.
 
$trigger =array()
 Event listeners.
 
+const E_Field ='Undefined field %s'
 
+ + + +

+Protected Member Functions

 factory ($row)
 
+ + + + + + + + +

+Protected Attributes

$db
 PDO wrapper.
 
- Protected Attributes inherited from DB\Cursor
$query =array()
 Query results.
 
+

Detailed Description

+

SQL data mapper.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DB\SQL\Mapper::__construct (\DB\SQL $db,
 $table,
 $fields = NULL,
 $ttl = 60 
)
+
+

Instantiate class

+
Parameters
+ + + + + +
$dbobject
$tablestring
$fieldsarray|string
$ttlint
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
DB\SQL\Mapper::cast ( $obj = NULL)
+
+

Return fields of mapper object as an associative array

+
Returns
array
+
Parameters
+ + +
$objobject
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Mapper::clear ( $key)
+
+

Clear value of field

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\SQL\Mapper::copyfrom ( $key,
 $func = NULL 
)
+
+

Hydrate mapper object using hive array variable

+
Returns
NULL
+
Parameters
+ + + +
$keystring
$funccallback
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Mapper::copyto ( $key)
+
+

Populate hive array variable with mapper fields

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\SQL\Mapper::count ( $filter = NULL,
 $ttl = 0 
)
+
+

Count records that match criteria

+
Returns
int
+
Parameters
+ + + +
$filterstring|array
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Mapper::erase ( $filter = NULL)
+
+

Delete current record

+
Returns
int
+
Parameters
+ + +
$filterstring|array
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Mapper::exists ( $key)
+
+

Return TRUE if field is defined

+
Returns
bool
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
DB\SQL\Mapper::factory ( $row)
+
+protected
+
+

Convert array to mapper object

+
Returns
object
+
Parameters
+ + +
$rowarray
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Mapper::fields ( $adhoc = TRUE)
+
+

Return field names

+
Returns
array
+
Parameters
+ + +
$adhocbool
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
DB\SQL\Mapper::find ( $filter = NULL,
array $options = NULL,
 $ttl = 0 
)
+
+

Return records that match criteria

+
Returns
array
+
Parameters
+ + + + +
$filterstring|array
$optionsarray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Mapper::get ( $key)
+
+

Retrieve value of field

+
Returns
scalar
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\SQL\Mapper::insert ()
+
+

Insert new record

+
Returns
object
+ +
+
+ +
+
+ + + + + + + +
DB\SQL\Mapper::reset ()
+
+

Reset cursor

+
Returns
NULL
+ +
+
+ +
+
+ + + + + + + +
DB\SQL\Mapper::schema ()
+
+

Return schema

+
Returns
array
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DB\SQL\Mapper::select ( $fields,
 $filter = NULL,
array $options = NULL,
 $ttl = 0 
)
+
+

Build query string and execute

+
Returns
array
+
Parameters
+ + + + + +
$fieldsstring
$filterstring|array
$optionsarray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\SQL\Mapper::set ( $key,
 $val 
)
+
+

Assign value to field

+
Returns
scalar
+
Parameters
+ + + +
$keystring
$valscalar
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Mapper::skip ( $ofs = 1)
+
+

Return record at specified offset using same criteria as previous load() call and make it active

+
Returns
array
+
Parameters
+ + +
$ofsint
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Mapper::type ( $pdo)
+
+

Get PHP type equivalent of PDO constant

+
Returns
string
+
Parameters
+ + +
$pdostring
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\SQL\Mapper::update ()
+
+

Update current record

+
Returns
object
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\SQL\Mapper::value ( $type,
 $val 
)
+
+

Cast value to PHP type

+
Returns
scalar
+
Parameters
+ + + +
$typestring
$valscalar
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • db/sql/mapper.php
  • +
+
diff --git a/lib/f3/api/classDB_1_1SQL_1_1Mapper.png b/lib/f3/api/classDB_1_1SQL_1_1Mapper.png new file mode 100755 index 0000000000000000000000000000000000000000..d14e2de5286c4b481392889c174b3cce7da69a2e GIT binary patch literal 1087 zcmeAS@N?(olHy`uVBq!ia0vp^SwQ@QgBeH~2R6S2QW60^A+G=b{|7SPy?Zxj&YTHA z78oBmaNvVusy&d)Q4-`A%m7pb0#{Fk7%?y~pYwEa45?szJNNab#R>v!v-`Cw|C`@C z!YyvvIq#DvV>%%sc+DD7BB#YLnykx% zoZbFr`Kr^IzqtcreWPn`s=i$RVe6_n#bt~S?1UTm>sDnJ75`i*r=~xB@hk80gcS@r zSR4m*@hVx%=Wm!JC)sdJRgwImAM&!Yq<81u7|%)ut>MRR(WJlrFA)%&VYM}L;j0+qRiwd`_Y z>-vwbxV1OD^y>C|u}ru5rYsSDB(34e=A`P$wl8dI@i{$)JLyax4*Hw==IPmAJ^bWp zQAq7eJ|5AA)&NEc4$+22G-|8z(kV3xj1>Y}49x$Xw!WEoEn?U9bGIVaM{T~!@IGVJ z+6d{~E$fOyawjwFIIsff=oPsSqOK=QpFKCL^QU1%_}aOlALByXtwXmK&Am43$6Bf7 zCChHz-AU5i$(B>mTQ8+P5n-Ih}iD-cq|`x@*Hjl8xe5`yIad{=#(Yf;(;P z0olKfS@>Olb-DWLqzm^}7pneVIBoa(vIqJ#x@}t-V6OfUx^&7UZieqO8EQTR`%a#H z+W)IT3)%gBmFn`n&bz0+sr#75E*CoK%kCDhNjxC@V^z_)o2~ZS9O`!8 TsY}`l% + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
DB\SQL\Session Member List
+
+
+ +

This is the complete list of members for DB\SQL\Session, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$_idDB\SQL\Mapper
$adhocDB\SQL\Mapper
$dbDB\SQL\Mapperprotected
$engineDB\SQL\Mapper
$fieldsDB\SQL\Mapper
$ptrDB\Cursor
$queryDB\Cursorprotected
$sourceDB\SQL\Mapper
$tableDB\SQL\Mapper
$triggerDB\Cursor
__construct(\DB\SQL $db, $table='sessions')DB\SQL\Session
DB::SQL::Mapper::__construct(\DB\SQL $db, $table, $fields=NULL, $ttl=60)DB\SQL\Mapper
__get($key)Magic
__isset($key)Magic
__set($key, $val)Magic
__unset($key)Magic
agent($id=NULL)DB\SQL\Session
cast($obj=NULL)DB\SQL\Mapper
cleanup($max)DB\SQL\Session
clear($key)DB\SQL\Mapper
close()DB\SQL\Session
copyfrom($key, $func=NULL)DB\SQL\Mapper
copyto($key)DB\SQL\Mapper
count($filter=NULL, $ttl=0)DB\SQL\Mapper
csrf($id=NULL)DB\SQL\Session
destroy($id)DB\SQL\Session
dry()DB\Cursor
E_Adhoc (defined in DB\SQL\Mapper)DB\SQL\Mapper
E_Field (defined in DB\Cursor)DB\Cursor
erase($filter=NULL)DB\SQL\Mapper
DB::Cursor::erase()DB\Cursor
exists($key)DB\SQL\Mapper
factory($row)DB\SQL\Mapperprotected
fields($adhoc=TRUE)DB\SQL\Mapper
find($filter=NULL, array $options=NULL, $ttl=0)DB\SQL\Mapper
findone($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
first()DB\Cursor
get($key)DB\SQL\Mapper
insert()DB\SQL\Mapper
ip($id=NULL)DB\SQL\Session
last()DB\Cursor
load($filter=NULL, array $options=NULL, $ttl=0)DB\Cursor
next()DB\Cursor
offsetexists($key)Magic
offsetget($key)Magic
offsetset($key, $val)Magic
offsetunset($key)Magic
onerase($func)DB\Cursor
oninsert($func)DB\Cursor
onload($func)DB\Cursor
onupdate($func)DB\Cursor
open($path, $name)DB\SQL\Session
paginate($pos=0, $size=10, $filter=NULL, array $options=NULL)DB\Cursor
prev()DB\Cursor
read($id)DB\SQL\Session
reset()DB\SQL\Mapper
save()DB\Cursor
schema()DB\SQL\Mapper
select($fields, $filter=NULL, array $options=NULL, $ttl=0)DB\SQL\Mapper
set($key, $val)DB\SQL\Mapper
skip($ofs=1)DB\SQL\Mapper
stamp($id=NULL)DB\SQL\Session
type($pdo)DB\SQL\Mapper
update()DB\SQL\Mapper
value($type, $val)DB\SQL\Mapper
write($id, $data)DB\SQL\Session
diff --git a/lib/f3/api/classDB_1_1SQL_1_1Session.html b/lib/f3/api/classDB_1_1SQL_1_1Session.html new file mode 100755 index 0000000..a785181 --- /dev/null +++ b/lib/f3/api/classDB_1_1SQL_1_1Session.html @@ -0,0 +1,552 @@ + + + + + + + +Fat-Free Framework: DB\SQL\Session Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+ +
+
DB\SQL\Session Class Reference
+
+
+ +

SQL-managed session handler. + More...

+
+ + Inheritance diagram for DB\SQL\Session:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 open ($path, $name)
 
 close ()
 
 read ($id)
 
 write ($id, $data)
 
 destroy ($id)
 
 cleanup ($max)
 
 csrf ($id=NULL)
 
 ip ($id=NULL)
 
 stamp ($id=NULL)
 
 agent ($id=NULL)
 
 __construct (\DB\SQL $db, $table='sessions')
 
- Public Member Functions inherited from DB\SQL\Mapper
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 type ($pdo)
 
 value ($type, $val)
 
 cast ($obj=NULL)
 
 select ($fields, $filter=NULL, array $options=NULL, $ttl=0)
 
 find ($filter=NULL, array $options=NULL, $ttl=0)
 
 count ($filter=NULL, $ttl=0)
 
 skip ($ofs=1)
 
 insert ()
 
 update ()
 
 erase ($filter=NULL)
 
 reset ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 schema ()
 
 fields ($adhoc=TRUE)
 
 __construct (\DB\SQL $db, $table, $fields=NULL, $ttl=60)
 
- Public Member Functions inherited from DB\Cursor
 cast ($obj=NULL)
 
 find ($filter=NULL, array $options=NULL, $ttl=0)
 
 count ($filter=NULL, $ttl=0)
 
 insert ()
 
 update ()
 
 copyfrom ($key, $func=NULL)
 
 copyto ($key)
 
 dry ()
 
 findone ($filter=NULL, array $options=NULL, $ttl=0)
 
 paginate ($pos=0, $size=10, $filter=NULL, array $options=NULL)
 
 load ($filter=NULL, array $options=NULL, $ttl=0)
 
 first ()
 
 last ()
 
 skip ($ofs=1)
 
 next ()
 
 prev ()
 
 save ()
 
 erase ()
 
 onload ($func)
 
 oninsert ($func)
 
 onupdate ($func)
 
 onerase ($func)
 
 reset ()
 
- Public Member Functions inherited from Magic
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 offsetexists ($key)
 
 __isset ($key)
 
 offsetset ($key, $val)
 
 __set ($key, $val)
 
 offsetget ($key)
 
 __get ($key)
 
 offsetunset ($key)
 
 __unset ($key)
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Public Attributes inherited from DB\SQL\Mapper
$engine
 Database engine.
 
$source
 SQL table.
 
$table
 SQL table (quoted)
 
$_id
 Last insert ID.
 
$fields
 Defined fields.
 
$adhoc =array()
 Adhoc fields.
 
+const E_Adhoc ='Unable to process ad hoc field %s'
 
- Public Attributes inherited from DB\Cursor
$ptr =0
 Current position.
 
$trigger =array()
 Event listeners.
 
+const E_Field ='Undefined field %s'
 
- Protected Member Functions inherited from DB\SQL\Mapper
 factory ($row)
 
- Protected Attributes inherited from DB\SQL\Mapper
$db
 PDO wrapper.
 
- Protected Attributes inherited from DB\Cursor
$query =array()
 Query results.
 
+

Detailed Description

+

SQL-managed session handler.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\SQL\Session::__construct (\DB\SQL $db,
 $table = 'sessions' 
)
+
+

Instantiate class

+
Parameters
+ + + +
$dbobject
$tablestring
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
DB\SQL\Session::agent ( $id = NULL)
+
+

Return HTTP user agent associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Session::cleanup ( $max)
+
+

Garbage collector

+
Returns
TRUE
+
Parameters
+ + +
$maxint
+
+
+ +
+
+ +
+
+ + + + + + + +
DB\SQL\Session::close ()
+
+

Close session

+
Returns
TRUE
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Session::csrf ( $id = NULL)
+
+

Return anti-CSRF tokan associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Session::destroy ( $id)
+
+

Destroy session

+
Returns
TRUE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Session::ip ( $id = NULL)
+
+

Return IP address associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\SQL\Session::open ( $path,
 $name 
)
+
+

Open session

+
Returns
TRUE
+
Parameters
+ + + +
$pathstring
$namestring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Session::read ( $id)
+
+

Return session data in serialized format

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
DB\SQL\Session::stamp ( $id = NULL)
+
+

Return Unix timestamp associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
DB\SQL\Session::write ( $id,
 $data 
)
+
+

Write session data

+
Returns
TRUE
+
Parameters
+ + + +
$idstring
$datastring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • db/sql/session.php
  • +
+
diff --git a/lib/f3/api/classDB_1_1SQL_1_1Session.png b/lib/f3/api/classDB_1_1SQL_1_1Session.png new file mode 100755 index 0000000000000000000000000000000000000000..e9d15add6d00d1f79cc042e56d7571b2afef12a8 GIT binary patch literal 1084 zcmeAS@N?(olHy`uVBq!ia0vp^SwQ@QgBeH~2R6S2QW60^A+G=b{|7SPy?Zxj&YTHA z78oBmaNvVusy&d)Q4-`A%m7pb0#{Fk7%?y~pZ0Wd45?szJNNaZ%{l^Xv)i?H{2iZH?R5%T}%ZUd42K%c@lud30TqO?v{oGM9&@My(dUx@YIHc~39xV)oX2 z%DPPdwC>cm(q-UyiDDPH%QRCk~@G)hnI>Ed@* zDlc`zg)RCc+2hY`-8Jj@?Nz0%R*O|)AAZ{Q;`7rbS$*-rb1mvJ*IHfM``z0*U{c?m zn$vZwcFoyVFL3qhmZQ^SC;j7$Uwz6lU7X>aG2@R1%V(*XPoMuP@l%oIs(mHwZCnSO zRxt3ia2;?!qi#(sK4&*U^<;B^=cLB}ty;GI>kPL~*Y@0XUixa-nqJp{YSou=@*(Go zr1xh1wmcKO;^Ozola?@U&f0nLZr#lL+N*YDEDtR8@7p}lWRCfws+Cbp9|L99iO9_8K6GJ8k26dcUqR zjn?&ipRsCfgmmtfb;TjMlP4_U?pc+-v-cL;x>DY+27bhW#5Hd zJyjZ&{b+mEoJ%vaw(G=}_--|sUEpyf;_Cc8eOWT4tB;)%3%cu7+Y=qNe#NnrePMIk zHs4>UU;bbRFaN@8UwRAYth>7W`zqCid&3`leRI|=kAHh0{zp{F?chmeptuI%A7puP z$&^X_Dh&LuyN&MzdQ7VxKQ~b%jA*G87mu3wdK+ zOT8)hEO|HRYEfG5)f4wuZ+q?+`u8l$@#1yA?#qPiPJPLgVSoF6PWNqli)YVDL;kKf ze5Aeg{WCMQ59_jgp81*HvFZ8fX_~XGPFl|CZQj24)y7xf?aexw`Tjzl>hAbGHyhnW m54;zGM9G8IUYe@n|Cj@0>ZWl7vz-BEbp}sYKbLh*2~7adcl%)g literal 0 HcmV?d00001 diff --git a/lib/f3/api/classF3-members.html b/lib/f3/api/classF3-members.html new file mode 100755 index 0000000..c03ccd2 --- /dev/null +++ b/lib/f3/api/classF3-members.html @@ -0,0 +1,43 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
F3 Member List
+
+
+ +

This is the complete list of members for F3, including all inherited members.

+ + + +
$fwF3static
__callstatic($func, array $args)F3static
diff --git a/lib/f3/api/classF3.html b/lib/f3/api/classF3.html new file mode 100755 index 0000000..73a9a7a --- /dev/null +++ b/lib/f3/api/classF3.html @@ -0,0 +1,107 @@ + + + + + + + +Fat-Free Framework: F3 Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

Legacy mode enabler. + More...

+ + + + +

+Static Public Member Functions

static __callstatic ($func, array $args)
 
+ + + + +

+Static Public Attributes

+static $fw
 Framework instance.
 
+

Detailed Description

+

Legacy mode enabler.

+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
static F3::__callstatic ( $func,
array $args 
)
+
+static
+
+

Forward function calls to framework

+
Returns
mixed
+
Parameters
+ + + +
$funccallback
$argsarray
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • f3.php
  • +
+
diff --git a/lib/f3/api/classISO-members.html b/lib/f3/api/classISO-members.html new file mode 100755 index 0000000..b318d3a --- /dev/null +++ b/lib/f3/api/classISO-members.html @@ -0,0 +1,377 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
ISO Member List
+
+
+ +

This is the complete list of members for ISO, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CC_ad (defined in ISO)ISO
CC_ae (defined in ISO)ISO
CC_af (defined in ISO)ISO
CC_ag (defined in ISO)ISO
CC_ai (defined in ISO)ISO
CC_al (defined in ISO)ISO
CC_am (defined in ISO)ISO
CC_ao (defined in ISO)ISO
CC_aq (defined in ISO)ISO
CC_ar (defined in ISO)ISO
CC_as (defined in ISO)ISO
CC_at (defined in ISO)ISO
CC_au (defined in ISO)ISO
CC_aw (defined in ISO)ISO
CC_ax (defined in ISO)ISO
CC_az (defined in ISO)ISO
CC_ba (defined in ISO)ISO
CC_bb (defined in ISO)ISO
CC_bd (defined in ISO)ISO
CC_be (defined in ISO)ISO
CC_bf (defined in ISO)ISO
CC_bg (defined in ISO)ISO
CC_bh (defined in ISO)ISO
CC_bi (defined in ISO)ISO
CC_bj (defined in ISO)ISO
CC_bl (defined in ISO)ISO
CC_bm (defined in ISO)ISO
CC_bn (defined in ISO)ISO
CC_bo (defined in ISO)ISO
CC_bq (defined in ISO)ISO
CC_br (defined in ISO)ISO
CC_bs (defined in ISO)ISO
CC_bt (defined in ISO)ISO
CC_bv (defined in ISO)ISO
CC_bw (defined in ISO)ISO
CC_by (defined in ISO)ISO
CC_bz (defined in ISO)ISO
CC_ca (defined in ISO)ISO
CC_cc (defined in ISO)ISO
CC_cd (defined in ISO)ISO
CC_cf (defined in ISO)ISO
CC_cg (defined in ISO)ISO
CC_ch (defined in ISO)ISO
CC_ci (defined in ISO)ISO
CC_ck (defined in ISO)ISO
CC_cl (defined in ISO)ISO
CC_cm (defined in ISO)ISO
CC_cn (defined in ISO)ISO
CC_co (defined in ISO)ISO
CC_cr (defined in ISO)ISO
CC_cu (defined in ISO)ISO
CC_cv (defined in ISO)ISO
CC_cw (defined in ISO)ISO
CC_cx (defined in ISO)ISO
CC_cy (defined in ISO)ISO
CC_cz (defined in ISO)ISO
CC_de (defined in ISO)ISO
CC_dj (defined in ISO)ISO
CC_dk (defined in ISO)ISO
CC_dm (defined in ISO)ISO
CC_do (defined in ISO)ISO
CC_dz (defined in ISO)ISO
CC_ec (defined in ISO)ISO
CC_ee (defined in ISO)ISO
CC_eg (defined in ISO)ISO
CC_eh (defined in ISO)ISO
CC_er (defined in ISO)ISO
CC_es (defined in ISO)ISO
CC_et (defined in ISO)ISO
CC_fi (defined in ISO)ISO
CC_fj (defined in ISO)ISO
CC_fk (defined in ISO)ISO
CC_fm (defined in ISO)ISO
CC_fo (defined in ISO)ISO
CC_fr (defined in ISO)ISO
CC_ga (defined in ISO)ISO
CC_gb (defined in ISO)ISO
CC_gd (defined in ISO)ISO
CC_ge (defined in ISO)ISO
CC_gf (defined in ISO)ISO
CC_gg (defined in ISO)ISO
CC_gh (defined in ISO)ISO
CC_gi (defined in ISO)ISO
CC_gl (defined in ISO)ISO
CC_gm (defined in ISO)ISO
CC_gn (defined in ISO)ISO
CC_gp (defined in ISO)ISO
CC_gq (defined in ISO)ISO
CC_gr (defined in ISO)ISO
CC_gs (defined in ISO)ISO
CC_gt (defined in ISO)ISO
CC_gu (defined in ISO)ISO
CC_gw (defined in ISO)ISO
CC_gy (defined in ISO)ISO
CC_hk (defined in ISO)ISO
CC_hm (defined in ISO)ISO
CC_hn (defined in ISO)ISO
CC_hr (defined in ISO)ISO
CC_ht (defined in ISO)ISO
CC_hu (defined in ISO)ISO
CC_id (defined in ISO)ISO
CC_ie (defined in ISO)ISO
CC_il (defined in ISO)ISO
CC_im (defined in ISO)ISO
CC_in (defined in ISO)ISO
CC_io (defined in ISO)ISO
CC_iq (defined in ISO)ISO
CC_ir (defined in ISO)ISO
CC_is (defined in ISO)ISO
CC_it (defined in ISO)ISO
CC_je (defined in ISO)ISO
CC_jm (defined in ISO)ISO
CC_jo (defined in ISO)ISO
CC_jp (defined in ISO)ISO
CC_ke (defined in ISO)ISO
CC_kg (defined in ISO)ISO
CC_kh (defined in ISO)ISO
CC_ki (defined in ISO)ISO
CC_km (defined in ISO)ISO
CC_kn (defined in ISO)ISO
CC_kp (defined in ISO)ISO
CC_kr (defined in ISO)ISO
CC_kw (defined in ISO)ISO
CC_ky (defined in ISO)ISO
CC_kz (defined in ISO)ISO
CC_la (defined in ISO)ISO
CC_lb (defined in ISO)ISO
CC_lc (defined in ISO)ISO
CC_li (defined in ISO)ISO
CC_lk (defined in ISO)ISO
CC_lr (defined in ISO)ISO
CC_ls (defined in ISO)ISO
CC_lt (defined in ISO)ISO
CC_lu (defined in ISO)ISO
CC_lv (defined in ISO)ISO
CC_ly (defined in ISO)ISO
CC_ma (defined in ISO)ISO
CC_mc (defined in ISO)ISO
CC_md (defined in ISO)ISO
CC_me (defined in ISO)ISO
CC_mf (defined in ISO)ISO
CC_mg (defined in ISO)ISO
CC_mh (defined in ISO)ISO
CC_mk (defined in ISO)ISO
CC_ml (defined in ISO)ISO
CC_mm (defined in ISO)ISO
CC_mn (defined in ISO)ISO
CC_mo (defined in ISO)ISO
CC_mp (defined in ISO)ISO
CC_mq (defined in ISO)ISO
CC_mr (defined in ISO)ISO
CC_ms (defined in ISO)ISO
CC_mt (defined in ISO)ISO
CC_mu (defined in ISO)ISO
CC_mv (defined in ISO)ISO
CC_mw (defined in ISO)ISO
CC_mx (defined in ISO)ISO
CC_my (defined in ISO)ISO
CC_mz (defined in ISO)ISO
CC_na (defined in ISO)ISO
CC_nc (defined in ISO)ISO
CC_ne (defined in ISO)ISO
CC_nf (defined in ISO)ISO
CC_ng (defined in ISO)ISO
CC_ni (defined in ISO)ISO
CC_nl (defined in ISO)ISO
CC_no (defined in ISO)ISO
CC_np (defined in ISO)ISO
CC_nr (defined in ISO)ISO
CC_nu (defined in ISO)ISO
CC_nz (defined in ISO)ISO
CC_om (defined in ISO)ISO
CC_pa (defined in ISO)ISO
CC_pe (defined in ISO)ISO
CC_pf (defined in ISO)ISO
CC_pg (defined in ISO)ISO
CC_ph (defined in ISO)ISO
CC_pk (defined in ISO)ISO
CC_pl (defined in ISO)ISO
CC_pm (defined in ISO)ISO
CC_pn (defined in ISO)ISO
CC_pr (defined in ISO)ISO
CC_ps (defined in ISO)ISO
CC_pt (defined in ISO)ISO
CC_pw (defined in ISO)ISO
CC_py (defined in ISO)ISO
CC_qa (defined in ISO)ISO
CC_re (defined in ISO)ISO
CC_ro (defined in ISO)ISO
CC_rs (defined in ISO)ISO
CC_ru (defined in ISO)ISO
CC_rw (defined in ISO)ISO
CC_sa (defined in ISO)ISO
CC_sb (defined in ISO)ISO
CC_sc (defined in ISO)ISO
CC_sd (defined in ISO)ISO
CC_se (defined in ISO)ISO
CC_sg (defined in ISO)ISO
CC_sh (defined in ISO)ISO
CC_si (defined in ISO)ISO
CC_sj (defined in ISO)ISO
CC_sk (defined in ISO)ISO
CC_sl (defined in ISO)ISO
CC_sm (defined in ISO)ISO
CC_sn (defined in ISO)ISO
CC_so (defined in ISO)ISO
CC_sr (defined in ISO)ISO
CC_ss (defined in ISO)ISO
CC_st (defined in ISO)ISO
CC_sv (defined in ISO)ISO
CC_sx (defined in ISO)ISO
CC_sy (defined in ISO)ISO
CC_sz (defined in ISO)ISO
CC_tc (defined in ISO)ISO
CC_td (defined in ISO)ISO
CC_tf (defined in ISO)ISO
CC_tg (defined in ISO)ISO
CC_th (defined in ISO)ISO
CC_tj (defined in ISO)ISO
CC_tk (defined in ISO)ISO
CC_tl (defined in ISO)ISO
CC_tm (defined in ISO)ISO
CC_tn (defined in ISO)ISO
CC_to (defined in ISO)ISO
CC_tr (defined in ISO)ISO
CC_tt (defined in ISO)ISO
CC_tv (defined in ISO)ISO
CC_tw (defined in ISO)ISO
CC_tz (defined in ISO)ISO
CC_ua (defined in ISO)ISO
CC_ug (defined in ISO)ISO
CC_um (defined in ISO)ISO
CC_us (defined in ISO)ISO
CC_uy (defined in ISO)ISO
CC_uz (defined in ISO)ISO
CC_va (defined in ISO)ISO
CC_vc (defined in ISO)ISO
CC_ve (defined in ISO)ISO
CC_vg (defined in ISO)ISO
CC_vi (defined in ISO)ISO
CC_vn (defined in ISO)ISO
CC_vu (defined in ISO)ISO
CC_wf (defined in ISO)ISO
CC_ws (defined in ISO)ISO
CC_ye (defined in ISO)ISO
CC_yt (defined in ISO)ISO
CC_za (defined in ISO)ISO
CC_zm (defined in ISO)ISO
CC_zw (defined in ISO)ISO
constants($prefix)ISOprotected
countries()ISO
instance()Prefabstatic
languages()ISO
LC_af (defined in ISO)ISO
LC_am (defined in ISO)ISO
LC_ar (defined in ISO)ISO
LC_as (defined in ISO)ISO
LC_ba (defined in ISO)ISO
LC_be (defined in ISO)ISO
LC_bg (defined in ISO)ISO
LC_bn (defined in ISO)ISO
LC_bo (defined in ISO)ISO
LC_br (defined in ISO)ISO
LC_ca (defined in ISO)ISO
LC_co (defined in ISO)ISO
LC_cs (defined in ISO)ISO
LC_cy (defined in ISO)ISO
LC_da (defined in ISO)ISO
LC_de (defined in ISO)ISO
LC_dv (defined in ISO)ISO
LC_el (defined in ISO)ISO
LC_en (defined in ISO)ISO
LC_es (defined in ISO)ISO
LC_et (defined in ISO)ISO
LC_eu (defined in ISO)ISO
LC_fa (defined in ISO)ISO
LC_fi (defined in ISO)ISO
LC_fo (defined in ISO)ISO
LC_fr (defined in ISO)ISO
LC_gd (defined in ISO)ISO
LC_gl (defined in ISO)ISO
LC_gu (defined in ISO)ISO
LC_he (defined in ISO)ISO
LC_hi (defined in ISO)ISO
LC_hr (defined in ISO)ISO
LC_hu (defined in ISO)ISO
LC_hy (defined in ISO)ISO
LC_id (defined in ISO)ISO
LC_ig (defined in ISO)ISO
LC_is (defined in ISO)ISO
LC_it (defined in ISO)ISO
LC_ja (defined in ISO)ISO
LC_ka (defined in ISO)ISO
LC_kk (defined in ISO)ISO
LC_km (defined in ISO)ISO
LC_kn (defined in ISO)ISO
LC_ko (defined in ISO)ISO
LC_lb (defined in ISO)ISO
LC_lo (defined in ISO)ISO
LC_lt (defined in ISO)ISO
LC_lv (defined in ISO)ISO
LC_mi (defined in ISO)ISO
LC_ml (defined in ISO)ISO
LC_mr (defined in ISO)ISO
LC_ms (defined in ISO)ISO
LC_mt (defined in ISO)ISO
LC_ne (defined in ISO)ISO
LC_nl (defined in ISO)ISO
LC_no (defined in ISO)ISO
LC_oc (defined in ISO)ISO
LC_or (defined in ISO)ISO
LC_pl (defined in ISO)ISO
LC_ps (defined in ISO)ISO
LC_pt (defined in ISO)ISO
LC_qu (defined in ISO)ISO
LC_ro (defined in ISO)ISO
LC_ru (defined in ISO)ISO
LC_rw (defined in ISO)ISO
LC_sa (defined in ISO)ISO
LC_si (defined in ISO)ISO
LC_sk (defined in ISO)ISO
LC_sl (defined in ISO)ISO
LC_sq (defined in ISO)ISO
LC_sv (defined in ISO)ISO
LC_ta (defined in ISO)ISO
LC_te (defined in ISO)ISO
LC_th (defined in ISO)ISO
LC_tk (defined in ISO)ISO
LC_tr (defined in ISO)ISO
LC_tt (defined in ISO)ISO
LC_uk (defined in ISO)ISO
LC_ur (defined in ISO)ISO
LC_vi (defined in ISO)ISO
LC_wo (defined in ISO)ISO
LC_yo (defined in ISO)ISO
LC_zh (defined in ISO)ISO
diff --git a/lib/f3/api/classISO.html b/lib/f3/api/classISO.html new file mode 100755 index 0000000..fb61d8e --- /dev/null +++ b/lib/f3/api/classISO.html @@ -0,0 +1,1148 @@ + + + + + + + +Fat-Free Framework: ISO Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

ISO language/country codes. + More...

+
+ + Inheritance diagram for ISO:
+
+
+ + + + + + + +

+Public Member Functions

 languages ()
 
 countries ()
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Attributes

+const CC_af ='Afghanistan'
 
+const CC_ax ='Åland Islands'
 
+const CC_al ='Albania'
 
+const CC_dz ='Algeria'
 
+const CC_as ='American Samoa'
 
+const CC_ad ='Andorra'
 
+const CC_ao ='Angola'
 
+const CC_ai ='Anguilla'
 
+const CC_aq ='Antarctica'
 
+const CC_ag ='Antigua and Barbuda'
 
+const CC_ar ='Argentina'
 
+const CC_am ='Armenia'
 
+const CC_aw ='Aruba'
 
+const CC_au ='Australia'
 
+const CC_at ='Austria'
 
+const CC_az ='Azerbaijan'
 
+const CC_bs ='Bahamas'
 
+const CC_bh ='Bahrain'
 
+const CC_bd ='Bangladesh'
 
+const CC_bb ='Barbados'
 
+const CC_by ='Belarus'
 
+const CC_be ='Belgium'
 
+const CC_bz ='Belize'
 
+const CC_bj ='Benin'
 
+const CC_bm ='Bermuda'
 
+const CC_bt ='Bhutan'
 
+const CC_bo ='Bolivia'
 
+const CC_bq ='Bonaire, Sint Eustatius and Saba'
 
+const CC_ba ='Bosnia and Herzegovina'
 
+const CC_bw ='Botswana'
 
+const CC_bv ='Bouvet Island'
 
+const CC_br ='Brazil'
 
+const CC_io ='British Indian Ocean Territory'
 
+const CC_bn ='Brunei Darussalam'
 
+const CC_bg ='Bulgaria'
 
+const CC_bf ='Burkina Faso'
 
+const CC_bi ='Burundi'
 
+const CC_kh ='Cambodia'
 
+const CC_cm ='Cameroon'
 
+const CC_ca ='Canada'
 
+const CC_cv ='Cape Verde'
 
+const CC_ky ='Cayman Islands'
 
+const CC_cf ='Central African Republic'
 
+const CC_td ='Chad'
 
+const CC_cl ='Chile'
 
+const CC_cn ='China'
 
+const CC_cx ='Christmas Island'
 
+const CC_cc ='Cocos (Keeling) Islands'
 
+const CC_co ='Colombia'
 
+const CC_km ='Comoros'
 
+const CC_cg ='Congo'
 
+const CC_cd ='Congo, The Democratic Republic of'
 
+const CC_ck ='Cook Islands'
 
+const CC_cr ='Costa Rica'
 
+const CC_ci ='Côte d\'ivoire'
 
+const CC_hr ='Croatia'
 
+const CC_cu ='Cuba'
 
+const CC_cw ='Curaçao'
 
+const CC_cy ='Cyprus'
 
+const CC_cz ='Czech Republic'
 
+const CC_dk ='Denmark'
 
+const CC_dj ='Djibouti'
 
+const CC_dm ='Dominica'
 
+const CC_do ='Dominican Republic'
 
+const CC_ec ='Ecuador'
 
+const CC_eg ='Egypt'
 
+const CC_sv ='El Salvador'
 
+const CC_gq ='Equatorial Guinea'
 
+const CC_er ='Eritrea'
 
+const CC_ee ='Estonia'
 
+const CC_et ='Ethiopia'
 
+const CC_fk ='Falkland Islands (Malvinas)'
 
+const CC_fo ='Faroe Islands'
 
+const CC_fj ='Fiji'
 
+const CC_fi ='Finland'
 
+const CC_fr ='France'
 
+const CC_gf ='French Guiana'
 
+const CC_pf ='French Polynesia'
 
+const CC_tf ='French Southern Territories'
 
+const CC_ga ='Gabon'
 
+const CC_gm ='Gambia'
 
+const CC_ge ='Georgia'
 
+const CC_de ='Germany'
 
+const CC_gh ='Ghana'
 
+const CC_gi ='Gibraltar'
 
+const CC_gr ='Greece'
 
+const CC_gl ='Greenland'
 
+const CC_gd ='Grenada'
 
+const CC_gp ='Guadeloupe'
 
+const CC_gu ='Guam'
 
+const CC_gt ='Guatemala'
 
+const CC_gg ='Guernsey'
 
+const CC_gn ='Guinea'
 
+const CC_gw ='Guinea-Bissau'
 
+const CC_gy ='Guyana'
 
+const CC_ht ='Haiti'
 
+const CC_hm ='Heard Island and McDonald Islands'
 
+const CC_va ='Holy See (Vatican City State)'
 
+const CC_hn ='Honduras'
 
+const CC_hk ='Hong Kong'
 
+const CC_hu ='Hungary'
 
+const CC_is ='Iceland'
 
+const CC_in ='India'
 
+const CC_id ='Indonesia'
 
+const CC_ir ='Iran, Islamic Republic of'
 
+const CC_iq ='Iraq'
 
+const CC_ie ='Ireland'
 
+const CC_im ='Isle of Man'
 
+const CC_il ='Israel'
 
+const CC_it ='Italy'
 
+const CC_jm ='Jamaica'
 
+const CC_jp ='Japan'
 
+const CC_je ='Jersey'
 
+const CC_jo ='Jordan'
 
+const CC_kz ='Kazakhstan'
 
+const CC_ke ='Kenya'
 
+const CC_ki ='Kiribati'
 
+const CC_kp ='Korea, Democratic People\'s Republic of'
 
+const CC_kr ='Korea, Republic of'
 
+const CC_kw ='Kuwait'
 
+const CC_kg ='Kyrgyzstan'
 
+const CC_la ='Lao People\'s Democratic Republic'
 
+const CC_lv ='Latvia'
 
+const CC_lb ='Lebanon'
 
+const CC_ls ='Lesotho'
 
+const CC_lr ='Liberia'
 
+const CC_ly ='Libya'
 
+const CC_li ='Liechtenstein'
 
+const CC_lt ='Lithuania'
 
+const CC_lu ='Luxembourg'
 
+const CC_mo ='Macao'
 
+const CC_mk ='Macedonia, The Former Yugoslav Republic of'
 
+const CC_mg ='Madagascar'
 
+const CC_mw ='Malawi'
 
+const CC_my ='Malaysia'
 
+const CC_mv ='Maldives'
 
+const CC_ml ='Mali'
 
+const CC_mt ='Malta'
 
+const CC_mh ='Marshall Islands'
 
+const CC_mq ='Martinique'
 
+const CC_mr ='Mauritania'
 
+const CC_mu ='Mauritius'
 
+const CC_yt ='Mayotte'
 
+const CC_mx ='Mexico'
 
+const CC_fm ='Micronesia, Federated States of'
 
+const CC_md ='Moldova, Republic of'
 
+const CC_mc ='Monaco'
 
+const CC_mn ='Mongolia'
 
+const CC_me ='Montenegro'
 
+const CC_ms ='Montserrat'
 
+const CC_ma ='Morocco'
 
+const CC_mz ='Mozambique'
 
+const CC_mm ='Myanmar'
 
+const CC_na ='Namibia'
 
+const CC_nr ='Nauru'
 
+const CC_np ='Nepal'
 
+const CC_nl ='Netherlands'
 
+const CC_nc ='New Caledonia'
 
+const CC_nz ='New Zealand'
 
+const CC_ni ='Nicaragua'
 
+const CC_ne ='Niger'
 
+const CC_ng ='Nigeria'
 
+const CC_nu ='Niue'
 
+const CC_nf ='Norfolk Island'
 
+const CC_mp ='Northern Mariana Islands'
 
+const CC_no ='Norway'
 
+const CC_om ='Oman'
 
+const CC_pk ='Pakistan'
 
+const CC_pw ='Palau'
 
+const CC_ps ='Palestinian Territory, Occupied'
 
+const CC_pa ='Panama'
 
+const CC_pg ='Papua New Guinea'
 
+const CC_py ='Paraguay'
 
+const CC_pe ='Peru'
 
+const CC_ph ='Philippines'
 
+const CC_pn ='Pitcairn'
 
+const CC_pl ='Poland'
 
+const CC_pt ='Portugal'
 
+const CC_pr ='Puerto Rico'
 
+const CC_qa ='Qatar'
 
+const CC_re ='Réunion'
 
+const CC_ro ='Romania'
 
+const CC_ru ='Russian Federation'
 
+const CC_rw ='Rwanda'
 
+const CC_bl ='Saint Barthélemy'
 
+const CC_sh ='Saint Helena, Ascension and Tristan da Cunha'
 
+const CC_kn ='Saint Kitts and Nevis'
 
+const CC_lc ='Saint Lucia'
 
+const CC_mf ='Saint Martin (French Part)'
 
+const CC_pm ='Saint Pierre and Miquelon'
 
+const CC_vc ='Saint Vincent and The Grenadines'
 
+const CC_ws ='Samoa'
 
+const CC_sm ='San Marino'
 
+const CC_st ='Sao Tome and Principe'
 
+const CC_sa ='Saudi Arabia'
 
+const CC_sn ='Senegal'
 
+const CC_rs ='Serbia'
 
+const CC_sc ='Seychelles'
 
+const CC_sl ='Sierra Leone'
 
+const CC_sg ='Singapore'
 
+const CC_sk ='Slovakia'
 
+const CC_sx ='Sint Maarten (Dutch Part)'
 
+const CC_si ='Slovenia'
 
+const CC_sb ='Solomon Islands'
 
+const CC_so ='Somalia'
 
+const CC_za ='South Africa'
 
+const CC_gs ='South Georgia and The South Sandwich Islands'
 
+const CC_ss ='South Sudan'
 
+const CC_es ='Spain'
 
+const CC_lk ='Sri Lanka'
 
+const CC_sd ='Sudan'
 
+const CC_sr ='Suriname'
 
+const CC_sj ='Svalbard and Jan Mayen'
 
+const CC_sz ='Swaziland'
 
+const CC_se ='Sweden'
 
+const CC_ch ='Switzerland'
 
+const CC_sy ='Syrian Arab Republic'
 
+const CC_tw ='Taiwan, Province of China'
 
+const CC_tj ='Tajikistan'
 
+const CC_tz ='Tanzania, United Republic of'
 
+const CC_th ='Thailand'
 
+const CC_tl ='Timor-Leste'
 
+const CC_tg ='Togo'
 
+const CC_tk ='Tokelau'
 
+const CC_to ='Tonga'
 
+const CC_tt ='Trinidad and Tobago'
 
+const CC_tn ='Tunisia'
 
+const CC_tr ='Turkey'
 
+const CC_tm ='Turkmenistan'
 
+const CC_tc ='Turks and Caicos Islands'
 
+const CC_tv ='Tuvalu'
 
+const CC_ug ='Uganda'
 
+const CC_ua ='Ukraine'
 
+const CC_ae ='United Arab Emirates'
 
+const CC_gb ='United Kingdom'
 
+const CC_us ='United States'
 
+const CC_um ='United States Minor Outlying Islands'
 
+const CC_uy ='Uruguay'
 
+const CC_uz ='Uzbekistan'
 
+const CC_vu ='Vanuatu'
 
+const CC_ve ='Venezuela'
 
+const CC_vn ='Viet Nam'
 
+const CC_vg ='Virgin Islands, British'
 
+const CC_vi ='Virgin Islands, U.S.'
 
+const CC_wf ='Wallis and Futuna'
 
+const CC_eh ='Western Sahara'
 
+const CC_ye ='Yemen'
 
+const CC_zm ='Zambia'
 
+const CC_zw ='Zimbabwe'
 
+const LC_af ='Afrikaans'
 
+const LC_am ='Amharic'
 
+const LC_ar ='Arabic'
 
+const LC_as ='Assamese'
 
+const LC_ba ='Bashkir'
 
+const LC_be ='Belarusian'
 
+const LC_bg ='Bulgarian'
 
+const LC_bn ='Bengali'
 
+const LC_bo ='Tibetan'
 
+const LC_br ='Breton'
 
+const LC_ca ='Catalan'
 
+const LC_co ='Corsican'
 
+const LC_cs ='Czech'
 
+const LC_cy ='Welsh'
 
+const LC_da ='Danish'
 
+const LC_de ='German'
 
+const LC_dv ='Divehi'
 
+const LC_el ='Greek'
 
+const LC_en ='English'
 
+const LC_es ='Spanish'
 
+const LC_et ='Estonian'
 
+const LC_eu ='Basque'
 
+const LC_fa ='Persian'
 
+const LC_fi ='Finnish'
 
+const LC_fo ='Faroese'
 
+const LC_fr ='French'
 
+const LC_gd ='Scottish Gaelic'
 
+const LC_gl ='Galician'
 
+const LC_gu ='Gujarati'
 
+const LC_he ='Hebrew'
 
+const LC_hi ='Hindi'
 
+const LC_hr ='Croatian'
 
+const LC_hu ='Hungarian'
 
+const LC_hy ='Armenian'
 
+const LC_id ='Indonesian'
 
+const LC_ig ='Igbo'
 
+const LC_is ='Icelandic'
 
+const LC_it ='Italian'
 
+const LC_ja ='Japanese'
 
+const LC_ka ='Georgian'
 
+const LC_kk ='Kazakh'
 
+const LC_km ='Khmer'
 
+const LC_kn ='Kannada'
 
+const LC_ko ='Korean'
 
+const LC_lb ='Luxembourgish'
 
+const LC_lo ='Lao'
 
+const LC_lt ='Lithuanian'
 
+const LC_lv ='Latvian'
 
+const LC_mi ='Maori'
 
+const LC_ml ='Malayalam'
 
+const LC_mr ='Marathi'
 
+const LC_ms ='Malay'
 
+const LC_mt ='Maltese'
 
+const LC_ne ='Nepali'
 
+const LC_nl ='Dutch'
 
+const LC_no ='Norwegian'
 
+const LC_oc ='Occitan'
 
+const LC_or ='Oriya'
 
+const LC_pl ='Polish'
 
+const LC_ps ='Pashto'
 
+const LC_pt ='Portuguese'
 
+const LC_qu ='Quechua'
 
+const LC_ro ='Romanian'
 
+const LC_ru ='Russian'
 
+const LC_rw ='Kinyarwanda'
 
+const LC_sa ='Sanskrit'
 
+const LC_si ='Sinhala'
 
+const LC_sk ='Slovak'
 
+const LC_sl ='Slovenian'
 
+const LC_sq ='Albanian'
 
+const LC_sv ='Swedish'
 
+const LC_ta ='Tamil'
 
+const LC_te ='Telugu'
 
+const LC_th ='Thai'
 
+const LC_tk ='Turkmen'
 
+const LC_tr ='Turkish'
 
+const LC_tt ='Tatar'
 
+const LC_uk ='Ukrainian'
 
+const LC_ur ='Urdu'
 
+const LC_vi ='Vietnamese'
 
+const LC_wo ='Wolof'
 
+const LC_yo ='Yoruba'
 
+const LC_zh ='Chinese'
 
+ + + +

+Protected Member Functions

 constants ($prefix)
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

ISO language/country codes.

+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + +
ISO::constants ( $prefix)
+
+protected
+
+

Convert class constants to array

+
Returns
array
+
Parameters
+ + +
$prefixstring
+
+
+ +
+
+ +
+
+ + + + + + + +
ISO::countries ()
+
+

Return list of countries indexed by ISO 3166-1 country code

+
Returns
array
+ +
+
+ +
+
+ + + + + + + +
ISO::languages ()
+
+

Return list of languages indexed by ISO 639-1 language code

+
Returns
array
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • base.php
  • +
+
diff --git a/lib/f3/api/classISO.png b/lib/f3/api/classISO.png new file mode 100755 index 0000000000000000000000000000000000000000..197c8fd2de962910a30382a9f4d6e3cb37bcd7a3 GIT binary patch literal 330 zcmeAS@N?(olHy`uVBq!ia0vp^MnD|E!3-pG?q0hDq$C1-LR|m<{|{uod-rb6oH-MK zEHFNB;J^pRRC^$oqa?^Lm;tB=1g@S60U2`B)5S5Qg7NL#NWQ}gJgmpJP5CXqlh>Ow zQcF($?}`kgD>}^wcQObHO113XeJEaQ+y6Uzt8br3T&20ZGx+=Jr0Us5&$cYhmCT<~ zTiACx{@&xsFRP|M-c`2Bs_Nt=qoNHjz7e U!ncQ(Kui_@% literal 0 HcmV?d00001 diff --git a/lib/f3/api/classImage-members.html b/lib/f3/api/classImage-members.html new file mode 100755 index 0000000..7fb7595 --- /dev/null +++ b/lib/f3/api/classImage-members.html @@ -0,0 +1,82 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Image Member List
+
+
+ +

This is the complete list of members for Image, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$countImage
$dataImage
$flagImage
__construct($file=NULL, $flag=FALSE, $path='')Image
__destruct()Image
blur($selective=FALSE)Image
brightness($level)Image
captcha($font, $size=24, $len=5, $key=NULL, $path='', $fg=0xFFFFFF, $bg=0x000000)Image
contrast($level)Image
crop($x1, $y1, $x2, $y2)Image
dump()Image
E_Color (defined in Image)Image
E_Font (defined in Image)Image
E_Length (defined in Image)Image
emboss()Image
grayscale()Image
height()Image
hflip()Image
identicon($str, $size=64, $blocks=4)Image
invert()Image
load($str)Image
overlay(Image $img, $align=NULL)Image
pixelate($size)Image
POS_Bottom (defined in Image)Image
POS_Center (defined in Image)Image
POS_Left (defined in Image)Image
POS_Middle (defined in Image)Image
POS_Right (defined in Image)Image
POS_Top (defined in Image)Image
render()Image
resize($width, $height, $crop=TRUE, $enlarge=TRUE)Image
restore($state=1)Image
rgb($color)Image
rotate($angle)Image
save()Image
sepia()Image
sketch()Image
smooth($level)Image
undo()Image
vflip()Image
width()Image
diff --git a/lib/f3/api/classImage.html b/lib/f3/api/classImage.html new file mode 100755 index 0000000..370bfaf --- /dev/null +++ b/lib/f3/api/classImage.html @@ -0,0 +1,898 @@ + + + + + + + +Fat-Free Framework: Image Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

Image manipulation tools. + More...

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 rgb ($color)
 
 invert ()
 
 brightness ($level)
 
 contrast ($level)
 
 grayscale ()
 
 smooth ($level)
 
 emboss ()
 
 sepia ()
 
 pixelate ($size)
 
 blur ($selective=FALSE)
 
 sketch ()
 
 hflip ()
 
 vflip ()
 
 crop ($x1, $y1, $x2, $y2)
 
 resize ($width, $height, $crop=TRUE, $enlarge=TRUE)
 
 rotate ($angle)
 
 overlay (Image $img, $align=NULL)
 
 identicon ($str, $size=64, $blocks=4)
 
 captcha ($font, $size=24, $len=5, $key=NULL, $path='', $fg=0xFFFFFF, $bg=0x000000)
 
 width ()
 
 height ()
 
 render ()
 
 dump ()
 
 save ()
 
 restore ($state=1)
 
 undo ()
 
 load ($str)
 
 __construct ($file=NULL, $flag=FALSE, $path='')
 
 __destruct ()
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Attributes

$data
 Image resource.
 
$flag =FALSE
 Enable/disable history.
 
$count =0
 Filter count.
 
+const E_Color ='Invalid color specified: %s'
 
+const E_Font ='CAPTCHA font not found'
 
+const E_Length ='Invalid CAPTCHA length: %s'
 
+const POS_Left =1
 
+const POS_Center =2
 
+const POS_Right =4
 
+const POS_Top =8
 
+const POS_Middle =16
 
+const POS_Bottom =32
 
+

Detailed Description

+

Image manipulation tools.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Image::__construct ( $file = NULL,
 $flag = FALSE,
 $path = '' 
)
+
+

Instantiate image

+
Parameters
+ + + + +
$filestring
$flagbool
$pathstring
+
+
+ +
+
+ +
+
+ + + + + + + +
Image::__destruct ()
+
+

Wrap-up

+
Returns
NULL
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
Image::blur ( $selective = FALSE)
+
+

Blur the image using Gaussian filter

+
Returns
object
+
Parameters
+ + +
$selectivebool
+
+
+ +
+
+ +
+
+ + + + + + + + +
Image::brightness ( $level)
+
+

Adjust brightness (range:-255 to 255)

+
Returns
object
+
Parameters
+ + +
$levelint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Image::captcha ( $font,
 $size = 24,
 $len = 5,
 $key = NULL,
 $path = '',
 $fg = 0xFFFFFF,
 $bg = 0x000000 
)
+
+

Generate CAPTCHA image

+
Returns
object|FALSE
+
Parameters
+ + + + + + + + +
$fontstring
$sizeint
$lenint
$keystring
$pathstring
$fgint
$bgint
+
+
+ +
+
+ +
+
+ + + + + + + + +
Image::contrast ( $level)
+
+

Adjust contrast (range:-100 to 100)

+
Returns
object
+
Parameters
+ + +
$levelint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Image::crop ( $x1,
 $y1,
 $x2,
 $y2 
)
+
+

Crop the image

+
Returns
object
+
Parameters
+ + + + + +
$x1int
$y1int
$x2int
$y2int
+
+
+ +
+
+ +
+
+ + + + + + + +
Image::dump ()
+
+

Return image as a string

+
Returns
string
+ +
+
+ +
+
+ + + + + + + +
Image::emboss ()
+
+

Emboss the image

+
Returns
object
+ +
+
+ +
+
+ + + + + + + +
Image::grayscale ()
+
+

Convert to grayscale

+
Returns
object
+ +
+
+ +
+
+ + + + + + + +
Image::height ()
+
+

Return image height

+
Returns
int
+ +
+
+ +
+
+ + + + + + + +
Image::hflip ()
+
+

Flip on horizontal axis

+
Returns
object
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Image::identicon ( $str,
 $size = 64,
 $blocks = 4 
)
+
+

Generate identicon

+
Returns
object
+
Parameters
+ + + + +
$strstring
$sizeint
$blocksint
+
+
+ +
+
+ +
+
+ + + + + + + +
Image::invert ()
+
+

Invert image

+
Returns
object
+ +
+
+ +
+
+ + + + + + + + +
Image::load ( $str)
+
+

Load string

+
Returns
object
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Image::overlay (Image $img,
 $align = NULL 
)
+
+

Apply an image overlay

+
Returns
object
+
Parameters
+ + + +
$imgobject
$alignint
+
+
+ +
+
+ +
+
+ + + + + + + + +
Image::pixelate ( $size)
+
+

Pixelate the image

+
Returns
object
+
Parameters
+ + +
$sizeint
+
+
+ +
+
+ +
+
+ + + + + + + +
Image::render ()
+
+

Send image to HTTP client

+
Returns
NULL
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Image::resize ( $width,
 $height,
 $crop = TRUE,
 $enlarge = TRUE 
)
+
+

Resize image (Maintain aspect ratio); Crop relative to center if flag is enabled; Enlargement allowed if flag is enabled

+
Returns
object
+
Parameters
+ + + + + +
$widthint
$heightint
$cropbool
$enlargebool
+
+
+ +
+
+ +
+
+ + + + + + + + +
Image::restore ( $state = 1)
+
+

Revert to specified state

+
Returns
object
+
Parameters
+ + +
$stateint
+
+
+ +
+
+ +
+
+ + + + + + + + +
Image::rgb ( $color)
+
+

Convert RGB hex triad to array

+
Returns
array|FALSE
+
Parameters
+ + +
$colorint
+
+
+ +
+
+ +
+
+ + + + + + + + +
Image::rotate ( $angle)
+
+

Rotate image

+
Returns
object
+
Parameters
+ + +
$angleint
+
+
+ +
+
+ +
+
+ + + + + + + +
Image::save ()
+
+

Save current state

+
Returns
object
+ +
+
+ +
+
+ + + + + + + +
Image::sepia ()
+
+

Apply sepia effect

+
Returns
object
+ +
+
+ +
+
+ + + + + + + +
Image::sketch ()
+
+

Apply sketch effect

+
Returns
object
+ +
+
+ +
+
+ + + + + + + + +
Image::smooth ( $level)
+
+

Adjust smoothness

+
Returns
object
+
Parameters
+ + +
$levelint
+
+
+ +
+
+ +
+
+ + + + + + + +
Image::undo ()
+
+

Undo most recently applied filter

+
Returns
object
+ +
+
+ +
+
+ + + + + + + +
Image::vflip ()
+
+

Flip on vertical axis

+
Returns
object
+ +
+
+ +
+
+ + + + + + + +
Image::width ()
+
+

Return image width

+
Returns
int
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • image.php
  • +
+
diff --git a/lib/f3/api/classLog-members.html b/lib/f3/api/classLog-members.html new file mode 100755 index 0000000..be31428 --- /dev/null +++ b/lib/f3/api/classLog-members.html @@ -0,0 +1,45 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Log Member List
+
+
+ +

This is the complete list of members for Log, including all inherited members.

+ + + + + +
$fileLogprotected
__construct($file)Log
erase()Log
write($text, $format='r')Log
diff --git a/lib/f3/api/classLog.html b/lib/f3/api/classLog.html new file mode 100755 index 0000000..cdeddc1 --- /dev/null +++ b/lib/f3/api/classLog.html @@ -0,0 +1,144 @@ + + + + + + + +Fat-Free Framework: Log Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

Custom logger. + More...

+ + + + + + + + +

+Public Member Functions

 write ($text, $format='r')
 
 erase ()
 
 __construct ($file)
 
+ + + + +

+Protected Attributes

$file
 File name.
 
+

Detailed Description

+

Custom logger.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
Log::__construct ( $file)
+
+

Instantiate class

+
Parameters
+ + +
$filestring
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + +
Log::erase ()
+
+

Erase log

+
Returns
NULL
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Log::write ( $text,
 $format = 'r' 
)
+
+

Write specified text to log file

+
Returns
string
+
Parameters
+ + + +
$textstring
$formatstring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • log.php
  • +
+
diff --git a/lib/f3/api/classMagic-members.html b/lib/f3/api/classMagic-members.html new file mode 100755 index 0000000..f93e743 --- /dev/null +++ b/lib/f3/api/classMagic-members.html @@ -0,0 +1,53 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Magic Member List
+
+
+ +

This is the complete list of members for Magic, including all inherited members.

+ + + + + + + + + + + + + +
__get($key)Magic
__isset($key)Magic
__set($key, $val)Magic
__unset($key)Magic
clear($key)Magic
exists($key)Magic
get($key)Magic
offsetexists($key)Magic
offsetget($key)Magic
offsetset($key, $val)Magic
offsetunset($key)Magic
set($key, $val)Magic
diff --git a/lib/f3/api/classMagic.html b/lib/f3/api/classMagic.html new file mode 100755 index 0000000..15f391f --- /dev/null +++ b/lib/f3/api/classMagic.html @@ -0,0 +1,450 @@ + + + + + + + +Fat-Free Framework: Magic Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+ +
+
Magic Class Reference
+
+
+ +

PHP magic wrapper. + More...

+
+ + Inheritance diagram for Magic:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 offsetexists ($key)
 
 __isset ($key)
 
 offsetset ($key, $val)
 
 __set ($key, $val)
 
 offsetget ($key)
 
 __get ($key)
 
 offsetunset ($key)
 
 __unset ($key)
 
+

Detailed Description

+

PHP magic wrapper.

+

Member Function Documentation

+ +
+
+ + + + + + + + +
Magic::__get ( $key)
+
+

Alias for offsetget()

+
Returns
mixed
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Magic::__isset ( $key)
+
+

Alias for offsetexists()

+
Returns
mixed
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Magic::__set ( $key,
 $val 
)
+
+

Alias for offsetset()

+
Returns
mixed
+
Parameters
+ + + +
$keystring
$valscalar
+
+
+ +
+
+ +
+
+ + + + + + + + +
Magic::__unset ( $key)
+
+

Alias for offsetunset()

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Magic::clear ( $key)
+
+abstract
+
+

Unset key

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Magic::exists ( $key)
+
+abstract
+
+

Return TRUE if key is not empty

+
Returns
bool
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Magic::get ( $key)
+
+abstract
+
+

Retrieve contents of key

+
Returns
mixed
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Magic::offsetexists ( $key)
+
+

Convenience method for checking property value

+
Returns
mixed
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Magic::offsetget ( $key)
+
+

Convenience method for retrieving property value

+
Returns
mixed
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Magic::offsetset ( $key,
 $val 
)
+
+

Convenience method for assigning property value

+
Returns
mixed
+
Parameters
+ + + +
$keystring
$valscalar
+
+
+ +
+
+ +
+
+ + + + + + + + +
Magic::offsetunset ( $key)
+
+

Convenience method for checking property value

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Magic::set ( $key,
 $val 
)
+
+abstract
+
+

Bind value to key

+
Returns
mixed
+
Parameters
+ + + +
$keystring
$valmixed
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • magic.php
  • +
+
diff --git a/lib/f3/api/classMagic.png b/lib/f3/api/classMagic.png new file mode 100755 index 0000000000000000000000000000000000000000..7a6c07cfaecc25aec4e5ccb8d9ce5c2d9d51ffda GIT binary patch literal 2601 zcmb_eX;c$g7A}^ChzpDa(Y6JghDK2k6h#mzKp71PLBIwTjJQD4ih!)LBoPH#)3^j% zRDz`#K}7=Mu!umAbVOx|vW0Yjum=bdq6vgRs;0pCfpcd1%$YNF&VBX0SNGlb-o0Oa zRhK+H_AJ%ABCx1wjxLj*pMiXtZl6nzx#o znhB?qAlk)5d3ksPsMFll_ReQB04yrU?RN5sQ~8)JDt)jKt6m>to`l%IXClWe5rq?K^1B>Bfk#hqvG66EEfXp9sN>WqcXKfU)W{~$6YrFu5G@MR4(*1eY zU(C}2Z_5|fSE{V{gZ_a`Gogu?Yxtf1=fK!rSijSSe38s=#Woo}ib`KId z%82B};fIExc`#wK4c!}lZqw-gN*0>6d&_R%C_ucqtOjWPMW)v3%H@HM4^fwb&M`jd zn2jQ~pTpOa76$nL;hMQ>=&F!aFeYy;ih$&E>q#;GMxyG;4_iy<^lcCE(k) zMcXtpQKVVE+{xgnp^j2aV%Jpi4H6m?~#tH(pn)7fuaIvTFFw;0mUsOgk1u$%O84>qK z?hC}t!$8O(P<{4=NYbvuciH8Y!RC+&l7_ymU|N3SM_D6_Cg!f?R zbW69LMG7k!+5}H+*mL@Z1-z?Hzy+6#ZR<`qJ8>K@#c$1^>w)(ORQMZcOi7j6l5X`# z^MjS`VM??_mt=&sDvlVmZf?!7&xoQ}RkEl5Y=x{Wl&{gF9->Ny9;jIYTT!Z)G)GTr zd#*?IXM@cQicC>tb@N{o2_5@Np}zEWc5|ZxWI!u!_I);BgwYo$RBFRj$wvMtSuw0d zKytXGz|d$3THac;yktw-pE}9OrJ;PU3bb*i8My;G&Kqz7Q}b%$B*@JKz`U9xh{6Ir z9m=`OC^4x+_(&v^X5VDU{QP;E+iHfZ^V26i=O5pRP2sgMcf!vi>{bzzJkuznhRoCq z|8p@demXe2x>UH}%vG5uHi&=(U2{3kU_M=@-wwLVPQ263E8E``+)@NZ_QkBXU6MYs zLHakOnBQfPiuLZFwk(ttCJ%TYWxUgjmgAID9G{GlgmoXnPudR*uK&Q~@4Az-uEAEB z(dVu_8C_lhCuU{II0qn2$oyJf(z8ZWQWXvB5-q>ZL!3#+ zhW0;U7o{n(TcM~d>BJG_g=JkZ^79nmUzfw}O_K^)4r@&h?ySy5Ja0uRKBpfgAh+%O z{Saw!Q-9+WOqVF{n&NDCC}JzRp8mAC-nF)}ovCLWM$?gHj=rEatbDOt+64 zo7WXW3C!*<=wVkb+WewRUj#V+WHK^CXQO9{e5?+vMP+ak zPQX?a2+&6nk^(~WY{)o5&8VC1k0m;EuEm{-xkJFBY?N3P8v0^`e340cULM{TWUyRh zR|%}Q&eMIlWjQ7xjdOI&qq;R)xCBnh!ZZ$A2Pqbd!UL5pKKR_(@c2lpyC%9prBXSu zTW-&%mOUWxLZ5)7&MoZLIERK)%6y|~?5+GyPHTu>h;mB+Ezj}$0+8289pda)evXC9 z2VSKFHjUt+>SlspTE2)=_9D@`g^{^5;b7I^=7_zd=8vgxW19ZOe{zzBzg%lK`(}*v z5X|?k9@Y~PJm`tbtKO5$8YDdCAIfdg%+`56Hnn#~`HTpN2N9m7P%2#gD&B45V^)d` zA1IUzB_JK;@ispubgxqG=sFXRpM{i+qE5uI=2ggf#E zEqEF&OZR&zc<-5Qp$hVB#IDQsy|=%Ra{LpAA>_M?!rf7gOD*xh*|E+@Oh$~LhjNNK z)u#zRD!AK7jY`E+kaJq1O{*2iT Pe;t5x@z~99KAQXwn*K6N literal 0 HcmV?d00001 diff --git a/lib/f3/api/classMarkdown-members.html b/lib/f3/api/classMarkdown-members.html new file mode 100755 index 0000000..4bdba5f --- /dev/null +++ b/lib/f3/api/classMarkdown-members.html @@ -0,0 +1,63 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Markdown Member List
+
+
+ +

This is the complete list of members for Markdown, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + +
$blocksMarkdownprotected
$specialMarkdown
_a($str)Markdownprotected
_atx($type, $str)Markdownprotected
_auto($str)Markdownprotected
_blockquote($str)Markdownprotected
_code($str)Markdownprotected
_fence($hint, $str)Markdownprotected
_hr()Markdownprotected
_img($str)Markdownprotected
_li($str)Markdownprotected
_p($str)Markdownprotected
_pre($str)Markdownprotected
_raw($str)Markdownprotected
_setext($str, $type)Markdownprotected
_text($str)Markdownprotected
build($str)Markdownprotected
convert($txt)Markdown
esc($str)Markdown
instance()Prefabstatic
scan($str)Markdown
snip($str)Markdownprotected
diff --git a/lib/f3/api/classMarkdown.html b/lib/f3/api/classMarkdown.html new file mode 100755 index 0000000..b430245 --- /dev/null +++ b/lib/f3/api/classMarkdown.html @@ -0,0 +1,739 @@ + + + + + + + +Fat-Free Framework: Markdown Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

Markdown-to-HTML converter. + More...

+
+ + Inheritance diagram for Markdown:
+
+
+ + + + + + + + + +

+Public Member Functions

 esc ($str)
 
 scan ($str)
 
 convert ($txt)
 
+ + + + +

+Public Attributes

$special
 Special characters.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Protected Member Functions

 _blockquote ($str)
 
 _pre ($str)
 
 _fence ($hint, $str)
 
 _hr ()
 
 _atx ($type, $str)
 
 _setext ($str, $type)
 
 _li ($str)
 
 _raw ($str)
 
 _p ($str)
 
 _text ($str)
 
 _img ($str)
 
 _a ($str)
 
 _auto ($str)
 
 _code ($str)
 
 snip ($str)
 
 build ($str)
 
+ + + + +

+Protected Attributes

$blocks
 Parsing rules.
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

Markdown-to-HTML converter.

+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::_a ( $str)
+
+protected
+
+

Process anchor span

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Markdown::_atx ( $type,
 $str 
)
+
+protected
+
+

Process atx-style heading

+
Returns
string
+
Parameters
+ + + +
$typestring
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::_auto ( $str)
+
+protected
+
+

Auto-convert links

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::_blockquote ( $str)
+
+protected
+
+

Process blockquote

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::_code ( $str)
+
+protected
+
+

Process code span

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Markdown::_fence ( $hint,
 $str 
)
+
+protected
+
+

Process fenced code block

+
Returns
string
+
Parameters
+ + + +
$hintstring
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + +
Markdown::_hr ()
+
+protected
+
+

Process horizontal rule

+
Returns
string
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::_img ( $str)
+
+protected
+
+

Process image span

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::_li ( $str)
+
+protected
+
+

Process ordered/unordered list

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::_p ( $str)
+
+protected
+
+

Process paragraph

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::_pre ( $str)
+
+protected
+
+

Process whitespace-prefixed code block

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::_raw ( $str)
+
+protected
+
+

Ignore raw HTML

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Markdown::_setext ( $str,
 $type 
)
+
+protected
+
+

Process setext-style heading

+
Returns
string
+
Parameters
+ + + +
$strstring
$typestring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::_text ( $str)
+
+protected
+
+

Process strong/em/strikethrough spans

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::build ( $str)
+
+protected
+
+

Assemble blocks

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Markdown::convert ( $txt)
+
+

Render HTML equivalent of markdown

+
Returns
string
+
Parameters
+ + +
$txtstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Markdown::esc ( $str)
+
+

Convert characters to HTML entities

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Markdown::scan ( $str)
+
+

Scan line for convertible spans

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Markdown::snip ( $str)
+
+protected
+
+

Reduce multiple line feeds

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • markdown.php
  • +
+
diff --git a/lib/f3/api/classMarkdown.png b/lib/f3/api/classMarkdown.png new file mode 100755 index 0000000000000000000000000000000000000000..a54469549d292782cbe9f9bbf51c8c85272a70c8 GIT binary patch literal 403 zcmeAS@N?(olHy`uVBq!ia0vp^?m!&C!3-p8_Rin~QW60^A+G=b{|7SPy?Zxj&YTHA z78oBmaNvVusy&d)Q4-`A%m7pb0#{Fk7%?y~DtWp%hEy=VoqKZ9VFezS`LkC2`LFJu zbD-%+k(hk7H^ z_j}x4m6ypN^L`zkGbKn${DAgd2DJ>K=Vh~*XC2v@ysROuur7A582baKZf1e(LWU$= zK8H0&89TnNw@gbDZeipBiOJ6Csy^`R!!MiXDbZ(S&V4J_$SzkuFA{vb^yX!YPph)` z6@EW`f|Gao8P++oTvKJ0&E2gZZi#&Ih0Ri~Vt(7~Z_oT*-OI1H_*eN*G+p2Oe^j)- pLDky#A`gNH!PC{xWt~$(696b_w?hB` literal 0 HcmV?d00001 diff --git a/lib/f3/api/classMatrix-members.html b/lib/f3/api/classMatrix-members.html new file mode 100755 index 0000000..ed8568d --- /dev/null +++ b/lib/f3/api/classMatrix-members.html @@ -0,0 +1,47 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Matrix Member List
+
+
+ +

This is the complete list of members for Matrix, including all inherited members.

+ + + + + + + +
calendar($date='now', $first=0)Matrix
changekey(array &$var, $old, $new)Matrix
instance()Prefabstatic
pick(array $var, $col)Matrix
sort(array &$var, $col, $order=SORT_ASC)Matrix
transpose(array &$var)Matrix
diff --git a/lib/f3/api/classMatrix.html b/lib/f3/api/classMatrix.html new file mode 100755 index 0000000..70a5b69 --- /dev/null +++ b/lib/f3/api/classMatrix.html @@ -0,0 +1,259 @@ + + + + + + + +Fat-Free Framework: Matrix Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+ +
+
Matrix Class Reference
+
+
+ +

Generic array utilities. + More...

+
+ + Inheritance diagram for Matrix:
+
+
+ + + + + + + + + + + + + +

+Public Member Functions

 pick (array $var, $col)
 
 transpose (array &$var)
 
 sort (array &$var, $col, $order=SORT_ASC)
 
 changekey (array &$var, $old, $new)
 
 calendar ($date='now', $first=0)
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

Generic array utilities.

+

Member Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
Matrix::calendar ( $date = 'now',
 $first = 0 
)
+
+

Return month calendar of specified date, with optional setting for first day of week (0 for Sunday)

+
Returns
array
+
Parameters
+ + + +
$datestring
$firstint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Matrix::changekey (array & $var,
 $old,
 $new 
)
+
+

Change the key of a two-dimensional array element

+
Returns
NULL
+
Parameters
+ + + + +
$vararray
$oldstring
$newstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Matrix::pick (array $var,
 $col 
)
+
+

Retrieve values from a specified column of a multi-dimensional array variable

+
Returns
array
+
Parameters
+ + + +
$vararray
$colmixed
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Matrix::sort (array & $var,
 $col,
 $order = SORT_ASC 
)
+
+

Sort a multi-dimensional array variable on a specified column

+
Returns
bool
+
Parameters
+ + + + +
$vararray
$colmixed
$orderint
+
+
+ +
+
+ +
+
+ + + + + + + + +
Matrix::transpose (array & $var)
+
+

Rotate a two-dimensional array variable

+
Returns
NULL
+
Parameters
+ + +
$vararray
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • matrix.php
  • +
+
diff --git a/lib/f3/api/classMatrix.png b/lib/f3/api/classMatrix.png new file mode 100755 index 0000000000000000000000000000000000000000..c256f4440a9c23e93cb2316cb567ecef0eb1a22c GIT binary patch literal 350 zcmeAS@N?(olHy`uVBq!ia0vp^MnD|E!3-pG?q0hDq$C1-LR|m<{|{uod-rb6oH-MK zEHFNB;J^pRRC^$oqa?^Lm;tB=1g@S60U7ev)5S5Qg7NL#=u6E89B%vukN-{o6Yf}S zSk}b<-&uXDe8Q8K(_99|r#XW|&%RI>yjj2M)}Pa!Uso#JZGZPwTWPngR@Kc7OCK@Z zoNUYYygX*=yUkZBm#+T&C2VQPr*r3ar%f=M``(=97xoX{(#!X{(fa$xZ#_rmI>x=o_!FcwYnJ<~W9tfTM9h!&lRLitw#B!S oM1GC~Q^c4iT(ov^QCVug^dEQYDqYcaK#wzcy85}Sb4q9e0ET>+2><{9 literal 0 HcmV?d00001 diff --git a/lib/f3/api/classPrefab-members.html b/lib/f3/api/classPrefab-members.html new file mode 100755 index 0000000..56fb125 --- /dev/null +++ b/lib/f3/api/classPrefab-members.html @@ -0,0 +1,42 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Prefab Member List
+
+
+ +

This is the complete list of members for Prefab, including all inherited members.

+ + +
instance()Prefabstatic
diff --git a/lib/f3/api/classPrefab.html b/lib/f3/api/classPrefab.html new file mode 100755 index 0000000..f61e880 --- /dev/null +++ b/lib/f3/api/classPrefab.html @@ -0,0 +1,103 @@ + + + + + + + +Fat-Free Framework: Prefab Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+ +
+
Prefab Class Reference
+
+
+ +

Factory class for single-instance objects. + More...

+
+ + Inheritance diagram for Prefab:
+
+
+ + + + + +

+Static Public Member Functions

static instance ()
 
+

Detailed Description

+

Factory class for single-instance objects.

+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + +
static Prefab::instance ()
+
+static
+
+

Return class instance

+
Returns
object
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • base.php
  • +
+
diff --git a/lib/f3/api/classPrefab.png b/lib/f3/api/classPrefab.png new file mode 100755 index 0000000000000000000000000000000000000000..3a1297a49280653bd55efc497792f5abf6478b57 GIT binary patch literal 2714 zcmcgu3s6&M7Dg0Hp$KUgr7VKLrOfIg3s!{X5rOasC`pw^Sv094-GcH+1_+Pvs8dL& ziRfilu>_QMF@PEnlxHv~S1>$^EDse3Ea6okB!NIkAS8POb!eU4tvj>bJ9Fp$XXeiQ z=X~e;zH@T00X}*<#yT1r8hU77)Cu?tX=rHHX>W&5ChvUP4u6cW#{#`nDiwSb3WW>? z;|hG*c$=G>#qJSEIMj|m5pYri{z?7xw+Gs5Xz2V7jdBl6+BVOd51xItJG+M)7Cxc0 zm1~ckw98(4_Dc8kGf$6r(u=>9KfzO4#wx?asxP`#pICktP0!3S-gZ80)y%c2WtgRK zY&E7@XT+^Yy9_AfbCJPQWlo%tE*)~25#LcESCI3AkhJQ7qB=AA{OD=clit}*DB59a zIliaKn!m7=hKQ}VHYLgA*W%q=*V&JG?<)Q2nGX+Z?vC1V_a34W3tzZ#J+|WAk*3ki z{M-0jGCit(%i4i-t#3sE*zdfL!s!@B?FcMIV2l5K&_%UteQA?aJWmB)m3cQ08eau; z4{Hw8>?HUuiWPN#K;})X?Kj_r&vxcy_&^JjeKYHA9c^fkj5mi8#I*@a=^Zl%_d1gri54Ti7q*gUSpA%c~b~dICP_M8t>ws!OOm2;RZ73Dm64ni(PF#ARA{6EnA^+ z<@@+9=GR{svQnsdyrlY;sLHl0%E#{BR>Xk8@6g2G71;$Wq_sZqGXc>trc?giY zjj0{{`lBpS3}vp`n4iATd1qGjRsQYB!M|JZYjCC^-ScsrFmR$cgM2B?WR9t?oU`?_ z3^-EUW;Z%o2zr|O6ITSW7vAiI)Y%}Mc0WYyQGmdfyovQM3I2yz%T2A-z{+F(gsk>_ z@r+F12f9?~oHd=3S0;+H5U|ZEh)Ov(@N=ia>E`#l-RmFmf_(V(cj z`hIM09L~?#LQSj(#sm(7#f+_DxaBGnC+QB-b-oiXk9DQi9pFm0u6s?cUqSbW;qDOg z&8EXa1=b5{@dp)wFi|pg-zWMjdTyxEKLN8Rv~=J)FX03BAq%v_|Ap-9RL4`eX_)C@ z?kJEQTs#?XqI%ep?03+LTicK7q~O1-bIm(f>_=kCtC93I*-M1o@!kg|FAQpRr!S!w zqe~uHn+mJ$kWfJonUsP-ffvd)m9#>~XBu%d7S1H4LOo(3HE&Esfjztl_HbI}{{PBL z)s~y_Tf0rA@4X5*_ix!i@V;Fn9t+^=!xk&G;K${62T*{}^1dROkyycw2kv5j$_CBL!vqP>r>}CxkGWWk#AAlj7DcHfKhWkUHvOX)&^JB&e>t)+2ufp2 z2uq}ImJ7(s+Nr&B#$J0NMVXn~WqgF>E3&h#DhWfTMWy5Zcv&KBcU?vV>)5HtAI?lJ z(Ngw6>`O@V@2e%^J3z7^0{ZxP@3lwuPjNnp_2#ag1{A^ z&PJNfBM(|3%}rGo)`%C6yZQ_dtgYWNZEdWyu8FzuvM&T0=gm0rxxB~`XMI(%3Tc7H z&CXm$fkV}f{FxOJ=n|Or(f9aR^kQ0UB?CNHzXg$cx-28VJR^(C`t<8V@FJ;!_6k6; IJU+YlPrR@6r~m)} literal 0 HcmV?d00001 diff --git a/lib/f3/api/classPreview-members.html b/lib/f3/api/classPreview-members.html new file mode 100755 index 0000000..aab76b3 --- /dev/null +++ b/lib/f3/api/classPreview-members.html @@ -0,0 +1,51 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Preview Member List
+
+
+ +

This is the complete list of members for Preview, including all inherited members.

+ + + + + + + + + + + +
$mimePreviewprotected
$viewViewprotected
build($node)Previewprotected
esc($arg)View
instance()Prefabstatic
raw($arg)View
render($file, $mime='text/html', array $hive=NULL, $ttl=0)Preview
resolve($str, array $hive=NULL)Preview
sandbox(array $hive=NULL)Viewprotected
token($str)Preview
diff --git a/lib/f3/api/classPreview.html b/lib/f3/api/classPreview.html new file mode 100755 index 0000000..3e20198 --- /dev/null +++ b/lib/f3/api/classPreview.html @@ -0,0 +1,248 @@ + + + + + + + +Fat-Free Framework: Preview Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

Lightweight template engine. + More...

+
+ + Inheritance diagram for Preview:
+
+
+ + + + + + + + + + + + + + + + +

+Public Member Functions

 token ($str)
 
 resolve ($str, array $hive=NULL)
 
 render ($file, $mime='text/html', array $hive=NULL, $ttl=0)
 
- Public Member Functions inherited from View
 esc ($arg)
 
 raw ($arg)
 
 render ($file, $mime='text/html', array $hive=NULL, $ttl=0)
 
+ + + + + + +

+Protected Member Functions

 build ($node)
 
- Protected Member Functions inherited from View
 sandbox (array $hive=NULL)
 
+ + + + + + + + +

+Protected Attributes

$mime
 MIME type.
 
- Protected Attributes inherited from View
$view
 Template file.
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

Lightweight template engine.

+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + +
Preview::build ( $node)
+
+protected
+
+

Assemble markup

+
Returns
string
+
Parameters
+ + +
$nodestring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Preview::render ( $file,
 $mime = 'text/html',
array $hive = NULL,
 $ttl = 0 
)
+
+

Render template

+
Returns
string
+
Parameters
+ + + + + +
$filestring
$mimestring
$hivearray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Preview::resolve ( $str,
array $hive = NULL 
)
+
+

Render template string

+
Returns
string
+
Parameters
+ + + +
$strstring
$hivearray
+
+
+ +
+
+ +
+
+ + + + + + + + +
Preview::token ( $str)
+
+

Convert token to variable

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • base.php
  • +
+
diff --git a/lib/f3/api/classPreview.png b/lib/f3/api/classPreview.png new file mode 100755 index 0000000000000000000000000000000000000000..1f60c748937e65cad81607d448936b245e8b9355 GIT binary patch literal 619 zcmV-x0+juUP)G5kltoJRF7*4vMBI)a^7~83e>%B$LI{VqlOYgni-E#yn`hDHIdfD{oH_u+? zFr_;+w@)|ol5~fuOOlJnbu%+J06i7}KV$l`4EbaF%O3Fu^@lS*bpRhz2XHZU02fmS zaPiZ+nVBCqN__%pK9={c@R<U*+m^y%qpVmVN!4Cnz%hdBL0JzfJ;;eTk0$i!-TVISMu~lowsjsc)dAT~) zZR-2k-?zQCPFt3{=Lq)bcQ1B)s~6+hSf2~0t>;(qmbCnOT6)TSkn1Q4`+Vr06wM;;9}|kE~XCP;-_^pvkr@ySsP4}yi8pR@sgw( zd7zwf+P&%C(PIcS^w4d@Wlet+bCEt)70B(&z_0Ca|XGk(}h(?r#B9 zTOZDTlzV4CGJljJ^YO8oc}cp^`!f9Zx+Hb@ + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Registry Member List
+
+
+ +

This is the complete list of members for Registry, including all inherited members.

+ + + + + +
clear($key)Registrystatic
exists($key)Registrystatic
get($key)Registrystatic
set($key, $obj)Registrystatic
diff --git a/lib/f3/api/classRegistry.html b/lib/f3/api/classRegistry.html new file mode 100755 index 0000000..474b9b2 --- /dev/null +++ b/lib/f3/api/classRegistry.html @@ -0,0 +1,201 @@ + + + + + + + +Fat-Free Framework: Registry Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+ +
+
Registry Class Reference
+
+
+ +

Container for singular object instances. + More...

+ + + + + + + + + + +

+Static Public Member Functions

static exists ($key)
 
static set ($key, $obj)
 
static get ($key)
 
static clear ($key)
 
+

Detailed Description

+

Container for singular object instances.

+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + +
static Registry::clear ( $key)
+
+static
+
+

Delete object from catalog

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
static Registry::exists ( $key)
+
+static
+
+

Return TRUE if object exists in catalog

+
Returns
bool
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
static Registry::get ( $key)
+
+static
+
+

Retrieve object from catalog

+
Returns
object
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
static Registry::set ( $key,
 $obj 
)
+
+static
+
+

Add object to catalog

+
Returns
object
+
Parameters
+ + + +
$keystring
$objobject
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • base.php
  • +
+
diff --git a/lib/f3/api/classSMTP-members.html b/lib/f3/api/classSMTP-members.html new file mode 100755 index 0000000..c823a3a --- /dev/null +++ b/lib/f3/api/classSMTP-members.html @@ -0,0 +1,70 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
SMTP Member List
+
+
+ +

This is the complete list of members for SMTP, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$attachmentsSMTP
$hostSMTP
$logSMTP
$portSMTP
$pwSMTP
$schemeSMTP
$socketSMTP
$userSMTP
__construct($host, $port, $scheme, $user, $pw)SMTP
__get($key)Magic
__isset($key)Magic
__set($key, $val)Magic
__unset($key)Magic
attach($file)SMTP
clear($key)SMTP
dialog($cmd=NULL, $log=TRUE)SMTPprotected
E_Attach (defined in SMTP)SMTP
E_Blank (defined in SMTP)SMTP
E_Header (defined in SMTP)SMTP
exists($key)SMTP
fixheader($key)SMTPprotected
get($key)SMTP
log()SMTP
offsetexists($key)Magic
offsetget($key)Magic
offsetset($key, $val)Magic
offsetunset($key)Magic
send($message, $log=TRUE)SMTP
set($key, $val)SMTP
diff --git a/lib/f3/api/classSMTP.html b/lib/f3/api/classSMTP.html new file mode 100755 index 0000000..7fb6d1c --- /dev/null +++ b/lib/f3/api/classSMTP.html @@ -0,0 +1,474 @@ + + + + + + + +Fat-Free Framework: SMTP Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

SMTP plug-in. + More...

+
+ + Inheritance diagram for SMTP:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 log ()
 
 attach ($file)
 
 send ($message, $log=TRUE)
 
 __construct ($host, $port, $scheme, $user, $pw)
 
- Public Member Functions inherited from Magic
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 offsetexists ($key)
 
 __isset ($key)
 
 offsetset ($key, $val)
 
 __set ($key, $val)
 
 offsetget ($key)
 
 __get ($key)
 
 offsetunset ($key)
 
 __unset ($key)
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Attributes

$attachments
 E-mail attachments.
 
$host
 SMTP host.
 
$port
 SMTP port.
 
$scheme
 TLS/SSL.
 
$user
 User ID.
 
$pw
 Password.
 
$socket
 TCP/IP socket.
 
$log
 Server-client conversation.
 
+const E_Header ='%s: header is required'
 
+const E_Blank ='Message must not be blank'
 
+const E_Attach ='Attachment %s not found'
 
+ + + + + +

+Protected Member Functions

 fixheader ($key)
 
 dialog ($cmd=NULL, $log=TRUE)
 
+

Detailed Description

+

SMTP plug-in.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SMTP::__construct ( $host,
 $port,
 $scheme,
 $user,
 $pw 
)
+
+

Instantiate class

+
Parameters
+ + + + + + +
$hoststring
$portint
$schemestring
$userstring
$pwstring
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
SMTP::attach ( $file)
+
+

Add e-mail attachment

+
Returns
NULL
+
Parameters
+ + +
$file
+
+
+ +
+
+ +
+
+ + + + + + + + +
SMTP::clear ( $key)
+
+

Remove header

+
Returns
NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
SMTP::dialog ( $cmd = NULL,
 $log = TRUE 
)
+
+protected
+
+

Send SMTP command and record server response

+
Returns
NULL
+
Parameters
+ + + +
$cmdstring
$logbool
+
+
+ +
+
+ +
+
+ + + + + + + + +
SMTP::exists ( $key)
+
+

Return TRUE if header exists

+
Returns
bool
+
Parameters
+ + +
$key
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
SMTP::fixheader ( $key)
+
+protected
+
+

Fix header

+
Returns
string
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
SMTP::get ( $key)
+
+

Return value of e-mail header

+
Returns
string|NULL
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + +
SMTP::log ()
+
+

Return client-server conversation history

+
Returns
string
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
SMTP::send ( $message,
 $log = TRUE 
)
+
+

Transmit message

+
Returns
bool
+
Parameters
+ + + +
$messagestring
$logbool
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
SMTP::set ( $key,
 $val 
)
+
+

Bind value to e-mail header

+
Returns
string
+
Parameters
+ + + +
$keystring
$valstring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • smtp.php
  • +
+
diff --git a/lib/f3/api/classSMTP.png b/lib/f3/api/classSMTP.png new file mode 100755 index 0000000000000000000000000000000000000000..87f91c4688719ad3af4842948ac69ca037290784 GIT binary patch literal 544 zcmV+*0^j|KP)C=lwk31bS`~NsYu(th zUbPO`xNGmhJd`iYZb{*)C*AIm=9VA2L@pK~`}p9(YcaE4uqALip+s}5%7PA=vl09lGHmGkKsbA*_v%&Ndz?(6o0x#j{W&0KTM1%Ni@n)@>@5s^Yb03aT7zv+gBT?XaB>td%f z0MN~;8&1uKM8vW=06-_#ZU*Jt42D5zsDzv3j{C3qT_+>7SO;$P#=7abITCKYe??sY icouWb{g6vUB%eP7MMO!Gu;3{G0000Jb literal 0 HcmV?d00001 diff --git a/lib/f3/api/classSession-members.html b/lib/f3/api/classSession-members.html new file mode 100755 index 0000000..4faba38 --- /dev/null +++ b/lib/f3/api/classSession-members.html @@ -0,0 +1,52 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Session Member List
+
+
+ +

This is the complete list of members for Session, including all inherited members.

+ + + + + + + + + + + + +
__construct()Session
agent($id=NULL)Session
cleanup($max)Session
close()Session
csrf($id=NULL)Session
destroy($id)Session
ip($id=NULL)Session
open($path, $name)Session
read($id)Session
stamp($id=NULL)Session
write($id, $data)Session
diff --git a/lib/f3/api/classSession.html b/lib/f3/api/classSession.html new file mode 100755 index 0000000..85752d9 --- /dev/null +++ b/lib/f3/api/classSession.html @@ -0,0 +1,349 @@ + + + + + + + +Fat-Free Framework: Session Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+ +
+
Session Class Reference
+
+
+ +

Cache-based session handler. + More...

+ + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 open ($path, $name)
 
 close ()
 
 read ($id)
 
 write ($id, $data)
 
 destroy ($id)
 
 cleanup ($max)
 
 csrf ($id=NULL)
 
 ip ($id=NULL)
 
 stamp ($id=NULL)
 
 agent ($id=NULL)
 
 __construct ()
 
+

Detailed Description

+

Cache-based session handler.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + +
Session::__construct ()
+
+

Instantiate class

+
Returns
object
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
Session::agent ( $id = NULL)
+
+

Return HTTP user agent associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Session::cleanup ( $max)
+
+

Garbage collector

+
Returns
TRUE
+
Parameters
+ + +
$maxint
+
+
+ +
+
+ +
+
+ + + + + + + +
Session::close ()
+
+

Close session

+
Returns
TRUE
+ +
+
+ +
+
+ + + + + + + + +
Session::csrf ( $id = NULL)
+
+

Return anti-CSRF tokan associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Session::destroy ( $id)
+
+

Destroy session

+
Returns
TRUE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Session::ip ( $id = NULL)
+
+

Return IP address associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Session::open ( $path,
 $name 
)
+
+

Open session

+
Returns
TRUE
+
Parameters
+ + + +
$pathstring
$namestring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Session::read ( $id)
+
+

Return session data in serialized format

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Session::stamp ( $id = NULL)
+
+

Return Unix timestamp associated with specified session ID

+
Returns
string|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Session::write ( $id,
 $data 
)
+
+

Write session data

+
Returns
TRUE
+
Parameters
+ + + +
$idstring
$datastring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • session.php
  • +
+
diff --git a/lib/f3/api/classTemplate-members.html b/lib/f3/api/classTemplate-members.html new file mode 100755 index 0000000..209a4fb --- /dev/null +++ b/lib/f3/api/classTemplate-members.html @@ -0,0 +1,70 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Template Member List
+
+
+ +

This is the complete list of members for Template, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$customTemplate
$mimePreviewprotected
$tagsTemplateprotected
$viewViewprotected
__call($func, array $args)Template
__construct()Template
_case(array $node)Templateprotected
_check(array $node)Templateprotected
_default(array $node)Templateprotected
_exclude()Templateprotected
_false(array $node)Templateprotected
_ignore(array $node)Templateprotected
_include(array $node)Templateprotected
_loop(array $node)Templateprotected
_repeat(array $node)Templateprotected
_set(array $node)Templateprotected
_switch(array $node)Templateprotected
_true(array $node)Templateprotected
build($node)Templateprotected
E_Method (defined in Template)Template
esc($arg)View
extend($tag, $func)Template
instance()Prefabstatic
parse($text)Template
raw($arg)View
render($file, $mime='text/html', array $hive=NULL, $ttl=0)Preview
resolve($str, array $hive=NULL)Preview
sandbox(array $hive=NULL)Viewprotected
token($str)Preview
diff --git a/lib/f3/api/classTemplate.html b/lib/f3/api/classTemplate.html new file mode 100755 index 0000000..c59a2ee --- /dev/null +++ b/lib/f3/api/classTemplate.html @@ -0,0 +1,681 @@ + + + + + + + +Fat-Free Framework: Template Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

XML-style template engine. + More...

+
+ + Inheritance diagram for Template:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 extend ($tag, $func)
 
 __call ($func, array $args)
 
 parse ($text)
 
 __construct ()
 
- Public Member Functions inherited from Preview
 token ($str)
 
 resolve ($str, array $hive=NULL)
 
 render ($file, $mime='text/html', array $hive=NULL, $ttl=0)
 
- Public Member Functions inherited from View
 esc ($arg)
 
 raw ($arg)
 
 render ($file, $mime='text/html', array $hive=NULL, $ttl=0)
 
+ + + + + + + +

+Public Attributes

$custom =array()
 Custom tag handlers.
 
+const E_Method ='Call to undefined method %s()'
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Protected Member Functions

 _set (array $node)
 
 _include (array $node)
 
 _exclude ()
 
 _ignore (array $node)
 
 _loop (array $node)
 
 _repeat (array $node)
 
 _check (array $node)
 
 _true (array $node)
 
 _false (array $node)
 
 _switch (array $node)
 
 _case (array $node)
 
 _default (array $node)
 
 build ($node)
 
- Protected Member Functions inherited from Preview
 build ($node)
 
- Protected Member Functions inherited from View
 sandbox (array $hive=NULL)
 
+ + + + + + + + + + + + +

+Protected Attributes

$tags
 Template tags.
 
- Protected Attributes inherited from Preview
$mime
 MIME type.
 
- Protected Attributes inherited from View
$view
 Template file.
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

XML-style template engine.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + +
Template::__construct ()
+
+

Class constructor return object

+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
Template::__call ( $func,
array $args 
)
+
+

Call custom tag handler

+
Returns
string|FALSE
+
Parameters
+ + + +
$funccallback
$argsarray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::_case (array $node)
+
+protected
+
+

Template -case- tag handler

+
Returns
string
+
Parameters
+ + +
$nodearray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::_check (array $node)
+
+protected
+
+

Template -check- tag handler

+
Returns
string
+
Parameters
+ + +
$nodearray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::_default (array $node)
+
+protected
+
+

Template -default- tag handler

+
Returns
string
+
Parameters
+ + +
$nodearray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + +
Template::_exclude ()
+
+protected
+
+

Template -exclude- tag handler

+
Returns
string
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::_false (array $node)
+
+protected
+
+

Template -false- tag handler

+
Returns
string
+
Parameters
+ + +
$nodearray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::_ignore (array $node)
+
+protected
+
+

Template -ignore- tag handler

+
Returns
string
+
Parameters
+ + +
$nodearray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::_include (array $node)
+
+protected
+
+

Template -include- tag handler

+
Returns
string
+
Parameters
+ + +
$nodearray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::_loop (array $node)
+
+protected
+
+

Template -loop- tag handler

+
Returns
string
+
Parameters
+ + +
$nodearray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::_repeat (array $node)
+
+protected
+
+

Template -repeat- tag handler

+
Returns
string
+
Parameters
+ + +
$nodearray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::_set (array $node)
+
+protected
+
+

Template -set- tag handler

+
Returns
string
+
Parameters
+ + +
$nodearray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::_switch (array $node)
+
+protected
+
+

Template -switch- tag handler

+
Returns
string
+
Parameters
+ + +
$nodearray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::_true (array $node)
+
+protected
+
+

Template -true- tag handler

+
Returns
string
+
Parameters
+ + +
$nodearray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Template::build ( $node)
+
+protected
+
+

Assemble markup

+
Returns
string
+
Parameters
+ + +
$nodearray|string
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Template::extend ( $tag,
 $func 
)
+
+

Extend template with custom tag

+
Returns
NULL
+
Parameters
+ + + +
$tagstring
$funccallback
+
+
+ +
+
+ +
+
+ + + + + + + + +
Template::parse ( $text)
+
+

Parse string for template directives and tokens

+
Returns
string|array
+
Parameters
+ + +
$textstring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • template.php
  • +
+
diff --git a/lib/f3/api/classTemplate.png b/lib/f3/api/classTemplate.png new file mode 100755 index 0000000000000000000000000000000000000000..0a9456fd513545cc525b180896bb5e23b302532b GIT binary patch literal 618 zcmV-w0+s!VP)9Hvlar06%^DGeLkDm%bO0Aa z2XOJzx|x|DOp?3|UDBq7wT}Zyx}vE|Qk!b>vzZAgjTK3y-Rbexsh1{c+v=5%`z^+N zb?7CKf|5$Rc<;M+cX{%AJy!myE=k`obV+jYx^8CX2B5{OKT^}w<@f0yyT|X;U#|Sn z0elP{z{Su3Tnrt+#ZT*IW_~b9@-p=03iBmNXD-5fy*W{m&eZfU_c4>ia+?F2*tK5f zm0Mo-QeV%0-1a=mM?CIcGFY=;y%_jb&*M!V>2r+T>g81&idJ6Fm7XfUE9kB;<6q{F z>t<$d09w5IBQ;H3exLrad;CuQ<;o8oz{k)5Tnrt+#n1s<{IniI2!03vUWT6Q4^X2# z*iYH)-b&+ZJ*KdP(;(i`lhRf7Gbtm)-RDROQ1Lju*& z&DnE%cJ^HP+;)|ZAFGuIIC1lx{J(X827g=+Ap|%70EnF^7lfrwivR!s07*qoM6N<$ Eg3=@~%m4rY literal 0 HcmV?d00001 diff --git a/lib/f3/api/classTest-members.html b/lib/f3/api/classTest-members.html new file mode 100755 index 0000000..aabba58 --- /dev/null +++ b/lib/f3/api/classTest-members.html @@ -0,0 +1,48 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Test Member List
+
+
+ +

This is the complete list of members for Test, including all inherited members.

+ + + + + + + + +
__construct($level=self::FLAG_Both)Test
expect($cond, $text=NULL)Test
FLAG_Both (defined in Test)Test
FLAG_False (defined in Test)Test
FLAG_True (defined in Test)Test
message($text)Test
results()Test
diff --git a/lib/f3/api/classTest.html b/lib/f3/api/classTest.html new file mode 100755 index 0000000..e68c4b1 --- /dev/null +++ b/lib/f3/api/classTest.html @@ -0,0 +1,176 @@ + + + + + + + +Fat-Free Framework: Test Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+ +
+
Test Class Reference
+
+
+ +

Unit test kit. + More...

+ + + + + + + + + + +

+Public Member Functions

 results ()
 
 expect ($cond, $text=NULL)
 
 message ($text)
 
 __construct ($level=self::FLAG_Both)
 
+ + + + + + + + +

+Public Attributes

+const FLAG_False =0
 
+const FLAG_True =1
 
+const FLAG_Both =2
 
+

Detailed Description

+

Unit test kit.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
Test::__construct ( $level = self::FLAG_Both)
+
+

Class constructor

+
Returns
NULL
+
Parameters
+ + +
$levelint
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
Test::expect ( $cond,
 $text = NULL 
)
+
+

Evaluate condition and save test result

+
Returns
object
+
Parameters
+ + + +
$condbool
$textstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Test::message ( $text)
+
+

Append message to test results

+
Returns
NULL
+
Parameters
+ + +
$textstring
+
+
+ +
+
+ +
+
+ + + + + + + +
Test::results ()
+
+

Return test results

+
Returns
array
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • test.php
  • +
+
diff --git a/lib/f3/api/classUTF-members.html b/lib/f3/api/classUTF-members.html new file mode 100755 index 0000000..5ec47c0 --- /dev/null +++ b/lib/f3/api/classUTF-members.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
UTF Member List
+
+
+ +

This is the complete list of members for UTF, including all inherited members.

+ + + + + + + + + + + + + + + + +
bom()UTF
emojify($str)UTF
instance()Prefabstatic
ltrim($str)UTF
rtrim($str)UTF
stripos($stack, $needle, $ofs=0)UTF
stristr($stack, $needle, $before=FALSE)UTF
strlen($str)UTF
strpos($stack, $needle, $ofs=0, $case=FALSE)UTF
strrev($str)UTF
strstr($stack, $needle, $before=FALSE, $case=FALSE)UTF
substr($str, $start, $len=0)UTF
substr_count($stack, $needle)UTF
translate($str)UTF
trim($str)UTF
diff --git a/lib/f3/api/classUTF.html b/lib/f3/api/classUTF.html new file mode 100755 index 0000000..e61e964 --- /dev/null +++ b/lib/f3/api/classUTF.html @@ -0,0 +1,543 @@ + + + + + + + +Fat-Free Framework: UTF Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+ +
+
UTF Class Reference
+
+
+ +

Unicode string manager. + More...

+
+ + Inheritance diagram for UTF:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 strlen ($str)
 
 strrev ($str)
 
 stripos ($stack, $needle, $ofs=0)
 
 strpos ($stack, $needle, $ofs=0, $case=FALSE)
 
 stristr ($stack, $needle, $before=FALSE)
 
 strstr ($stack, $needle, $before=FALSE, $case=FALSE)
 
 substr ($str, $start, $len=0)
 
 substr_count ($stack, $needle)
 
 ltrim ($str)
 
 rtrim ($str)
 
 trim ($str)
 
 bom ()
 
 translate ($str)
 
 emojify ($str)
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

Unicode string manager.

+

Member Function Documentation

+ +
+
+ + + + + + + +
UTF::bom ()
+
+

Return UTF-8 byte order mark

+
Returns
string
+ +
+
+ +
+
+ + + + + + + + +
UTF::emojify ( $str)
+
+

Translate emoji tokens to Unicode font-supported symbols

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
UTF::ltrim ( $str)
+
+

Strip whitespaces from the beginning of a string

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
UTF::rtrim ( $str)
+
+

Strip whitespaces from the end of a string

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
UTF::stripos ( $stack,
 $needle,
 $ofs = 0 
)
+
+

Find position of first occurrence of a string (case-insensitive)

+
Returns
int|FALSE
+
Parameters
+ + + + +
$stackstring
$needlestring
$ofsint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
UTF::stristr ( $stack,
 $needle,
 $before = FALSE 
)
+
+

Returns part of haystack string from the first occurrence of needle to the end of haystack (case-insensitive)

+
Returns
string|FALSE
+
Parameters
+ + + + +
$stackstring
$needlestring
$beforebool
+
+
+ +
+
+ +
+
+ + + + + + + + +
UTF::strlen ( $str)
+
+

Get string length

+
Returns
int
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UTF::strpos ( $stack,
 $needle,
 $ofs = 0,
 $case = FALSE 
)
+
+

Find position of first occurrence of a string

+
Returns
int|FALSE
+
Parameters
+ + + + + +
$stackstring
$needlestring
$ofsint
$casebool
+
+
+ +
+
+ +
+
+ + + + + + + + +
UTF::strrev ( $str)
+
+

Reverse a string

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UTF::strstr ( $stack,
 $needle,
 $before = FALSE,
 $case = FALSE 
)
+
+

Returns part of haystack string from the first occurrence of needle to the end of haystack

+
Returns
string|FALSE
+
Parameters
+ + + + + +
$stackstring
$needlestring
$beforebool
$casebool
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
UTF::substr ( $str,
 $start,
 $len = 0 
)
+
+

Return part of a string

+
Returns
string|FALSE
+
Parameters
+ + + + +
$strstring
$startint
$lenint
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
UTF::substr_count ( $stack,
 $needle 
)
+
+

Count the number of substring occurrences

+
Returns
int
+
Parameters
+ + + +
$stackstring
$needlestring
+
+
+ +
+
+ +
+
+ + + + + + + + +
UTF::translate ( $str)
+
+

Convert code points to Unicode symbols

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
UTF::trim ( $str)
+
+

Strip whitespaces from the beginning and end of a string

+
Returns
string
+
Parameters
+ + +
$strstring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • utf.php
  • +
+
diff --git a/lib/f3/api/classUTF.png b/lib/f3/api/classUTF.png new file mode 100755 index 0000000000000000000000000000000000000000..2d2df3328c1b0d30f4fb1efe1fb7e4a7d75cb7d9 GIT binary patch literal 316 zcmeAS@N?(olHy`uVBq!ia0vp^MnD|E!3-pG?q0hDq$C1-LR|m<{|{uod-rb6oH-MK zEHFNB;J^pRRC^$oqa?^Lm;tB=1g@S60U2`I)5S5Qg7NL#Y`$g%0k-sV;rI1Vv^);F zOWW1YxVC`DzrD4WT|vpIxu86}VoB2J$M0qbrO#Tr>Wx_0;q_g*rCl=)uPg1XSfnHW z{NJr7w)ZCXm1pi>y6Ek*K%R3jAhwoVC z;^M(D$CxqW#VM1Mee2G&y^0CQJ9Q&~L8Xmpfq@7^>q3S(32Dn388vJoJr`GQdZK3T zpesMcmvzfi^C^!*|2@}x`Ndi?9ZuWo63G^0&r>mdKI;Vst E0C53@wg3PC literal 0 HcmV?d00001 diff --git a/lib/f3/api/classView-members.html b/lib/f3/api/classView-members.html new file mode 100755 index 0000000..bf5552a --- /dev/null +++ b/lib/f3/api/classView-members.html @@ -0,0 +1,47 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
View Member List
+
+
+ +

This is the complete list of members for View, including all inherited members.

+ + + + + + + +
$viewViewprotected
esc($arg)View
instance()Prefabstatic
raw($arg)View
render($file, $mime='text/html', array $hive=NULL, $ttl=0)View
sandbox(array $hive=NULL)Viewprotected
diff --git a/lib/f3/api/classView.html b/lib/f3/api/classView.html new file mode 100755 index 0000000..8ccfba8 --- /dev/null +++ b/lib/f3/api/classView.html @@ -0,0 +1,222 @@ + + + + + + + +Fat-Free Framework: View Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

View handler. + More...

+
+ + Inheritance diagram for View:
+
+
+ + + + + + + + + +

+Public Member Functions

 esc ($arg)
 
 raw ($arg)
 
 render ($file, $mime='text/html', array $hive=NULL, $ttl=0)
 
+ + + +

+Protected Member Functions

 sandbox (array $hive=NULL)
 
+ + + + +

+Protected Attributes

$view
 Template file.
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

View handler.

+

Member Function Documentation

+ +
+
+ + + + + + + + +
View::esc ( $arg)
+
+

Encode characters to equivalent HTML entities

+
Returns
string
+
Parameters
+ + +
$argmixed
+
+
+ +
+
+ +
+
+ + + + + + + + +
View::raw ( $arg)
+
+

Decode HTML entities to equivalent characters

+
Returns
string
+
Parameters
+ + +
$argmixed
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
View::render ( $file,
 $mime = 'text/html',
array $hive = NULL,
 $ttl = 0 
)
+
+

Render template

+
Returns
string
+
Parameters
+ + + + + +
$filestring
$mimestring
$hivearray
$ttlint
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
View::sandbox (array $hive = NULL)
+
+protected
+
+

Create sandbox for template execution

+
Returns
string
+
Parameters
+ + +
$hivearray
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • base.php
  • +
+
diff --git a/lib/f3/api/classView.png b/lib/f3/api/classView.png new file mode 100755 index 0000000000000000000000000000000000000000..2e24d19efd8305cfca0ef29cd4f74edd7884f4aa GIT binary patch literal 623 zcmV-#0+9WQP)n!%+7gN-51mamwZ`N1T~OV`&UOoyah%aPO6 zQ7_!Ix%^lU(|OJ$rjyQ_OzQe1#&PQ6dWQ_I_P%xU(o3}Z^qfJ=ep&aaz8`w@hkM`G zFqJzE=f7&@CFu!Wmn0Xj>t<$d0BQ^Xe%kb5X!6_i(Qfe@^_MH(bpRh-2XN7K02f^c zaPif82qE|(0C?#-uxT+ep6^$#>Hu|$$xoq`@!jqMKyG(>>>BmlfNd*RK1C;E{$=|0 z94J@0SmE8fyWIJ`9xMM;2l#}p1Gsoy4dti{GffT=}j8_~<%- zi>?E>=sJLluhz}XDhy_3*I<(5rR(z%rbCj>T!i;}^+riLQ_{n9j+rFpZVGH-*LuD$ zck8;B`m*=qW6z^?i^r$u43_K{F9tr<*YPHgbRA>2dVUp$qUG0frKig83c4#y|Cjl3 z-OS7lK#f;FQp3>Xx9OwZ;y3CqSH9~2KDrLzqU!)Ix(?vtt93K83WJ&1HJBuM>ADo+ zAxS0j#Qv7e(=Xj8dQ2fqS7{KtG?Pz7J>5IbPi-Egm6n-xRMXE=n!V9u0ZV$G$we+b z{g6O$bhG!hJ=^t<$d{s8enCym7^4Y&XR002ov JPDHLkV1nzNGUosQ literal 0 HcmV?d00001 diff --git a/lib/f3/api/classWeb-members.html b/lib/f3/api/classWeb-members.html new file mode 100755 index 0000000..71422e6 --- /dev/null +++ b/lib/f3/api/classWeb-members.html @@ -0,0 +1,59 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Web Member List
+
+
+ +

This is the complete list of members for Web, including all inherited members.

+ + + + + + + + + + + + + + + + + + + +
_curl($url, $options)Webprotected
_socket($url, $options)Webprotected
_stream($url, $options)Webprotected
acceptable($list=NULL)Web
E_Request (defined in Web)Web
engine($arg='curl')Web
filler($count=1, $max=20, $std=TRUE)Web
instance()Prefabstatic
mime($file)Web
minify($files, $mime=NULL, $header=TRUE, $path='')Web
progress($id)Web
receive($func=NULL, $overwrite=FALSE, $slug=TRUE)Web
request($url, array $options=NULL)Web
rss($url, $max=10, $tags=NULL)Web
send($file, $mime=NULL, $kbps=0, $force=TRUE)Web
slug($text)Web
subst(array &$old, $new)Web
whois($addr, $server='whois.internic.net')Web
diff --git a/lib/f3/api/classWeb.html b/lib/f3/api/classWeb.html new file mode 100755 index 0000000..488bdcf --- /dev/null +++ b/lib/f3/api/classWeb.html @@ -0,0 +1,692 @@ + + + + + + + +Fat-Free Framework: Web Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+ +
+ +

Wrapper for various HTTP utilities. + More...

+
+ + Inheritance diagram for Web:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 mime ($file)
 
 acceptable ($list=NULL)
 
 send ($file, $mime=NULL, $kbps=0, $force=TRUE)
 
 receive ($func=NULL, $overwrite=FALSE, $slug=TRUE)
 
 progress ($id)
 
 engine ($arg='curl')
 
 subst (array &$old, $new)
 
 request ($url, array $options=NULL)
 
 minify ($files, $mime=NULL, $header=TRUE, $path='')
 
 rss ($url, $max=10, $tags=NULL)
 
 whois ($addr, $server='whois.internic.net')
 
 slug ($text)
 
 filler ($count=1, $max=20, $std=TRUE)
 
+ + + + +

+Public Attributes

+const E_Request ='No suitable HTTP request engine found'
 
+ + + + + + + +

+Protected Member Functions

 _curl ($url, $options)
 
 _stream ($url, $options)
 
 _socket ($url, $options)
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

Wrapper for various HTTP utilities.

+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Web::_curl ( $url,
 $options 
)
+
+protected
+
+

HTTP request via cURL

+
Returns
array
+
Parameters
+ + + +
$urlstring
$optionsarray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Web::_socket ( $url,
 $options 
)
+
+protected
+
+

HTTP request via low-level TCP/IP socket

+
Returns
array
+
Parameters
+ + + +
$urlstring
$optionsarray
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Web::_stream ( $url,
 $options 
)
+
+protected
+
+

HTTP request via PHP stream wrapper

+
Returns
array
+
Parameters
+ + + +
$urlstring
$optionsarray
+
+
+ +
+
+ +
+
+ + + + + + + + +
Web::acceptable ( $list = NULL)
+
+

Return the MIME types stated in the HTTP Accept header as an array; If a list of MIME types is specified, return the best match; or FALSE if none found

+
Returns
array|string|FALSE
+
Parameters
+ + +
$liststring|array
+
+
+ +
+
+ +
+
+ + + + + + + + +
Web::engine ( $arg = 'curl')
+
+

Specify the HTTP request engine to use; If not available, fall back to an applicable substitute

+
Returns
string
+
Parameters
+ + +
$argstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Web::filler ( $count = 1,
 $max = 20,
 $std = TRUE 
)
+
+

Return chunk of text from standard Lorem Ipsum passage

+
Returns
string
+
Parameters
+ + + + +
$countint
$maxint
$stdbool
+
+
+ +
+
+ +
+
+ + + + + + + + +
Web::mime ( $file)
+
+

Detect MIME type using file extension

+
Returns
string
+
Parameters
+ + +
$filestring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Web::minify ( $files,
 $mime = NULL,
 $header = TRUE,
 $path = '' 
)
+
+

Strip Javascript/CSS files of extraneous whitespaces and comments; Return combined output as a minified string

+
Returns
string
+
Parameters
+ + + + + +
$filesstring|array
$mimestring
$headerbool
$pathstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Web::progress ( $id)
+
+

Return upload progress in bytes, FALSE on failure

+
Returns
int|FALSE
+
Parameters
+ + +
$idstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Web::receive ( $func = NULL,
 $overwrite = FALSE,
 $slug = TRUE 
)
+
+

Receive file(s) from HTTP client

+
Returns
array|bool
+
Parameters
+ + + + +
$funccallback
$overwritebool
$slugcallback|bool
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Web::request ( $url,
array $options = NULL 
)
+
+

Submit HTTP request; Use HTTP context options (described in http://www.php.net/manual/en/context.http.php) if specified; Cache the page as instructed by remote server

+
Returns
array|FALSE
+
Parameters
+ + + +
$urlstring
$optionsarray
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Web::rss ( $url,
 $max = 10,
 $tags = NULL 
)
+
+

Retrieve RSS feed and return as an array

+
Returns
array|FALSE
+
Parameters
+ + + + +
$urlstring
$maxint
$tagsstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Web::send ( $file,
 $mime = NULL,
 $kbps = 0,
 $force = TRUE 
)
+
+

Transmit file to HTTP client; Return file size if successful, FALSE otherwise

+
Returns
int|FALSE
+
Parameters
+ + + + + +
$filestring
$mimestring
$kbpsint
$forcebool
+
+
+ +
+
+ +
+
+ + + + + + + + +
Web::slug ( $text)
+
+

Return a URL/filesystem-friendly version of string

+
Returns
string
+
Parameters
+ + +
$textstring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Web::subst (array & $old,
 $new 
)
+
+

Replace old headers with new elements

+
Returns
NULL
+
Parameters
+ + + +
$oldarray
$newstring|array
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Web::whois ( $addr,
 $server = 'whois.internic.net' 
)
+
+

Retrieve information from whois server

+
Returns
string|FALSE
+
Parameters
+ + + +
$addrstring
$serverstring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • web.php
  • +
+
diff --git a/lib/f3/api/classWeb.png b/lib/f3/api/classWeb.png new file mode 100755 index 0000000000000000000000000000000000000000..c446b303fc8f29de60611e5064eef6111aaeb5a9 GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^MnD|E!3-pG?q0hDq$C1-LR|m<{|{uod-rb6oH-MK zEHFNB;J^pRRC^$oqa?^Lm;tB=1g@S60U7ex)5S5Qg7NL#*uKLGJZ#6eP5CWf$=%ZG zaOIQh>e>|^GpES&vu$TrP;zQ6C=dVPb@bBXchj$>?OM8whx_n{wMj4M8c*Bue0S=e zz@UPc^W#(d@B4g?{k5ZPm6dgB=FC$kU&U#k+PZs{&Yh=0=c1Nvo^2m|^v>PuH@bH3 zK4h$_~tF2Cn!uOB|P; zWr+P9t@@YAGGW89-Fw`YhE6hQJM-8meCo@B{3(C#M+8Kjuw1X@UH-BxcCEw#_H9fH fKKK|KPyWFe6VIKo=~E&o2pBwF{an^LB{Ts56!w++ literal 0 HcmV?d00001 diff --git a/lib/f3/api/classWeb_1_1Geo-members.html b/lib/f3/api/classWeb_1_1Geo-members.html new file mode 100755 index 0000000..b582d2a --- /dev/null +++ b/lib/f3/api/classWeb_1_1Geo-members.html @@ -0,0 +1,49 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
Web\Geo Member List
+
+
+ +

This is the complete list of members for Web\Geo, including all inherited members.

+ + + + + +
instance()Prefabstatic
location($ip=NULL)Web\Geo
tzinfo($zone)Web\Geo
weather($latitude, $longitude)Web\Geo
diff --git a/lib/f3/api/classWeb_1_1Geo.html b/lib/f3/api/classWeb_1_1Geo.html new file mode 100755 index 0000000..f3c3fa5 --- /dev/null +++ b/lib/f3/api/classWeb_1_1Geo.html @@ -0,0 +1,164 @@ + + + + + + + +Fat-Free Framework: Web\Geo Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+ +
+
Web\Geo Class Reference
+
+
+ +

Geo plug-in. + More...

+
+ + Inheritance diagram for Web\Geo:
+
+
+ + + + + + + + + +

+Public Member Functions

 tzinfo ($zone)
 
 location ($ip=NULL)
 
 weather ($latitude, $longitude)
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

Geo plug-in.

+

Member Function Documentation

+ +
+
+ + + + + + + + +
Web\Geo::location ( $ip = NULL)
+
+

Return geolocation data based on specified/auto-detected IP address

+
Returns
array|FALSE
+
Parameters
+ + +
$ipstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Web\Geo::tzinfo ( $zone)
+
+

Return information about specified Unix time zone

+
Returns
array
+
Parameters
+ + +
$zonestring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Web\Geo::weather ( $latitude,
 $longitude 
)
+
+

Return weather data based on specified latitude/longitude

+
Returns
array|FALSE
+
Parameters
+ + + +
$latitudefloat
$longitudefloat
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • web/geo.php
  • +
+
diff --git a/lib/f3/api/classWeb_1_1Geo.png b/lib/f3/api/classWeb_1_1Geo.png new file mode 100755 index 0000000000000000000000000000000000000000..8a65bfaa0e5bf7d92c09b436eabc27ee8e917359 GIT binary patch literal 370 zcmeAS@N?(olHy`uVBq!ia0vp^4nQ2h!3-qlB{r7>DTx4|5ZC|z{{xxt-o2YMXU+s5 z3ycpOIPk$S)gH*@C<*clW&kPzfvcxNj2IXg89iMbLn;{G&J7egtia(SKI7!y{yP#| z61Mm%+s~b*vYPE{=V?|2B_Y9jcMdFeXVpZ*K`}kk9XE)rI`;r&-`t^qj{Z$9f)Od6L5N+u2 zaA5clCe7d?!kQC3L4ftm@8lMP2i&VBG_a^BFmnDdW)KW?QDBG&XOdY^;wx79Pri=% zK%_iVUzyhorY~D+vz)HF=*WLgc>gt9D?8?h{Np6K1@AYk;?@2j++bD4bY;!1mHT?m zzj)Eb=;s~Je1^Ha{d;)9#dTcI8bmXqSQ#P$nCe&^TtqG~d#&SZIub2)92h_hp00i_ I>zopr0I<4{!2kdN literal 0 HcmV?d00001 diff --git a/lib/f3/api/classWeb_1_1Google_1_1StaticMap-members.html b/lib/f3/api/classWeb_1_1Google_1_1StaticMap-members.html new file mode 100755 index 0000000..4bffb19 --- /dev/null +++ b/lib/f3/api/classWeb_1_1Google_1_1StaticMap-members.html @@ -0,0 +1,49 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
Web\Google\StaticMap Member List
+
+
+ +

This is the complete list of members for Web\Google\StaticMap, including all inherited members.

+ + + + + +
$queryWeb\Google\StaticMapprotected
__call($func, array $args)Web\Google\StaticMap
dump()Web\Google\StaticMap
URL_StaticWeb\Google\StaticMap
diff --git a/lib/f3/api/classWeb_1_1Google_1_1StaticMap.html b/lib/f3/api/classWeb_1_1Google_1_1StaticMap.html new file mode 100755 index 0000000..9d39d65 --- /dev/null +++ b/lib/f3/api/classWeb_1_1Google_1_1StaticMap.html @@ -0,0 +1,130 @@ + + + + + + + +Fat-Free Framework: Web\Google\StaticMap Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+ +
+
Web\Google\StaticMap Class Reference
+
+
+ +

Google Static Maps API v2 plug-in. + More...

+ + + + + + +

+Public Member Functions

 __call ($func, array $args)
 
 dump ()
 
+ + + + +

+Public Attributes

+const URL_Static ='http://maps.googleapis.com/maps/api/staticmap'
 API URL.
 
+ + + + +

+Protected Attributes

$query =array()
 Query arguments.
 
+

Detailed Description

+

Google Static Maps API v2 plug-in.

+

Member Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
Web\Google\StaticMap::__call ( $func,
array $args 
)
+
+

Specify API key-value pair via magic call

+
Returns
object
+
Parameters
+ + + +
$funcstring
$argsarray
+
+
+ +
+
+ +
+
+ + + + + + + +
Web\Google\StaticMap::dump ()
+
+

Generate map

+
Returns
string
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • web/google/staticmap.php
  • +
+
diff --git a/lib/f3/api/classWeb_1_1OpenID-members.html b/lib/f3/api/classWeb_1_1OpenID-members.html new file mode 100755 index 0000000..762da7b --- /dev/null +++ b/lib/f3/api/classWeb_1_1OpenID-members.html @@ -0,0 +1,63 @@ + + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
Web\OpenID Member List
+
+
+ +

This is the complete list of members for Web\OpenID, including all inherited members.

+ + + + + + + + + + + + + + + + + + + +
$argsWeb\OpenID
$urlWeb\OpenIDprotected
__get($key)Magic
__isset($key)Magic
__set($key, $val)Magic
__unset($key)Magic
auth($proxy=NULL, $attr=array(), array $reqd=NULL)Web\OpenID
clear($key)Web\OpenID
discover($proxy)Web\OpenIDprotected
exists($key)Web\OpenID
get($key)Web\OpenID
offsetexists($key)Magic
offsetget($key)Magic
offsetset($key, $val)Magic
offsetunset($key)Magic
response()Web\OpenID
set($key, $val)Web\OpenID
verified($proxy=NULL)Web\OpenID
diff --git a/lib/f3/api/classWeb_1_1OpenID.html b/lib/f3/api/classWeb_1_1OpenID.html new file mode 100755 index 0000000..dabaf30 --- /dev/null +++ b/lib/f3/api/classWeb_1_1OpenID.html @@ -0,0 +1,352 @@ + + + + + + + +Fat-Free Framework: Web\OpenID Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+ +
+ +

OpenID consumer. + More...

+
+ + Inheritance diagram for Web\OpenID:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 auth ($proxy=NULL, $attr=array(), array $reqd=NULL)
 
 verified ($proxy=NULL)
 
 response ()
 
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
- Public Member Functions inherited from Magic
 exists ($key)
 
 set ($key, $val)
 
 get ($key)
 
 clear ($key)
 
 offsetexists ($key)
 
 __isset ($key)
 
 offsetset ($key, $val)
 
 __set ($key, $val)
 
 offsetget ($key)
 
 __get ($key)
 
 offsetunset ($key)
 
 __unset ($key)
 
+ + + + +

+Public Attributes

$args =array()
 HTTP request parameters.
 
+ + + +

+Protected Member Functions

 discover ($proxy)
 
+ + + + +

+Protected Attributes

$url
 OpenID provider endpoint URL.
 
+

Detailed Description

+

OpenID consumer.

+

Member Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Web\OpenID::auth ( $proxy = NULL,
 $attr = array(),
array $reqd = NULL 
)
+
+

Initiate OpenID authentication sequence; Return FALSE on failure or redirect to OpenID provider URL

+
Returns
bool
+
Parameters
+ + + + +
$proxystring
$attrarray
$reqdstring|array
+
+
+ +
+
+ +
+
+ + + + + + + + +
Web\OpenID::clear ( $key)
+
+

Remove OpenID request parameter

+
Returns
NULL
+
Parameters
+ + +
$key
+
+
+ +
+
+ +
+
+ + + + + +
+ + + + + + + + +
Web\OpenID::discover ( $proxy)
+
+protected
+
+

Determine OpenID provider

+
Returns
string|FALSE
+
Parameters
+ + +
$proxystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Web\OpenID::exists ( $key)
+
+

Return TRUE if OpenID request parameter exists

+
Returns
bool
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Web\OpenID::get ( $key)
+
+

Return value of OpenID request parameter

+
Returns
mixed
+
Parameters
+ + +
$keystring
+
+
+ +
+
+ +
+
+ + + + + + + +
Web\OpenID::response ()
+
+

Return OpenID response fields

+
Returns
array
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Web\OpenID::set ( $key,
 $val 
)
+
+

Bind value to OpenID request parameter

+
Returns
string
+
Parameters
+ + + +
$keystring
$valstring
+
+
+ +
+
+ +
+
+ + + + + + + + +
Web\OpenID::verified ( $proxy = NULL)
+
+

Return TRUE if OpenID verification was successful

+
Returns
bool
+
Parameters
+ + +
$proxystring
+
+
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • web/openid.php
  • +
+
diff --git a/lib/f3/api/classWeb_1_1OpenID.png b/lib/f3/api/classWeb_1_1OpenID.png new file mode 100755 index 0000000000000000000000000000000000000000..ef874dcd2e80ba8fa2fe97dca419ba05a13a28b4 GIT binary patch literal 595 zcmV-Z0<8UsP)vF9i34XXQ%w^eNdX6l1L9RP4u$NpFxLfVTJjergS0Y?7(&HXcul&;OpWlj`mRi^3%SZbm#uzX1;w#zXzWJtixUYUd z{CD!RE)miA06=dh05FJ=J54sQkvp>{u$B9{{ot;<0OWAjU3URM$6a^-j2l7-20>tE z9v*l9qf3YKbc30>p0=C&uLU!6ce-857xQ^8iwb7uN^a&M0lSoswP;UAue;7_!80>o z=WgA~VOzKYj&UpCi1{tD?t~HhftmT7uHF35y&3)c_ic~fe + + + + + + +Fat-Free Framework: Member List + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
Web\Pingback Member List
+
+
+ +

This is the complete list of members for Web\Pingback, including all inherited members.

+ + + + + + + +
__construct()Web\Pingback
enabled($url)Web\Pingbackprotected
inspect($source)Web\Pingback
instance()Prefabstatic
listen($func, $path=NULL)Web\Pingback
log()Web\Pingback
diff --git a/lib/f3/api/classWeb_1_1Pingback.html b/lib/f3/api/classWeb_1_1Pingback.html new file mode 100755 index 0000000..e633312 --- /dev/null +++ b/lib/f3/api/classWeb_1_1Pingback.html @@ -0,0 +1,215 @@ + + + + + + + +Fat-Free Framework: Web\Pingback Class Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+ +
+
Web\Pingback Class Reference
+
+
+ +

Pingback 1.0 protocol (client and server) implementation. + More...

+
+ + Inheritance diagram for Web\Pingback:
+
+
+ + + + + + + + + + + +

+Public Member Functions

 inspect ($source)
 
 listen ($func, $path=NULL)
 
 log ()
 
 __construct ()
 
+ + + +

+Protected Member Functions

 enabled ($url)
 
+ + + + +

+Additional Inherited Members

- Static Public Member Functions inherited from Prefab
static instance ()
 
+

Detailed Description

+

Pingback 1.0 protocol (client and server) implementation.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + +
Web\Pingback::__construct ()
+
+

Instantiate class

+
Returns
object
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + +
Web\Pingback::enabled ( $url)
+
+protected
+
+

Return TRUE if URL points to a pingback-enabled resource

+
Returns
bool
+
Parameters
+ + +
$url
+
+
+ +
+
+ +
+
+ + + + + + + + +
Web\Pingback::inspect ( $source)
+
+

Load local page contents, parse HTML anchor tags, find permalinks, and send XML-RPC calls to corresponding pingback servers

+
Returns
NULL
+
Parameters
+ + +
$sourcestring
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
Web\Pingback::listen ( $func,
 $path = NULL 
)
+
+

Receive ping, check if local page is pingback-enabled, verify source contents, and return XML-RPC response

+
Returns
string
+
Parameters
+ + + +
$funccallback
$pathstring
+
+
+ +
+
+ +
+
+ + + + + + + +
Web\Pingback::log ()
+
+

Return transaction history

+
Returns
string
+ +
+
+
The documentation for this class was generated from the following file:
    +
  • web/pingback.php
  • +
+
diff --git a/lib/f3/api/classWeb_1_1Pingback.png b/lib/f3/api/classWeb_1_1Pingback.png new file mode 100755 index 0000000000000000000000000000000000000000..9caff175e90763aaf621d04144b355ef70408264 GIT binary patch literal 466 zcmeAS@N?(olHy`uVBq!ia0vp^u|OQa!3-pQ3_JCKlth3}i0l9V|AEYR@7~RsGiL&j z1;z&s9QfdvY7gXclmz(&GXNEVz|~VBMhpy$iJmTwAr*{o=RTaYSV4eocE8sB{}ana z1=RYM&rbQKwN=GT;b5AC!Tyt$&kasY5;?NPd(!d$Tb6%SJ{hz3`G?6W#j!VJj~D#b ztByLIE1PP#Rpy$aC;Piw;rW@@SNW6+{y)2?|CC+v>!~W!r8j>6;hlABOa8XoX$^n( zR&Ku?&F__)cR&1GkILRdAajA(eTVJyIg1&7FmgLcEc}+*d8Pf<{-=$5#3>4~z_qQoQT+J*3N479m{Fzj{R%-9^X{rB@%b%4<*yDCo_xH?~lGWTL z{o8MD&wd^2U2Gnby5MYebw#?Y<(Dmt)$gwvC4XCGeLQUE=H%`ZE~P7eJt>X+ze)W1 zVVCBI8Snk)-0XRZeH&Fd&O0EX20Ge|6H;t<6KXE`8l7P^4e7oWB1m5iroGC v8I#1kzP + + + + + + +Fat-Free Framework: Class Index + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Class Index
+
+
+
A | B | C | F | G | I | J | L | M | O | P | R | S | T | U | V | W
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  A  
+
Audit   
Auth   
  B  
+
Base   
Basket   
Bcrypt   
  C  
+
Cache   
Cursor (DB)   
  F  
+
F3   
  G  
+
Web\Geo   
  I  
+
Image   
ISO   
  J  
+
Jig (DB)   
  L  
+
Log   
  M  
+
Magic   
Mongo\Mapper (DB)   
SQL\Mapper (DB)   
Jig\Mapper (DB)   
Markdown   
Matrix   
Mongo (DB)   
  O  
+
Web\OpenID   
  P  
+
Web\Pingback   
Prefab   
Preview   
  R  
+
Registry   
  S  
+
Jig\Session (DB)   
SQL\Session (DB)   
Session   
Mongo\Session (DB)   
SMTP   
SQL (DB)   
StaticMap (Web\Google)   
  T  
+
Template   
Test   
  U  
+
UTF   
  V  
+
View   
  W  
+
Web   
+
A | B | C | F | G | I | J | L | M | O | P | R | S | T | U | V | W
+
diff --git a/lib/f3/api/closed.png b/lib/f3/api/closed.png new file mode 100755 index 0000000000000000000000000000000000000000..e4e2b25adb14b76c58d22aa1e4122e0c3338d4ac GIT binary patch literal 125 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{VE}kxqAr*{o=U(JwP~dQh&wG{9 z7bU@>l`1S#9&h*6jlsikGp7o-gD)%l1R2KAyPsb#-E|=@%i8tlX|Z2rRtJQ;8nPKn XltlO!^KID#G>^g4)z4*}Q$iB}Y*r*7 literal 0 HcmV?d00001 diff --git a/lib/f3/api/dir_3a960e52dd9a2c9686c19ff6ef19d5fb.html b/lib/f3/api/dir_3a960e52dd9a2c9686c19ff6ef19d5fb.html new file mode 100755 index 0000000..cd3aa3b --- /dev/null +++ b/lib/f3/api/dir_3a960e52dd9a2c9686c19ff6ef19d5fb.html @@ -0,0 +1,48 @@ + + + + + + + +Fat-Free Framework: web/google Directory Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
google Directory Reference
+
+
+ + + + +

+Files

file  staticmap.php
 
+
diff --git a/lib/f3/api/dir_562abdcd8625d4bf7bad2fe6fe01354c.html b/lib/f3/api/dir_562abdcd8625d4bf7bad2fe6fe01354c.html new file mode 100755 index 0000000..0e1d671 --- /dev/null +++ b/lib/f3/api/dir_562abdcd8625d4bf7bad2fe6fe01354c.html @@ -0,0 +1,57 @@ + + + + + + + +Fat-Free Framework: web Directory Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
web Directory Reference
+
+
+ + + + +

+Directories

directory  google
 
+ + + + + + + +

+Files

file  geo.php
 
file  openid.php
 
file  pingback.php
 
+
diff --git a/lib/f3/api/dir_60985a986063d10a97c0bb7f42d76d6f.html b/lib/f3/api/dir_60985a986063d10a97c0bb7f42d76d6f.html new file mode 100755 index 0000000..f6556fe --- /dev/null +++ b/lib/f3/api/dir_60985a986063d10a97c0bb7f42d76d6f.html @@ -0,0 +1,50 @@ + + + + + + + +Fat-Free Framework: db/sql Directory Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
sql Directory Reference
+
+
+ + + + + + +

+Files

file  mapper.php
 
file  session.php
 
+
diff --git a/lib/f3/api/dir_826b1e4cd13f4e7f528ca52e638927e5.html b/lib/f3/api/dir_826b1e4cd13f4e7f528ca52e638927e5.html new file mode 100755 index 0000000..034a699 --- /dev/null +++ b/lib/f3/api/dir_826b1e4cd13f4e7f528ca52e638927e5.html @@ -0,0 +1,50 @@ + + + + + + + +Fat-Free Framework: db/jig Directory Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
jig Directory Reference
+
+
+ + + + + + +

+Files

file  mapper.php
 
file  session.php
 
+
diff --git a/lib/f3/api/dir_9d4753e6cb22f68b75f0462ac2496f38.html b/lib/f3/api/dir_9d4753e6cb22f68b75f0462ac2496f38.html new file mode 100755 index 0000000..3445ce9 --- /dev/null +++ b/lib/f3/api/dir_9d4753e6cb22f68b75f0462ac2496f38.html @@ -0,0 +1,50 @@ + + + + + + + +Fat-Free Framework: db/mongo Directory Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
mongo Directory Reference
+
+
+ + + + + + +

+Files

file  mapper.php
 
file  session.php
 
+
diff --git a/lib/f3/api/dir_ce5981f09099a3fa6071b9eb8fe67a2c.html b/lib/f3/api/dir_ce5981f09099a3fa6071b9eb8fe67a2c.html new file mode 100755 index 0000000..0da07b4 --- /dev/null +++ b/lib/f3/api/dir_ce5981f09099a3fa6071b9eb8fe67a2c.html @@ -0,0 +1,63 @@ + + + + + + + +Fat-Free Framework: db Directory Reference + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + + +
+
+
+
db Directory Reference
+
+
+ + + + + + + + +

+Directories

directory  jig
 
directory  mongo
 
directory  sql
 
+ + + + + + + + + +

+Files

file  cursor.php
 
file  jig.php
 
file  mongo.php
 
file  sql.php
 
+
diff --git a/lib/f3/api/doxygen.css b/lib/f3/api/doxygen.css new file mode 100755 index 0000000..b5b775c --- /dev/null +++ b/lib/f3/api/doxygen.css @@ -0,0 +1,1382 @@ +/* The standard CSS for doxygen 1.8.5 */ + +body, table, div, p, dl { + font: 400 16px/22px Ubuntu,Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Ubuntu,Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 0px; + margin: 0px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view when not used as main index */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 200% Ubuntu,Roboto,sans-serif; + font-weight: bold; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Ubuntu,Roboto,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 75% Ubuntu,Roboto,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectname .menu +{ + font: 75% Ubuntu,Roboto,sans-serif; +} + +#projectname .menu a +{ + padding-left:1em; + text-decoration:none; +} + +#projectname .menu a:hover +{ + color:white; +} + +#titlearea +{ + color: white; + background: black; + padding: 0px; + margin: 0px; + width: 100%; +} + +#titlearea table +{ + width:100%; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Ubuntu,Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + +/* Fluid Fonts */ +@media screen and (max-width:640px){body{font-size:0.81255em!important}} diff --git a/lib/f3/api/doxygen.png b/lib/f3/api/doxygen.png new file mode 100755 index 0000000000000000000000000000000000000000..da7e8aa7670c5559c8c1ee1405452e327c0c848d GIT binary patch literal 3529 zcmV;)4L0(LP) z^Fd)@VK)CI)Mo$y8VCS>A6+Rx@fjHz0K7XSBt!s90DuMpfIo(=6d+u>bO``zk*{+A zXdnQ%JT-3I7yx`y13&=q7t-$m$d439a_VzT{?yde06;CWpZDz9Q)EL(4(;f;=-9b) zXO4|e>~sfU-n+?HW#iNR(3j}bb=N6Zmu}t{)ZwS-7GBYrUx)7Fl#??6un^^=H5(GE zzQl&aYO&?Rr!(X$=BN-KM3>kVTREKT#$dMtlt7BzpAdp$-loKI~k-eto?! zC^R&5y3DH4qenY}f`Z`h@2}1)D=Se}RwfR*_%nO^_U#$ur5V4)) zB~OW_b8+9kePz}etD>R;0RaI3yjzp=r(BgU-Mo+FeF5*oH9w;z##XIbDIYg)-W+Gw zEx#$(g>nW+l#dnp!Gi~fbne_4ojP?g_;>Bv~+_gkO8@HJ=FvVA(XN03t=*dh4xkEnBt>En2hy0H0J{ zU5&>de;g-HoEW7UeT&N?w_w2neE8vqsnqGV>zqA%wgjL0$Rm%qr%s(}oF6-O4CBU) zD`rq(l8B{CmpYk9<32Mp6KmJ56@lRC)2GJ|A3hua>ZMhyR)IN5q~3Jujit`4)YMdq zPhwkuHQSRVh08?eQ#OXOP8NhmVgrEsNRNjrOb5s{VZwxz#~ypkl1yoB(w?McneSxX zci(+FK%ON_mRJ%Z2G*@xr@p1)J9Ow^-0=m0ucF}d&p(f(j^v1l2=~)ZKW(u)Wy%!w z+RSqK`T3xoYTne0f2WiAe=mTvJ3A@?RP_m4wY)|5*Qd*DoHo5FTeZ}AAInE z`X=y}M8E#}>sYa3MIwDor>{l)4l(=m%rnnm+qP{oFV3)iIbVG7MGJV-rcIOfE3M}G z-o1N!=FOW2z`G^ZqeqXb*Jv+p&1Zidpwc(reA8imJ#0UC=bd*_`6+$WQ&3=?drqgC z-708l1!kjT$BxC>vu7vE@9VC+E^GDb)fNY&{YWyY^EmY^W+3syh7Ggmuvh8Ci4!Fe zqbO5OnLGv?-K$qGgXfJm-jJ4*IB3wI6loD=0GLQ=Z@XzX<y+V5y?MU$YDW&f@VEyac%Ux%Vrl6qDJhngFWrQBDqxPBoIL=%J25d)USXsFVS_qWh~nVdNs4gj!__#)2k-@kt{`Exa$(Z1|5iP87pf4_15>Z`9xp-Fpl z+WpY)s5gf?U9qvTDKRn1ZME|9@{pUGD+#`yE!7nj6=mGfAMD+`7l3zn?b;Q0-g&2m z=gB9ZR0Y6d@^HS^x?>xQ3<(J-%FfOXF~|Sxv(HKqD1e-yp`o7Vo_o$BJY&WTQ5>lQ zBm>;M*qRj3Y<($X#*8t}*Q{A1ts#;8YOs>ebp<@JcieGDR(iVn3BbEG-c<4?+3Z)c z1^by_nzX2wUw#>F+O)Bpu}Y=T^3u}MoaO{d%-gqbkEHH`%lRqb+GPQtJ~HJo-B*q^ zfIPl@Qvk85Jc5|M4jecDx7%$2$m8(<@b1V+b(P3=mNI(uXycr%5^QOS?BZ@*E4C-BuQ`(dCP6~GZ|o9|Ni}rv-jVB9}hqLu<`q|&prbK&!Ozpy7Ws$ z^W{bIzTk3x3P5&Q0H}{lc}(|}V;vx0zA1ou_U!4AHlnZ6(o%46TL60Rz4rik_mCk& z6hLeVDN?2STDx|ww1!0TtK^fC(lx&&kQb#*G`N@;>KsehNT#S?(xi-Gsj|>!?S?=3S9E#@ptsy zci(OB%%49WUw!peBzX#WA4U6bEnK(|&6_s|fLgR<$r5=DspPk`Im%Wtfqr$#{rvOK zV8W{?qvj}iU3?uWBS(&`<*Sy+?h_|YjMh4XTI<%WlUJm&YM1@thaV6hAAg*mlWC*S z*f7!BSjvH^h(O`J{?YE_ZishTh z4I$b9ynDom5%SNUPE=-QW?GUfmGaFu->BEoxpQZiRD*dS^*REYMqj384Y01+WIb%MY{rdI8;K74ci`C?d?Y6}( z^JD;I&jDW)zW(}a1E5SMAWjsU*U6J7)&Ic2Kmf3iR!z<1HI5%Y-jXCqXkp=RMHL<% zZUOJ3k3Pc6l`FGZoe9*jm=v#pZP(Z7*vt;YXFwL zbm>y@A%?v9CZCHIEm{;(S3Ce++T(zTGBoQ$%vvdPq$CA_U$w>Iwb^YbO>>@{oF7=wp?NPBje`NUtg zt19xT_GaRZrOm9FGiTNrr}$@%L9>@gJ?WIag-7lwQ>MiA>C*=Q>Lp!X0P5boyJyCX z8O9xBlvoXbm8A(_ z3&YT%L+$<~Qjcoalnv&;cqTipfB*hqVgaBQ3D5@*9#lHN{q|cmg9My?Uu1-+%u-wr<@jZRLnK2Ee?tNeQb~tx`Y6jT@(&r+i#+ za4=f5Xra!ltE*8`Qi96L${dj)e~HFFUDN5X>6}X*)xyXlO~001-m4eHdk5{6O20O* zjEoFO;N%nE0eClM;xwBwGo0G7fbC?$Ld-8{`SRrwe+=~)ZBo-Aa-t`iMP$UP6cwww zkw0QPhqA|g#3J|E66^rU66d3}Z&7Y>4uECn=H>$M?%3E^krzXL z+EJA_Lq6pw0Q|Rzwp_!84NHlNlK6gGKmGI*TrSsf+LOu!;N9ep8#r)aW}7x`uz&x4 z?AfzNofBk)hK9ndN7l4y)8xhbQIDPuG z{5&S@_V(Lv$CfQyaP;WW<~21n5Nh1GF#yy_d-v|ercIl0)m2x`(T-X>ole|z(@g;I zhm*{(qM{=8Z2$xS{}j66h8u9{(xrZZfq{(tW3=jwzjOMO`9I&)f9pg{%3&$z_N`N z*Qryde^iSjFnPcJ`fG>g&71eq&zdx8A^`2=|4;cdkTDtUO<$#@rAsbeyckBgyQ{0K zjq_`+xke59mMvT2#~*)m^XL%CMIC(s;Lj$;r&^p2kPP*I0l@zNoznjQfBN+fQd`ok z0Pq*l5du`uM4q$EM2!HTfdJrdLcS*@05lK){H63CTk-+(MgWZ}00000NkvXXu0mjf D-zDsi literal 0 HcmV?d00001 diff --git a/lib/f3/api/doxygen_8h_source.html b/lib/f3/api/doxygen_8h_source.html new file mode 100755 index 0000000..d9895bd --- /dev/null +++ b/lib/f3/api/doxygen_8h_source.html @@ -0,0 +1,39 @@ + + + + + + + +Fat-Free Framework: doxygen.h Source File + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
doxygen.h
+
+
+
1 
+
diff --git a/lib/f3/api/dynsections.js b/lib/f3/api/dynsections.js new file mode 100755 index 0000000..ed092c7 --- /dev/null +++ b/lib/f3/api/dynsections.js @@ -0,0 +1,97 @@ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} +function toggleLevel(level) +{ + $('table.directory tr').each(function(){ + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (ldjv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/lib/f3/api/ftv2cl.png b/lib/f3/api/ftv2cl.png new file mode 100755 index 0000000000000000000000000000000000000000..d660c7bbe88349cdf68f8934adbf7c90409fab0b GIT binary patch literal 416 zcmV;R0bl-!P)FzG0u~x4 zd;alKLu-y$vi0!89f#hJ{Qr8ch4p$3keefbJmns6q8H=w*iqB9at@Hj#B4Uk15 zpkDv3l;?ReM^Pj}0EgK7J6Nq&0DrbOV7CVVhe`x27K?b@Xf)#WU@(wxQ?uCw$RyE& zFbtW`=hEm}ttN-=j$*M0kVzt7Gp5t2G`8Jt$7NbBm(q0K_W?4|0q@GG-ki;50w6^I zV4{2Q0Fco=fQdYTs`Z1qygs%UnW@m9+uQUBz@+g1j|Pw?_kb_|XIkEL(RQf-0000< KMNUMnLSTYU!o1}G literal 0 HcmV?d00001 diff --git a/lib/f3/api/ftv2doc.png b/lib/f3/api/ftv2doc.png new file mode 100755 index 0000000000000000000000000000000000000000..7f92e54f9bbca8844816fcd6aa869e13e3bdff4c GIT binary patch literal 652 zcmV;70(1R|P)cnV*D^DtB-yoj}pMkCRXU@YX~C0x&} z9Wh6k@f0T(r`TbInXqTA|6l9hLu<`uGk_n12jD01;{rZ_MYLM2*<>gq25CpcPUKZM8QF|aHPpU-E6Bq-virzi8hv$LaOXt&$0lj3NRQT`zR z+-QqvY3d#yAI-HywA6_$K3iX3U$VC)@xY=w{uh+S_xZwT$oo=@a zumr~pI-O3nEStxAnQ4w2PTT5BETBHZG?(Xi4ExBBd>+5SX zS$3#%Lf+oq%)a4p2(ScKi&VWTFBXd?OihulkB*MWX0t{xnM|^>vVtaVJRSoq;oFe4 zE-x>+zrSa5bJK*YQMD~(Z*R|#r_*Vs)2XY#w5EDwT|V08Vi2K;tQ!QmGWXySp48 zA9Hqg#^K>1+uPgbzFaPU9!LNuxOOnlK^dr8WgzbtGst8z-wOP7ij;w>&FAxu8E9Pp zJn_JnkE4L5Lgbo%5$NR3Uwq0yYyLK!cdBOq7U5`-HdiVYuCA^ODS#UkzA`#LKL=QX mqkwIL)o3&T{u%%OU*>O3D#HaCe_}EK0000cnSpKB@lNY;uIWU55XLTOAL2_gp^l8N{obf_2QC>adp=$Gtv@F z(DE-=xvKozWp{TPgkcEqG9&30iswe7U5>I0Y0Q!t2w&{_C39*=9$M(?(Y+6+>DsmyOQn^ArjNa=Dxt7mGz!s};Ro@9pUo9S#R4G8^^fa(US8SnSv9 zm1NTEDo!8=PN$RO*xGNmn;BazHVaMuGy`!Uu=lJh=X3i4ll{YzTmB5#qUBW$E{NDgbK)*;}?mokt?+Elk9Kopi#&jF(F)?mF}e|opk*46b% zrBVP6VxNlpEC0LO?an)$&b-xX&6~}pL8H+ysMqU8%bMWcab~Zasnu%pJIVV$Gq`_u j{s8YiHL!LAZViKd{Yg*+weeQQZLm#cE44xRW+uT@B08h1{>ff@&5;K0FrPx9Q@sGht%kPzbmv_ExO&V1@J0T z0|gUV zuv)F$UazOJtyC(?Ye?qW7mGy&Q6Z3ZP&Y=SQAkN*4X)R#`e~vHv#%FgVDKL{UlQ2zW?n|-f9vXsd+TT-u+_RkVXon(_Bjoc(m3YZ#T zzuyC2rb*43MAzbFx`B|z1}zw(x8ZQ;1*7i;FE+2;ZYu;YIKb|TG4!#5YEByYW0X)TDg2x&V0V3h-00000NkvXXu0mjff?DA& literal 0 HcmV?d00001 diff --git a/lib/f3/api/ftv2lastnode.png b/lib/f3/api/ftv2lastnode.png new file mode 100755 index 0000000000000000000000000000000000000000..63c605bb4c3d941c921a4b6cfa74951e946bcb48 GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/lib/f3/api/ftv2link.png b/lib/f3/api/ftv2link.png new file mode 100755 index 0000000000000000000000000000000000000000..7f92e54f9bbca8844816fcd6aa869e13e3bdff4c GIT binary patch literal 652 zcmV;70(1R|P)cnV*D^DtB-yoj}pMkCRXU@YX~C0x&} z9Wh6k@f0T(r`TbInXqTA|6l9hLu<`uGk_n12jD01;{rZ_MYLM2*<>gq25CpcPUKZM8QF|aHPpU-E6Bq-virzi8hv$LaOXt&$0lj3NRQT`zR z+-QqvY3d#yAI-HywA6_$K3iX3U$VC)@xY=w{uh+S_xZwT$oo=@a zumr~pI-O3nEStxAnQ4w2PTT5BETBHZG?(Xi4ExBBd>+5SX zS$3#%Lf+oq%)a4p2(ScKi&VWTFBXd?OihulkB*MWX0t{xnM|^>vVtaVJRSoq;oFe4 zE-x>+zrSa5bJK*YQMD~(Z*R|#r_*Vs)2XY#w5EDwT|V08Vi2K;tQ!QmGWXySp48 zA9Hqg#^K>1+uPgbzFaPU9!LNuxOOnlK^dr8WgzbtGst8z-wOP7ij;w>&FAxu8E9Pp zJn_JnkE4L5Lgbo%5$NR3Uwq0yYyLK!cdBOq7U5`-HdiVYuCA^ODS#UkzA`#LKL=QX mqkwIL)o3&T{u%%OU*>O3D#HaCe_}EK0000e21mjbI09ldh6KR{+5;4Ut*>snJQBn%-5Jp$5KZ1c zFW=1Uo5_5${-WzTIGPEZ!a3j%0xtVS+qRq76%<%EO*5^XU;!287-$fX^fvYeBRpsR z9RrQs!EM-~uWh)4-y8&Fmyg&Z`nu2f_x-?t(Jo~1L+taXT%~@3F=}nR3HvaE62*Y* r`Wm~AFQG*BA?4#2sB!+8{zJeQs>~svYa<7n00000NkvXXu0mjf_~v80 literal 0 HcmV?d00001 diff --git a/lib/f3/api/ftv2mnode.png b/lib/f3/api/ftv2mnode.png new file mode 100755 index 0000000000000000000000000000000000000000..9d1437d2010806e6ce1610d15a7ec44fbce925df GIT binary patch literal 241 zcmVe21mjbI09ldh6KR{+5;4Ut*>snJQBn%-5Jp$5KZ1c zFW=1Uo5_5${-WzTIGPEZ!a3j%0xtVS+qRq76%<%EO*5^XU;!287-$fX^fvYeBRpsR z9RrQs!EM-~uWh)4-y8&Fmyg&Z`nu2f_x-?t(Jo~1L+taXT%~@3F=}nR3HvaE62*Y* r`Wm~AFQG*BA?4#2sB!+8{zJeQs>~svYa<7n00000NkvXXu0mjf_~v80 literal 0 HcmV?d00001 diff --git a/lib/f3/api/ftv2mo.png b/lib/f3/api/ftv2mo.png new file mode 100755 index 0000000000000000000000000000000000000000..e2513ee47eaef5279ea8ff75de8487dd186fe0c4 GIT binary patch literal 373 zcmV-*0gC>KP)D5Qo1-Ba}3|G_Z+7A79RSim+5t%;$+dC!Gl z0zAQ`uz1PGybOPSGXpcUv$8A!Cc^@llF0>*t4$oomtwAkbATRRg@^Te{Q_V@XCM!c z#5@T%z=Z*I&9mHd1z@5o(JjCLj)Xe^6P3VH9VG3VFbwqx$8mo6qevyI*C~LB&X?@E z?zi$%YXgj;RiG#eeBamm#bQzW0EW^ku-$I4Z5z+?Y9ZwV7)q-^mSx%oLBM=IC(rZ4 zW{{?-wyV|ZPtkV@>~=dHu_{wDBY>fFenriwlOzEcMW;X&wW_~mjUQPvHLj)Y-+$XU zjrAstcLvZ$71{=1Aol51evq92^zgZ#rjGz7bcq0_;{X5ACKvbu;}ldjv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/lib/f3/api/ftv2ns.png b/lib/f3/api/ftv2ns.png new file mode 100755 index 0000000000000000000000000000000000000000..c61a541e88e66b1c74582ad0eda4a97907cf033b GIT binary patch literal 370 zcmV-&0ge8NP)CTb7y#hMwiW~@7e%npp{smQa4Jp?ow~U>6gvAa3hgQm{RjOOPIl^0=;Tzoxac0} zXfMIY#|I`g9~n9vJh>1~-@JGCUe?NHvw_kaL77SqaFX6kr_-y@-3EUk!+Y>F9*^H3 zPm)3S^PAAU1b4X15s!Hdzqy7y=@i|=0gi(Q$dd**i!beVTSz@I91eGb`u+ayc|2y@ z&LPjEWid>$&`W>cuROa+fa>f3JEvH8>Ugbo1ENCaZkSa z>pLL?fS>6Cl+X&G_q_1lU({C4xf4JRF9Ov-93|STuO*5?fFxG%sJWO*w2@>7kRm0B z)fZby7V1lhDgaB)A&$jaq8WfCM^KB25*z?5pSExljc1Tb5N~1BH2f~Xwdfsaa0u`X d?Qi@C!5#X2Cu4fy23i0B002ovPDHLkV1fr0Rs{e6 literal 0 HcmV?d00001 diff --git a/lib/f3/api/ftv2pnode.png b/lib/f3/api/ftv2pnode.png new file mode 100755 index 0000000000000000000000000000000000000000..a2fffb6fcffd16be189938656c53c9d2c7a52a01 GIT binary patch literal 227 zcmV<90382`P)EWid>$&`W>cuROa+fa>f3JEvH8>Ugbo1ENCaZkSa z>pLL?fS>6Cl+X&G_q_1lU({C4xf4JRF9Ov-93|STuO*5?fFxG%sJWO*w2@>7kRm0B z)fZby7V1lhDgaB)A&$jaq8WfCM^KB25*z?5pSExljc1Tb5N~1BH2f~Xwdfsaa0u`X d?Qi@C!5#X2Cu4fy23i0B002ovPDHLkV1fr0Rs{e6 literal 0 HcmV?d00001 diff --git a/lib/f3/api/ftv2splitbar.png b/lib/f3/api/ftv2splitbar.png new file mode 100755 index 0000000000000000000000000000000000000000..343046b612b0bef5191e66080ff3bff2338a121e GIT binary patch literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^Yzz!63>-{AmhX=Jf@Vh3v=57WL!Tw zYfCnYCNSG5Pk3-a=ZFUXdA1Eq$_q4ov(~NreaG|M?nl#~|KqNi9(1iVc3SGZ=b5vP z75-s5q3-FRLMp1A(D%6F`@Z+~t5&Ugy=zs@kf3$>Phsonp+`m)LO(%OI5^=;38 qepfl~ectV77gZD{k%9g#loz>Y`|5vS(>$PO89ZJ6T-G@yGywqTerZbp literal 0 HcmV?d00001 diff --git a/lib/f3/api/ftv2vertline.png b/lib/f3/api/ftv2vertline.png new file mode 100755 index 0000000000000000000000000000000000000000..63c605bb4c3d941c921a4b6cfa74951e946bcb48 GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/lib/f3/api/functions.html b/lib/f3/api/functions.html new file mode 100755 index 0000000..7385044 --- /dev/null +++ b/lib/f3/api/functions.html @@ -0,0 +1,207 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- $ -

+
diff --git a/lib/f3/api/functions_0x5f.html b/lib/f3/api/functions_0x5f.html new file mode 100755 index 0000000..032e12c --- /dev/null +++ b/lib/f3/api/functions_0x5f.html @@ -0,0 +1,183 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- _ -

+
diff --git a/lib/f3/api/functions_0x61.html b/lib/f3/api/functions_0x61.html new file mode 100755 index 0000000..4cc6a8c --- /dev/null +++ b/lib/f3/api/functions_0x61.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- a -

+
diff --git a/lib/f3/api/functions_0x62.html b/lib/f3/api/functions_0x62.html new file mode 100755 index 0000000..0cb7301 --- /dev/null +++ b/lib/f3/api/functions_0x62.html @@ -0,0 +1,65 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- b -

+
diff --git a/lib/f3/api/functions_0x63.html b/lib/f3/api/functions_0x63.html new file mode 100755 index 0000000..60cb378 --- /dev/null +++ b/lib/f3/api/functions_0x63.html @@ -0,0 +1,158 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- c -

+
diff --git a/lib/f3/api/functions_0x64.html b/lib/f3/api/functions_0x64.html new file mode 100755 index 0000000..0a241b3 --- /dev/null +++ b/lib/f3/api/functions_0x64.html @@ -0,0 +1,82 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- d -

+
diff --git a/lib/f3/api/functions_0x65.html b/lib/f3/api/functions_0x65.html new file mode 100755 index 0000000..677ee28 --- /dev/null +++ b/lib/f3/api/functions_0x65.html @@ -0,0 +1,95 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- e -

+
diff --git a/lib/f3/api/functions_0x66.html b/lib/f3/api/functions_0x66.html new file mode 100755 index 0000000..7080074 --- /dev/null +++ b/lib/f3/api/functions_0x66.html @@ -0,0 +1,77 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- f -

+
diff --git a/lib/f3/api/functions_0x67.html b/lib/f3/api/functions_0x67.html new file mode 100755 index 0000000..0bd3d07 --- /dev/null +++ b/lib/f3/api/functions_0x67.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- g -

+
diff --git a/lib/f3/api/functions_0x68.html b/lib/f3/api/functions_0x68.html new file mode 100755 index 0000000..555f258 --- /dev/null +++ b/lib/f3/api/functions_0x68.html @@ -0,0 +1,54 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- h -

+
diff --git a/lib/f3/api/functions_0x69.html b/lib/f3/api/functions_0x69.html new file mode 100755 index 0000000..a0316dd --- /dev/null +++ b/lib/f3/api/functions_0x69.html @@ -0,0 +1,87 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- i -

+
diff --git a/lib/f3/api/functions_0x6a.html b/lib/f3/api/functions_0x6a.html new file mode 100755 index 0000000..438573b --- /dev/null +++ b/lib/f3/api/functions_0x6a.html @@ -0,0 +1,41 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- j -

+
diff --git a/lib/f3/api/functions_0x6c.html b/lib/f3/api/functions_0x6c.html new file mode 100755 index 0000000..24c326f --- /dev/null +++ b/lib/f3/api/functions_0x6c.html @@ -0,0 +1,75 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- l -

+
diff --git a/lib/f3/api/functions_0x6d.html b/lib/f3/api/functions_0x6d.html new file mode 100755 index 0000000..bc75583 --- /dev/null +++ b/lib/f3/api/functions_0x6d.html @@ -0,0 +1,68 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- m -

+
diff --git a/lib/f3/api/functions_0x6e.html b/lib/f3/api/functions_0x6e.html new file mode 100755 index 0000000..cbfd02a --- /dev/null +++ b/lib/f3/api/functions_0x6e.html @@ -0,0 +1,47 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- n -

+
diff --git a/lib/f3/api/functions_0x6f.html b/lib/f3/api/functions_0x6f.html new file mode 100755 index 0000000..b5cb49f --- /dev/null +++ b/lib/f3/api/functions_0x6f.html @@ -0,0 +1,71 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- o -

+
diff --git a/lib/f3/api/functions_0x70.html b/lib/f3/api/functions_0x70.html new file mode 100755 index 0000000..71b152b --- /dev/null +++ b/lib/f3/api/functions_0x70.html @@ -0,0 +1,63 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- p -

+
diff --git a/lib/f3/api/functions_0x71.html b/lib/f3/api/functions_0x71.html new file mode 100755 index 0000000..f87cc36 --- /dev/null +++ b/lib/f3/api/functions_0x71.html @@ -0,0 +1,44 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- q -

+
diff --git a/lib/f3/api/functions_0x72.html b/lib/f3/api/functions_0x72.html new file mode 100755 index 0000000..14ab5be --- /dev/null +++ b/lib/f3/api/functions_0x72.html @@ -0,0 +1,116 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- r -

+
diff --git a/lib/f3/api/functions_0x73.html b/lib/f3/api/functions_0x73.html new file mode 100755 index 0000000..ef35112 --- /dev/null +++ b/lib/f3/api/functions_0x73.html @@ -0,0 +1,160 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- s -

+
diff --git a/lib/f3/api/functions_0x74.html b/lib/f3/api/functions_0x74.html new file mode 100755 index 0000000..4ff0e21 --- /dev/null +++ b/lib/f3/api/functions_0x74.html @@ -0,0 +1,55 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- t -

+
diff --git a/lib/f3/api/functions_0x75.html b/lib/f3/api/functions_0x75.html new file mode 100755 index 0000000..76acaf5 --- /dev/null +++ b/lib/f3/api/functions_0x75.html @@ -0,0 +1,67 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- u -

+
diff --git a/lib/f3/api/functions_0x76.html b/lib/f3/api/functions_0x76.html new file mode 100755 index 0000000..a194598 --- /dev/null +++ b/lib/f3/api/functions_0x76.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- v -

+
diff --git a/lib/f3/api/functions_0x77.html b/lib/f3/api/functions_0x77.html new file mode 100755 index 0000000..6fe98be --- /dev/null +++ b/lib/f3/api/functions_0x77.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- w -

+
diff --git a/lib/f3/api/functions_0x78.html b/lib/f3/api/functions_0x78.html new file mode 100755 index 0000000..1b4a444 --- /dev/null +++ b/lib/f3/api/functions_0x78.html @@ -0,0 +1,44 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- x -

+
diff --git a/lib/f3/api/functions__.html b/lib/f3/api/functions__.html new file mode 100755 index 0000000..c308ee6 --- /dev/null +++ b/lib/f3/api/functions__.html @@ -0,0 +1,184 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- _ -

+
diff --git a/lib/f3/api/functions_a.html b/lib/f3/api/functions_a.html new file mode 100755 index 0000000..ea17875 --- /dev/null +++ b/lib/f3/api/functions_a.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- a -

+
diff --git a/lib/f3/api/functions_b.html b/lib/f3/api/functions_b.html new file mode 100755 index 0000000..d1cf23f --- /dev/null +++ b/lib/f3/api/functions_b.html @@ -0,0 +1,65 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- b -

+
diff --git a/lib/f3/api/functions_c.html b/lib/f3/api/functions_c.html new file mode 100755 index 0000000..b2b3285 --- /dev/null +++ b/lib/f3/api/functions_c.html @@ -0,0 +1,165 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- c -

+
diff --git a/lib/f3/api/functions_d.html b/lib/f3/api/functions_d.html new file mode 100755 index 0000000..d912e70 --- /dev/null +++ b/lib/f3/api/functions_d.html @@ -0,0 +1,82 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- d -

+
diff --git a/lib/f3/api/functions_e.html b/lib/f3/api/functions_e.html new file mode 100755 index 0000000..2a11a60 --- /dev/null +++ b/lib/f3/api/functions_e.html @@ -0,0 +1,98 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- e -

+
diff --git a/lib/f3/api/functions_f.html b/lib/f3/api/functions_f.html new file mode 100755 index 0000000..dc360c7 --- /dev/null +++ b/lib/f3/api/functions_f.html @@ -0,0 +1,77 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- f -

+
diff --git a/lib/f3/api/functions_func.html b/lib/f3/api/functions_func.html new file mode 100755 index 0000000..1ecd0c6 --- /dev/null +++ b/lib/f3/api/functions_func.html @@ -0,0 +1,184 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- _ -

+
diff --git a/lib/f3/api/functions_func_0x61.html b/lib/f3/api/functions_func_0x61.html new file mode 100755 index 0000000..f316286 --- /dev/null +++ b/lib/f3/api/functions_func_0x61.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- a -

+
diff --git a/lib/f3/api/functions_func_0x62.html b/lib/f3/api/functions_func_0x62.html new file mode 100755 index 0000000..db37cf8 --- /dev/null +++ b/lib/f3/api/functions_func_0x62.html @@ -0,0 +1,65 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- b -

+
diff --git a/lib/f3/api/functions_func_0x63.html b/lib/f3/api/functions_func_0x63.html new file mode 100755 index 0000000..d5eec47 --- /dev/null +++ b/lib/f3/api/functions_func_0x63.html @@ -0,0 +1,152 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- c -

+
diff --git a/lib/f3/api/functions_func_0x64.html b/lib/f3/api/functions_func_0x64.html new file mode 100755 index 0000000..1e23497 --- /dev/null +++ b/lib/f3/api/functions_func_0x64.html @@ -0,0 +1,82 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- d -

+
diff --git a/lib/f3/api/functions_func_0x65.html b/lib/f3/api/functions_func_0x65.html new file mode 100755 index 0000000..c5f238b --- /dev/null +++ b/lib/f3/api/functions_func_0x65.html @@ -0,0 +1,95 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- e -

+
diff --git a/lib/f3/api/functions_func_0x66.html b/lib/f3/api/functions_func_0x66.html new file mode 100755 index 0000000..5a7018d --- /dev/null +++ b/lib/f3/api/functions_func_0x66.html @@ -0,0 +1,77 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- f -

+
diff --git a/lib/f3/api/functions_func_0x67.html b/lib/f3/api/functions_func_0x67.html new file mode 100755 index 0000000..77e7d65 --- /dev/null +++ b/lib/f3/api/functions_func_0x67.html @@ -0,0 +1,53 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- g -

+
diff --git a/lib/f3/api/functions_func_0x68.html b/lib/f3/api/functions_func_0x68.html new file mode 100755 index 0000000..f9d4939 --- /dev/null +++ b/lib/f3/api/functions_func_0x68.html @@ -0,0 +1,54 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- h -

+
diff --git a/lib/f3/api/functions_func_0x69.html b/lib/f3/api/functions_func_0x69.html new file mode 100755 index 0000000..9e38c65 --- /dev/null +++ b/lib/f3/api/functions_func_0x69.html @@ -0,0 +1,87 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- i -

+
diff --git a/lib/f3/api/functions_func_0x6a.html b/lib/f3/api/functions_func_0x6a.html new file mode 100755 index 0000000..080b330 --- /dev/null +++ b/lib/f3/api/functions_func_0x6a.html @@ -0,0 +1,41 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- j -

+
diff --git a/lib/f3/api/functions_func_0x6c.html b/lib/f3/api/functions_func_0x6c.html new file mode 100755 index 0000000..bb7a208 --- /dev/null +++ b/lib/f3/api/functions_func_0x6c.html @@ -0,0 +1,75 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- l -

+
diff --git a/lib/f3/api/functions_func_0x6d.html b/lib/f3/api/functions_func_0x6d.html new file mode 100755 index 0000000..c657218 --- /dev/null +++ b/lib/f3/api/functions_func_0x6d.html @@ -0,0 +1,65 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- m -

+
diff --git a/lib/f3/api/functions_func_0x6e.html b/lib/f3/api/functions_func_0x6e.html new file mode 100755 index 0000000..f37e19d --- /dev/null +++ b/lib/f3/api/functions_func_0x6e.html @@ -0,0 +1,47 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- n -

+
diff --git a/lib/f3/api/functions_func_0x6f.html b/lib/f3/api/functions_func_0x6f.html new file mode 100755 index 0000000..ece5e26 --- /dev/null +++ b/lib/f3/api/functions_func_0x6f.html @@ -0,0 +1,71 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- o -

+
diff --git a/lib/f3/api/functions_func_0x70.html b/lib/f3/api/functions_func_0x70.html new file mode 100755 index 0000000..d1e9efb --- /dev/null +++ b/lib/f3/api/functions_func_0x70.html @@ -0,0 +1,63 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- p -

+
diff --git a/lib/f3/api/functions_func_0x71.html b/lib/f3/api/functions_func_0x71.html new file mode 100755 index 0000000..8cca107 --- /dev/null +++ b/lib/f3/api/functions_func_0x71.html @@ -0,0 +1,44 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- q -

+
diff --git a/lib/f3/api/functions_func_0x72.html b/lib/f3/api/functions_func_0x72.html new file mode 100755 index 0000000..33e5d59 --- /dev/null +++ b/lib/f3/api/functions_func_0x72.html @@ -0,0 +1,116 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- r -

+
diff --git a/lib/f3/api/functions_func_0x73.html b/lib/f3/api/functions_func_0x73.html new file mode 100755 index 0000000..d86bc87 --- /dev/null +++ b/lib/f3/api/functions_func_0x73.html @@ -0,0 +1,160 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- s -

+
diff --git a/lib/f3/api/functions_func_0x74.html b/lib/f3/api/functions_func_0x74.html new file mode 100755 index 0000000..76fb3cc --- /dev/null +++ b/lib/f3/api/functions_func_0x74.html @@ -0,0 +1,55 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- t -

+
diff --git a/lib/f3/api/functions_func_0x75.html b/lib/f3/api/functions_func_0x75.html new file mode 100755 index 0000000..5e48214 --- /dev/null +++ b/lib/f3/api/functions_func_0x75.html @@ -0,0 +1,64 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- u -

+
diff --git a/lib/f3/api/functions_func_0x76.html b/lib/f3/api/functions_func_0x76.html new file mode 100755 index 0000000..4fac96b --- /dev/null +++ b/lib/f3/api/functions_func_0x76.html @@ -0,0 +1,53 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- v -

+
diff --git a/lib/f3/api/functions_func_0x77.html b/lib/f3/api/functions_func_0x77.html new file mode 100755 index 0000000..75553ea --- /dev/null +++ b/lib/f3/api/functions_func_0x77.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- w -

+
diff --git a/lib/f3/api/functions_func_0x78.html b/lib/f3/api/functions_func_0x78.html new file mode 100755 index 0000000..fda6468 --- /dev/null +++ b/lib/f3/api/functions_func_0x78.html @@ -0,0 +1,44 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.0 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- x -

+
diff --git a/lib/f3/api/functions_func_a.html b/lib/f3/api/functions_func_a.html new file mode 100755 index 0000000..3783de3 --- /dev/null +++ b/lib/f3/api/functions_func_a.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- a -

+
diff --git a/lib/f3/api/functions_func_b.html b/lib/f3/api/functions_func_b.html new file mode 100755 index 0000000..2e97d29 --- /dev/null +++ b/lib/f3/api/functions_func_b.html @@ -0,0 +1,65 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- b -

+
diff --git a/lib/f3/api/functions_func_c.html b/lib/f3/api/functions_func_c.html new file mode 100755 index 0000000..f34e1a3 --- /dev/null +++ b/lib/f3/api/functions_func_c.html @@ -0,0 +1,159 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- c -

+
diff --git a/lib/f3/api/functions_func_d.html b/lib/f3/api/functions_func_d.html new file mode 100755 index 0000000..4b46ed6 --- /dev/null +++ b/lib/f3/api/functions_func_d.html @@ -0,0 +1,82 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- d -

+
diff --git a/lib/f3/api/functions_func_e.html b/lib/f3/api/functions_func_e.html new file mode 100755 index 0000000..0c0e0e9 --- /dev/null +++ b/lib/f3/api/functions_func_e.html @@ -0,0 +1,98 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- e -

+
diff --git a/lib/f3/api/functions_func_f.html b/lib/f3/api/functions_func_f.html new file mode 100755 index 0000000..f766c6b --- /dev/null +++ b/lib/f3/api/functions_func_f.html @@ -0,0 +1,77 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- f -

+
diff --git a/lib/f3/api/functions_func_g.html b/lib/f3/api/functions_func_g.html new file mode 100755 index 0000000..c859dd4 --- /dev/null +++ b/lib/f3/api/functions_func_g.html @@ -0,0 +1,53 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- g -

+
diff --git a/lib/f3/api/functions_func_h.html b/lib/f3/api/functions_func_h.html new file mode 100755 index 0000000..26ea34a --- /dev/null +++ b/lib/f3/api/functions_func_h.html @@ -0,0 +1,54 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- h -

+
diff --git a/lib/f3/api/functions_func_i.html b/lib/f3/api/functions_func_i.html new file mode 100755 index 0000000..f939de6 --- /dev/null +++ b/lib/f3/api/functions_func_i.html @@ -0,0 +1,86 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- i -

+
diff --git a/lib/f3/api/functions_func_j.html b/lib/f3/api/functions_func_j.html new file mode 100755 index 0000000..577a662 --- /dev/null +++ b/lib/f3/api/functions_func_j.html @@ -0,0 +1,41 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- j -

+
diff --git a/lib/f3/api/functions_func_l.html b/lib/f3/api/functions_func_l.html new file mode 100755 index 0000000..f681f63 --- /dev/null +++ b/lib/f3/api/functions_func_l.html @@ -0,0 +1,75 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- l -

+
diff --git a/lib/f3/api/functions_func_m.html b/lib/f3/api/functions_func_m.html new file mode 100755 index 0000000..4cf9e0f --- /dev/null +++ b/lib/f3/api/functions_func_m.html @@ -0,0 +1,65 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- m -

+
diff --git a/lib/f3/api/functions_func_n.html b/lib/f3/api/functions_func_n.html new file mode 100755 index 0000000..1e245d2 --- /dev/null +++ b/lib/f3/api/functions_func_n.html @@ -0,0 +1,47 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- n -

+
diff --git a/lib/f3/api/functions_func_o.html b/lib/f3/api/functions_func_o.html new file mode 100755 index 0000000..474b42e --- /dev/null +++ b/lib/f3/api/functions_func_o.html @@ -0,0 +1,71 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- o -

+
diff --git a/lib/f3/api/functions_func_p.html b/lib/f3/api/functions_func_p.html new file mode 100755 index 0000000..c4b35f1 --- /dev/null +++ b/lib/f3/api/functions_func_p.html @@ -0,0 +1,63 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- p -

+
diff --git a/lib/f3/api/functions_func_q.html b/lib/f3/api/functions_func_q.html new file mode 100755 index 0000000..ece7573 --- /dev/null +++ b/lib/f3/api/functions_func_q.html @@ -0,0 +1,44 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- q -

+
diff --git a/lib/f3/api/functions_func_r.html b/lib/f3/api/functions_func_r.html new file mode 100755 index 0000000..11339fa --- /dev/null +++ b/lib/f3/api/functions_func_r.html @@ -0,0 +1,119 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- r -

+
diff --git a/lib/f3/api/functions_func_s.html b/lib/f3/api/functions_func_s.html new file mode 100755 index 0000000..6a59960 --- /dev/null +++ b/lib/f3/api/functions_func_s.html @@ -0,0 +1,157 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- s -

+
diff --git a/lib/f3/api/functions_func_t.html b/lib/f3/api/functions_func_t.html new file mode 100755 index 0000000..71c27b6 --- /dev/null +++ b/lib/f3/api/functions_func_t.html @@ -0,0 +1,58 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- t -

+
diff --git a/lib/f3/api/functions_func_u.html b/lib/f3/api/functions_func_u.html new file mode 100755 index 0000000..ac9dbc2 --- /dev/null +++ b/lib/f3/api/functions_func_u.html @@ -0,0 +1,64 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- u -

+
diff --git a/lib/f3/api/functions_func_v.html b/lib/f3/api/functions_func_v.html new file mode 100755 index 0000000..48e2354 --- /dev/null +++ b/lib/f3/api/functions_func_v.html @@ -0,0 +1,53 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- v -

+
diff --git a/lib/f3/api/functions_func_w.html b/lib/f3/api/functions_func_w.html new file mode 100755 index 0000000..8745279 --- /dev/null +++ b/lib/f3/api/functions_func_w.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- w -

+
diff --git a/lib/f3/api/functions_g.html b/lib/f3/api/functions_g.html new file mode 100755 index 0000000..4742748 --- /dev/null +++ b/lib/f3/api/functions_g.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- g -

+
diff --git a/lib/f3/api/functions_h.html b/lib/f3/api/functions_h.html new file mode 100755 index 0000000..71045ec --- /dev/null +++ b/lib/f3/api/functions_h.html @@ -0,0 +1,54 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- h -

+
diff --git a/lib/f3/api/functions_i.html b/lib/f3/api/functions_i.html new file mode 100755 index 0000000..4e20e39 --- /dev/null +++ b/lib/f3/api/functions_i.html @@ -0,0 +1,86 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- i -

+
diff --git a/lib/f3/api/functions_j.html b/lib/f3/api/functions_j.html new file mode 100755 index 0000000..64210ec --- /dev/null +++ b/lib/f3/api/functions_j.html @@ -0,0 +1,41 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- j -

+
diff --git a/lib/f3/api/functions_l.html b/lib/f3/api/functions_l.html new file mode 100755 index 0000000..ff3712d --- /dev/null +++ b/lib/f3/api/functions_l.html @@ -0,0 +1,75 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- l -

+
diff --git a/lib/f3/api/functions_m.html b/lib/f3/api/functions_m.html new file mode 100755 index 0000000..e73871f --- /dev/null +++ b/lib/f3/api/functions_m.html @@ -0,0 +1,68 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- m -

+
diff --git a/lib/f3/api/functions_n.html b/lib/f3/api/functions_n.html new file mode 100755 index 0000000..1e1f441 --- /dev/null +++ b/lib/f3/api/functions_n.html @@ -0,0 +1,47 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- n -

+
diff --git a/lib/f3/api/functions_o.html b/lib/f3/api/functions_o.html new file mode 100755 index 0000000..4f0cdf5 --- /dev/null +++ b/lib/f3/api/functions_o.html @@ -0,0 +1,71 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- o -

+
diff --git a/lib/f3/api/functions_p.html b/lib/f3/api/functions_p.html new file mode 100755 index 0000000..0f439e8 --- /dev/null +++ b/lib/f3/api/functions_p.html @@ -0,0 +1,63 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- p -

+
diff --git a/lib/f3/api/functions_q.html b/lib/f3/api/functions_q.html new file mode 100755 index 0000000..c20a7a0 --- /dev/null +++ b/lib/f3/api/functions_q.html @@ -0,0 +1,44 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- q -

+
diff --git a/lib/f3/api/functions_r.html b/lib/f3/api/functions_r.html new file mode 100755 index 0000000..d310325 --- /dev/null +++ b/lib/f3/api/functions_r.html @@ -0,0 +1,119 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- r -

+
diff --git a/lib/f3/api/functions_s.html b/lib/f3/api/functions_s.html new file mode 100755 index 0000000..7096499 --- /dev/null +++ b/lib/f3/api/functions_s.html @@ -0,0 +1,157 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- s -

+
diff --git a/lib/f3/api/functions_t.html b/lib/f3/api/functions_t.html new file mode 100755 index 0000000..f1e9b58 --- /dev/null +++ b/lib/f3/api/functions_t.html @@ -0,0 +1,58 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- t -

+
diff --git a/lib/f3/api/functions_u.html b/lib/f3/api/functions_u.html new file mode 100755 index 0000000..182b01b --- /dev/null +++ b/lib/f3/api/functions_u.html @@ -0,0 +1,67 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- u -

+
diff --git a/lib/f3/api/functions_v.html b/lib/f3/api/functions_v.html new file mode 100755 index 0000000..a07f222 --- /dev/null +++ b/lib/f3/api/functions_v.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- v -

+
diff --git a/lib/f3/api/functions_vars.html b/lib/f3/api/functions_vars.html new file mode 100755 index 0000000..0dcbfd9 --- /dev/null +++ b/lib/f3/api/functions_vars.html @@ -0,0 +1,245 @@ + + + + + + + +Fat-Free Framework: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+  + +

- $ -

+ + +

- c -

+ + +

- g -

    +
  • GLOBALS +: Base +
  • +
+ + +

- m -

+ + +

- u -

+ + +

- v -

+
diff --git a/lib/f3/api/functions_w.html b/lib/f3/api/functions_w.html new file mode 100755 index 0000000..a4afa68 --- /dev/null +++ b/lib/f3/api/functions_w.html @@ -0,0 +1,56 @@ + + + + + + + +Fat-Free Framework: Class Members + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- w -

+
diff --git a/lib/f3/api/hierarchy.html b/lib/f3/api/hierarchy.html new file mode 100755 index 0000000..7f1c25d --- /dev/null +++ b/lib/f3/api/hierarchy.html @@ -0,0 +1,82 @@ + + + + + + + +Fat-Free Framework: Class Hierarchy + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Class Hierarchy
+
+
+
This inheritance list is sorted roughly, but not completely, alphabetically:
+
[detail level 12345]
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
oCArrayAccess
|\CMagicPHP magic wrapper
| oCDB\CursorSimple cursor implementation
| |oCDB\Jig\MapperFlat-file DB mapper
| ||\CDB\Jig\SessionJig-managed session handler
| |oCDB\Mongo\MapperMongoDB mapper
| ||\CDB\Mongo\SessionMongoDB-managed session handler
| |\CDB\SQL\MapperSQL data mapper
| | \CDB\SQL\SessionSQL-managed session handler
| oCSMTPSMTP plug-in
| \CWeb\OpenIDOpenID consumer
oCAuthAuthorization/authentication plug-in
oCBasketSession-based pseudo-mapper
oCF3Legacy mode enabler
oCImageImage manipulation tools
oCDB\JigFlat-file DB wrapper
oCLogCustom logger
oCMongoDB
|\CDB\MongoMongoDB wrapper
oCPDO
|\CDB\SQLPDO wrapper
oCPrefabFactory class for single-instance objects
|oCAuditData validator
|oCBaseBase structure
|oCBcryptLightweight password hashing library
|oCCacheCache engine
|oCISOISO language/country codes
|oCMarkdownMarkdown-to-HTML converter
|oCMatrixGeneric array utilities
|oCUTFUnicode string manager
|oCViewView handler
||\CPreviewLightweight template engine
|| \CTemplateXML-style template engine
|oCWebWrapper for various HTTP utilities
|oCWeb\GeoGeo plug-in
|\CWeb\PingbackPingback 1.0 protocol (client and server) implementation
oCRegistryContainer for singular object instances
oCSessionCache-based session handler
oCWeb\Google\StaticMapGoogle Static Maps API v2 plug-in
\CTestUnit test kit
+
+
diff --git a/lib/f3/api/index.html b/lib/f3/api/index.html new file mode 100755 index 0000000..acc43ba --- /dev/null +++ b/lib/f3/api/index.html @@ -0,0 +1,44 @@ + + + + + + + +Fat-Free Framework: Overview + + + + + + +
+
+ + + + + + +
+
Fat-Free Framework +  3.2.1 +  Overview Class List Hierarchy +
+
+
+ + +
+
+
+
Overview
+
+
+

A powerful yet easy-to-use PHP micro-framework designed to help you build dynamic and robust Web applications - fast!

+

Condensed in a single ~50KB file, F3 (as we fondly call it) gives you solid foundation, a mature code base, and a no-nonsense approach to writing Web applications. Under the hood is an easy-to-use Web development tool kit, a high-performance URL routing and cache engine, built-in code highlighting, and support for multilingual applications. It's lightweight, easy-to-use, and fast. Most of all, it doesn't get in your way.

+

Whether you're a novice or an expert PHP programmer, F3 will get you up and running in no time. No unnecessary and painstaking installation procedures. No complex configuration required. No convoluted directory structures. There's no better time to start developing Web applications the easy way than right now!

+

F3 supports both SQL and NoSQL databases off-the-shelf: MySQL, SQLite, MSSQL/Sybase, PostgreSQL, DB2, and MongoDB. It also comes with powerful object-relational mappers for data abstraction and modeling that are just as lightweight as the framework. No configuration needed.

+

Unlike other frameworks, F3 aims to be usable - not usual.

+

The philosophy behind the framework and its approach to software architecture is towards minimalism in structural components, avoiding application complexity and striking a balance between code elegance, application performance and programmer productivity.

+
diff --git a/lib/f3/api/jquery.js b/lib/f3/api/jquery.js new file mode 100755 index 0000000..c197801 --- /dev/null +++ b/lib/f3/api/jquery.js @@ -0,0 +1,31 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType; +if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1 +},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av); +ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length; +if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b +})}})(window); diff --git a/lib/f3/api/nav_f.png b/lib/f3/api/nav_f.png new file mode 100755 index 0000000000000000000000000000000000000000..5ceae878cc8eb5b28d21195e7980e041cd58c003 GIT binary patch literal 136 zcmeAS@N?(olHy`uVBq!ia0vp^j6iI`!2~2XGqLUlQvRMUjv*C{Z|`p8Wl`jDxyY#H zb|_(kba~k)mp569S3gj#U&i6$Qv5wFZ6#C2bD3M!>Sm!!w}vInE}qnJL85u@_c+Es kOQ!@e+T3}&xBjobeYv5uSL0MUXQ0sxp00i_>zopr0ILoz;s5{u literal 0 HcmV?d00001 diff --git a/lib/f3/api/nav_g.png b/lib/f3/api/nav_g.png new file mode 100755 index 0000000000000000000000000000000000000000..2093a237a94f6c83e19ec6e5fd42f7ddabdafa81 GIT binary patch literal 95 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrB!3HFm1ilyoDK$?Q$B+ufw|5PB85lU25BhtE tr?otc=hd~V+ws&_A@j8Fiv!K1|%O$WD@{VR-P`7Ar*{o?>cfFFyLT0aB==G zqxrWkIO(aLv^?JED*lDDVD^i5?0%b8F_qn`J;zXA{BLU5(Z{V<`k&sW_1@dU27*sGi1(Rd+`(5Tb_g-g2#qH&Mm~-zP&hMUce&?L6YjkuJ zAf1z=7cuoZoFCh`8e_(wbx{{yy?DnOTb zB2EG9!4Yv&To8A}3+u}az*??|SNmw(db!1OaW`Fnka)JsumSAFBXP|cK%+lBgvQP5 zZxOHt_*3`+oC*pG08+}%&IU;3sCXb;8sLPu3fPLv4_0rSRLrzW( zfKym|p#i$ZG3Qqg3=9wm1Tr=^Hvv+L#bQ)dRWUR)L~(I3fYXQuXth2mEiEM+4pUZE z2Cyd{kH-j7US1B^O1B1RFz<9Y1_uWzDk|FkM`dLtEiEmywY3?{tF^V2`uciXulxG? zXlU4O&PW~&;L%!pdpjK+9XlpYdsJ6fM@>zQ@ulWfTU%=cx8;0B2F=aQ^!N9FGbdXE zxU^PSSO~DIv9U4Z*V+>Rr~LfUCMG7>*w_GY3TgnY=q9(lL0Pjx(l0J^kg^*( z2U}ZP#N%-Qr?+}onE`ZF{U?$O0N~($CKm8}bF=#-ZUG#U``WnkM0=@;k=V}x4oZjQ zuXHEcV{t=70QN~2*FACD`Y^M%w->M#O?o{xb$ir9!}$>aPOrsvp=%0AmUKzJBrc1y t;-csh#}fyM28@a?;$5OqW4r;Jegpgiqt?P@;@1EG002ovPDHLkV1oT3Z1w;E literal 0 HcmV?d00001 diff --git a/lib/f3/api/sync_on.png b/lib/f3/api/sync_on.png new file mode 100755 index 0000000000000000000000000000000000000000..e5044af075745db2ffb725f2611bcfacac939c95 GIT binary patch literal 809 zcmV+^1J?YBP)M{tTizw(O2%@g+qN@ms zX#at|NTh|G!HX5vbZ%lnA{N0Qf>FDebNhxFUWL*Tr+|hhD%MzllE%(7E;Ti)Z3Sz625RbdPBR*pCO|qBDVJfARx5 zH=jo$Y)x=mgaF)>mX-q86ciKy&hq|O%N~_t-rsYfq{W<7Enjj+S*EUbF-nPrNu~Ut9P%L?(S~J#>OZqDfwhB zwkGhHUnnap1Nbh|x%QRbEfhKI-pb#TWWmDc>iZN@ZaWP_g-8D_(ASy=gu4Lg%(HlJO?-|os#?cZnTHu zvPc0OkZ!J<;+nPb$jHbDU<)mHy*BlT)JwzpBLJLUiAzHF6p)L2H&{}f7pKLqVo+3N nFA`0tCG}DKmF?7+ZvdyS;`pQy6Lk2K00000NkvXXu0mjfgGGNF literal 0 HcmV?d00001 diff --git a/lib/f3/api/tab_a.png b/lib/f3/api/tab_a.png new file mode 100755 index 0000000000000000000000000000000000000000..170a784114dae128e94ed1f2f074bca70d1c92d2 GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfy!2~3aiye;!QqG<(jv*C{Z|5H5WN_qQPQEt% z!D%O!-}-rhW&MwLh%p^*>9AEWe)+D4W0qv-R3)Pl2A;Y1{Nh8u=3I}j`*-a9@2@YV YKQCkQ6e(m{2Q-es)78&qol`;+0GNgh%teF!%WXO?%BLs!-BjV zy*Mq?k4OkQHGH3E@jPK|tKqZ7Tib%Tg1o9)1?12Dl)v;vc{1yyl@oy0F?hQAxvXget('AGENT'); + return (bool)preg_match('/('.self::UA_Desktop.')/i',$agent) && + !$this->ismobile(); + } + + /** + * Return TRUE if user agent is a mobile device + * @return bool + **/ + function ismobile() { + $agent=Base::instance()->get('AGENT'); + return (bool)preg_match('/('.self::UA_Mobile.')/i',$agent); + } + + /** + * Return TRUE if user agent is a Web bot + * @return bool + **/ + function isbot() { + $agent=Base::instance()->get('AGENT'); + return (bool)preg_match('/('.self::UA_Bot.')/i',$agent); + } + + /** + * Return TRUE if specified ID has a valid (Luhn) Mod-10 check digit + * @return bool + * @param $id string + **/ + function mod10($id) { + if (!ctype_digit($id)) + return FALSE; + $id=strrev($id); + $sum=0; + for ($i=0,$l=strlen($id);$i<$l;$i++) + $sum+=$id[$i]+$i%2*(($id[$i]>4)*-4+$id[$i]%5); + return !($sum%10); + } + + /** + * Return credit card type if number is valid + * @return string|FALSE + * @param $id string + **/ + function card($id) { + $id=preg_replace('/[^\d]/','',$id); + if ($this->mod10($id)) { + if (preg_match('/^3[47][0-9]{13}$/',$id)) + return 'American Express'; + if (preg_match('/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/',$id)) + return 'Diners Club'; + if (preg_match('/^6(?:011|5[0-9][0-9])[0-9]{12}$/',$id)) + return 'Discover'; + if (preg_match('/^(?:2131|1800|35\d{3})\d{11}$/',$id)) + return 'JCB'; + if (preg_match('/^5[1-5][0-9]{14}$/',$id)) + return 'MasterCard'; + if (preg_match('/^4[0-9]{12}(?:[0-9]{3})?$/',$id)) + return 'Visa'; + } + return FALSE; + } + + /** + * Return entropy estimate of a password (NIST 800-63) + * @return int|float + * @param $str string + **/ + function entropy($str) { + $len=strlen($str); + return 4*min($len,1)+($len>1?(2*(min($len,8)-1)):0)+ + ($len>8?(1.5*(min($len,20)-8)):0)+($len>20?($len-20):0)+ + 6*(bool)(preg_match( + '/[A-Z].*?[0-9[:punct:]]|[0-9[:punct:]].*?[A-Z]/',$str)); + } + +} diff --git a/lib/f3/auth.php b/lib/f3/auth.php new file mode 100755 index 0000000..e0aa6dc --- /dev/null +++ b/lib/f3/auth.php @@ -0,0 +1,234 @@ +mapper,'load'), + array( + array_merge( + array( + '@'.$this->args['id'].'==? AND '. + '@'.$this->args['pw'].'==?'. + (isset($this->args['realm'])? + (' AND @'.$this->args['realm'].'==?'):''), + $id,$pw + ), + (isset($this->args['realm'])?array($realm):array()) + ) + ) + ); + } + + /** + * MongoDB storage handler + * @return bool + * @param $id string + * @param $pw string + * @param $realm string + **/ + protected function _mongo($id,$pw,$realm) { + return (bool) + $this->mapper->load( + array( + $this->args['id']=>$id, + $this->args['pw']=>$pw + )+ + (isset($this->args['realm'])? + array($this->args['realm']=>$realm):array()) + ); + } + + /** + * SQL storage handler + * @return bool + * @param $id string + * @param $pw string + * @param $realm string + **/ + protected function _sql($id,$pw,$realm) { + return (bool) + call_user_func_array( + array($this->mapper,'load'), + array( + array_merge( + array( + $this->args['id'].'=? AND '. + $this->args['pw'].'=?'. + (isset($this->args['realm'])? + (' AND '.$this->args['realm'].'=?'):''), + $id,$pw + ), + (isset($this->args['realm'])?array($realm):array()) + ) + ) + ); + } + + /** + * LDAP storage handler + * @return bool + * @param $id string + * @param $pw string + **/ + protected function _ldap($id,$pw) { + $dc=@ldap_connect($this->args['dc']); + if ($dc && + ldap_set_option($dc,LDAP_OPT_PROTOCOL_VERSION,3) && + ldap_set_option($dc,LDAP_OPT_REFERRALS,0) && + ldap_bind($dc,$this->args['rdn'],$this->args['pw']) && + ($result=ldap_search($dc,$this->args['base_dn'], + 'uid='.$id)) && + ldap_count_entries($dc,$result) && + ($info=ldap_get_entries($dc,$result)) && + @ldap_bind($dc,$info[0]['dn'],$pw) && + @ldap_close($dc)) { + return $info[0]['uid'][0]==$id; + } + user_error(self::E_LDAP); + } + + /** + * SMTP storage handler + * @return bool + * @param $id string + * @param $pw string + **/ + protected function _smtp($id,$pw) { + $socket=@fsockopen( + (strtolower($this->args['scheme'])=='ssl'? + 'ssl://':'').$this->args['host'], + $this->args['port']); + $dialog=function($cmd=NULL) use($socket) { + if (!is_null($cmd)) + fputs($socket,$cmd."\r\n"); + $reply=''; + while (!feof($socket) && + ($info=stream_get_meta_data($socket)) && + !$info['timed_out'] && $str=fgets($socket,4096)) { + $reply.=$str; + if (preg_match('/(?:^|\n)\d{3} .+\r\n/s', + $reply)) + break; + } + return $reply; + }; + if ($socket) { + stream_set_blocking($socket,TRUE); + $dialog(); + $fw=Base::instance(); + $dialog('EHLO '.$fw->get('HOST')); + if (strtolower($this->args['scheme'])=='tls') { + $dialog('STARTTLS'); + stream_socket_enable_crypto( + $socket,TRUE,STREAM_CRYPTO_METHOD_TLS_CLIENT); + $dialog('EHLO '.$fw->get('HOST')); + } + // Authenticate + $dialog('AUTH LOGIN'); + $dialog(base64_encode($id)); + $reply=$dialog(base64_encode($pw)); + $dialog('QUIT'); + fclose($socket); + return (bool)preg_match('/^235 /',$reply); + } + user_error(self::E_SMTP); + } + + /** + * Login auth mechanism + * @return bool + * @param $id string + * @param $pw string + * @param $realm string + **/ + function login($id,$pw,$realm=NULL) { + return $this->{'_'.$this->storage}($id,$pw,$realm); + } + + /** + * HTTP basic auth mechanism + * @return bool + * @param $func callback + **/ + function basic($func=NULL) { + $fw=Base::instance(); + $realm=$fw->get('REALM'); + $hdr=NULL; + if (isset($_SERVER['HTTP_AUTHORIZATION'])) + $hdr=$_SERVER['HTTP_AUTHORIZATION']; + elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) + $hdr=$_SERVER['REDIRECT_HTTP_AUTHORIZATION']; + if (!empty($hdr)) + list($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'])= + explode(':',base64_decode(substr($hdr,6))); + if (isset($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']) && + $this->login( + $_SERVER['PHP_AUTH_USER'], + $func? + $fw->call($func,$_SERVER['PHP_AUTH_PW']): + $_SERVER['PHP_AUTH_PW'], + $realm + )) + return TRUE; + if (PHP_SAPI!='cli') + header('WWW-Authenticate: Basic realm="'.$realm.'"'); + $fw->status(401); + return FALSE; + } + + /** + * Instantiate class + * @return object + * @param $storage string|object + * @param $args array + **/ + function __construct($storage,array $args=NULL) { + if (is_object($storage) && is_a($storage,'DB\Cursor')) { + $ref=new ReflectionClass(get_class($storage)); + $this->storage=basename(dirname($ref->getfilename())); + $this->mapper=$storage; + unset($ref); + } + else + $this->storage=$storage; + $this->args=$args; + } + +} diff --git a/lib/f3/base.php b/lib/f3/base.php new file mode 100755 index 0000000..8ebfae5 --- /dev/null +++ b/lib/f3/base.php @@ -0,0 +1,3119 @@ +. + +*/ + +//! Factory class for single-instance objects +abstract class Prefab { + + /** + * Return class instance + * @return static + **/ + static function instance() { + if (!Registry::exists($class=get_called_class())) { + $ref=new Reflectionclass($class); + $args=func_get_args(); + Registry::set($class, + $args?$ref->newinstanceargs($args):new $class); + } + return Registry::get($class); + } + +} + +//! Base structure +final class Base extends Prefab implements ArrayAccess { + + //@{ Framework details + const + PACKAGE='Fat-Free Framework', + VERSION='3.5.2-Dev'; + //@} + + //@{ HTTP status codes (RFC 2616) + const + HTTP_100='Continue', + HTTP_101='Switching Protocols', + HTTP_200='OK', + HTTP_201='Created', + HTTP_202='Accepted', + HTTP_203='Non-Authorative Information', + HTTP_204='No Content', + HTTP_205='Reset Content', + HTTP_206='Partial Content', + HTTP_300='Multiple Choices', + HTTP_301='Moved Permanently', + HTTP_302='Found', + HTTP_303='See Other', + HTTP_304='Not Modified', + HTTP_305='Use Proxy', + HTTP_307='Temporary Redirect', + HTTP_400='Bad Request', + HTTP_401='Unauthorized', + HTTP_402='Payment Required', + HTTP_403='Forbidden', + HTTP_404='Not Found', + HTTP_405='Method Not Allowed', + HTTP_406='Not Acceptable', + HTTP_407='Proxy Authentication Required', + HTTP_408='Request Timeout', + HTTP_409='Conflict', + HTTP_410='Gone', + HTTP_411='Length Required', + HTTP_412='Precondition Failed', + HTTP_413='Request Entity Too Large', + HTTP_414='Request-URI Too Long', + HTTP_415='Unsupported Media Type', + HTTP_416='Requested Range Not Satisfiable', + HTTP_417='Expectation Failed', + HTTP_500='Internal Server Error', + HTTP_501='Not Implemented', + HTTP_502='Bad Gateway', + HTTP_503='Service Unavailable', + HTTP_504='Gateway Timeout', + HTTP_505='HTTP Version Not Supported'; + //@} + + const + //! Mapped PHP globals + GLOBALS='GET|POST|COOKIE|REQUEST|SESSION|FILES|SERVER|ENV', + //! HTTP verbs + VERBS='GET|HEAD|POST|PUT|PATCH|DELETE|CONNECT', + //! Default directory permissions + MODE=0755, + //! Syntax highlighting stylesheet + CSS='code.css'; + + //@{ HTTP request types + const + REQ_SYNC=1, + REQ_AJAX=2; + //@} + + //@{ Error messages + const + E_Pattern='Invalid routing pattern: %s', + E_Named='Named route does not exist: %s', + E_Fatal='Fatal error: %s', + E_Open='Unable to open %s', + E_Routes='No routes specified', + E_Class='Invalid class %s', + E_Method='Invalid method %s', + E_Hive='Invalid hive key %s'; + //@} + + private + //! Globals + $hive, + //! Initial settings + $init, + //! Language lookup sequence + $languages, + //! Default fallback language + $fallback='en'; + + /** + * Sync PHP global with corresponding hive key + * @return array + * @param $key string + **/ + function sync($key) { + return $this->hive[$key]=&$GLOBALS['_'.$key]; + } + + /** + * Return the parts of specified hive key + * @return array + * @param $key string + **/ + private function cut($key) { + return preg_split('/\[\h*[\'"]?(.+?)[\'"]?\h*\]|(->)|\./', + $key,NULL,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE); + } + + /** + * Replace tokenized URL with available token values + * @return string + * @param $url array|string + * @param $params array + **/ + function build($url,$params=[]) { + $params+=$this->hive['PARAMS']; + if (is_array($url)) + foreach ($url as &$var) { + $var=$this->build($var,$params); + unset($var); + } + else { + $i=0; + $url=preg_replace_callback('/@(\w+)|\*/', + function($match) use(&$i,$params) { + $i++; + if (isset($match[1]) && + array_key_exists($match[1],$params)) + return $params[$match[1]]; + return array_key_exists($i,$params)? + $params[$i]: + $match[0]; + },$url); + } + return $url; + } + + /** + * Assemble url from alias name + * @return string + * @param $name string + * @param $params array|string + **/ + function alias($name,$params=[]) { + if (!is_array($params)) + $params=$this->parse($params); + if (empty($this->hive['ALIASES'][$name])) + user_error(sprintf(self::E_Named,$name),E_USER_ERROR); + $url=$this->build($this->hive['ALIASES'][$name],$params); + return $url; + } + + /** + * Parse string containing key-value pairs + * @return array + * @param $str string + **/ + function parse($str) { + preg_match_all('/(\w+)\h*=\h*(.+?)(?=,|$)/', + $str,$pairs,PREG_SET_ORDER); + $out=[]; + foreach ($pairs as $pair) + $out[$pair[1]]=trim($pair[2]); + return $out; + } + + /** + * Convert JS-style token to PHP expression + * @return string + * @param $str string + **/ + function compile($str) { + $fw=$this; + return preg_replace_callback( + '/(?|::)*)/', + function($var) use($fw) { + return '$'.preg_replace_callback( + '/\.(\w+)\(|\.(\w+)|\[((?:[^\[\]]*|(?R))*)\]/', + function($expr) use($fw) { + return $expr[1]? + ((function_exists($expr[1])? + ('.'.$expr[1]): + ('['.var_export($expr[1],TRUE).']')).'('): + ('['. + (isset($expr[3])? + (strlen($expr[3])? + var_export( + trim($fw->compile($expr[3])), + TRUE): + ''): + var_export(ctype_digit($expr[2])? + (int)$expr[2]: + $expr[2],TRUE)). + ']'); + }, + $var[1] + ); + }, + $str + ); + } + + /** + * Get hive key reference/contents; Add non-existent hive keys, + * array elements, and object properties by default + * @return mixed + * @param $key string + * @param $add bool + **/ + function &ref($key,$add=TRUE) { + $null=NULL; + $parts=$this->cut($key); + if ($parts[0]=='SESSION') { + @session_start(); + $this->sync('SESSION'); + } + elseif (!preg_match('/^\w+$/',$parts[0])) + user_error(sprintf(self::E_Hive,$this->stringify($key)), + E_USER_ERROR); + if ($add) + $var=&$this->hive; + else + $var=$this->hive; + $obj=FALSE; + foreach ($parts as $part) + if ($part=='->') + $obj=TRUE; + elseif ($obj) { + $obj=FALSE; + if (!is_object($var)) + $var=new stdclass; + if ($add || property_exists($var,$part)) + $var=&$var->$part; + else { + $var=&$null; + break; + } + } + else { + if (!is_array($var)) + $var=[]; + if ($add || array_key_exists($part,$var)) + $var=&$var[$part]; + else { + $var=&$null; + break; + } + } + return $var; + } + + /** + * Return TRUE if hive key is set + * (or return timestamp and TTL if cached) + * @return bool + * @param $key string + * @param $val mixed + **/ + function exists($key,&$val=NULL) { + $val=$this->ref($key,FALSE); + return isset($val)? + TRUE: + (Cache::instance()->exists($this->hash($key).'.var',$val)?:FALSE); + } + + /** + * Return TRUE if hive key is empty and not cached + * @param $key string + * @param $val mixed + * @return bool + **/ + function devoid($key,&$val=NULL) { + $val=$this->ref($key,FALSE); + return empty($val) && + (!Cache::instance()->exists($this->hash($key).'.var',$val) || + !$val); + } + + /** + * Bind value to hive key + * @return mixed + * @param $key string + * @param $val mixed + * @param $ttl int + **/ + function set($key,$val,$ttl=0) { + $time=time(); + if (preg_match('/^(GET|POST|COOKIE)\b(.+)/',$key,$expr)) { + $this->set('REQUEST'.$expr[2],$val); + if ($expr[1]=='COOKIE') { + $parts=$this->cut($key); + $jar=$this->unserialize($this->serialize($this->hive['JAR'])); + if ($ttl) + $jar['expire']=$time+$ttl; + call_user_func_array('setcookie',[$parts[1],$val]+$jar); + $_COOKIE[$parts[1]]=$val; + return $val; + } + } + else switch ($key) { + case 'CACHE': + $val=Cache::instance()->load($val,TRUE); + break; + case 'ENCODING': + ini_set('default_charset',$val); + if (extension_loaded('mbstring')) + mb_internal_encoding($val); + break; + case 'FALLBACK': + $this->fallback=$val; + $lang=$this->language($this->hive['LANGUAGE']); + case 'LANGUAGE': + if (!isset($lang)) + $val=$this->language($val); + $lex=$this->lexicon($this->hive['LOCALES']); + case 'LOCALES': + if (isset($lex) || $lex=$this->lexicon($val)) + $this->mset($lex,$this->hive['PREFIX'],$ttl); + break; + case 'TZ': + date_default_timezone_set($val); + break; + } + $ref=&$this->ref($key); + $ref=$val; + if (preg_match('/^JAR\b/',$key)) { + $jar=$this->unserialize($this->serialize($this->hive['JAR'])); + $jar['expire']-=$time; + call_user_func_array('session_set_cookie_params',$jar); + } + $cache=Cache::instance(); + if ($cache->exists($hash=$this->hash($key).'.var') || $ttl) + // Persist the key-value pair + $cache->set($hash,$val,$ttl); + return $ref; + } + + /** + * Retrieve contents of hive key + * @return mixed + * @param $key string + * @param $args string|array + **/ + function get($key,$args=NULL) { + if (is_string($val=$this->ref($key,FALSE)) && !is_null($args)) + return call_user_func_array( + [$this,'format'], + array_merge([$val],is_array($args)?$args:[$args]) + ); + if (is_null($val)) { + // Attempt to retrieve from cache + if (Cache::instance()->exists($this->hash($key).'.var',$data)) + return $data; + } + return $val; + } + + /** + * Unset hive key + * @return NULL + * @param $key string + **/ + function clear($key) { + // Normalize array literal + $cache=Cache::instance(); + $parts=$this->cut($key); + if ($key=='CACHE') + // Clear cache contents + $cache->reset(); + elseif (preg_match('/^(GET|POST|COOKIE)\b(.+)/',$key,$expr)) { + $this->clear('REQUEST'.$expr[2]); + if ($expr[1]=='COOKIE') { + $parts=$this->cut($key); + $jar=$this->hive['JAR']; + $jar['expire']=strtotime('-1 year'); + call_user_func_array('setcookie', + array_merge([$parts[1],''],$jar)); + unset($_COOKIE[$parts[1]]); + } + } + elseif ($parts[0]=='SESSION') { + @session_start(); + if (empty($parts[1])) { + // End session + session_unset(); + session_destroy(); + $this->clear('COOKIE.'.session_name()); + } + $this->sync('SESSION'); + } + if (!isset($parts[1]) && array_key_exists($parts[0],$this->init)) + // Reset global to default value + $this->hive[$parts[0]]=$this->init[$parts[0]]; + else { + eval('unset('.$this->compile('@this->hive.'.$key).');'); + if ($parts[0]=='SESSION') { + session_commit(); + session_start(); + } + if ($cache->exists($hash=$this->hash($key).'.var')) + // Remove from cache + $cache->clear($hash); + } + } + + /** + * Return TRUE if hive variable is 'on' + * @return bool + * @param $key string + **/ + function checked($key) { + $ref=&$this->ref($key); + return $ref=='on'; + } + + /** + * Return TRUE if property has public visibility + * @return bool + * @param $obj object + * @param $key string + **/ + function visible($obj,$key) { + if (property_exists($obj,$key)) { + $ref=new ReflectionProperty(get_class($obj),$key); + $out=$ref->ispublic(); + unset($ref); + return $out; + } + return FALSE; + } + + /** + * Multi-variable assignment using associative array + * @return NULL + * @param $vars array + * @param $prefix string + * @param $ttl int + **/ + function mset(array $vars,$prefix='',$ttl=0) { + foreach ($vars as $key=>$val) + $this->set($prefix.$key,$val,$ttl); + } + + /** + * Publish hive contents + * @return array + **/ + function hive() { + return $this->hive; + } + + /** + * Copy contents of hive variable to another + * @return mixed + * @param $src string + * @param $dst string + **/ + function copy($src,$dst) { + $ref=&$this->ref($dst); + return $ref=$this->ref($src,FALSE); + } + + /** + * Concatenate string to hive string variable + * @return string + * @param $key string + * @param $val string + **/ + function concat($key,$val) { + $ref=&$this->ref($key); + $ref.=$val; + return $ref; + } + + /** + * Swap keys and values of hive array variable + * @return array + * @param $key string + * @public + **/ + function flip($key) { + $ref=&$this->ref($key); + return $ref=array_combine(array_values($ref),array_keys($ref)); + } + + /** + * Add element to the end of hive array variable + * @return mixed + * @param $key string + * @param $val mixed + **/ + function push($key,$val) { + $ref=&$this->ref($key); + $ref[] = $val; + return $val; + } + + /** + * Remove last element of hive array variable + * @return mixed + * @param $key string + **/ + function pop($key) { + $ref=&$this->ref($key); + return array_pop($ref); + } + + /** + * Add element to the beginning of hive array variable + * @return mixed + * @param $key string + * @param $val mixed + **/ + function unshift($key,$val) { + $ref=&$this->ref($key); + array_unshift($ref,$val); + return $val; + } + + /** + * Remove first element of hive array variable + * @return mixed + * @param $key string + **/ + function shift($key) { + $ref=&$this->ref($key); + return array_shift($ref); + } + + /** + * Merge array with hive array variable + * @return array + * @param $key string + * @param $src string|array + **/ + function merge($key,$src) { + $ref=&$this->ref($key); + return array_merge($ref,is_string($src)?$this->hive[$src]:$src); + } + + /** + * Convert backslashes to slashes + * @return string + * @param $str string + **/ + function fixslashes($str) { + return $str?strtr($str,'\\','/'):$str; + } + + /** + * Split comma-, semi-colon, or pipe-separated string + * @return array + * @param $str string + * @param $noempty bool + **/ + function split($str,$noempty=TRUE) { + return array_map('trim', + preg_split('/[,;|]/',$str,0,$noempty?PREG_SPLIT_NO_EMPTY:0)); + } + + /** + * Convert PHP expression/value to compressed exportable string + * @return string + * @param $arg mixed + * @param $stack array + **/ + function stringify($arg,array $stack=NULL) { + if ($stack) { + foreach ($stack as $node) + if ($arg===$node) + return '*RECURSION*'; + } + else + $stack=[]; + switch (gettype($arg)) { + case 'object': + $str=''; + foreach (get_object_vars($arg) as $key=>$val) + $str.=($str?',':''). + var_export($key,TRUE).'=>'. + $this->stringify($val, + array_merge($stack,[$arg])); + return get_class($arg).'::__set_state(['.$str.'])'; + case 'array': + $str=''; + $num=isset($arg[0]) && + ctype_digit(implode('',array_keys($arg))); + foreach ($arg as $key=>$val) + $str.=($str?',':''). + ($num?'':(var_export($key,TRUE).'=>')). + $this->stringify($val,array_merge($stack,[$arg])); + return '['.$str.']'; + default: + return var_export($arg,TRUE); + } + } + + /** + * Flatten array values and return as CSV string + * @return string + * @param $args array + **/ + function csv(array $args) { + return implode(',',array_map('stripcslashes', + array_map([$this,'stringify'],$args))); + } + + /** + * Convert snakecase string to camelcase + * @return string + * @param $str string + **/ + function camelcase($str) { + return preg_replace_callback( + '/_(\w)/', + function($match) { + return strtoupper($match[1]); + }, + $str + ); + } + + /** + * Convert camelcase string to snakecase + * @return string + * @param $str string + **/ + function snakecase($str) { + return strtolower(preg_replace('/[[:upper:]]/','_\0',$str)); + } + + /** + * Return -1 if specified number is negative, 0 if zero, + * or 1 if the number is positive + * @return int + * @param $num mixed + **/ + function sign($num) { + return $num?($num/abs($num)):0; + } + + /** + * Extract values of associative array whose keys start with the given prefix + * @return array + * @param $arr array + * @param $prefix string + **/ + function extract($arr,$prefix) { + $out=[]; + foreach (preg_grep('/^'.preg_quote($prefix,'/').'/',array_keys($arr)) + as $key) + $out[substr($key,strlen($prefix))]=$arr[$key]; + return $out; + } + + /** + * Convert class constants to array + * @return array + * @param $class object|string + * @param $prefix string + **/ + function constants($class,$prefix='') { + $ref=new ReflectionClass($class); + return $this->extract($ref->getconstants(),$prefix); + } + + /** + * Generate 64bit/base36 hash + * @return string + * @param $str + **/ + function hash($str) { + return str_pad(base_convert( + substr(sha1($str),-16),16,36),11,'0',STR_PAD_LEFT); + } + + /** + * Return Base64-encoded equivalent + * @return string + * @param $data string + * @param $mime string + **/ + function base64($data,$mime) { + return 'data:'.$mime.';base64,'.base64_encode($data); + } + + /** + * Convert special characters to HTML entities + * @return string + * @param $str string + **/ + function encode($str) { + return @htmlspecialchars($str,$this->hive['BITMASK'], + $this->hive['ENCODING'])?:$this->scrub($str); + } + + /** + * Convert HTML entities back to characters + * @return string + * @param $str string + **/ + function decode($str) { + return htmlspecialchars_decode($str,$this->hive['BITMASK']); + } + + /** + * Invoke callback recursively for all data types + * @return mixed + * @param $arg mixed + * @param $func callback + * @param $stack array + **/ + function recursive($arg,$func,$stack=NULL) { + if ($stack) { + foreach ($stack as $node) + if ($arg===$node) + return $arg; + } + else + $stack=[]; + switch (gettype($arg)) { + case 'object': + if (method_exists('ReflectionClass','iscloneable')) { + $ref=new ReflectionClass($arg); + if ($ref->iscloneable()) { + $arg=clone($arg); + $cast=is_a($arg,'IteratorAggregate')? + iterator_to_array($arg):get_object_vars($arg); + foreach ($cast as $key=>$val) + $arg->$key=$this->recursive( + $val,$func,array_merge($stack,[$arg])); + } + } + return $arg; + case 'array': + $copy=[]; + foreach ($arg as $key=>$val) + $copy[$key]=$this->recursive($val,$func, + array_merge($stack,[$arg])); + return $copy; + } + return $func($arg); + } + + /** + * Remove HTML tags (except those enumerated) and non-printable + * characters to mitigate XSS/code injection attacks + * @return mixed + * @param $arg mixed + * @param $tags string + **/ + function clean($arg,$tags=NULL) { + $fw=$this; + return $this->recursive($arg, + function($val) use($fw,$tags) { + if ($tags!='*') + $val=trim(strip_tags($val, + '<'.implode('><',$fw->split($tags)).'>')); + return trim(preg_replace( + '/[\x00-\x08\x0B\x0C\x0E-\x1F]/','',$val)); + } + ); + } + + /** + * Similar to clean(), except that variable is passed by reference + * @return mixed + * @param $var mixed + * @param $tags string + **/ + function scrub(&$var,$tags=NULL) { + return $var=$this->clean($var,$tags); + } + + /** + * Return locale-aware formatted string + * @return string + **/ + function format() { + $args=func_get_args(); + $val=array_shift($args); + // Get formatting rules + $conv=localeconv(); + return preg_replace_callback( + '/\{(?P\d+)\s*(?:,\s*(?P\w+)\s*'. + '(?:,\s*(?P(?:\w+(?:\s*\{.+?\}\s*,?\s*)?)*)'. + '(?:,\s*(?P.+?))?)?)?\}/', + function($expr) use($args,$conv) { + extract($expr); + extract($conv); + if (!array_key_exists($pos,$args)) + return $expr[0]; + if (isset($type)) + switch ($type) { + case 'plural': + preg_match_all('/(?\w+)'. + '(?:\s*\{\s*(?.+?)\s*\})/', + $mod,$matches,PREG_SET_ORDER); + $ord=['zero','one','two']; + foreach ($matches as $match) { + extract($match); + if (isset($ord[$args[$pos]]) && + $tag==$ord[$args[$pos]] || $tag=='other') + return str_replace('#',$args[$pos],$data); + } + case 'number': + if (isset($mod)) + switch ($mod) { + case 'integer': + return number_format( + $args[$pos],0,'',$thousands_sep); + case 'currency': + $int=$cstm=false; + if (isset($prop) && $cstm=!$int=($prop=='int')) + $currency_symbol=$prop; + if (!$cstm && function_exists('money_format')) + return money_format( + '%'.($int?'i':'n'),$args[$pos]); + $fmt=[ + 0=>'(nc)',1=>'(n c)', + 2=>'(nc)',10=>'+nc', + 11=>'+n c',12=>'+ nc', + 20=>'nc+',21=>'n c+', + 22=>'nc +',30=>'n+c', + 31=>'n +c',32=>'n+ c', + 40=>'nc+',41=>'n c+', + 42=>'nc +',100=>'(cn)', + 101=>'(c n)',102=>'(cn)', + 110=>'+cn',111=>'+c n', + 112=>'+ cn',120=>'cn+', + 121=>'c n+',122=>'cn +', + 130=>'+cn',131=>'+c n', + 132=>'+ cn',140=>'c+n', + 141=>'c+ n',142=>'c +n' + ]; + if ($args[$pos]<0) { + $sgn=$negative_sign; + $pre='n'; + } + else { + $sgn=$positive_sign; + $pre='p'; + } + return str_replace( + ['+','n','c'], + [$sgn,number_format( + abs($args[$pos]), + $frac_digits, + $decimal_point, + $thousands_sep), + $int?$int_curr_symbol + :$currency_symbol], + $fmt[(int)( + (${$pre.'_cs_precedes'}%2). + (${$pre.'_sign_posn'}%5). + (${$pre.'_sep_by_space'}%3) + )] + ); + case 'percent': + return number_format( + $args[$pos]*100,0,$decimal_point, + $thousands_sep).'%'; + case 'decimal': + return number_format( + $args[$pos],isset($prop)?$prop:2, + $decimal_point,$thousands_sep); + } + break; + case 'date': + if (empty($mod) || $mod=='short') + $prop='%x'; + elseif ($mod=='long') + $prop='%A, %d %B %Y'; + return strftime($prop,$args[$pos]); + case 'time': + if (empty($mod) || $mod=='short') + $prop='%X'; + return strftime($prop,$args[$pos]); + default: + return $expr[0]; + } + return $args[$pos]; + }, + $val + ); + } + + /** + * Assign/auto-detect language + * @return string + * @param $code string + **/ + function language($code) { + $code=preg_replace('/\h+|;q=[0-9.]+/','',$code); + $code.=($code?',':'').$this->fallback; + $this->languages=[]; + foreach (array_reverse(explode(',',$code)) as $lang) { + if (preg_match('/^(\w{2})(?:-(\w{2}))?\b/i',$lang,$parts)) { + // Generic language + array_unshift($this->languages,$parts[1]); + if (isset($parts[2])) { + // Specific language + $parts[0]=$parts[1].'-'.($parts[2]=strtoupper($parts[2])); + array_unshift($this->languages,$parts[0]); + } + } + } + $this->languages=array_unique($this->languages); + $locales=[]; + $windows=preg_match('/^win/i',PHP_OS); + foreach ($this->languages as $locale) { + if ($windows) { + $parts=explode('-',$locale); + $locale=@constant('ISO::LC_'.$parts[0]); + if (isset($parts[1]) && + $country=@constant('ISO::CC_'.strtolower($parts[1]))) + $locale.='-'.$country; + } + $locales[]=$locale; + $locales[]=$locale.'.'.ini_get('default_charset'); + } + setlocale(LC_ALL,str_replace('-','_',$locales)); + return implode(',',$this->languages); + } + + /** + * Return lexicon entries + * @return array + * @param $path string + **/ + function lexicon($path) { + $lex=[]; + foreach ($this->languages?:explode(',',$this->fallback) as $lang) + foreach ($this->split($path) as $dir) + if ((is_file($file=($base=$dir.$lang).'.php') || + is_file($file=$base.'.php')) && + is_array($dict=require($file))) + $lex+=$dict; + elseif (is_file($file=$base.'.ini')) { + preg_match_all( + '/(?<=^|\n)(?:'. + '\[(?.+?)\]|'. + '(?[^\h\r\n;].*?)\h*=\h*'. + '(?(?:\\\\\h*\r?\n|.+?)*)'. + ')(?=\r?\n|$)/', + $this->read($file),$matches,PREG_SET_ORDER); + if ($matches) { + $prefix=''; + foreach ($matches as $match) + if ($match['prefix']) + $prefix=$match['prefix'].'.'; + elseif (!array_key_exists( + $key=$prefix.$match['lval'],$lex)) + $lex[$key]=trim(preg_replace( + '/\\\\\h*\r?\n/','',$match['rval'])); + } + } + return $lex; + } + + /** + * Return string representation of PHP value + * @return string + * @param $arg mixed + **/ + function serialize($arg) { + switch (strtolower($this->hive['SERIALIZER'])) { + case 'igbinary': + return igbinary_serialize($arg); + default: + return serialize($arg); + } + } + + /** + * Return PHP value derived from string + * @return string + * @param $arg mixed + **/ + function unserialize($arg) { + switch (strtolower($this->hive['SERIALIZER'])) { + case 'igbinary': + return igbinary_unserialize($arg); + default: + return unserialize($arg); + } + } + + /** + * Send HTTP status header; Return text equivalent of status code + * @return string + * @param $code int + **/ + function status($code) { + $reason=@constant('self::HTTP_'.$code); + if (PHP_SAPI!='cli' && !headers_sent()) + header($_SERVER['SERVER_PROTOCOL'].' '.$code.' '.$reason); + return $reason; + } + + /** + * Send cache metadata to HTTP client + * @return NULL + * @param $secs int + **/ + function expire($secs=0) { + if (PHP_SAPI!='cli') { + header('X-Content-Type-Options: nosniff'); + header('X-Frame-Options: '.$this->hive['XFRAME']); + header('X-Powered-By: '.$this->hive['PACKAGE']); + header('X-XSS-Protection: 1; mode=block'); + if ($secs) { + $time=microtime(TRUE); + header_remove('Pragma'); + header('Expires: '.gmdate('r',$time+$secs)); + header('Cache-Control: max-age='.$secs); + header('Last-Modified: '.gmdate('r')); + } + else + header('Cache-Control: no-cache, no-store, must-revalidate'); + } + } + + /** + * Return HTTP user agent + * @return string + **/ + function agent() { + $headers=$this->hive['HEADERS']; + return isset($headers['X-Operamini-Phone-UA'])? + $headers['X-Operamini-Phone-UA']: + (isset($headers['X-Skyfire-Phone'])? + $headers['X-Skyfire-Phone']: + (isset($headers['User-Agent'])? + $headers['User-Agent']:'')); + } + + /** + * Return TRUE if XMLHttpRequest detected + * @return bool + **/ + function ajax() { + $headers=$this->hive['HEADERS']; + return isset($headers['X-Requested-With']) && + $headers['X-Requested-With']=='XMLHttpRequest'; + } + + /** + * Sniff IP address + * @return string + **/ + function ip() { + $headers=$this->hive['HEADERS']; + return isset($headers['Client-IP'])? + $headers['Client-IP']: + (isset($headers['X-Forwarded-For'])? + $headers['X-Forwarded-For']: + (isset($_SERVER['REMOTE_ADDR'])? + $_SERVER['REMOTE_ADDR']:'')); + } + + /** + * Return filtered, formatted stack trace + * @return string|array + * @param $trace array|NULL + * @param $format bool + **/ + function trace(array $trace=NULL, $format=TRUE) { + if (!$trace) { + $trace=debug_backtrace(FALSE); + $frame=$trace[0]; + if (isset($frame['file']) && $frame['file']==__FILE__) + array_shift($trace); + } + $debug=$this->hive['DEBUG']; + $trace=array_filter( + $trace, + function($frame) use($debug) { + return $debug && isset($frame['file']) && + ($frame['file']!=__FILE__ || $debug>1) && + (empty($frame['function']) || + !preg_match('/^(?:(?:trigger|user)_error|'. + '__call|call_user_func)/',$frame['function'])); + } + ); + if (!$format) + return $trace; + $out=''; + $eol="\n"; + // Analyze stack trace + foreach ($trace as $frame) { + $line=''; + if (isset($frame['class'])) + $line.=$frame['class'].$frame['type']; + if (isset($frame['function'])) + $line.=$frame['function'].'('. + ($debug>2 && isset($frame['args'])? + $this->csv($frame['args']):'').')'; + $src=$this->fixslashes(str_replace($_SERVER['DOCUMENT_ROOT']. + '/','',$frame['file'])).':'.$frame['line']; + $out.='['.$src.'] '.$line.$eol; + } + return $out; + } + + /** + * Log error; Execute ONERROR handler if defined, else display + * default error page (HTML for synchronous requests, JSON string + * for AJAX requests) + * @return NULL + * @param $code int + * @param $text string + * @param $trace array + **/ + function error($code,$text='',array $trace=NULL) { + $prior=$this->hive['ERROR']; + $header=$this->status($code); + $req=$this->hive['VERB'].' '.$this->hive['PATH']; + if (!$text) + $text='HTTP '.$code.' ('.$req.')'; + error_log($text); + $trace=$this->trace($trace); + foreach (explode("\n",$trace) as $nexus) + if ($nexus) + error_log($nexus); + if ($highlight=PHP_SAPI!='cli' && !$this->hive['AJAX'] && + $this->hive['HIGHLIGHT'] && is_file($css=__DIR__.'/'.self::CSS)) + $trace=$this->highlight($trace); + $this->hive['ERROR']=[ + 'status'=>$header, + 'code'=>$code, + 'text'=>$text, + 'trace'=>$trace + ]; + $handler=$this->hive['ONERROR']; + $this->hive['ONERROR']=NULL; + $eol="\n"; + if ((!$handler || + $this->call($handler,[$this,$this->hive['PARAMS']], + 'beforeroute,afterroute')===FALSE) && + !$prior && PHP_SAPI!='cli' && !$this->hive['QUIET']) + echo $this->hive['AJAX']? + json_encode($this->hive['ERROR']): + (''.$eol. + ''.$eol. + ''. + ''.$code.' '.$header.''. + ($highlight? + (''):''). + ''.$eol. + ''.$eol. + '

'.$header.'

'.$eol. + '

'.$this->encode($text?:$req).'

'.$eol. + ($this->hive['DEBUG']?('
'.$trace.'
'.$eol):''). + ''.$eol. + ''); + if ($this->hive['HALT']) + die; + } + + /** + * Mock HTTP request + * @return mixed + * @param $pattern string + * @param $args array + * @param $headers array + * @param $body string + **/ + function mock($pattern, + array $args=NULL,array $headers=NULL,$body=NULL) { + if (!$args) + $args=[]; + $types=['sync','ajax']; + preg_match('/([\|\w]+)\h+(?:@(\w+)(?:(\(.+?)\))*|([^\h]+))'. + '(?:\h+\[('.implode('|',$types).')\])?/',$pattern,$parts); + $verb=strtoupper($parts[1]); + if ($parts[2]) { + if (empty($this->hive['ALIASES'][$parts[2]])) + user_error(sprintf(self::E_Named,$parts[2]),E_USER_ERROR); + $parts[4]=$this->hive['ALIASES'][$parts[2]]; + $parts[4]=$this->build($parts[4], + isset($parts[3])?$this->parse($parts[3]):[]); + } + if (empty($parts[4])) + user_error(sprintf(self::E_Pattern,$pattern),E_USER_ERROR); + $url=parse_url($parts[4]); + parse_str(@$url['query'],$GLOBALS['_GET']); + if (preg_match('/GET|HEAD/',$verb)) + $GLOBALS['_GET']=array_merge($GLOBALS['_GET'],$args); + $GLOBALS['_POST']=$verb=='POST'?$args:[]; + $GLOBALS['_REQUEST']=array_merge($GLOBALS['_GET'],$GLOBALS['_POST']); + foreach ($headers?:[] as $key=>$val) + $_SERVER['HTTP_'.strtr(strtoupper($key),'-','_')]=$val; + $this->hive['VERB']=$verb; + $this->hive['URI']=$this->hive['BASE'].$url['path']; + if ($GLOBALS['_GET']) + $this->hive['URI'].='?'.http_build_query($GLOBALS['_GET']); + $this->hive['BODY']=''; + if (!preg_match('/GET|HEAD/',$verb)) + $this->hive['BODY']=$body?:http_build_query($args); + $this->hive['AJAX']=isset($parts[5]) && + preg_match('/ajax/i',$parts[5]); + return $this->run(); + } + + /** + * Bind handler to route pattern + * @return NULL + * @param $pattern string|array + * @param $handler callback + * @param $ttl int + * @param $kbps int + **/ + function route($pattern,$handler,$ttl=0,$kbps=0) { + $types=['sync','ajax']; + $alias=null; + if (is_array($pattern)) { + foreach ($pattern as $item) + $this->route($item,$handler,$ttl,$kbps); + return; + } + preg_match('/([\|\w]+)\h+(?:(?:@(\w+)\h*:\h*)?(@(\w+)|[^\h]+))'. + '(?:\h+\[('.implode('|',$types).')\])?/',$pattern,$parts); + if (isset($parts[2]) && $parts[2]) + $this->hive['ALIASES'][$alias=$parts[2]]=$parts[3]; + elseif (!empty($parts[4])) { + if (empty($this->hive['ALIASES'][$parts[4]])) + user_error(sprintf(self::E_Named,$parts[4]),E_USER_ERROR); + $parts[3]=$this->hive['ALIASES'][$alias=$parts[4]]; + } + if (empty($parts[3])) + user_error(sprintf(self::E_Pattern,$pattern),E_USER_ERROR); + $type=empty($parts[5])? + self::REQ_SYNC|self::REQ_AJAX: + constant('self::REQ_'.strtoupper($parts[5])); + foreach ($this->split($parts[1]) as $verb) { + if (!preg_match('/'.self::VERBS.'/',$verb)) + $this->error(501,$verb.' '.$this->hive['URI']); + $this->hive['ROUTES'][$parts[3]][$type][strtoupper($verb)]= + [$handler,$ttl,$kbps,$alias]; + } + } + + /** + * Reroute to specified URI + * @return NULL + * @param $url string + * @param $permanent bool + **/ + function reroute($url=NULL,$permanent=FALSE) { + if (!$url) + $url=$this->hive['REALM']; + if (preg_match('/^(?:@(\w+)(?:(\(.+?)\))*(\?.+)*)/',$url,$parts)) { + if (empty($this->hive['ALIASES'][$parts[1]])) + user_error(sprintf(self::E_Named,$parts[1]),E_USER_ERROR); + $url=$this->hive['ALIASES'][$parts[1]]; + } + $url=$this->build($url,isset($parts[2])?$this->parse($parts[2]):[]). + (isset($parts[3])?$parts[3]:''); + if (($handler=$this->hive['ONREROUTE']) && + $this->call($handler,[$url,$permanent])!==FALSE) + return; + if ($url[0]=='/') + $url=$this->hive['SCHEME'].'://'. + $this->hive['HOST'].(($port=$this->hive['PORT']) && $port!=80 && + $port!=443?(':'.$port):'').$this->hive['BASE'].$url; + if (PHP_SAPI!='cli') { + header('Location: '.$url); + $this->status($permanent?301:302); + die; + } + $this->mock('GET '.$url); + } + + /** + * Provide ReST interface by mapping HTTP verb to class method + * @return NULL + * @param $url string + * @param $class string|object + * @param $ttl int + * @param $kbps int + **/ + function map($url,$class,$ttl=0,$kbps=0) { + if (is_array($url)) { + foreach ($url as $item) + $this->map($item,$class,$ttl,$kbps); + return; + } + foreach (explode('|',self::VERBS) as $method) + $this->route($method.' '.$url,is_string($class)? + $class.'->'.$this->hive['PREMAP'].strtolower($method): + [$class,$this->hive['PREMAP'].strtolower($method)], + $ttl,$kbps); + } + + /** + * Redirect a route to another URL + * @return NULL + * @param $pattern string|array + * @param $url string + * @param $permanent bool + */ + function redirect($pattern,$url,$permanent=TRUE) { + if (is_array($pattern)) { + foreach ($pattern as $item) + $this->redirect($item,$url,$permanent); + return; + } + $this->route($pattern,function($fw) use($url,$permanent) { + $fw->reroute($url,$permanent); + }); + } + + /** + * Return TRUE if IPv4 address exists in DNSBL + * @return bool + * @param $ip string + **/ + function blacklisted($ip) { + if ($this->hive['DNSBL'] && + !in_array($ip, + is_array($this->hive['EXEMPT'])? + $this->hive['EXEMPT']: + $this->split($this->hive['EXEMPT']))) { + // Reverse IPv4 dotted quad + $rev=implode('.',array_reverse(explode('.',$ip))); + foreach (is_array($this->hive['DNSBL'])? + $this->hive['DNSBL']: + $this->split($this->hive['DNSBL']) as $server) + // DNSBL lookup + if (checkdnsrr($rev.'.'.$server,'A')) + return TRUE; + } + return FALSE; + } + + /** + * Applies the specified URL mask and returns parameterized matches + * @return $args array + * @param $pattern string + * @param $url string|NULL + **/ + function mask($pattern,$url=NULL) { + if (!$url) + $url=$this->rel($this->hive['URI']); + $case=$this->hive['CASELESS']?'i':''; + preg_match('/^'. + preg_replace('/((\\\{)?@(\w+\b)(?(2)\\\}))/','(?P<\3>[^\/\?]+)', + str_replace('\*','([^\?]+)',preg_quote($pattern,'/'))). + '\/?$/'.$case.'um',$url,$args); + return $args; + } + + /** + * Match routes against incoming URI + * @return mixed + **/ + function run() { + if ($this->blacklisted($this->hive['IP'])) + // Spammer detected + $this->error(403); + if (!$this->hive['ROUTES']) + // No routes defined + user_error(self::E_Routes,E_USER_ERROR); + // Match specific routes first + $paths=[]; + foreach ($keys=array_keys($this->hive['ROUTES']) as $key) + $paths[]=str_replace('@','*@',$key); + $vals=array_values($this->hive['ROUTES']); + array_multisort($paths,SORT_DESC,$keys,$vals); + $this->hive['ROUTES']=array_combine($keys,$vals); + // Convert to BASE-relative URL + $req=$this->rel(urldecode($this->hive['PATH'])); + if ($cors=(isset($this->hive['HEADERS']['Origin']) && + $this->hive['CORS']['origin'])) { + $cors=$this->hive['CORS']; + header('Access-Control-Allow-Origin: '.$cors['origin']); + header('Access-Control-Allow-Credentials: '. + ($cors['credentials']?'true':'false')); + } + $allowed=[]; + foreach ($this->hive['ROUTES'] as $pattern=>$routes) { + if (!$args=$this->mask($pattern,$req)) + continue; + ksort($args); + $route=NULL; + if (isset( + $routes[$ptr=$this->hive['AJAX']+1][$this->hive['VERB']])) + $route=$routes[$ptr]; + elseif (isset($routes[self::REQ_SYNC|self::REQ_AJAX])) + $route=$routes[self::REQ_SYNC|self::REQ_AJAX]; + if (!$route) + continue; + if ($this->hive['VERB']!='OPTIONS' && + isset($route[$this->hive['VERB']])) { + if ($this->hive['VERB']=='GET' && + preg_match('/.+\/$/',$this->hive['PATH'])) + $this->reroute(substr($this->hive['PATH'],0,-1). + ($this->hive['QUERY']?('?'.$this->hive['QUERY']):'')); + list($handler,$ttl,$kbps,$alias)=$route[$this->hive['VERB']]; + if (is_bool(strpos($pattern,'/*'))) + foreach (array_keys($args) as $key) + if (is_numeric($key) && $key) + unset($args[$key]); + // Capture values of route pattern tokens + $this->hive['PARAMS']=$args; + // Save matching route + $this->hive['ALIAS']=$alias; + $this->hive['PATTERN']=$pattern; + if ($cors && $cors['expose']) + header('Access-Control-Expose-Headers: '.(is_array($cors['expose'])? + implode(',',$cors['expose']):$cors['expose'])); + if (is_string($handler)) { + // Replace route pattern tokens in handler if any + $handler=preg_replace_callback('/({)?@(\w+\b)(?(1)})/', + function($id) use($args) { + $pid=count($id)>2?2:1; + return isset($args[$id[$pid]])?$args[$id[$pid]]:$id[0]; + }, + $handler + ); + if (preg_match('/(.+)\h*(?:->|::)/',$handler,$match) && + !class_exists($match[1])) + $this->error(404); + } + // Process request + $result=NULL; + $body=''; + $now=microtime(TRUE); + if (preg_match('/GET|HEAD/',$this->hive['VERB']) && $ttl) { + // Only GET and HEAD requests are cacheable + $headers=$this->hive['HEADERS']; + $cache=Cache::instance(); + $cached=$cache->exists( + $hash=$this->hash($this->hive['VERB'].' '. + $this->hive['URI']).'.url',$data); + if ($cached) { + if (isset($headers['If-Modified-Since']) && + strtotime($headers['If-Modified-Since'])+ + $ttl>$now) { + $this->status(304); + die; + } + // Retrieve from cache backend + list($headers,$body,$result)=$data; + if (PHP_SAPI!='cli') + array_walk($headers,'header'); + $this->expire($cached[0]+$ttl-$now); + } + else + // Expire HTTP client-cached page + $this->expire($ttl); + } + else + $this->expire(0); + if (!strlen($body)) { + if (!$this->hive['RAW'] && !$this->hive['BODY']) + $this->hive['BODY']=file_get_contents('php://input'); + ob_start(); + // Call route handler + $result=$this->call($handler,[$this,$args], + 'beforeroute,afterroute'); + $body=ob_get_clean(); + if (isset($cache) && !error_get_last()) { + // Save to cache backend + $cache->set($hash,[ + // Remove cookies + preg_grep('/Set-Cookie\:/',headers_list(), + PREG_GREP_INVERT),$body,$result],$ttl); + } + } + $this->hive['RESPONSE']=$body; + if (!$this->hive['QUIET']) { + if ($kbps) { + $ctr=0; + foreach (str_split($body,1024) as $part) { + // Throttle output + $ctr++; + if ($ctr/$kbps>($elapsed=microtime(TRUE)-$now) && + !connection_aborted()) + usleep(1e6*($ctr/$kbps-$elapsed)); + echo $part; + } + } + else + echo $body; + } + return $result; + } + $allowed=array_merge($allowed,array_keys($route)); + } + if (!$allowed) + // URL doesn't match any route + $this->error(404); + elseif (PHP_SAPI!='cli') { + // Unhandled HTTP method + header('Allow: '.implode(',',array_unique($allowed))); + if ($cors) { + header('Access-Control-Allow-Methods: OPTIONS,'. + implode(',',$allowed)); + if ($cors['headers']) + header('Access-Control-Allow-Headers: '. + (is_array($cors['headers'])? + implode(',',$cors['headers']): + $cors['headers'])); + if ($cors['ttl']>0) + header('Access-Control-Max-Age: '.$cors['ttl']); + } + if ($this->hive['VERB']!='OPTIONS') + $this->error(405); + } + return FALSE; + } + + /** + * Loop until callback returns TRUE (for long polling) + * @return mixed + * @param $func callback + * @param $args array + * @param $timeout int + **/ + function until($func,$args=NULL,$timeout=60) { + if (!$args) + $args=[]; + $time=time(); + $max=ini_get('max_execution_time'); + $limit=max(0,($max?min($timeout,$max):$timeout)-1); + $out=''; + // Turn output buffering on + ob_start(); + // Not for the weak of heart + while ( + // No error occurred + !$this->hive['ERROR'] && + // Got time left? + time()-$time+1<$limit && + // Still alive? + !connection_aborted() && + // Restart session + @session_start() && + // CAUTION: Callback will kill host if it never becomes truthy! + !$out=$this->call($func,$args)) { + if (PHP_SAPI!='cli') + session_commit(); + // Hush down + sleep(1); + } + ob_flush(); + flush(); + return $out; + } + + /** + * Disconnect HTTP client + **/ + function abort() { + @session_start(); + session_commit(); + $out=''; + while (ob_get_level()) + $out=ob_get_clean().$out; + header('Content-Length: '.strlen($out)); + echo $out; + flush(); + if (function_exists('fastcgi_finish_request')) + fastcgi_finish_request(); + } + + /** + * Grab the real route handler behind the string expression + * @return string|array + * @param $func string + * @param $args array + **/ + function grab($func,$args=NULL) { + if (preg_match('/(.+)\h*(->|::)\h*(.+)/s',$func,$parts)) { + // Convert string to executable PHP callback + if (!class_exists($parts[1])) + user_error(sprintf(self::E_Class,$parts[1]),E_USER_ERROR); + if ($parts[2]=='->') { + if (is_subclass_of($parts[1],'Prefab')) + $parts[1]=call_user_func($parts[1].'::instance'); + else { + $ref=new ReflectionClass($parts[1]); + $parts[1]=method_exists($parts[1],'__construct') && $args? + $ref->newinstanceargs($args): + $ref->newinstance(); + } + } + $func=[$parts[1],$parts[3]]; + } + return $func; + } + + /** + * Execute callback/hooks (supports 'class->method' format) + * @return mixed|FALSE + * @param $func callback + * @param $args mixed + * @param $hooks string + **/ + function call($func,$args=NULL,$hooks='') { + if (!is_array($args)) + $args=[$args]; + // Grab the real handler behind the string representation + if (is_string($func)) + $func=$this->grab($func,$args); + // Execute function; abort if callback/hook returns FALSE + if (!is_callable($func)) + // No route handler + if ($hooks=='beforeroute,afterroute') { + $allowed=[]; + if (is_array($func)) + $allowed=array_intersect( + array_map('strtoupper',get_class_methods($func[0])), + explode('|',self::VERBS) + ); + header('Allow: '.implode(',',$allowed)); + $this->error(405); + } + else + user_error(sprintf(self::E_Method, + is_string($func)?$func:$this->stringify($func)), + E_USER_ERROR); + $obj=FALSE; + if (is_array($func)) { + $hooks=$this->split($hooks); + $obj=TRUE; + } + // Execute pre-route hook if any + if ($obj && $hooks && in_array($hook='beforeroute',$hooks) && + method_exists($func[0],$hook) && + call_user_func_array([$func[0],$hook],$args)===FALSE) + return FALSE; + // Execute callback + $out=call_user_func_array($func,$args?:[]); + if ($out===FALSE) + return FALSE; + // Execute post-route hook if any + if ($obj && $hooks && in_array($hook='afterroute',$hooks) && + method_exists($func[0],$hook) && + call_user_func_array([$func[0],$hook],$args)===FALSE) + return FALSE; + return $out; + } + + /** + * Execute specified callbacks in succession; Apply same arguments + * to all callbacks + * @return array + * @param $funcs array|string + * @param $args mixed + **/ + function chain($funcs,$args=NULL) { + $out=[]; + foreach (is_array($funcs)?$funcs:$this->split($funcs) as $func) + $out[]=$this->call($func,$args); + return $out; + } + + /** + * Execute specified callbacks in succession; Relay result of + * previous callback as argument to the next callback + * @return array + * @param $funcs array|string + * @param $args mixed + **/ + function relay($funcs,$args=NULL) { + foreach (is_array($funcs)?$funcs:$this->split($funcs) as $func) + $args=[$this->call($func,$args)]; + return array_shift($args); + } + + /** + * Configure framework according to .ini-style file settings; + * If optional 2nd arg is provided, template strings are interpreted + * @return object + * @param $file string + * @param $allow bool + **/ + function config($file,$allow=FALSE) { + preg_match_all( + '/(?<=^|\n)(?:'. + '\[(?
.+?)\]|'. + '(?[^\h\r\n;].*?)\h*=\h*'. + '(?(?:\\\\\h*\r?\n|.+?)*)'. + ')(?=\r?\n|$)/', + $this->read($file), + $matches,PREG_SET_ORDER); + if ($matches) { + $sec='globals'; + foreach ($matches as $match) { + if ($match['section']) { + $sec=$match['section']; + if (preg_match('/^(?!(?:global|config|route|map|redirect)s\b)'. + '((?:\.?\w)+)/i',$sec,$msec) && !$this->exists($msec[0])) + $this->set($msec[0],NULL); + } + else { + if ($allow) { + $match['lval']=Preview::instance()-> + resolve($match['lval']); + $match['rval']=Preview::instance()-> + resolve($match['rval']); + } + if (preg_match('/^(config|route|map|redirect)s\b/i', + $sec,$cmd)) { + call_user_func_array( + [$this,$cmd[1]], + array_merge([$match['lval']], + str_getcsv($match['rval']))); + } + else { + $args=array_map( + function($val) { + if (is_numeric($val)) + return $val+0; + $val=ltrim($val); + if (preg_match('/^\w+$/i',$val) && + defined($val)) + return constant($val); + return trim(preg_replace( + ['/\\\\"/','/\\\\\h*(\r?\n)/'], + ['"','\1'],$val)); + }, + // Mark quoted strings with 0x00 whitespace + str_getcsv(preg_replace('/(?[^:]+)(?:\:(?.+))?/', + $sec,$parts); + $func=isset($parts['func'])?$parts['func']:NULL; + $custom=(strtolower($parts['section'])!='globals'); + if ($func) + $args=[$this->call($func, + count($args)>1?[$args]:$args)]; + call_user_func_array( + [$this,'set'], + array_merge( + [ + ($custom?($parts['section'].'.'):''). + $match['lval'] + ], + count($args)>1?[$args]:$args + ) + ); + } + } + } + } + return $this; + } + + /** + * Create mutex, invoke callback then drop ownership when done + * @return mixed + * @param $id string + * @param $func callback + * @param $args mixed + **/ + function mutex($id,$func,$args=NULL) { + if (!is_dir($tmp=$this->hive['TEMP'])) + mkdir($tmp,self::MODE,TRUE); + // Use filesystem lock + if (is_file($lock=$tmp. + $this->hash($this->hive['ROOT'].$this->hive['BASE']).'.'. + $this->hash($id).'.lock') && + filemtime($lock)+ini_get('max_execution_time')call($func,$args); + fclose($handle); + @unlink($lock); + return $out; + } + + /** + * Read file (with option to apply Unix LF as standard line ending) + * @return string + * @param $file string + * @param $lf bool + **/ + function read($file,$lf=FALSE) { + $out=@file_get_contents($file); + return $lf?preg_replace('/\r\n|\r/',"\n",$out):$out; + } + + /** + * Exclusive file write + * @return int|FALSE + * @param $file string + * @param $data mixed + * @param $append bool + **/ + function write($file,$data,$append=FALSE) { + return file_put_contents($file,$data,LOCK_EX|($append?FILE_APPEND:0)); + } + + /** + * Apply syntax highlighting + * @return string + * @param $text string + **/ + function highlight($text) { + $out=''; + $pre=FALSE; + $text=trim($text); + if ($text && !preg_match('/^<\?php/',$text)) { + $text=''. + $this->encode($token[1]).''): + ('>'.$this->encode($token))). + ''; + return $out?(''.$out.''):$text; + } + + /** + * Dump expression with syntax highlighting + * @return NULL + * @param $expr mixed + **/ + function dump($expr) { + echo $this->highlight($this->stringify($expr)); + } + + /** + * Return path (and query parameters) relative to the base directory + * @return string + * @param $url string + **/ + function rel($url) { + return preg_replace('/^(?:https?:\/\/)?'. + preg_quote($this->hive['BASE'],'/').'(\/.*|$)/','\1',$url); + } + + /** + * Namespace-aware class autoloader + * @return mixed + * @param $class string + **/ + protected function autoload($class) { + $class=$this->fixslashes(ltrim($class,'\\')); + $func=NULL; + if (is_array($path=$this->hive['AUTOLOAD']) && + isset($path[1]) && is_callable($path[1])) + list($path,$func)=$path; + foreach ($this->split($this->hive['PLUGINS'].';'.$path) as $auto) + if ($func && is_file($file=$func($auto.$class).'.php') || + is_file($file=$auto.$class.'.php') || + is_file($file=$auto.strtolower($class).'.php') || + is_file($file=strtolower($auto.$class).'.php')) + return require($file); + } + + /** + * Execute framework/application shutdown sequence + * @return NULL + * @param $cwd string + **/ + function unload($cwd) { + chdir($cwd); + if (!$error=error_get_last()) + @session_commit(); + $handler=$this->hive['UNLOAD']; + if ((!$handler || $this->call($handler,$this)===FALSE) && + $error && in_array($error['type'], + [E_ERROR,E_PARSE,E_CORE_ERROR,E_COMPILE_ERROR])) + // Fatal error detected + $this->error(500, + sprintf(self::E_Fatal,$error['message']),[$error]); + } + + /** + * Convenience method for checking hive key + * @return mixed + * @param $key string + **/ + function offsetexists($key) { + return $this->exists($key); + } + + /** + * Convenience method for assigning hive value + * @return mixed + * @param $key string + * @param $val scalar + **/ + function offsetset($key,$val) { + return $this->set($key,$val); + } + + /** + * Convenience method for retrieving hive value + * @return mixed + * @param $key string + **/ + function &offsetget($key) { + $val=&$this->ref($key); + return $val; + } + + /** + * Convenience method for removing hive key + * @return NULL + * @param $key string + **/ + function offsetunset($key) { + $this->clear($key); + } + + /** + * Alias for offsetexists() + * @return mixed + * @param $key string + **/ + function __isset($key) { + return $this->offsetexists($key); + } + + /** + * Alias for offsetset() + * @return mixed + * @param $key string + * @param $val mixed + **/ + function __set($key,$val) { + return $this->offsetset($key,$val); + } + + /** + * Alias for offsetget() + * @return mixed + * @param $key string + **/ + function &__get($key) { + $val=&$this->offsetget($key); + return $val; + } + + /** + * Alias for offsetunset() + * @return mixed + * @param $key string + **/ + function __unset($key) { + $this->offsetunset($key); + } + + /** + * Call function identified by hive key + * @return mixed + * @param $key string + * @param $args array + **/ + function __call($key,$args) { + return call_user_func_array($this->get($key),$args); + } + + //! Prohibit cloning + private function __clone() { + } + + //! Bootstrap + function __construct() { + // Managed directives + ini_set('default_charset',$charset='UTF-8'); + if (extension_loaded('mbstring')) + mb_internal_encoding($charset); + ini_set('display_errors',0); + // Deprecated directives + @ini_set('magic_quotes_gpc',0); + @ini_set('register_globals',0); + // Intercept errors/exceptions; PHP5.3-compatible + $check=error_reporting((E_ALL|E_STRICT)&~(E_NOTICE|E_USER_NOTICE)); + $fw=$this; + set_exception_handler( + function($obj) use($fw) { + $fw->hive['EXCEPTION']=$obj; + $fw->error(500,$obj->getmessage(),$obj->gettrace()); + } + ); + set_error_handler( + function($code,$text) use($fw) { + if ($code & error_reporting()) + $fw->error(500,$text); + } + ); + if (!isset($_SERVER['SERVER_NAME'])) + $_SERVER['SERVER_NAME']=gethostname(); + if (PHP_SAPI=='cli') { + // Emulate HTTP request + if (isset($_SERVER['argc']) && $_SERVER['argc']<2) { + $_SERVER['argc']++; + $_SERVER['argv'][1]='/'; + } + $_SERVER['REQUEST_METHOD']='GET'; + $_SERVER['REQUEST_URI']=$_SERVER['argv'][1]; + } + $headers=[]; + if (PHP_SAPI!='cli') + foreach (array_keys($_SERVER) as $key) + if (substr($key,0,5)=='HTTP_') + $headers[strtr(ucwords(strtolower(strtr( + substr($key,5),'_',' '))),' ','-')]=&$_SERVER[$key]; + if (isset($headers['X-HTTP-Method-Override'])) + $_SERVER['REQUEST_METHOD']=$headers['X-HTTP-Method-Override']; + elseif ($_SERVER['REQUEST_METHOD']=='POST' && isset($_POST['_method'])) + $_SERVER['REQUEST_METHOD']=$_POST['_method']; + $scheme=isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']=='on' || + isset($headers['X-Forwarded-Proto']) && + $headers['X-Forwarded-Proto']=='https'?'https':'http'; + // Create hive early on to expose header methods + $this->hive=['HEADERS'=>$headers]; + if (function_exists('apache_setenv')) { + // Work around Apache pre-2.4 VirtualDocumentRoot bug + $_SERVER['DOCUMENT_ROOT']=str_replace($_SERVER['SCRIPT_NAME'],'', + $_SERVER['SCRIPT_FILENAME']); + apache_setenv("DOCUMENT_ROOT",$_SERVER['DOCUMENT_ROOT']); + } + $_SERVER['DOCUMENT_ROOT']=realpath($_SERVER['DOCUMENT_ROOT']); + $base=''; + if (PHP_SAPI!='cli') + $base=rtrim($this->fixslashes( + dirname($_SERVER['SCRIPT_NAME'])),'/'); + $uri=parse_url($_SERVER['REQUEST_URI']); + $path=preg_replace('/^'.preg_quote($base,'/').'/','',$uri['path']); + call_user_func_array('session_set_cookie_params', + $jar=[ + 'expire'=>0, + 'path'=>$base?:'/', + 'domain'=>is_int(strpos($_SERVER['SERVER_NAME'],'.')) && + !filter_var($_SERVER['SERVER_NAME'],FILTER_VALIDATE_IP)? + $_SERVER['SERVER_NAME']:'', + 'secure'=>($scheme=='https'), + 'httponly'=>TRUE + ] + ); + $port=0; + if (isset($_SERVER['SERVER_PORT'])) + $port=$_SERVER['SERVER_PORT']; + // Default configuration + $this->hive+=[ + 'AGENT'=>$this->agent(), + 'AJAX'=>$this->ajax(), + 'ALIAS'=>NULL, + 'ALIASES'=>[], + 'AUTOLOAD'=>'./', + 'BASE'=>$base, + 'BITMASK'=>ENT_COMPAT, + 'BODY'=>NULL, + 'CACHE'=>FALSE, + 'CASELESS'=>TRUE, + 'CONFIG'=>NULL, + 'CORS'=>[ + 'headers'=>'', + 'origin'=>FALSE, + 'credentials'=>FALSE, + 'expose'=>FALSE, + 'ttl'=>0 + ], + 'DEBUG'=>0, + 'DIACRITICS'=>[], + 'DNSBL'=>'', + 'EMOJI'=>[], + 'ENCODING'=>$charset, + 'ERROR'=>NULL, + 'ESCAPE'=>TRUE, + 'EXCEPTION'=>NULL, + 'EXEMPT'=>NULL, + 'FALLBACK'=>$this->fallback, + 'FRAGMENT'=>isset($uri['fragment'])?$uri['fragment']:'', + 'HALT'=>TRUE, + 'HIGHLIGHT'=>TRUE, + 'HOST'=>$_SERVER['SERVER_NAME'], + 'IP'=>$this->ip(), + 'JAR'=>$jar, + 'LANGUAGE'=>isset($headers['Accept-Language'])? + $this->language($headers['Accept-Language']): + $this->fallback, + 'LOCALES'=>'./', + 'LOGS'=>'./', + 'ONERROR'=>NULL, + 'ONREROUTE'=>NULL, + 'PACKAGE'=>self::PACKAGE, + 'PARAMS'=>[], + 'PATH'=>$path, + 'PATTERN'=>NULL, + 'PLUGINS'=>$this->fixslashes(__DIR__).'/', + 'PORT'=>$port, + 'PREFIX'=>NULL, + 'PREMAP'=>'', + 'QUERY'=>isset($uri['query'])?$uri['query']:'', + 'QUIET'=>FALSE, + 'RAW'=>FALSE, + 'REALM'=>$scheme.'://'.$_SERVER['SERVER_NAME']. + ($port && $port!=80 && $port!=443? + (':'.$port):'').$_SERVER['REQUEST_URI'], + 'RESPONSE'=>'', + 'ROOT'=>$_SERVER['DOCUMENT_ROOT'], + 'ROUTES'=>[], + 'SCHEME'=>$scheme, + 'SERIALIZER'=>extension_loaded($ext='igbinary')?$ext:'php', + 'TEMP'=>'tmp/', + 'TIME'=>&$_SERVER['REQUEST_TIME_FLOAT'], + 'TZ'=>@date_default_timezone_get(), + 'UI'=>'./', + 'UNLOAD'=>NULL, + 'UPLOADS'=>'./', + 'URI'=>&$_SERVER['REQUEST_URI'], + 'VERB'=>&$_SERVER['REQUEST_METHOD'], + 'VERSION'=>self::VERSION, + 'XFRAME'=>'SAMEORIGIN' + ]; + if (PHP_SAPI=='cli-server' && + preg_match('/^'.preg_quote($base,'/').'$/',$this->hive['URI'])) + $this->reroute('/'); + if (ini_get('auto_globals_jit')) + // Override setting + $GLOBALS+=['_ENV'=>$_ENV,'_REQUEST'=>$_REQUEST]; + // Sync PHP globals with corresponding hive keys + $this->init=$this->hive; + foreach (explode('|',self::GLOBALS) as $global) { + $sync=$this->sync($global); + $this->init+=[ + $global=>preg_match('/SERVER|ENV/',$global)?$sync:[] + ]; + } + if ($check && $error=error_get_last()) + // Error detected + $this->error(500, + sprintf(self::E_Fatal,$error['message']),[$error]); + date_default_timezone_set($this->hive['TZ']); + // Register framework autoloader + spl_autoload_register([$this,'autoload']); + // Register shutdown handler + register_shutdown_function([$this,'unload'],getcwd()); + } + +} + +//! Cache engine +class Cache extends Prefab { + + protected + //! Cache DSN + $dsn, + //! Prefix for cache entries + $prefix, + //! MemCache or Redis object + $ref; + + /** + * Return timestamp and TTL of cache entry or FALSE if not found + * @return array|FALSE + * @param $key string + * @param $val mixed + **/ + function exists($key,&$val=NULL) { + $fw=Base::instance(); + if (!$this->dsn) + return FALSE; + $ndx=$this->prefix.'.'.$key; + $parts=explode('=',$this->dsn,2); + switch ($parts[0]) { + case 'apc': + case 'apcu': + $raw=apc_fetch($ndx); + break; + case 'redis': + $raw=$this->ref->get($ndx); + break; + case 'memcache': + $raw=memcache_get($this->ref,$ndx); + break; + case 'wincache': + $raw=wincache_ucache_get($ndx); + break; + case 'xcache': + $raw=xcache_get($ndx); + break; + case 'folder': + $raw=$fw->read($parts[1].$ndx); + break; + } + if (!empty($raw)) { + list($val,$time,$ttl)=(array)$fw->unserialize($raw); + if ($ttl===0 || $time+$ttl>microtime(TRUE)) + return [$time,$ttl]; + $val=null; + $this->clear($key); + } + return FALSE; + } + + /** + * Store value in cache + * @return mixed|FALSE + * @param $key string + * @param $val mixed + * @param $ttl int + **/ + function set($key,$val,$ttl=0) { + $fw=Base::instance(); + if (!$this->dsn) + return TRUE; + $ndx=$this->prefix.'.'.$key; + $time=microtime(TRUE); + if ($cached=$this->exists($key)) + list($time,$ttl)=$cached; + $data=$fw->serialize([$val,$time,$ttl]); + $parts=explode('=',$this->dsn,2); + switch ($parts[0]) { + case 'apc': + case 'apcu': + return apc_store($ndx,$data,$ttl); + case 'redis': + return $this->ref->set($ndx,$data,['ex'=>$ttl]); + case 'memcache': + return memcache_set($this->ref,$ndx,$data,0,$ttl); + case 'wincache': + return wincache_ucache_set($ndx,$data,$ttl); + case 'xcache': + return xcache_set($ndx,$data,$ttl); + case 'folder': + return $fw->write($parts[1].$ndx,$data); + } + return FALSE; + } + + /** + * Retrieve value of cache entry + * @return mixed|FALSE + * @param $key string + **/ + function get($key) { + return $this->dsn && $this->exists($key,$data)?$data:FALSE; + } + + /** + * Delete cache entry + * @return bool + * @param $key string + **/ + function clear($key) { + if (!$this->dsn) + return; + $ndx=$this->prefix.'.'.$key; + $parts=explode('=',$this->dsn,2); + switch ($parts[0]) { + case 'apc': + case 'apcu': + return apc_delete($ndx); + case 'redis': + return $this->ref->del($ndx); + case 'memcache': + return memcache_delete($this->ref,$ndx); + case 'wincache': + return wincache_ucache_delete($ndx); + case 'xcache': + return xcache_unset($ndx); + case 'folder': + return @unlink($parts[1].$ndx); + } + return FALSE; + } + + /** + * Clear contents of cache backend + * @return bool + * @param $suffix string + * @param $lifetime int + **/ + function reset($suffix=NULL,$lifetime=0) { + if (!$this->dsn) + return TRUE; + $regex='/'.preg_quote($this->prefix.'.','/').'.+?'. + preg_quote($suffix,'/').'/'; + $parts=explode('=',$this->dsn,2); + switch ($parts[0]) { + case 'apc': + case 'apcu': + $info=apc_cache_info('user'); + if (!empty($info['cache_list'])) { + $key=array_key_exists('info',$info['cache_list'][0])?'info':'key'; + $mtkey=array_key_exists('mtime',$info['cache_list'][0])? + 'mtime':'modification_time'; + foreach ($info['cache_list'] as $item) + if (preg_match($regex,$item[$key]) && + $item[$mtkey]+$lifetimeref->keys($this->prefix.'.*'.$suffix); + foreach($keys as $key) { + $val=$fw->unserialize($this->ref->get($key)); + if ($val[1]+$lifetimeref->del($key); + } + return TRUE; + case 'memcache': + foreach (memcache_get_extended_stats( + $this->ref,'slabs') as $slabs) + foreach (array_filter(array_keys($slabs),'is_numeric') + as $id) + foreach (memcache_get_extended_stats( + $this->ref,'cachedump',$id) as $data) + if (is_array($data)) + foreach ($data as $key=>$val) + if (preg_match($regex,$key) && + $val[1]+$lifetimeref,$key); + return TRUE; + case 'wincache': + $info=wincache_ucache_info(); + foreach ($info['ucache_entries'] as $item) + if (preg_match($regex,$item['key_name']) && + $item['use_time']+$lifetime1) + list($host,$port)=$parts; + else + $host=$parts[0]; + $this->ref=new Redis; + if(!$this->ref->connect($host,$port,2)) + $this->ref=NULL; + } + elseif (preg_match('/^memcache=(.+)/',$dsn,$parts) && + extension_loaded('memcache')) + foreach ($fw->split($parts[1]) as $server) { + $port=11211; + $parts=explode(':',$server,2); + if (count($parts)>1) + list($host,$port)=$parts; + else + $host=$parts[0]; + if (empty($this->ref)) + $this->ref=@memcache_connect($host,$port)?:NULL; + else + memcache_add_server($this->ref,$host,$port); + } + if (empty($this->ref) && !preg_match('/^folder\h*=/',$dsn)) + $dsn=($grep=preg_grep('/^(apc|wincache|xcache)/', + array_map('strtolower',get_loaded_extensions())))? + // Auto-detect + current($grep): + // Use filesystem as fallback + ('folder='.$fw->get('TEMP').'cache/'); + if (preg_match('/^folder\h*=\h*(.+)/',$dsn,$parts) && + !is_dir($parts[1])) + mkdir($parts[1],Base::MODE,TRUE); + } + $this->prefix=$fw->hash($_SERVER['SERVER_NAME'].$fw->get('BASE')); + return $this->dsn=$dsn; + } + + /** + * Class constructor + * @return object + * @param $dsn bool|string + **/ + function __construct($dsn=FALSE) { + if ($dsn) + $this->load($dsn); + } + +} + +//! View handler +class View extends Prefab { + + protected + //! Template file + $view, + //! post-rendering handler + $trigger, + //! Nesting level + $level=0; + + /** + * Encode characters to equivalent HTML entities + * @return string + * @param $arg mixed + **/ + function esc($arg) { + $fw=Base::instance(); + return $fw->recursive($arg, + function($val) use($fw) { + return is_string($val)?$fw->encode($val):$val; + } + ); + } + + /** + * Decode HTML entities to equivalent characters + * @return string + * @param $arg mixed + **/ + function raw($arg) { + $fw=Base::instance(); + return $fw->recursive($arg, + function($val) use($fw) { + return is_string($val)?$fw->decode($val):$val; + } + ); + } + + /** + * Create sandbox for template execution + * @return string + * @param $hive array + **/ + protected function sandbox(array $hive=NULL) { + $this->level++; + $fw=Base::instance(); + $implicit=false; + if ($hive === null) { + $implicit=true; + $hive=$fw->hive(); + } + if ($this->level<2 || $implicit) { + if ($fw->get('ESCAPE')) + $hive=$this->esc($hive); + if (isset($hive['ALIASES'])) + $hive['ALIASES']=$fw->build($hive['ALIASES']); + } + unset($fw, $implicit); + extract($hive); + unset($hive); + ob_start(); + require($this->view); + $this->level--; + return ob_get_clean(); + } + + /** + * Render template + * @return string + * @param $file string + * @param $mime string + * @param $hive array + * @param $ttl int + **/ + function render($file,$mime='text/html',array $hive=NULL,$ttl=0) { + $fw=Base::instance(); + $cache=Cache::instance(); + if ($cache->exists($hash=$fw->hash($file),$data)) + return $data; + foreach ($fw->split($fw->get('UI').';./') as $dir) + if (is_file($this->view=$fw->fixslashes($dir.$file))) { + if (isset($_COOKIE[session_name()])) + @session_start(); + $fw->sync('SESSION'); + if ($mime && PHP_SAPI!='cli' && !headers_sent()) + header('Content-Type: '.$mime.'; '. + 'charset='.$fw->get('ENCODING')); + $data=$this->sandbox($hive); + if(isset($this->trigger['afterrender'])) + foreach($this->trigger['afterrender'] as $func) + $data=$fw->call($func,$data); + if ($ttl) + $cache->set($hash,$data,$ttl); + return $data; + } + user_error(sprintf(Base::E_Open,$file),E_USER_ERROR); + } + + /** + * post rendering handler + * @param $func callback + */ + function afterrender($func) { + $this->trigger['afterrender'][]=$func; + } + +} + +//! Lightweight template engine +class Preview extends View { + + protected + //! MIME type + $mime, + //! token filter + $filter=[ + 'esc'=>'$this->esc', + 'raw'=>'$this->raw', + 'alias'=>'\Base::instance()->alias', + 'format'=>'\Base::instance()->format' + ]; + + /** + * Convert token to variable + * @return string + * @param $str string + **/ + function token($str) { + $str=trim(preg_replace('/\{\{(.+?)\}\}/s',trim('\1'), + Base::instance()->compile($str))); + if (preg_match('/^(.+)(?split($parts[2]) as $func) + $str=is_string($cmd=$this->filter($func))?$cmd.'('.$str.')': + '\Base::instance()->call('. + '$this->filter(\''.$func.'\'),['.$str.'])'; + } + return $str; + } + + /** + * Register or get (a specific one or all) token filters + * @param string $key + * @param string|closure $func + * @return array|closure|string + */ + function filter($key=NULL,$func=NULL) { + if (!$key) + return array_keys($this->filter); + if (!$func) + return $this->filter[$key]; + $this->filter[$key]=$func; + } + + /** + * Assemble markup + * @return string + * @param $node string + **/ + protected function build($node) { + $self=$this; + return preg_replace_callback( + '/\{\-(.+?)\-\}|\{\{(.+?)\}\}(\n+)?|(\{\*.*?\*\})/s', + function($expr) use($self) { + if ($expr[1]) + return $expr[1]; + $str=trim($self->token($expr[2])); + return empty($expr[4])? + (''. + (isset($expr[3])?$expr[3]."\n":'')): + ''; + }, + preg_replace_callback( + '/\{~(.+?)~\}/s', + function($expr) use($self) { + return 'token($expr[1]).' ?>'; + }, + $node + ) + ); + } + + /** + * Render template string + * @return string + * @param $str string + * @param $hive array + **/ + function resolve($str,array $hive=NULL) { + if (!$hive) + $hive=\Base::instance()->hive(); + extract($hive); + ob_start(); + eval(' ?>'.$this->build($str).'mime=$mime; + elseif (!$this->mime) + $this->mime='text/html'; + if (!is_dir($tmp=$fw->get('TEMP'))) + mkdir($tmp,Base::MODE,TRUE); + foreach ($fw->split($fw->get('UI')) as $dir) { + if ($cache->exists($hash=$fw->hash($dir.$file),$data)) + return $data; + if (is_file($view=$fw->fixslashes($dir.$file))) { + if (!is_file($this->view=($tmp. + $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash($view).'.php')) || + filemtime($this->view)\h*'. + '(?!["\'])|\{\*.+?\*\}/is','', + $fw->read($view)); + if (method_exists($this,'parse')) + $text=$this->parse($text); + $fw->write($this->view,$this->build($text)); + } + if (isset($_COOKIE[session_name()])) + @session_start(); + $fw->sync('SESSION'); + if (PHP_SAPI!='cli' && !headers_sent()) + header('Content-Type: '.$this->mime.'; '. + 'charset='.$fw->get('ENCODING')); + $data=$this->sandbox($hive); + if(isset($this->trigger['afterrender'])) + foreach ($this->trigger['afterrender'] as $func) + $data = $fw->call($func, $data); + if ($ttl) + $cache->set($hash,$data,$ttl); + return $data; + } + } + user_error(sprintf(Base::E_Open,$file),E_USER_ERROR); + } + +} + +//! ISO language/country codes +class ISO extends Prefab { + + //@{ ISO 3166-1 country codes + const + CC_af='Afghanistan', + CC_ax='Åland Islands', + CC_al='Albania', + CC_dz='Algeria', + CC_as='American Samoa', + CC_ad='Andorra', + CC_ao='Angola', + CC_ai='Anguilla', + CC_aq='Antarctica', + CC_ag='Antigua and Barbuda', + CC_ar='Argentina', + CC_am='Armenia', + CC_aw='Aruba', + CC_au='Australia', + CC_at='Austria', + CC_az='Azerbaijan', + CC_bs='Bahamas', + CC_bh='Bahrain', + CC_bd='Bangladesh', + CC_bb='Barbados', + CC_by='Belarus', + CC_be='Belgium', + CC_bz='Belize', + CC_bj='Benin', + CC_bm='Bermuda', + CC_bt='Bhutan', + CC_bo='Bolivia', + CC_bq='Bonaire, Sint Eustatius and Saba', + CC_ba='Bosnia and Herzegovina', + CC_bw='Botswana', + CC_bv='Bouvet Island', + CC_br='Brazil', + CC_io='British Indian Ocean Territory', + CC_bn='Brunei Darussalam', + CC_bg='Bulgaria', + CC_bf='Burkina Faso', + CC_bi='Burundi', + CC_kh='Cambodia', + CC_cm='Cameroon', + CC_ca='Canada', + CC_cv='Cape Verde', + CC_ky='Cayman Islands', + CC_cf='Central African Republic', + CC_td='Chad', + CC_cl='Chile', + CC_cn='China', + CC_cx='Christmas Island', + CC_cc='Cocos (Keeling) Islands', + CC_co='Colombia', + CC_km='Comoros', + CC_cg='Congo', + CC_cd='Congo, The Democratic Republic of', + CC_ck='Cook Islands', + CC_cr='Costa Rica', + CC_ci='Côte d\'ivoire', + CC_hr='Croatia', + CC_cu='Cuba', + CC_cw='Curaçao', + CC_cy='Cyprus', + CC_cz='Czech Republic', + CC_dk='Denmark', + CC_dj='Djibouti', + CC_dm='Dominica', + CC_do='Dominican Republic', + CC_ec='Ecuador', + CC_eg='Egypt', + CC_sv='El Salvador', + CC_gq='Equatorial Guinea', + CC_er='Eritrea', + CC_ee='Estonia', + CC_et='Ethiopia', + CC_fk='Falkland Islands (Malvinas)', + CC_fo='Faroe Islands', + CC_fj='Fiji', + CC_fi='Finland', + CC_fr='France', + CC_gf='French Guiana', + CC_pf='French Polynesia', + CC_tf='French Southern Territories', + CC_ga='Gabon', + CC_gm='Gambia', + CC_ge='Georgia', + CC_de='Germany', + CC_gh='Ghana', + CC_gi='Gibraltar', + CC_gr='Greece', + CC_gl='Greenland', + CC_gd='Grenada', + CC_gp='Guadeloupe', + CC_gu='Guam', + CC_gt='Guatemala', + CC_gg='Guernsey', + CC_gn='Guinea', + CC_gw='Guinea-Bissau', + CC_gy='Guyana', + CC_ht='Haiti', + CC_hm='Heard Island and McDonald Islands', + CC_va='Holy See (Vatican City State)', + CC_hn='Honduras', + CC_hk='Hong Kong', + CC_hu='Hungary', + CC_is='Iceland', + CC_in='India', + CC_id='Indonesia', + CC_ir='Iran, Islamic Republic of', + CC_iq='Iraq', + CC_ie='Ireland', + CC_im='Isle of Man', + CC_il='Israel', + CC_it='Italy', + CC_jm='Jamaica', + CC_jp='Japan', + CC_je='Jersey', + CC_jo='Jordan', + CC_kz='Kazakhstan', + CC_ke='Kenya', + CC_ki='Kiribati', + CC_kp='Korea, Democratic People\'s Republic of', + CC_kr='Korea, Republic of', + CC_kw='Kuwait', + CC_kg='Kyrgyzstan', + CC_la='Lao People\'s Democratic Republic', + CC_lv='Latvia', + CC_lb='Lebanon', + CC_ls='Lesotho', + CC_lr='Liberia', + CC_ly='Libya', + CC_li='Liechtenstein', + CC_lt='Lithuania', + CC_lu='Luxembourg', + CC_mo='Macao', + CC_mk='Macedonia, The Former Yugoslav Republic of', + CC_mg='Madagascar', + CC_mw='Malawi', + CC_my='Malaysia', + CC_mv='Maldives', + CC_ml='Mali', + CC_mt='Malta', + CC_mh='Marshall Islands', + CC_mq='Martinique', + CC_mr='Mauritania', + CC_mu='Mauritius', + CC_yt='Mayotte', + CC_mx='Mexico', + CC_fm='Micronesia, Federated States of', + CC_md='Moldova, Republic of', + CC_mc='Monaco', + CC_mn='Mongolia', + CC_me='Montenegro', + CC_ms='Montserrat', + CC_ma='Morocco', + CC_mz='Mozambique', + CC_mm='Myanmar', + CC_na='Namibia', + CC_nr='Nauru', + CC_np='Nepal', + CC_nl='Netherlands', + CC_nc='New Caledonia', + CC_nz='New Zealand', + CC_ni='Nicaragua', + CC_ne='Niger', + CC_ng='Nigeria', + CC_nu='Niue', + CC_nf='Norfolk Island', + CC_mp='Northern Mariana Islands', + CC_no='Norway', + CC_om='Oman', + CC_pk='Pakistan', + CC_pw='Palau', + CC_ps='Palestinian Territory, Occupied', + CC_pa='Panama', + CC_pg='Papua New Guinea', + CC_py='Paraguay', + CC_pe='Peru', + CC_ph='Philippines', + CC_pn='Pitcairn', + CC_pl='Poland', + CC_pt='Portugal', + CC_pr='Puerto Rico', + CC_qa='Qatar', + CC_re='Réunion', + CC_ro='Romania', + CC_ru='Russian Federation', + CC_rw='Rwanda', + CC_bl='Saint Barthélemy', + CC_sh='Saint Helena, Ascension and Tristan da Cunha', + CC_kn='Saint Kitts and Nevis', + CC_lc='Saint Lucia', + CC_mf='Saint Martin (French Part)', + CC_pm='Saint Pierre and Miquelon', + CC_vc='Saint Vincent and The Grenadines', + CC_ws='Samoa', + CC_sm='San Marino', + CC_st='Sao Tome and Principe', + CC_sa='Saudi Arabia', + CC_sn='Senegal', + CC_rs='Serbia', + CC_sc='Seychelles', + CC_sl='Sierra Leone', + CC_sg='Singapore', + CC_sk='Slovakia', + CC_sx='Sint Maarten (Dutch Part)', + CC_si='Slovenia', + CC_sb='Solomon Islands', + CC_so='Somalia', + CC_za='South Africa', + CC_gs='South Georgia and The South Sandwich Islands', + CC_ss='South Sudan', + CC_es='Spain', + CC_lk='Sri Lanka', + CC_sd='Sudan', + CC_sr='Suriname', + CC_sj='Svalbard and Jan Mayen', + CC_sz='Swaziland', + CC_se='Sweden', + CC_ch='Switzerland', + CC_sy='Syrian Arab Republic', + CC_tw='Taiwan, Province of China', + CC_tj='Tajikistan', + CC_tz='Tanzania, United Republic of', + CC_th='Thailand', + CC_tl='Timor-Leste', + CC_tg='Togo', + CC_tk='Tokelau', + CC_to='Tonga', + CC_tt='Trinidad and Tobago', + CC_tn='Tunisia', + CC_tr='Turkey', + CC_tm='Turkmenistan', + CC_tc='Turks and Caicos Islands', + CC_tv='Tuvalu', + CC_ug='Uganda', + CC_ua='Ukraine', + CC_ae='United Arab Emirates', + CC_gb='United Kingdom', + CC_us='United States', + CC_um='United States Minor Outlying Islands', + CC_uy='Uruguay', + CC_uz='Uzbekistan', + CC_vu='Vanuatu', + CC_ve='Venezuela', + CC_vn='Viet Nam', + CC_vg='Virgin Islands, British', + CC_vi='Virgin Islands, U.S.', + CC_wf='Wallis and Futuna', + CC_eh='Western Sahara', + CC_ye='Yemen', + CC_zm='Zambia', + CC_zw='Zimbabwe'; + //@} + + //@{ ISO 639-1 language codes (Windows-compatibility subset) + const + LC_af='Afrikaans', + LC_am='Amharic', + LC_ar='Arabic', + LC_as='Assamese', + LC_ba='Bashkir', + LC_be='Belarusian', + LC_bg='Bulgarian', + LC_bn='Bengali', + LC_bo='Tibetan', + LC_br='Breton', + LC_ca='Catalan', + LC_co='Corsican', + LC_cs='Czech', + LC_cy='Welsh', + LC_da='Danish', + LC_de='German', + LC_dv='Divehi', + LC_el='Greek', + LC_en='English', + LC_es='Spanish', + LC_et='Estonian', + LC_eu='Basque', + LC_fa='Persian', + LC_fi='Finnish', + LC_fo='Faroese', + LC_fr='French', + LC_gd='Scottish Gaelic', + LC_gl='Galician', + LC_gu='Gujarati', + LC_he='Hebrew', + LC_hi='Hindi', + LC_hr='Croatian', + LC_hu='Hungarian', + LC_hy='Armenian', + LC_id='Indonesian', + LC_ig='Igbo', + LC_is='Icelandic', + LC_it='Italian', + LC_ja='Japanese', + LC_ka='Georgian', + LC_kk='Kazakh', + LC_km='Khmer', + LC_kn='Kannada', + LC_ko='Korean', + LC_lb='Luxembourgish', + LC_lo='Lao', + LC_lt='Lithuanian', + LC_lv='Latvian', + LC_mi='Maori', + LC_ml='Malayalam', + LC_mr='Marathi', + LC_ms='Malay', + LC_mt='Maltese', + LC_ne='Nepali', + LC_nl='Dutch', + LC_no='Norwegian', + LC_oc='Occitan', + LC_or='Oriya', + LC_pl='Polish', + LC_ps='Pashto', + LC_pt='Portuguese', + LC_qu='Quechua', + LC_ro='Romanian', + LC_ru='Russian', + LC_rw='Kinyarwanda', + LC_sa='Sanskrit', + LC_si='Sinhala', + LC_sk='Slovak', + LC_sl='Slovenian', + LC_sq='Albanian', + LC_sv='Swedish', + LC_ta='Tamil', + LC_te='Telugu', + LC_th='Thai', + LC_tk='Turkmen', + LC_tr='Turkish', + LC_tt='Tatar', + LC_uk='Ukrainian', + LC_ur='Urdu', + LC_vi='Vietnamese', + LC_wo='Wolof', + LC_yo='Yoruba', + LC_zh='Chinese'; + //@} + + /** + * Return list of languages indexed by ISO 639-1 language code + * @return array + **/ + function languages() { + return \Base::instance()->constants($this,'LC_'); + } + + /** + * Return list of countries indexed by ISO 3166-1 country code + * @return array + **/ + function countries() { + return \Base::instance()->constants($this,'CC_'); + } + +} + +//! Container for singular object instances +final class Registry { + + private static + //! Object catalog + $table; + + /** + * Return TRUE if object exists in catalog + * @return bool + * @param $key string + **/ + static function exists($key) { + return isset(self::$table[$key]); + } + + /** + * Add object to catalog + * @return object + * @param $key string + * @param $obj object + **/ + static function set($key,$obj) { + return self::$table[$key]=$obj; + } + + /** + * Retrieve object from catalog + * @return object + * @param $key string + **/ + static function get($key) { + return self::$table[$key]; + } + + /** + * Delete object from catalog + * @return NULL + * @param $key string + **/ + static function clear($key) { + self::$table[$key]=NULL; + unset(self::$table[$key]); + } + + //! Prohibit cloning + private function __clone() { + } + + //! Prohibit instantiation + private function __construct() { + } + +} + +return Base::instance(); \ No newline at end of file diff --git a/lib/f3/basket.php b/lib/f3/basket.php new file mode 100755 index 0000000..ff4b7b0 --- /dev/null +++ b/lib/f3/basket.php @@ -0,0 +1,227 @@ +item); + } + + /** + * Assign value to field + * @return scalar|FALSE + * @param $key string + * @param $val scalar + **/ + function set($key,$val) { + return ($key=='_id')?FALSE:($this->item[$key]=$val); + } + + /** + * Retrieve value of field + * @return scalar|FALSE + * @param $key string + **/ + function get($key) { + if ($key=='_id') + return $this->id; + if (array_key_exists($key,$this->item)) + return $this->item[$key]; + user_error(sprintf(self::E_Field,$key)); + return FALSE; + } + + /** + * Delete field + * @return NULL + * @param $key string + **/ + function clear($key) { + unset($this->item[$key]); + } + + /** + * Return items that match key/value pair + * @return array|FALSE + * @param $key string + * @param $val mixed + **/ + function find($key,$val) { + if (isset($_SESSION[$this->key])) { + $out=array(); + foreach ($_SESSION[$this->key] as $id=>$item) + if (array_key_exists($key,$item) && $item[$key]==$val) { + $obj=clone($this); + $obj->id=$id; + $obj->item=$item; + $out[]=$obj; + } + return $out; + } + return FALSE; + } + + /** + * Return first item that matches key/value pair + * @return object|FALSE + * @param $key string + * @param $val mixed + **/ + function findone($key,$val) { + return ($data=$this->find($key,$val))?$data[0]:FALSE; + } + + /** + * Map current item to matching key/value pair + * @return array + * @param $key string + * @param $val mixed + **/ + function load($key,$val) { + if ($found=$this->find($key,$val)) { + $this->id=$found[0]->id; + return $this->item=$found[0]->item; + } + $this->reset(); + return array(); + } + + /** + * Return TRUE if current item is empty/undefined + * @return bool + **/ + function dry() { + return !$this->item; + } + + /** + * Return number of items in basket + * @return int + **/ + function count() { + return isset($_SESSION[$this->key])?count($_SESSION[$this->key]):0; + } + + /** + * Save current item + * @return array + **/ + function save() { + if (!$this->id) + $this->id=uniqid(NULL,TRUE); + $_SESSION[$this->key][$this->id]=$this->item; + return $this->item; + } + + /** + * Erase item matching key/value pair + * @return bool + * @param $key string + * @param $val mixed + **/ + function erase($key,$val) { + $found=$this->find($key,$val); + if ($found && $id=$found[0]->id) { + unset($_SESSION[$this->key][$id]); + if ($id==$this->id) + $this->reset(); + return TRUE; + } + return FALSE; + } + + /** + * Reset cursor + * @return NULL + **/ + function reset() { + $this->id=NULL; + $this->item=array(); + } + + /** + * Empty basket + * @return NULL + **/ + function drop() { + unset($_SESSION[$this->key]); + } + + /** + * Hydrate item using hive array variable + * @return NULL + * @param $key string + **/ + function copyfrom($key) { + foreach (\Base::instance()->get($key) as $key=>$val) + $this->item[$key]=$val; + } + + /** + * Populate hive array variable with item contents + * @return NULL + * @param $key string + **/ + function copyto($key) { + $var=&\Base::instance()->ref($key); + foreach ($this->item as $key=>$field) + $var[$key]=$field; + } + + /** + * Check out basket contents + * @return array + **/ + function checkout() { + if (isset($_SESSION[$this->key])) { + $out=$_SESSION[$this->key]; + unset($_SESSION[$this->key]); + return $out; + } + return array(); + } + + /** + * Instantiate class + * @return void + * @param $key string + **/ + function __construct($key='basket') { + $this->key=$key; + @session_start(); + Base::instance()->sync('SESSION'); + $this->reset(); + } + +} diff --git a/lib/f3/bcrypt.php b/lib/f3/bcrypt.php new file mode 100755 index 0000000..311c1e3 --- /dev/null +++ b/lib/f3/bcrypt.php @@ -0,0 +1,89 @@ +31) + user_error(self::E_CostArg); + $len=22; + if ($salt) { + if (!preg_match('/^[[:alnum:]\.\/]{'.$len.',}$/',$salt)) + user_error(self::E_SaltArg); + } + else { + $raw=16; + $iv=''; + if (extension_loaded('mcrypt')) + $iv=mcrypt_create_iv($raw,MCRYPT_DEV_URANDOM); + if (!$iv && extension_loaded('openssl')) + $iv=openssl_random_pseudo_bytes($raw); + if (!$iv) + for ($i=0;$i<$raw;$i++) + $iv.=chr(mt_rand(0,255)); + $salt=str_replace('+','.',base64_encode($iv)); + } + $salt=substr($salt,0,$len); + $hash=crypt($pw,sprintf('$2y$%02d$',$cost).$salt); + return strlen($hash)>13?$hash:FALSE; + } + + /** + * Check if password is still strong enough + * @return bool + * @param $hash string + * @param $cost int + **/ + function needs_rehash($hash,$cost=self::COST) { + list($pwcost)=sscanf($hash,"$2y$%d$"); + return $pwcost<$cost; + } + + /** + * Verify password against hash using timing attack resistant approach + * @return bool + * @param $pw string + * @param $hash string + **/ + function verify($pw,$hash) { + $val=crypt($pw,$hash); + $len=strlen($val); + if ($len!=strlen($hash) || $len<14) + return FALSE; + $out=0; + for ($i=0;$i<$len;$i++) + $out|=(ord($val[$i])^ord($hash[$i])); + return $out===0; + } + +} diff --git a/lib/f3/changelog.txt b/lib/f3/changelog.txt new file mode 100755 index 0000000..958843b --- /dev/null +++ b/lib/f3/changelog.txt @@ -0,0 +1,376 @@ +CHANGELOG + +3.2.1 (7 January 2014) +* NEW: EMOJI variable, UTF->translate(), UTF->emojify(), and UTF->strrev() +* Allow empty strings in config() +* Add support for turning off php://input buffering via RAW + (FALSE by default) +* Add Cursor->load() and Cursor->find() TTL support +* Support Web->receive() large file downloads via PUT +* ONERROR safety check +* Fix session CSRF cookie detection +* Framework object now passed to route handler contructors +* Allow override of DIACRITICS +* Various code optimizations +* Support log disabling (Issue #483) +* Implicit mapper load() on authentication +* Declare abstract methods for Cursor derivatives +* Support single-quoted HTML/XML attributes (Feature request #503) +* Relax property visibility of mappers and derivatives +* Deprecated: {{~ ~}} instructions and {{* *}} comments; Use {~ ~} and + {* *} instead +* Minor fix: Audit->ipv4() return value +* Bug fix: Backslashes in BASE not converted on Windows +* Bug fix: UTF->substr() with negative offset and specified length +* Bug fix: Replace named URL tokens on render() +* Bug fix: BASE is not empty when run from document root +* Bug fix: stringify() recursion + +3.2.0 (18 December 2013) +* NEW: Automatic CSRF protection (with IP and User-Agent checks) for + sessions mapped to SQL-, Jig-, Mongo- and Cache-based backends +* NEW: Named routes +* NEW: PATH variable; returns the URL relative to BASE +* NEW: Image->captcha() color parameters +* NEW: Ability to access MongoCuror thru the cursor() method +* NEW: Mapper->fields() method returns array of field names +* NEW: Mapper onload(), oninsert(), onupdate(), and onerase() event + listeners/triggers +* NEW: Preview class (a lightweight template engine) +* NEW: rel() method derives path from URL relative to BASE; useful for + rerouting +* NEW: PREFIX variable for prepending a string to a dictionary term; + Enable support for prefixed dictionary arrays and .ini files (Feature + request #440) +* NEW: Google static map plugin +* NEW: devoid() method +* Introduce clean(); similar to scrub(), except that arg is passed by + value +* Use $ttl for cookie expiration (Issue #457) +* Fix needs_rehash() cost comparison +* Add pass-by-reference argument to exists() so if method returns TRUE, + a subsequent get() is unnecessary +* Improve MySQL support +* Move esc(), raw(), and dupe() to View class where they more + appropriately belong +* Allow user-defined fields in SQL mapper constructor (Feature request + #450) +* Re-implement the pre-3.0 template resolve() feature +* Remove redundant instances of session_commit() +* Add support for input filtering in Mapper->copyfrom() +* Prevent intrusive behavior of Mapper->copyfrom() +* Support multiple SQL primary keys +* Support custom tag attributes/inline tokens defined at runtime + (Feature request #438) +* Broader support for HTTP basic auth +* Prohibit Jig _id clear() +* Add support for detailed stringify() output +* Add base directory to UI path as fallback +* Support Test->expect() chaining +* Support __tostring() in stringify() +* Trigger error on invalid CAPTCHA length (Issue #458) +* Bug fix: exists() pass-by-reference argument returns incorrect value +* Bug fix: DB Exec does not return affected row if query contains a + sub-SELECT (Issue #437) +* Improve seed generator and add code for detecting of acceptable + limits in Image->captcha() (Feature request #460) +* Add decimal format ICU extension +* Bug fix: 404-reported URI contains HTTP query +* Bug fix: Data type detection in DB->schema() +* Bug fix: TZ initialization +* Bug fix: paginate() passes incorrect argument to count() +* Bug fix: Incorrect query when reloading after insert() +* Bug fix: SQL preg_match error in pdo_type matching (Issue #447) +* Bug fix: Missing merge() function (Issue #444) +* Bug fix: BASE misdefined in command line mode +* Bug fix: Stringifying hive may run infinite (Issue #436) +* Bug fix: Incomplete stringify() when DEBUG<3 (Issue #432) +* Bug fix: Redirection of basic auth (Issue #430) +* Bug fix: Filter only PHP code (including short tags) in templates +* Bug fix: Markdown paragraph parser does not convert PHP code blocks + properly +* Bug fix: identicon() colors on same keys are randomized +* Bug fix: quotekey() fails on aliased keys +* Bug fix: Missing _id in Jig->find() return value +* Bug fix: LANGUAGE/LOCALES handling +* Bug fix: Loose comparison in stringify() + +3.1.2 (5 November 2013) +* Abandon .chm help format; Package API documentation in plain HTML; + (Launch lib/api/index.html in your browser) +* Deprecate BAIL in favor of HALT (default: TRUE) +* Revert to 3.1.0 autoload behavior; Add support for lowercase folder + names +* Allow Spring-style HTTP method overrides +* Add support for SQL Server-based sessions +* Capture full X-Forwarded-For header +* Add protection against malicious scripts; Extra check if file was really + uploaded +* Pass-thru page limit in return value of Cursor->paginate() +* Optimize code: Implement single-pass escaping +* Short circuit Jig->find() if source file is empty +* Bug fix: PHP globals passed by reference in hive() result (Issue #424) +* Bug fix: ZIP mime type incorrect behavior +* Bug fix: Jig->erase() filter malfunction +* Bug fix: Mongo->select() group +* Bug fix: Unknown bcrypt constant + +3.1.1 (13 October 2013) +* NEW: Support OpenID attribute exchange +* NEW: BAIL variable enables/disables continuance of execution on non-fatal + errors +* Deprecate BAIL in favor of HALT (default: FALSE) +* Add support for Oracle +* Mark cached queries in log (Feature Request #405) +* Implement Bcrypt->needs_reshash() +* Add entropy to SQL cache hash; Add uuid() method to DB backends +* Find real document root; Simplify debug paths +* Permit OpenID required fields to be declared as comma-separated string or + array +* Pass modified filename as argument to user-defined function in + Web->receive() +* Quote keys in optional SQL clauses (Issue #408) +* Allow UNLOAD to override fatal error detection (Issue #404) +* Mutex operator precedence error (Issue #406) +* Bug fix: exists() malfunction (Issue #401) +* Bug fix: Jig mapper triggers error when loading from CACHE (Issue #403) +* Bug fix: Array index check +* Bug fix: OpenID verified() return value +* Bug fix: Basket->find() should return a set of results (Issue #407); + Also implemented findone() for consistency with mappers +* Bug fix: PostgreSQL last insert ID (Issue #410) +* Bug fix: $port component URL overwritten by _socket() +* Bug fix: Calculation of elapsed time + +3.1.0 (20 August 2013) +* NEW: Web->filler() returns a chunk of text from the standard + Lorem Ipsum passage +* Change in behavior: Drop support for JSON serialization +* SQL->exec() now returns value of RETURNING clause +* Add support for $ttl argument in count() (Issue #393) +* Allow UI to be overridden by custom $path +* Return result of PDO primitives: begintransaction(), rollback(), and + commit() +* Full support for PHP 5.5 +* Flush buffers only when DEBUG=0 +* Support class->method, class::method, and lambda functions as + Web->basic() arguments +* Commit session on Basket->save() +* Optional enlargement in Image->resize() +* Support authentication on hosts running PHP-CGI +* Change visibility level of Cache properties +* Prevent ONERROR recursion +* Work around Apache pre-2.4 VirtualDocumentRoot bug +* Prioritize cURL in HTTP engine detection +* Bug fix: Minify tricky JS +* Bug fix: desktop() detection +* Bug fix: Double-slash on TEMP-relative path +* Bug fix: Cursor mapping of first() and last() records +* Bug fix: Premature end of Web->receive() on multiple files +* Bug fix: German umlaute to its corresponding grammatically-correct + equivalent + +3.0.9 (12 June 2013) +* NEW: Web->whois() +* NEW: Template tags +* Improve CACHE consistency +* Case-insensitive MIME type detection +* Support pre-PHP 5.3.4 in Prefab->instance() +* Refactor isdesktop() and ismobile(); Add isbot() +* Add support for Markdown strike-through +* Work around ODBC's lack of quote() support +* Remove useless Prefab destructor +* Support multiple cache instances +* Bug fix: Underscores in OpenId keys mangled +* Refactor format() +* Numerous tweaks +* Bug fix: MongoId object not preserved +* Bug fix: Double-quotes included in lexicon() string (Issue #341) +* Bug fix: UTF-8 formatting mangled on Windows (Issue #342) +* Bug fix: Cache->load() error when CACHE is FALSE (Issue #344) +* Bug fix: send() ternary expression +* Bug fix: Country code constants + +3.0.8 (17 May 2013) +* NEW: Bcrypt lightweight hashing library\ +* Return total number of records in superset in Cursor->paginate() +* ONERROR short-circuit (Enhancement #334) +* Apply quotes/backticks on DB identifiers +* Allow enabling/disabling of SQL log +* Normalize glob() behavior (Issue #330) +* Bug fix: mbstring 2-byte text truncation (Issue #325) +* Bug fix: Unsupported operand types (Issue #324) + +3.0.7 (2 May 2013) +* NEW: route() now allows an array of routing patterns as first argument; + support array as first argument of map() +* NEW: entropy() for calculating password strength (NIST 800-63) +* NEW: AGENT variable containing auto-detected HTTP user agent string +* NEW: ismobile() and isdesktop() methods +* NEW: Prefab class and descendants now accept constructor arguments +* Change in behavior: Cache->exists() now returns timestamp and TTL of + cache entry or FALSE if not found (Feature request #315) +* Preserve timestamp and TTL when updating cache entry (Feature request + #316) +* Improved currency formatting with C99 compliance +* Suppress unnecessary program halt at startup caused by misconfigured + server +* Add support for dashes in custom attribute names in templates +* Bug fix: Routing precedene (Issue #313) +* Bug fix: Remove Jig _id element from document property +* Bug fix: Web->rss() error when not enough items in the feed (Issue #299) +* Bug fix: Web engine fallback (Issue #300) +* Bug fix: and formatting +* Bug fix: Text rendering of text with trailing punctuation (Issue #303) +* Bug fix: Incorrect regex in SMTP + +3.0.6 (31 Mar 2013) +* NEW: Image->crop() +* Modify documentation blocks for PHPDoc interoperability +* Allow user to control whether Base->rerouet() uses a permanent or + temporary redirect +* Allow JAR elements to be set individually +* Refactor DB\SQL\Mapper->insert() to cope with autoincrement fields +* Trigger error when captcha() font is missing +* Remove unnecessary markdown regex recursion +* Check for scalars instead of DB\SQL strings +* Implement more comprehensive diacritics table +* Add option for disabling 401 errors when basic auth() fails +* Add markdown syntax highlighting for Apache configuration +* Markdown->render() deprecated to remove dependency on UI variable; + Feature replaced by Markdown->convert() to enable translation from + markdown string to HTML +* Optimize factory() code of all data mappers +* Apply backticks on MySQL table names +* Bug fix: Routing failure when directory path contains a tilde (Issue #291) +* Bug fix: Incorrect markdown parsing of strong/em sequences and inline HTML +* Bug fix: Cached page not echoed (Issue #278) +* Bug fix: Object properties not escaped when rendering +* Bug fix: OpenID error response ignored +* Bug fix: memcache_get_extended_stats() timeout +* Bug fix: Base->set() doesn't pass TTL to Cache->set() +* Bug fix: Base->scrub() ignores pass-thru * argument (Issue #274) + +3.0.5 (16 Feb 2013) +* NEW: Markdown class with PHP, HTML, and .ini syntax highlighting support +* NEW: Options for caching of select() and find() results +* NEW: Web->acceptable() +* Add send() argument for forcing downloads +* Provide read() option for applying Unix LF as standard line ending +* Bypass lexicon() call if LANGUAGE is undefined +* Load fallback language dictionary if LANGUAGE is undefined +* map() now checks existence of class/methods for non-tokenized URLs +* Improve error reporting of non-existent Template methods +* Address output buffer issues on some servers +* Bug fix: Setting DEBUG to 0 won't suppress the stack trace when the + content type is application/json (Issue #257) +* Bug fix: Image dump/render additional arguments shifted +* Bug fix: ob_clean() causes buffer issues with zlib compression +* Bug fix: minify() fails when commenting CSS @ rules (Issue #251) +* Bug fix: Handling of commas inside quoted strings +* Bug fix: Glitch in stringify() handling of closures +* Bug fix: dry() in mappers returns TRUE despite being hydrated by + factory() (Issue #265) +* Bug fix: expect() not handling flags correctly +* Bug fix: weather() fails when server is unreachable + +3.0.4 (29 Jan 2013) +* NEW: Support for ICU/CLDR pluralization +* NEW: User-defined FALLBACK language +* NEW: minify() now recognizes CSS @import directives +* NEW: UTF->bom() returns byte order mark for UTF-8 encoding +* Expose SQL\Mapper->schema() +* Change in behavior: Send error response as JSON string if AJAX request is + detected +* Deprecated: afind*() methods +* Discard output buffer in favor of debug output +* Make _id available to Jig queries +* Magic class now implements ArrayAccess +* Abort execution on startup errors +* Suppress stack trace on DEBUG level 0 +* Allow single = as equality operator in Jig query expressions +* Abort OpenID discovery if Web->request() fails +* Mimic PHP *RECURSION* in stringify() +* Modify Jig parser to allow wildcard-search using preg_match() +* Abort execution after error() execution +* Concatenate cached/uncached minify() iterations; Prevent spillover + caching of previous minify() result +* Work around obscure PHP session id regeneration bug +* Revise algorithm for Jig filter involving undefined fields (Issue #230) +* Use checkdnsrr() instead of gethostbyname() in DNSBL check +* Auto-adjust pagination to cursor boundaries +* Add Romanian diacritics +* Bug fix: Root namespace reference and sorting with undefined Jig fields +* Bug fix: Greedy receive() regex +* Bug fix: Default LANGUAGE always 'en' +* Bug fix: minify() hammers cache backend +* Bug fix: Previous values of primary keys not saved during factory() + instantiation +* Bug fix: Jig find() fails when search key is not present in all records +* Bug fix: Jig SORT_DESC (Issue #233) +* Bug fix: Error reporting (Issue #225) +* Bug fix: language() return value + +3.0.3 (29 Dec 2013) +* NEW: [ajax] and [sync] routing pattern modifiers +* NEW: Basket class (session-based pseudo-mapper, shopping cart, etc.) +* NEW: Test->message() method +* NEW: DB profiling via DB->log() +* NEW: Matrix->calendar() +* NEW: Audit->card() and Audit->mod10() for credit card verification +* NEW: Geo->weather() +* NEW: Base->relay() accepts comma-separated callbacks; but unlike + Base->chain(), result of previous callback becomes argument of the next +* Numerous performance tweaks +* Interoperability with new MongoClient class +* Web->request() now recognizes gzip and deflate encoding +* Differences in behavior of Web->request() engines rectified +* mutex() now uses an ID as argument (instead of filename to make it clear + that specified file is not the target being locked, but a primitive + cross-platform semaphore) +* DB\SQL\Mapper field _id now returned even in the absence of any + auto-increment field +* Magic class spinned off as a separate file +* ISO 3166-1 alpha-2 table updated +* Apache redirect emulation for PHP 5.4 CLI server mode +* Framework instance now passed as argument to any user-defined shutdown + function +* Cache engine now used as storage for Web->minify() output +* Flag added for enabling/disabling Image class filter history +* Bug fix: Trailing routing token consumes HTTP query +* Bug fix: LANGUAGE spills over to LOCALES setting +* Bug fix: Inconsistent dry() return value +* Bug fix: URL-decoding + +3.0.2 (23 Dec 2013) +* NEW: Syntax-highlighted stack traces via Base->highlight(); boolean + HIGHLIGHT global variable can be used to enable/disable this feature +* NEW: Template engine tag +* NEW: Image->captcha() +* NEW: DNSBL-based spammer detection (ported from 2.x) +* NEW: paginate(), first(), and last() methods for data mappers +* NEW: X-HTTP-Method-Override header now recognized +* NEW: Base->chain() method for executing callbacks in succession +* NEW: HOST global variable; derived from either $_SERVER['SERVER_NAME'] or + gethostname() +* NEW: REALM global variable representing full canonical URI +* NEW: Auth plug-in +* NEW: Pingback plug-in (implements both Pingback 1.0 protocol client and + server) +* NEW: DEBUG verbosity can now reach up to level 3; Base->stringify() drills + down to object properties at this setting +* NEW: HTTP PATCH method added to recognized HTTP ReST methods +* Web->slug() now trims trailing dashes +* Web->request() now allows relative local URLs as argument +* Use of PARAMS in route handlers now unnecessary; framework now passes two + arguments to route handlers: the framework object instance and an array + containing the captured values of tokens in route patterns +* Standardized timeout settings among Web->request() backends +* Session IDs regenerated for additional security +* Automatic HTTP 404 responses by Base->call() now restricted to route + handlers +* Empty comments in ini-style files now parsed properly +* Use file_get_contents() in methods that don't involve high concurrency + +3.0.1 (14 Dec 2013) +* Major rewrite of much of the framework's core features diff --git a/lib/f3/code.css b/lib/f3/code.css new file mode 100755 index 0000000..618703f --- /dev/null +++ b/lib/f3/code.css @@ -0,0 +1 @@ +code{word-wrap:break-word;color:black}.comment,.doc_comment,.ml_comment{color:dimgray;font-style:italic}.variable{color:blueviolet}.const,.constant_encapsed_string,.class_c,.dir,.file,.func_c,.halt_compiler,.line,.method_c,.lnumber,.dnumber{color:crimson}.string,.and_equal,.boolean_and,.boolean_or,.concat_equal,.dec,.div_equal,.inc,.is_equal,.is_greater_or_equal,.is_identical,.is_not_equal,.is_not_identical,.is_smaller_or_equal,.logical_and,.logical_or,.logical_xor,.minus_equal,.mod_equal,.mul_equal,.ns_c,.ns_separator,.or_equal,.plus_equal,.sl,.sl_equal,.sr,.sr_equal,.xor_equal,.start_heredoc,.end_heredoc,.object_operator,.paamayim_nekudotayim{color:black}.abstract,.array,.array_cast,.as,.break,.case,.catch,.class,.clone,.continue,.declare,.default,.do,.echo,.else,.elseif,.empty.enddeclare,.endfor,.endforach,.endif,.endswitch,.endwhile,.eval,.exit,.extends,.final,.for,.foreach,.function,.global,.goto,.if,.implements,.include,.include_once,.instanceof,.interface,.isset,.list,.namespace,.new,.print,.private,.public,.protected,.require,.require_once,.return,.static,.switch,.throw,.try,.unset,.use,.var,.while{color:royalblue}.open_tag,.open_tag_with_echo,.close_tag{color:orange}.ini_section{color:black}.ini_key{color:royalblue}.ini_value{color:crimson}.xml_tag{color:dodgerblue}.xml_attr{color:blueviolet}.xml_data{color:red}.section{color:black}.directive{color:blue}.data{color:dimgray} diff --git a/lib/f3/db/cortex.php b/lib/f3/db/cortex.php new file mode 100644 index 0000000..8af634a --- /dev/null +++ b/lib/f3/db/cortex.php @@ -0,0 +1,2672 @@ + + * https://github.com/ikkez/F3-Sugar/ + * + * @package DB + * @version 1.4.2-dev + * @date 29.01.2016 + * @since 24.04.2012 + */ + +namespace DB; +use DB\SQL\Schema; + +class Cortex extends Cursor { + + protected + // config + $db, // DB object [ \DB\SQL, \DB\Jig, \DB\Mongo ] + $table, // selected table, string + $fluid, // fluid sql schema mode, boolean + $fieldConf, // field configuration, array + $ttl, // default mapper schema ttl + $rel_ttl, // default mapper rel ttl + $primary, // SQL table primary key + // behaviour + $smartLoading, // intelligent lazy eager loading, boolean + $standardiseID, // return standardized '_id' field for SQL when casting + // internals + $dbsType, // mapper engine type [jig, sql, mongo] + $fieldsCache, // relation field cache + $saveCsd, // mm rel save cascade + $collection, // collection + $relFilter, // filter for loading related models + $hasCond, // IDs of records the next find should have + $whitelist, // restrict to these fields + $relWhitelist, // restrict relations to these fields + $grp_stack, // stack of group conditions + $countFields, // relational counter buffer + $preBinds, // bind values to be prepended to $filter + $vFields, // virtual fields buffer + $_ttl; // rel_ttl overwrite + + /** @var Cursor */ + protected $mapper; + + /** @var CortexQueryParser */ + protected $queryParser; + + static + $init = false; // just init without mapper + + const + // special datatypes + DT_SERIALIZED = 'SERIALIZED', + DT_JSON = 'JSON', + + // error messages + E_ARRAY_DATATYPE = 'Unable to save an Array in field %s. Use DT_SERIALIZED or DT_JSON.', + E_CONNECTION = 'No valid DB Connection given.', + E_NO_TABLE = 'No table specified.', + E_UNKNOWN_DB_ENGINE = 'This unknown DB system is not supported: %s', + E_FIELD_SETUP = 'No field setup defined', + E_UNKNOWN_FIELD = 'Field %s does not exist in %s.', + E_INVALID_RELATION_OBJECT = 'You can only save hydrated mapper objects', + E_NULLABLE_COLLISION = 'Unable to set NULL to the NOT NULLABLE field: %s', + E_WRONG_RELATION_CLASS = 'Relations only works with Cortex objects', + E_MM_REL_VALUE = 'Invalid value for many field "%s". Expecting null, split-able string, hydrated mapper object, or array of mapper objects.', + E_MM_REL_CLASS = 'Mismatching m:m relation config from class `%s` to `%s`.', + E_MM_REL_FIELD = 'Mismatching m:m relation keys from `%s` to `%s`.', + E_REL_CONF_INC = 'Incomplete relation config for `%s`. Linked key is missing.', + E_MISSING_REL_CONF = 'Cannot create related model. Specify a model name or relConf array.', + E_HAS_COND = 'Cannot use a "has"-filter on a non-bidirectional relation field'; + + /** + * init the ORM, based on given DBS + * @param null|object $db + * @param string $table + * @param null|bool $fluid + * @param int $ttl + */ + public function __construct($db = NULL, $table = NULL, $fluid = NULL, $ttl = 0) + { + if (!is_null($fluid)) + $this->fluid = $fluid; + if (!is_object($this->db=(is_string($db=($db?:$this->db))?\Base::instance()->get($db):$db))) + trigger_error(self::E_CONNECTION); + if ($this->db instanceof Jig) + $this->dbsType = 'jig'; + elseif ($this->db instanceof SQL) + $this->dbsType = 'sql'; + elseif ($this->db instanceof Mongo) + $this->dbsType = 'mongo'; + if ($table) + $this->table = $table; + if ($this->dbsType != 'sql') + $this->primary = '_id'; + elseif (!$this->primary) + $this->primary = 'id'; + $this->table = $this->getTable(); + if (!$this->table) + trigger_error(self::E_NO_TABLE); + $this->ttl = $ttl ?: 60; + if (!$this->rel_ttl) + $this->rel_ttl = 0; + $this->_ttl = $this->rel_ttl ?: 0; + if (static::$init == TRUE) return; + if ($this->fluid) + static::setup($this->db,$this->table,array()); + $this->initMapper(); + } + + /** + * create mapper instance + */ + public function initMapper() + { + switch ($this->dbsType) { + case 'jig': + $this->mapper = new Jig\Mapper($this->db, $this->table); + break; + case 'sql': + $this->mapper = new SQL\Mapper($this->db, $this->table, $this->whitelist, + ($this->fluid)?0:$this->ttl); + break; + case 'mongo': + $this->mapper = new Mongo\Mapper($this->db, $this->table); + break; + default: + trigger_error(sprintf(self::E_UNKNOWN_DB_ENGINE,$this->dbsType)); + } + $this->queryParser = CortexQueryParser::instance(); + $this->reset(); + $this->clearFilter(); + $f3 = \Base::instance(); + $this->smartLoading = $f3->exists('CORTEX.smartLoading') ? + $f3->get('CORTEX.smartLoading') : TRUE; + $this->standardiseID = $f3->exists('CORTEX.standardiseID') ? + $f3->get('CORTEX.standardiseID') : TRUE; + if(!empty($this->fieldConf)) + foreach($this->fieldConf as &$conf) { + $conf=static::resolveRelationConf($conf); + unset($conf); + } + } + + /** + * get fields or set whitelist / blacklist of fields + * @param array $fields + * @param bool $exclude + * @return array + */ + public function fields(array $fields=array(), $exclude=false) + { + if ($fields) + // collect restricted fields for related mappers + foreach($fields as $i=>$val) + if(is_int(strpos($val,'.'))) { + list($key, $relField) = explode('.',$val,2); + $this->relWhitelist[$key][(int)$exclude][] = $relField; + unset($fields[$i]); + $fields[] = $key; + } + $fields = array_unique($fields); + $schema = $this->whitelist ?: $this->mapper->fields(); + if (!$schema && !$this->dbsType != 'sql' && $this->dry()) { + $schema = $this->load()->mapper->fields(); + $this->reset(); + } + if (!$this->whitelist && $this->fieldConf) + $schema=array_unique(array_merge($schema,array_keys($this->fieldConf))); + if (!$fields || empty($fields)) + return $schema; + elseif ($exclude) { + $this->whitelist=array_diff($schema,$fields); + } else + $this->whitelist=$fields; + $id=$this->dbsType=='sql'?$this->primary:'_id'; + if(!in_array($id,$this->whitelist)) + $this->whitelist[]=$id; + $this->initMapper(); + return $this->whitelist; + } + + /** + * set model definition + * config example: + * array('title' => array( + * 'type' => \DB\SQL\Schema::DT_TEXT, + * 'default' => 'new record title', + * 'nullable' => true + * ) + * '...' => ... + * ) + * @param array $config + */ + function setFieldConfiguration(array $config) + { + $this->fieldConf = $config; + $this->reset(); + } + + /** + * returns model field conf array + * @return array|null + */ + public function getFieldConfiguration() + { + return $this->fieldConf; + } + + /** + * kick start to just fetch the config + * @return array + */ + static public function resolveConfiguration() + { + static::$init=true; + $self = new static(); + static::$init=false; + $conf = array ( + 'table'=>$self->getTable(), + 'fieldConf'=>$self->getFieldConfiguration(), + 'db'=>$self->db, + 'fluid'=>$self->fluid, + 'primary'=>$self->primary, + ); + unset($self); + return $conf; + } + + /** + * give this model a reference to the collection it is part of + * @param CortexCollection $cx + */ + public function addToCollection($cx) { + $this->collection = $cx; + } + + /** + * returns the collection where this model lives in + * @return CortexCollection + */ + protected function getCollection() + { + return ($this->collection && $this->smartLoading) + ? $this->collection : false; + } + + /** + * returns model table name + * @return string + */ + public function getTable() + { + if (!$this->table && ($this->fluid || static::$init)) + $this->table = strtolower(get_class($this)); + return $this->table; + } + + /** + * setup / update table schema + * @static + * @param $db + * @param $table + * @param $fields + * @return bool + */ + static public function setup($db=null, $table=null, $fields=null) + { + /** @var Cortex $self */ + $self = get_called_class(); + if (is_null($db) || is_null($table) || is_null($fields)) + $df = $self::resolveConfiguration(); + if (!is_object($db=(is_string($db=($db?:$df['db']))?\Base::instance()->get($db):$db))) + trigger_error(self::E_CONNECTION); + if (strlen($table=$table?:$df['table'])==0) + trigger_error(self::E_NO_TABLE); + if (is_null($fields)) + if (!empty($df['fieldConf'])) + $fields = $df['fieldConf']; + elseif(!$df['fluid']) { + trigger_error(self::E_FIELD_SETUP); + return false; + } else + $fields = array(); + if ($db instanceof SQL) { + $schema = new Schema($db); + // prepare field configuration + if (!empty($fields)) + foreach($fields as $key => &$field) { + // fetch relation field types + $field = static::resolveRelationConf($field); + // check m:m relation + if (array_key_exists('has-many', $field)) { + // m:m relation conf [class,to-key,from-key] + if (is_array($relConf = $field['has-many'])) { + $rel = $relConf[0]::resolveConfiguration(); + // check if foreign conf matches m:m + if (array_key_exists($relConf[1],$rel['fieldConf']) + && !is_null($rel['fieldConf'][$relConf[1]]) + && $relConf['hasRel'] == 'has-many') { + // compute mm table name + $mmTable = isset($relConf[2]) ? $relConf[2] : + static::getMMTableName( + $rel['table'], $relConf[1], $table, $key, + $rel['fieldConf'][$relConf[1]]['has-many']); + if (!in_array($mmTable,$schema->getTables())) { + $mmt = $schema->createTable($mmTable); + $mmt->addColumn($relConf[1])->type($relConf['relFieldType']); + $mmt->addColumn($key)->type($field['type']); + $index = array($relConf[1],$key); + sort($index); + $mmt->addIndex($index); + $mmt->build(); + } + } + } + unset($fields[$key]); + continue; + } + // skip virtual fields with no type + if (!array_key_exists('type', $field)) { + unset($fields[$key]); + continue; + } + // transform array fields + if (in_array($field['type'], array(self::DT_JSON, self::DT_SERIALIZED))) + $field['type']=$schema::DT_TEXT; + // defaults values + if (!array_key_exists('nullable', $field)) + $field['nullable'] = true; + unset($field); + } + if (!in_array($table, $schema->getTables())) { + // create table + $table = $schema->createTable($table); + foreach ($fields as $field_key => $field_conf) + $table->addColumn($field_key, $field_conf); + if(isset($df) && $df['primary'] != 'id') { + $table->addColumn($df['primary'])->type_int(); + $table->primary($df['primary']); + } + $table->build(); + } else { + // add missing fields + $table = $schema->alterTable($table); + $existingCols = $table->getCols(); + foreach ($fields as $field_key => $field_conf) + if (!in_array($field_key, $existingCols)) + $table->addColumn($field_key, $field_conf); + // remove unused fields + // foreach ($existingCols as $col) + // if (!in_array($col, array_keys($fields)) && $col!='id') + // $table->dropColumn($col); + $table->build(); + } + } + return true; + } + + /** + * erase all model data, handle with care + * @param null $db + * @param null $table + */ + static public function setdown($db=null, $table=null) + { + $self = get_called_class(); + if (is_null($db) || is_null($table)) + $df = $self::resolveConfiguration(); + if (!is_object($db=(is_string($db=($db?:$df['db']))?\Base::instance()->get($db):$db))) + trigger_error(self::E_CONNECTION); + if (strlen($table=strtolower($table?:$df['table']))==0) + trigger_error(self::E_NO_TABLE); + if (isset($df) && !empty($df['fieldConf'])) + $fields = $df['fieldConf']; + else + $fields = array(); + $deletable = array(); + $deletable[] = $table; + foreach ($fields as $key => $field) { + $field = static::resolveRelationConf($field); + if (array_key_exists('has-many',$field)) { + if (!is_array($relConf = $field['has-many'])) + continue; + $rel = $relConf[0]::resolveConfiguration(); + // check if foreign conf matches m:m + if (array_key_exists($relConf[1],$rel['fieldConf']) && !is_null($relConf[1]) + && key($rel['fieldConf'][$relConf[1]]) == 'has-many') { + // compute mm table name + $deletable[] = isset($relConf[2]) ? $relConf[2] : + static::getMMTableName( + $rel['table'], $relConf[1], $table, $key, + $rel['fieldConf'][$relConf[1]]['has-many']); + } + } + } + + if($db instanceof Jig) { + /** @var Jig $db */ + $dir = $db->dir(); + foreach ($deletable as $item) + if(file_exists($dir.$item)) + unlink($dir.$item); + } elseif($db instanceof SQL) { + /** @var SQL $db */ + $schema = new Schema($db); + $tables = $schema->getTables(); + foreach ($deletable as $item) + if(in_array($item, $tables)) + $schema->dropTable($item); + } elseif($db instanceof Mongo) { + /** @var Mongo $db */ + foreach ($deletable as $item) + $db->selectCollection($item)->drop(); + } + } + + /** + * computes the m:m table name + * @param string $ftable foreign table + * @param string $fkey foreign key + * @param string $ptable own table + * @param string $pkey own key + * @param null|array $fConf foreign conf [class,key] + * @return string + */ + static protected function getMMTableName($ftable, $fkey, $ptable, $pkey, $fConf=null) + { + if ($fConf) { + list($fclass, $pfkey) = $fConf; + $self = get_called_class(); + // check for a matching config + if (!is_int(strpos($fclass, $self))) + trigger_error(sprintf(self::E_MM_REL_CLASS, $fclass, $self)); + if ($pfkey != $pkey) + trigger_error(sprintf(self::E_MM_REL_FIELD, + $fclass.'.'.$pfkey, $self.'.'.$pkey)); + } + $mmTable = array($ftable.'__'.$fkey, $ptable.'__'.$pkey); + natcasesort($mmTable); + $return = strtolower(str_replace('\\', '_', implode('_mm_', $mmTable))); + return $return; + } + + /** + * get mm table name from config + * @param array $conf own relation config + * @param string $key relation field + * @param null|array $fConf optional foreign config + * @return string + */ + protected function mmTable($conf, $key, $fConf=null) + { + if (!isset($conf['refTable'])) { + // compute mm table name + $mmTable = isset($conf[2]) ? $conf[2] : + static::getMMTableName($conf['relTable'], + $conf['relField'], $this->table, $key, $fConf); + $this->fieldConf[$key]['has-many']['refTable'] = $mmTable; + } else + $mmTable = $conf['refTable']; + return $mmTable; + } + + /** + * resolve relation field types + * @param $field + * @return mixed + */ + protected static function resolveRelationConf($field) + { + if (array_key_exists('belongs-to-one', $field)) { + // find primary field definition + if (!is_array($relConf = $field['belongs-to-one'])) + $relConf = array($relConf, '_id'); + // set field type + if ($relConf[1] == '_id') + $field['type'] = Schema::DT_INT4; + else { + // find foreign field type + $fc = $relConf[0]::resolveConfiguration(); + $field['belongs-to-one']['relPK'] = $fc['primary']; + $field['type'] = $fc['fieldConf'][$relConf[1]]['type']; + } + $field['nullable'] = true; + $field['relType'] = 'belongs-to-one'; + } + elseif (array_key_exists('belongs-to-many', $field)){ + $field['type'] = self::DT_JSON; + $field['nullable'] = true; + $field['relType'] = 'belongs-to-many'; + } + elseif (array_key_exists('has-many', $field)){ + $field['relType'] = 'has-many'; + if (!isset($field['type'])) + $field['type'] = Schema::DT_INT; + $relConf = $field['has-many']; + if(!is_array($relConf)) + return $field; + $rel = $relConf[0]::resolveConfiguration(); + if(array_key_exists('has-many',$rel['fieldConf'][$relConf[1]])) { + $field['has-many']['hasRel'] = 'has-many'; + $field['has-many']['relTable'] = $rel['table']; + $field['has-many']['relField'] = $relConf[1]; + $field['has-many']['relFieldType'] = isset($rel['fieldConf'][$relConf[1]]['type']) ? + $rel['fieldConf'][$relConf[1]]['type'] : Schema::DT_INT; + $field['has-many']['relPK'] = isset($relConf[3])?$relConf[3]:$rel['primary']; + } else { + $field['has-many']['hasRel'] = 'belongs-to-one'; + $toConf=$rel['fieldConf'][$relConf[1]]['belongs-to-one']; + if (is_array($toConf)) + $field['has-many']['relField'] = $toConf[1]; + } + } elseif(array_key_exists('has-one', $field)) + $field['relType'] = 'has-one'; + return $field; + } + + /** + * Return an array of result arrays matching criteria + * @param null $filter + * @param array $options + * @param int $ttl + * @param int $rel_depths + * @return array + */ + public function afind($filter = NULL, array $options = NULL, $ttl = 0, $rel_depths = 1) + { + $result = $this->find($filter, $options, $ttl); + return $result ? $result->castAll($rel_depths): NULL; + } + + /** + * Return an array of objects matching criteria + * @param array|null $filter + * @param array|null $options + * @param int $ttl + * @return CortexCollection + */ + public function find($filter = NULL, array $options = NULL, $ttl = 0) + { + $sort=false; + if ($this->dbsType!='sql') { + if (!empty($this->countFields)) + // see if reordering is needed + foreach($this->countFields as $counter) { + if ($options && isset($options['order']) && + preg_match('/count_'.$counter.'\h+(asc|desc)/i',$options['order'],$match)) + $sort=true; + } + if ($sort) { + // backup slice settings + if (isset($options['limit'])) { + $limit = $options['limit']; + unset($options['limit']); + } + if (isset($options['offset'])) { + $offset = $options['offset']; + unset($options['offset']); + } + } + } + $this->_ttl=$ttl?:$this->rel_ttl; + $result = $this->filteredFind($filter,$options,$ttl); + if (empty($result)) + return false; + foreach($result as &$record) { + $record = $this->factory($record); + unset($record); + } + if (!empty($this->countFields)) + // add counter for NoSQL engines + foreach($this->countFields as $counter) + foreach($result as &$mapper) { + $cr=$mapper->get($counter); + $mapper->virtual('count_'.$counter,$cr?count($cr):null); + unset($mapper); + } + $cc = new CortexCollection(); + $cc->setModels($result); + if($sort) { + $cc->orderBy($options['order']); + $cc->slice(isset($offset)?$offset:0,isset($limit)?$limit:NULL); + } + $this->clearFilter(); + return $cc; + } + + /** + * wrapper for custom find queries + * @param array $filter + * @param array $options + * @param int $ttl + * @param bool $count + * @return array|false array of underlying cursor objects + */ + protected function filteredFind($filter = NULL, array $options = NULL, $ttl = 0, $count=false) + { + if ($this->grp_stack) { + if ($this->dbsType == 'mongo') { + $group = array( + 'keys' => $this->grp_stack['keys'], + 'reduce' => 'function (obj, prev) {'.$this->grp_stack['reduce'].'}', + 'initial' => $this->grp_stack['initial'], + 'finalize' => $this->grp_stack['finalize'], + ); + if ($options && isset($options['group'])) { + if(is_array($options['group'])) + $options['group'] = array_merge($options['group'],$group); + else { + $keys = explode(',',$options['group']); + $keys = array_combine($keys,array_fill(0,count($keys),1)); + $group['keys'] = array_merge($group['keys'],$keys); + $options['group'] = $group; + } + } else + $options = array('group'=>$group); + } + if($this->dbsType == 'sql') { + if ($options && isset($options['group'])) + $options['group'].= ','.$this->grp_stack; + else + $options['group'] = $this->grp_stack; + } + // Jig can't group yet, but pending enhancement https://github.com/bcosca/fatfree/pull/616 + } + if ($this->dbsType == 'sql' && !$count) { + $m_refl=new \ReflectionObject($this->mapper); + $m_ad_prop=$m_refl->getProperty('adhoc'); + $m_ad_prop->setAccessible(true); + $m_refl_adhoc=$m_ad_prop->getValue($this->mapper); + $m_ad_prop->setAccessible(false); + unset($m_ad_prop,$m_refl); + } + $hasJoin = array(); + if ($this->hasCond) { + foreach($this->hasCond as $key => $hasCond) { + $addToFilter = null; + if ($deep = is_int(strpos($key,'.'))) { + $key = rtrim($key,'.'); + $hasCond = array(null,null); + } + list($has_filter,$has_options) = $hasCond; + $type = $this->fieldConf[$key]['relType']; + $fromConf = $this->fieldConf[$key][$type]; + switch($type) { + case 'has-one': + case 'has-many': + if (!is_array($fromConf)) + trigger_error(sprintf(self::E_REL_CONF_INC, $key)); + $id = $this->dbsType == 'sql' ? $this->primary : '_id'; + if ($type=='has-many' && isset($fromConf['relField']) + && $fromConf['hasRel'] == 'belongs-to-one') + $id=$fromConf['relField']; + // many-to-many + if ($type == 'has-many' && $fromConf['hasRel'] == 'has-many') { + if (!$deep && $this->dbsType == 'sql' + && !isset($has_options['limit']) && !isset($has_options['offset'])) { + $hasJoin = array_merge($hasJoin, + $this->_hasJoinMM_sql($key,$hasCond,$filter,$options)); + $options['group'] = (isset($options['group'])?$options['group'].',':''). + $this->table.'.'.$this->primary; + $groupFields = explode(',', preg_replace('/"/','',$options['group'])); + // all non-aggregated fields need to be present in the GROUP BY clause + if (isset($m_refl_adhoc) && preg_match('/sybase|dblib|odbc|sqlsrv/i',$this->db->driver())) + foreach (array_diff($this->mapper->fields(),array_keys($m_refl_adhoc)) as $field) + if (!in_array($this->table.'.'.$field,$groupFields)) + $options['group'] .= ', '.$this->table.'.'.$field; + } + elseif ($result = $this->_hasRefsInMM($key,$has_filter,$has_options,$ttl)) + $addToFilter = array($id.' IN ?', $result); + } // *-to-one + elseif ($result = $this->_hasRefsIn($key,$has_filter,$has_options,$ttl)) + $addToFilter = array($id.' IN ?', $result); + break; + // one-to-* + case 'belongs-to-one': + if (!$deep && $this->dbsType == 'sql' + && !isset($has_options['limit']) && !isset($has_options['offset'])) { + if (!is_array($fromConf)) + $fromConf = array($fromConf, '_id'); + $rel = $fromConf[0]::resolveConfiguration(); + if ($this->dbsType == 'sql' && $fromConf[1] == '_id') + $fromConf[1] = $rel['primary']; + $hasJoin[] = $this->_hasJoin_sql($key,$rel['table'],$hasCond,$filter,$options); + } elseif ($result = $this->_hasRefsIn($key,$has_filter,$has_options,$ttl)) + $addToFilter = array($key.' IN ?', $result); + break; + default: + trigger_error(self::E_HAS_COND); + } + if (isset($result) && !isset($addToFilter)) + return false; + elseif (isset($addToFilter)) { + if (!$filter) + $filter = array(''); + if (!empty($filter[0])) + $filter[0] .= ' and '; + $cond = array_shift($addToFilter); + if ($this->dbsType=='sql') + $cond = $this->_sql_prependTableToFields($cond,$this->table); + $filter[0] .= '('.$cond.')'; + $filter = array_merge($filter, $addToFilter); + } + } + $this->hasCond = null; + } + $filter = $this->queryParser->prepareFilter($filter, $this->dbsType, $this->db, $this->fieldConf); + if ($this->dbsType=='sql') { + $qtable = $this->db->quotekey($this->table); + if (isset($options['order']) && $this->db->driver() == 'pgsql') + // PostgreSQLism: sort NULL values to the end of a table + $options['order'] = preg_replace('/\h+DESC/i',' DESC NULLS LAST',$options['order']); + if (!empty($hasJoin)) { + // assemble full sql query + $adhoc=''; + if ($count) + $sql = 'SELECT COUNT(*) AS '.$this->db->quotekey('rows').' FROM '.$qtable; + else { + if (!empty($this->preBinds)) { + $crit = array_shift($filter); + $filter = array_merge($this->preBinds,$filter); + array_unshift($filter,$crit); + } + if (!empty($m_refl_adhoc)) + foreach ($m_refl_adhoc as $key=>$val) + $adhoc.=', '.$val['expr'].' AS '.$key; + $sql = 'SELECT '.$qtable.'.*'.$adhoc.' FROM '.$qtable; + } + $sql .= ' '.implode(' ',$hasJoin).' WHERE '.$filter[0]; + if (!$count) { + $db=$this->db; + if (isset($options['group'])) + $sql.=' GROUP BY '.preg_replace_callback('/\w+[._\-\w]*/i', function($match) use($db) { + return $db->quotekey($match[0]); + }, $options['group']); + if (isset($options['order'])) + $sql .= ' ORDER BY '.$options['order']; + if (preg_match('/mssql|sqlsrv|odbc/', $this->db->driver()) && + (isset($options['limit']) || isset($options['offset']))) { + $ofs=isset($options['offset'])?(int)$options['offset']:0; + $lmt=isset($options['limit'])?(int)$options['limit']:0; + if (strncmp($this->db->version(),'11',2)>=0) { + // SQL Server 2012 + if (!isset($options['order'])) + $sql.=' ORDER BY '.$this->db->quotekey($this->primary); + $sql.=' OFFSET '.$ofs.' ROWS'.($lmt?' FETCH NEXT '.$lmt.' ROWS ONLY':''); + } else { + // SQL Server 2008 + $order=(!isset($options['order'])) + ?($this->db->quotekey($this->table.'.'.$this->primary)):$options['order']; + $sql=str_replace('SELECT','SELECT '.($lmt>0?'TOP '.($ofs+$lmt):'').' ROW_NUMBER() '. + 'OVER (ORDER BY '.$order.') AS rnum,',$sql); + $sql='SELECT * FROM ('.$sql.') x WHERE rnum > '.($ofs); + } + } else { + if (isset($options['limit'])) + $sql.=' LIMIT '.(int)$options['limit']; + if (isset($options['offset'])) + $sql.=' OFFSET '.(int)$options['offset']; + } + } + unset($filter[0]); + $result = $this->db->exec($sql, $filter, $ttl); + if ($count) + return $result[0]['rows']; + foreach ($result as &$record) { + // factory new mappers + $mapper = clone($this->mapper); + $mapper->reset(); + // TODO: refactor this. Reflection can be removed for F3 >= v3.4.1 + $mapper->query= array($record); + $m_adhoc = empty($adhoc) ? array() : $m_refl_adhoc; + foreach ($record as $key=>$val) + if (isset($m_refl_adhoc[$key])) + $m_adhoc[$key]['value']=$val; + else + $mapper->set($key, $val); + if (!empty($adhoc)) { + $refl = new \ReflectionObject($mapper); + $prop = $refl->getProperty('adhoc'); + $prop->setAccessible(true); + $prop->setValue($mapper,$m_adhoc); + $prop->setAccessible(false); + } + $record = $mapper; + unset($record, $mapper); + } + return $result; + } elseif (!empty($this->preBinds) && !$count) { + // bind values to adhoc queries + if (!$filter) + // we (PDO) need any filter to bind values + $filter = array('1=1'); + $crit = array_shift($filter); + $filter = array_merge($this->preBinds,$filter); + array_unshift($filter,$crit); + } + } + return ($count) + ? $this->mapper->count($filter,$ttl) + : $this->mapper->find($filter,$this->queryParser->prepareOptions($options,$this->dbsType),$ttl); + } + + /** + * Retrieve first object that satisfies criteria + * @param null $filter + * @param array $options + * @param int $ttl + * @return Cortex + */ + public function load($filter = NULL, array $options = NULL, $ttl = 0) + { + $this->reset(); + $this->_ttl=$ttl?:$this->rel_ttl; + $res = $this->filteredFind($filter, $options, $ttl); + if ($res) { + $this->mapper->query = $res; + $this->first(); + } else + $this->mapper->reset(); + $this->emit('load'); + return $this; + } + + /** + * add has-conditional filter to next find call + * @param string $key + * @param array $filter + * @param null $options + * @return $this + */ + public function has($key, $filter, $options = null) { + if (is_string($filter)) + $filter=array($filter); + if (is_int(strpos($key,'.'))) { + list($key,$fkey) = explode('.',$key,2); + if (!isset($this->hasCond[$key.'.'])) + $this->hasCond[$key.'.'] = array(); + $this->hasCond[$key.'.'][$fkey] = array($filter,$options); + } else { + if (!isset($this->fieldConf[$key])) + trigger_error(sprintf(self::E_UNKNOWN_FIELD,$key,get_called_class())); + if (!isset($this->fieldConf[$key]['relType'])) + trigger_error(self::E_HAS_COND); + $this->hasCond[$key] = array($filter,$options); + } + return $this; + } + + /** + * return IDs of records that has a linkage to this mapper + * @param string $key relation field + * @param array $filter condition for foreign records + * @param array $options filter options for foreign records + * @param int $ttl + * @return array|false + */ + protected function _hasRefsIn($key, $filter, $options, $ttl = 0) + { + $type = $this->fieldConf[$key]['relType']; + $fieldConf = $this->fieldConf[$key][$type]; + // one-to-many shortcut + $rel = $this->getRelFromConf($fieldConf,$key); + $hasSet = $rel->find($filter, $options, $ttl); + if (!$hasSet) + return false; + $hasSetByRelId = array_unique($hasSet->getAll($fieldConf[1], true)); + return empty($hasSetByRelId) ? false : $hasSetByRelId; + } + + /** + * return IDs of own mappers that match the given relation filter on pivot tables + * @param string $key + * @param array $filter + * @param array $options + * @param int $ttl + * @return array|false + */ + protected function _hasRefsInMM($key, $filter, $options, $ttl=0) + { + $fieldConf = $this->fieldConf[$key]['has-many']; + $rel = $this->getRelInstance($fieldConf[0],null,$key,true); + $hasSet = $rel->find($filter,$options,$ttl); + $result = false; + if ($hasSet) { + $hasIDs = $hasSet->getAll('_id',true); + $mmTable = $this->mmTable($fieldConf,$key); + $pivot = $this->getRelInstance(null,array('db'=>$this->db,'table'=>$mmTable)); + $pivotSet = $pivot->find(array($key.' IN ?',$hasIDs),null,$ttl); + if ($pivotSet) + $result = array_unique($pivotSet->getAll($fieldConf['relField'],true)); + } + return $result; + } + + /** + * build query for SQL pivot table join and merge conditions + */ + protected function _hasJoinMM_sql($key, $hasCond, &$filter, &$options) + { + $fieldConf = $this->fieldConf[$key]['has-many']; + $hasJoin = array(); + $mmTable = $this->mmTable($fieldConf,$key); + $hasJoin[] = $this->_sql_left_join($this->primary,$this->table,$fieldConf['relField'],$mmTable); + $hasJoin[] = $this->_sql_left_join($key,$mmTable,$fieldConf['relPK'],$fieldConf['relTable']); + $this->_sql_mergeRelCondition($hasCond,$fieldConf['relTable'],$filter,$options); + return $hasJoin; + } + + /** + * build query for single SQL table join and merge conditions + */ + protected function _hasJoin_sql($key, $table, $cond, &$filter, &$options) + { + $relConf = $this->fieldConf[$key]['belongs-to-one']; + $relModel = is_array($relConf)?$relConf[0]:$relConf; + $rel = $this->getRelInstance($relModel,null,$key); + $fkey = is_array($this->fieldConf[$key]['belongs-to-one']) ? + $this->fieldConf[$key]['belongs-to-one'][1] : $rel->primary; + $query = $this->_sql_left_join($key,$this->table,$fkey,$table); + $this->_sql_mergeRelCondition($cond,$table,$filter,$options); + return $query; + } + + /** + * assemble SQL join query string + */ + protected function _sql_left_join($skey,$sTable,$fkey,$fTable) + { + $skey = $this->db->quotekey($skey); + $sTable = $this->db->quotekey($sTable); + $fkey = $this->db->quotekey($fkey); + $fTable = $this->db->quotekey($fTable); + return 'LEFT JOIN '.$fTable.' ON '.$sTable.'.'.$skey.' = '.$fTable.'.'.$fkey; + } + + /** + * merge condition of relation with current condition + * @param array $cond condition of related model + * @param string $table table of related model + * @param array $filter current filter to merge with + * @param array $options current options to merge with + */ + protected function _sql_mergeRelCondition($cond, $table, &$filter, &$options) + { + if (!empty($cond[0])) { + $whereClause = '('.array_shift($cond[0]).')'; + $whereClause = $this->_sql_prependTableToFields($whereClause,$table); + if (!$filter) + $filter = array($whereClause); + elseif (!empty($filter[0])) + $filter[0] = '('.$this->_sql_prependTableToFields($filter[0],$this->table).') and '.$whereClause; + $filter = array_merge($filter, $cond[0]); + } + if ($cond[1] && isset($cond[1]['group'])) { + $hasGroup = preg_replace('/(\w+)/i', $table.'.$1', $cond[1]['group']); + $options['group'] .= ','.$hasGroup; + } + } + + /** + * add table prefix to identifiers which do not have a table prefix yet + * @param string $cond + * @param string $table + * @return string + */ + protected function _sql_prependTableToFields($cond, $table) { + return preg_replace_callback('/(\w+\((?:[^)(]+|(?R))*\))|'. + '(?:(\s)|^|(?<=[(]))([a-zA-Z_](?:[\w\-_]+))(?=[\s<>=!)]|$)/i', + function($match) use($table) { + if (!isset($match[3])) + return $match[1]; + if (preg_match('/\b(AND|OR|IN|LIKE|NOT)\b/i',$match[3])) + return $match[0]; + return $match[2].$table.'.'.$match[3]; + }, $cond); + } + + /** + * add filter for loading related models + * @param string $key + * @param array $filter + * @param array $option + * @return $this + */ + public function filter($key,$filter=null,$option=null) + { + if (is_int(strpos($key,'.'))) { + list($key,$fkey) = explode('.',$key,2); + if (!isset($this->relFilter[$key.'.'])) + $this->relFilter[$key.'.'] = array(); + $this->relFilter[$key.'.'][$fkey] = array($filter,$option); + } else + $this->relFilter[$key] = array($filter,$option); + return $this; + } + + /** + * removes one or all relation filter + * @param null|string $key + */ + public function clearFilter($key = null) + { + if (!$key) + $this->relFilter = array(); + elseif(isset($this->relFilter[$key])) + unset($this->relFilter[$key]); + } + + /** + * merge the relation filter to the query criteria if it exists + * @param string $key + * @param array $crit + * @return array + */ + protected function mergeWithRelFilter($key,$crit) + { + if (array_key_exists($key, $this->relFilter) && + !empty($this->relFilter[$key][0])) + $crit=$this->mergeFilter(array($this->relFilter[$key][0],$crit)); + return $crit; + } + + /** + * merge multiple filters + * @param array $filters + * @param string $glue + * @return array + */ + public function mergeFilter($filters,$glue='and') { + $crit = array(); + $params = array(); + if ($filters) { + foreach($filters as $filter) { + $crit[] = array_shift($filter); + $params = array_merge($params,$filter); + } + array_unshift($params,'( '.implode(' ) '.$glue.' ( ',$crit).' )'); + } + return $params; + } + + /** + * returns the option condition for a relation filter, if defined + * @param string $key + * @return array null + */ + protected function getRelFilterOption($key) + { + return (array_key_exists($key, $this->relFilter) && + !empty($this->relFilter[$key][1])) + ? $this->relFilter[$key][1] : null; + } + + /** + * Delete object/s and reset ORM + * @param $filter + * @return bool + */ + public function erase($filter = null) + { + $filter = $this->queryParser->prepareFilter($filter, $this->dbsType, $this->db); + if (!$filter) { + if ($this->emit('beforeerase')===false) + return false; + if ($this->fieldConf) { + foreach($this->fieldConf as $field => $conf) + if (isset($conf['has-many']) && + $conf['has-many']['hasRel']=='has-many') + $this->set($field,null); + $this->save(); + } + $this->mapper->erase(); + $this->emit('aftererase'); + } elseif($filter) + $this->mapper->erase($filter); + return true; + } + + /** + * Save mapped record + * @return mixed + **/ + function save() + { + // update changed collections + $fields = $this->fieldConf; + if ($fields) + foreach($fields as $key=>$conf) + if (!empty($this->fieldsCache[$key]) && $this->fieldsCache[$key] instanceof CortexCollection + && $this->fieldsCache[$key]->hasChanged()) + $this->set($key,$this->fieldsCache[$key]->getAll('_id',true)); + // perform event & save operations + if ($new = $this->dry()) { + if ($this->emit('beforeinsert')===false) + return false; + $result=$this->insert(); + } else { + if ($this->emit('beforeupdate')===false) + return false; + $result=$this->update(); + } + // m:m save cascade + if (!empty($this->saveCsd)) { + foreach($this->saveCsd as $key => $val) { + if($fields[$key]['relType'] == 'has-many') { + $relConf = $fields[$key]['has-many']; + $mmTable = $this->mmTable($relConf,$key); + $rel = $this->getRelInstance(null, array('db'=>$this->db, 'table'=>$mmTable)); + $id = $this->get($relConf['relPK'],true); + // delete all refs + if (is_null($val)) + $rel->erase(array($relConf['relField'].' = ?', $id)); + // update refs + elseif (is_array($val)) { + $rel->erase(array($relConf['relField'].' = ?', $id)); + foreach($val as $v) { + $rel->set($key,$v); + $rel->set($relConf['relField'],$id); + $rel->save(); + $rel->reset(); + } + } + unset($rel); + } elseif($fields[$key]['relType'] == 'has-one') { + $val->save(); + } + } + $this->saveCsd = array(); + } + $this->emit($new?'afterinsert':'afterupdate'); + return $result; + } + + /** + * Count records that match criteria + * @param null $filter + * @param int $ttl + * @return mixed + */ + public function count($filter = NULL, $ttl = 60) + { + $has=$this->hasCond; + $count=$this->filteredFind($filter,null,$ttl,true); + $this->hasCond=$has; + return $count; + } + + /** + * Count records that are currently loaded + * @return int + */ + public function loaded() { + return count($this->mapper->query); + } + + /** + * add a virtual field that counts occurring relations + * @param $key + */ + public function countRel($key) { + if (isset($this->fieldConf[$key])){ + // one-to-one, one-to-many + if ($this->fieldConf[$key]['relType'] == 'belongs-to-one') { + if ($this->dbsType == 'sql') { + $this->mapper->set('count_'.$key,'count('.$key.')'); + $this->grp_stack=(!$this->grp_stack)?$key:$this->grp_stack.','.$key; + } elseif ($this->dbsType == 'mongo') + $this->_mongo_addGroup(array( + 'keys'=>array($key=>1), + 'reduce' => 'prev.count_'.$key.'++;', + "initial" => array("count_".$key => 0) + )); + else + trigger_error('Cannot add direct relational counter.'); + } elseif($this->fieldConf[$key]['relType'] == 'has-many') { + $relConf=$this->fieldConf[$key]['has-many']; + if ($relConf['hasRel']=='has-many') { + // many-to-many + if ($this->dbsType == 'sql') { + $mmTable = $this->mmTable($relConf,$key); + $filter = array($mmTable.'.'.$relConf['relField'] + .' = '.$this->table.'.'.$this->primary); + $from=$mmTable; + if (array_key_exists($key, $this->relFilter) && + !empty($this->relFilter[$key][0])) { + $options=array(); + $from = $mmTable.' '.$this->_sql_left_join($key,$mmTable,$relConf['relPK'],$relConf['relTable']); + $relFilter = $this->relFilter[$key]; + $this->_sql_mergeRelCondition($relFilter,$relConf['relTable'],$filter,$options); + } + $filter = $this->queryParser->prepareFilter($filter, $this->dbsType, $this->db, $this->fieldConf); + $crit = array_shift($filter); + if (count($filter)>0) + $this->preBinds+=$filter; + $this->mapper->set('count_'.$key,'(select count('.$mmTable.'.'.$relConf['relField'].') from '.$from. + ' where '.$crit.' group by '.$mmTable.'.'.$relConf['relField'].')'); + } else { + // count rel + $this->countFields[]=$key; + } + } elseif($this->fieldConf[$key]['has-many']['hasRel']=='belongs-to-one') { + // many-to-one + if ($this->dbsType == 'sql') { + $fConf=$relConf[0]::resolveConfiguration(); + $fTable=$fConf['table']; + $rKey=$relConf[1]; + $crit = $fTable.'.'.$rKey.' = '.$this->table.'.'.$this->primary; + $filter = $this->mergeWithRelFilter($key,array($crit)); + $filter = $this->queryParser->prepareFilter($filter, $this->dbsType, $this->db, $this->fieldConf); + $crit = array_shift($filter); + if (count($filter)>0) + $this->preBinds+=$filter; + $this->mapper->set('count_'.$key,'(select count('.$fTable.'.'.$fConf['primary'].') from '.$fTable.' where '. + $crit.' group by '.$fTable.'.'.$rKey.')'); + } else { + // count rel + $this->countFields[]=$key; + } + } + } + } + } + + /** + * merge mongo group options array + * @param $opt + */ + protected function _mongo_addGroup($opt){ + if (!$this->grp_stack) + $this->grp_stack = array('keys'=>array(),'initial'=>array(),'reduce'=>'','finalize'=>''); + if (isset($opt['keys'])) + $this->grp_stack['keys']+=$opt['keys']; + if (isset($opt['reduce'])) + $this->grp_stack['reduce'].=$opt['reduce']; + if (isset($opt['initial'])) + $this->grp_stack['initial']+=$opt['initial']; + if (isset($opt['finalize'])) + $this->grp_stack['finalize'].=$opt['finalize']; + } + + /** + * update a given date or time field with the current time + * @param string $key + */ + public function touch($key) { + if (isset($this->fieldConf[$key]) + && isset($this->fieldConf[$key]['type'])) { + $type = $this->fieldConf[$key]['type']; + $date = ($this->dbsType=='sql' && preg_match('/mssql|sybase|dblib|odbc|sqlsrv/', + $this->db->driver())) ? 'Ymd' : 'Y-m-d'; + if ($type == Schema::DT_DATETIME || Schema::DT_TIMESTAMP) + $this->set($key,date($date.' H:i:s')); + elseif ($type == Schema::DT_DATE) + $this->set($key,date($date)); + } + } + + /** + * Bind value to key + * @return mixed + * @param $key string + * @param $val mixed + */ + function set($key, $val) + { + $fields = $this->fieldConf; + unset($this->fieldsCache[$key]); + // pre-process if field config available + if (!empty($fields) && isset($fields[$key]) && is_array($fields[$key])) { + // handle relations + if (isset($fields[$key]['belongs-to-one'])) { + // one-to-many, one-to-one + if (is_null($val)) + $val = NULL; + elseif (is_object($val) && + !($this->dbsType=='mongo' && $val instanceof \MongoId)) { + // fetch fkey from mapper + if (!$val instanceof Cortex || $val->dry()) + trigger_error(self::E_INVALID_RELATION_OBJECT); + else { + $relConf = $fields[$key]['belongs-to-one']; + $rel_field = (is_array($relConf) ? $relConf[1] : '_id'); + $val = $val->get($rel_field,true); + } + } elseif ($this->dbsType == 'mongo' && !$val instanceof \MongoId) + $val = new \MongoId($val); + } elseif (isset($fields[$key]['has-one'])){ + $relConf = $fields[$key]['has-one']; + if (is_null($val)) { + $val = $this->get($key); + $val->set($relConf[1],NULL); + } else { + if (!$val instanceof Cortex) { + $rel = $this->getRelInstance($relConf[0],null,$key); + $rel->load(array('_id = ?', $val)); + $val = $rel; + } + $val->set($relConf[1], $this->_id); + } + $this->saveCsd[$key] = $val; + return $val; + } elseif (isset($fields[$key]['belongs-to-many'])) { + // many-to-many, unidirectional + $fields[$key]['type'] = self::DT_JSON; + $relConf = $fields[$key]['belongs-to-many']; + $rel_field = (is_array($relConf) ? $relConf[1] : '_id'); + $val = $this->getForeignKeysArray($val, $rel_field, $key); + } + elseif (isset($fields[$key]['has-many'])) { + // many-to-many, bidirectional + $relConf = $fields[$key]['has-many']; + if ($relConf['hasRel'] == 'has-many') { + // custom setter + $val = $this->emit('set_'.$key, $val); + $val = $this->getForeignKeysArray($val,'_id',$key); + $this->saveCsd[$key] = $val; // array of keys + $this->fieldsCache[$key] = $val; + return $val; + } elseif ($relConf['hasRel'] == 'belongs-to-one') { + // TODO: many-to-one, bidirectional, inverse way + trigger_error("not implemented"); + } + } + // convert array content + if (is_array($val) && $this->dbsType == 'sql') + if ($fields[$key]['type'] == self::DT_SERIALIZED) + $val = serialize($val); + elseif ($fields[$key]['type'] == self::DT_JSON) + $val = json_encode($val); + else + trigger_error(sprintf(self::E_ARRAY_DATATYPE, $key)); + // add nullable polyfill + if ($val === NULL && ($this->dbsType == 'jig' || $this->dbsType == 'mongo') + && array_key_exists('nullable', $fields[$key]) && $fields[$key]['nullable'] === false) + trigger_error(sprintf(self::E_NULLABLE_COLLISION,$key)); + // MongoId shorthand + if ($this->dbsType == 'mongo' && !$val instanceof \MongoId) { + if ($key == '_id') + $val = new \MongoId($val); + elseif (preg_match('/INT/i',$fields[$key]['type']) + && !isset($fields[$key]['relType'])) + $val = (int) $val; + } + if (preg_match('/BOOL/i',$fields[$key]['type'])) { + $val = !$val || $val==='false' ? false : (bool) $val; + if ($this->dbsType == 'sql') + $val = (int) $val; + } + } + // fluid SQL + if ($this->fluid && $this->dbsType == 'sql') { + $schema = new Schema($this->db); + $table = $schema->alterTable($this->table); + // add missing field + if (!in_array($key,$table->getCols())) { + // determine data type + if (isset($this->fieldConf[$key]) && isset($this->fieldConf[$key]['type'])) + $type = $this->fieldConf[$key]['type']; + elseif (is_int($val)) $type = $schema::DT_INT; + elseif (is_double($val)) $type = $schema::DT_DOUBLE; + elseif (is_float($val)) $type = $schema::DT_FLOAT; + elseif (is_bool($val)) $type = $schema::DT_BOOLEAN; + elseif (date('Y-m-d H:i:s', strtotime($val)) == $val) $type = $schema::DT_DATETIME; + elseif (date('Y-m-d', strtotime($val)) == $val) $type = $schema::DT_DATE; + elseif (\UTF::instance()->strlen($val)<=255) $type = $schema::DT_VARCHAR256; + else $type = $schema::DT_TEXT; + $table->addColumn($key)->type($type); + $table->build(); + // update mapper fields + $newField = $table->getCols(true); + $newField = $newField[$key]; + $refl = new \ReflectionObject($this->mapper); + $prop = $refl->getProperty('fields'); + $prop->setAccessible(true); + $fields = $prop->getValue($this->mapper); + $fields[$key] = $newField + array('value'=>NULL,'changed'=>NULL); + $prop->setValue($this->mapper,$fields); + } + } + // custom setter + $val = $this->emit('set_'.$key, $val); + return $this->mapper->set($key, $val); + } + + /** + * call custom field handlers + * @param $event + * @param $val + * @return mixed + */ + protected function emit($event, $val=null) + { + if (isset($this->trigger[$event])) { + if (preg_match('/^[sg]et_/',$event)) { + $val = (is_string($f=$this->trigger[$event]) + && preg_match('/^[sg]et_/',$f)) + ? call_user_func(array($this,$event),$val) + : \Base::instance()->call($f,array($this,$val)); + } else + $val = \Base::instance()->call($this->trigger[$event],array($this,$val)); + } elseif (preg_match('/^[sg]et_/',$event) && method_exists($this,$event)) { + $this->trigger[] = $event; + $val = call_user_func(array($this,$event),$val); + } + return $val; + } + + /** + * Define a custom field setter + * @param $key + * @param $func + */ + public function onset($key,$func) { + $this->trigger['set_'.$key] = $func; + } + + /** + * Define a custom field getter + * @param $key + * @param $func + */ + public function onget($key,$func) { + $this->trigger['get_'.$key] = $func; + } + + /** + * virtual mapper field setter + * @param string $key + * @param mixed|callback $val + * @return mixed|null + */ + public function virtual($key,$val) { + $this->vFields[$key]=$val; + } + + /** + * Retrieve contents of key + * @return mixed + * @param string $key + * @param bool $raw + */ + function &get($key,$raw = false) + { + // handle virtual fields + if (isset($this->vFields[$key])) { + $out = (is_callable($this->vFields[$key])) + ? call_user_func($this->vFields[$key], $this) : $this->vFields[$key]; + return $out; + } + $fields = $this->fieldConf; + $id = $this->primary; + if ($key == '_id' && $this->dbsType == 'sql') + $key = $id; + if ($this->whitelist && !in_array($key,$this->whitelist)) { + $out = null; + return $out; + } + if ($raw) { + $out = $this->exists($key) ? $this->mapper->{$key} : NULL; + return $out; + } + if (!empty($fields) && isset($fields[$key]) && is_array($fields[$key]) + && !array_key_exists($key,$this->fieldsCache)) { + // load relations + if (isset($fields[$key]['belongs-to-one'])) { + // one-to-X, bidirectional, direct way + if (!$this->exists($key) || is_null($this->mapper->{$key})) + $this->fieldsCache[$key] = null; + else { + // get config for this field + $relConf = $fields[$key]['belongs-to-one']; + // fetch related model + $rel = $this->getRelFromConf($relConf,$key); + // am i part of a result collection? + if ($cx = $this->getCollection()) { + // does the collection has cached results for this key? + if (!$cx->hasRelSet($key)) { + // build the cache, find all values of current key + $relKeys = array_unique($cx->getAll($key,true)); + // find related models + $crit = array($relConf[1].' IN ?', $relKeys); + $relSet = $rel->find($this->mergeWithRelFilter($key, $crit), + $this->getRelFilterOption($key),$this->_ttl); + // cache relSet, sorted by ID + $cx->setRelSet($key, $relSet ? $relSet->getBy($relConf[1]) : NULL); + } + // get a subset of the preloaded set + $result = $cx->getSubset($key,(string) $this->get($key,true)); + $this->fieldsCache[$key] = $result ? $result[0] : NULL; + } else { + $crit = array($relConf[1].' = ?', $this->get($key, true)); + $crit = $this->mergeWithRelFilter($key, $crit); + $this->fieldsCache[$key] = $rel->findone($crit, + $this->getRelFilterOption($key),$this->_ttl); + } + } + } + elseif (($type = isset($fields[$key]['has-one'])) + || isset($fields[$key]['has-many'])) { + $type = $type ? 'has-one' : 'has-many'; + $fromConf = $fields[$key][$type]; + if (!is_array($fromConf)) + trigger_error(sprintf(self::E_REL_CONF_INC, $key)); + $rel = $this->getRelInstance($fromConf[0],null,$key,true); + $relFieldConf = $rel->getFieldConfiguration(); + $relType = isset($relFieldConf[$fromConf[1]]['belongs-to-one']) ? + 'belongs-to-one' : 'has-many'; + // one-to-*, bidirectional, inverse way + if ($relType == 'belongs-to-one') { + $toConf = $relFieldConf[$fromConf[1]]['belongs-to-one']; + if(!is_array($toConf)) + $toConf = array($toConf, $id); + if ($toConf[1] != $id && (!$this->exists($toConf[1]) + || is_null($this->mapper->get($toConf[1])))) + $this->fieldsCache[$key] = null; + elseif($cx = $this->getCollection()) { + // part of a result set + if(!$cx->hasRelSet($key)) { + // emit eager loading + $relKeys = $cx->getAll($toConf[1],true); + $crit = array($fromConf[1].' IN ?', $relKeys); + $relSet = $rel->find($this->mergeWithRelFilter($key,$crit), + $this->getRelFilterOption($key),$this->_ttl); + $cx->setRelSet($key, $relSet ? $relSet->getBy($fromConf[1],true) : NULL); + } + $result = $cx->getSubset($key, array($this->get($toConf[1]))); + $this->fieldsCache[$key] = $result ? (($type == 'has-one') + ? $result[0][0] : CortexCollection::factory($result[0])) : NULL; + } else { + $crit = array($fromConf[1].' = ?', $this->get($toConf[1],true)); + $crit = $this->mergeWithRelFilter($key, $crit); + $opt = $this->getRelFilterOption($key); + $this->fieldsCache[$key] = (($type == 'has-one') + ? $rel->findone($crit,$opt,$this->_ttl) + : $rel->find($crit,$opt,$this->_ttl)) ?: NULL; + } + } + // many-to-many, bidirectional + elseif ($relType == 'has-many') { + $toConf = $relFieldConf[$fromConf[1]]['has-many']; + $mmTable = $this->mmTable($fromConf,$key,$toConf); + // create mm table mapper + if (!$this->get($id,true)) { + $this->fieldsCache[$key] = null; + return $this->fieldsCache[$key]; + } + $id = $toConf['relPK']; + $rel = $this->getRelInstance(null,array('db'=>$this->db,'table'=>$mmTable)); + if ($cx = $this->getCollection()) { + if (!$cx->hasRelSet($key)) { + // get IDs of all results + $relKeys = $cx->getAll($id,true); + // get all pivot IDs + $mmRes = $rel->find(array($fromConf['relField'].' IN ?', $relKeys),null,$this->_ttl); + if (!$mmRes) + $cx->setRelSet($key, NULL); + else { + $pivotRel = array(); + $pivotKeys = array(); + foreach($mmRes as $model) { + $val = $model->get($key,true); + $pivotRel[ (string) $model->get($fromConf['relField'])][] = $val; + $pivotKeys[] = $val; + } + // cache pivot keys + $cx->setRelSet($key.'_pivot', $pivotRel); + // preload all rels + $pivotKeys = array_unique($pivotKeys); + $fRel = $this->getRelInstance($fromConf[0],null,$key,true); + $crit = array($toConf['relPK'].' IN ?', $pivotKeys); + $relSet = $fRel->find($this->mergeWithRelFilter($key, $crit), + $this->getRelFilterOption($key),$this->_ttl); + $cx->setRelSet($key, $relSet ? $relSet->getBy($id) : NULL); + unset($fRel); + } + } + // fetch subset from preloaded rels using cached pivot keys + $fkeys = $cx->getSubset($key.'_pivot', array($this->get($id))); + $this->fieldsCache[$key] = $fkeys ? + CortexCollection::factory($cx->getSubset($key, $fkeys[0])) : NULL; + } // no collection + else { + // find foreign keys + $results = $rel->find( + array($fromConf['relField'].' = ?', $this->get($fromConf['relPK'],true)),null,$this->_ttl); + if(!$results) + $this->fieldsCache[$key] = NULL; + else { + $fkeys = $results->getAll($key,true); + // create foreign table mapper + unset($rel); + $rel = $this->getRelInstance($fromConf[0],null,$key,true); + // load foreign models + $filter = array($toConf['relPK'].' IN ?', $fkeys); + $filter = $this->mergeWithRelFilter($key, $filter); + $this->fieldsCache[$key] = $rel->find($filter, + $this->getRelFilterOption($key),$this->_ttl); + } + } + } + } + elseif (isset($fields[$key]['belongs-to-many'])) { + // many-to-many, unidirectional + $fields[$key]['type'] = self::DT_JSON; + $result = !$this->exists($key) ? null :$this->mapper->get($key); + if ($this->dbsType == 'sql') + $result = json_decode($result, true); + if (!is_array($result)) + $this->fieldsCache[$key] = $result; + else { + // create foreign table mapper + $relConf = $fields[$key]['belongs-to-many']; + $rel = $this->getRelFromConf($relConf,$key); + $fkeys = array(); + foreach ($result as $el) + $fkeys[] = is_int($el)||ctype_digit($el)?(int)$el:(string)$el; + // if part of a result set + if ($cx = $this->getCollection()) { + if (!$cx->hasRelSet($key)) { + // find all keys + $relKeys = ($cx->getAll($key,true)); + if ($this->dbsType == 'sql'){ + foreach ($relKeys as &$val) { + $val = substr($val, 1, -1); + unset($val); + } + $relKeys = json_decode('['.implode(',',$relKeys).']'); + } else + $relKeys = call_user_func_array('array_merge', $relKeys); + // get related models + $crit = array($relConf[1].' IN ?', array_unique($relKeys)); + $relSet = $rel->find($this->mergeWithRelFilter($key, $crit), + $this->getRelFilterOption($key),$this->_ttl); + // cache relSet, sorted by ID + $cx->setRelSet($key, $relSet ? $relSet->getBy($relConf[1]) : NULL); + } + // get a subset of the preloaded set + $this->fieldsCache[$key] = CortexCollection::factory($cx->getSubset($key, $fkeys)); + } else { + // load foreign models + $filter = array($relConf[1].' IN ?', $fkeys); + $filter = $this->mergeWithRelFilter($key, $filter); + $this->fieldsCache[$key] = $rel->find($filter, + $this->getRelFilterOption($key),$this->_ttl); + } + } + } + // resolve array fields + elseif (isset($fields[$key]['type'])) { + if ($this->dbsType == 'sql') { + if ($fields[$key]['type'] == self::DT_SERIALIZED) + $this->fieldsCache[$key] = unserialize($this->mapper->{$key}); + elseif ($fields[$key]['type'] == self::DT_JSON) + $this->fieldsCache[$key] = json_decode($this->mapper->{$key},true); + } + if ($this->exists($key) && preg_match('/BOOL/i',$fields[$key]['type'])) { + $this->fieldsCache[$key] = (bool) $this->mapper->{$key}; + } + } + } + // fetch cached value, if existing + $val = array_key_exists($key,$this->fieldsCache) ? $this->fieldsCache[$key] + : (($this->exists($key)) ? $this->mapper->{$key} : null); + if ($this->dbsType == 'mongo' && $val instanceof \MongoId) { + // conversion to string makes further processing in template, etc. much easier + $val = (string) $val; + } + // custom getter + $out = $this->emit('get_'.$key, $val); + return $out; + } + + /** + * find the ID values of given relation collection + * @param $val string|array|object|bool + * @param $rel_field string + * @param $key string + * @return array|Cortex|null|object + */ + protected function getForeignKeysArray($val, $rel_field, $key) + { + if (is_null($val)) + return NULL; + if (is_object($val) && $val instanceof CortexCollection) + $val = $val->expose(); + elseif (is_string($val)) + // split-able string of collection IDs + $val = \Base::instance()->split($val); + elseif (!is_array($val) && !(is_object($val) + && ($val instanceof Cortex && !$val->dry()))) + trigger_error(sprintf(self::E_MM_REL_VALUE, $key)); + // hydrated mapper as collection + if (is_object($val)) { + $nval = array(); + while (!$val->dry()) { + $nval[] = $val->get($rel_field,true); + $val->next(); + } + $val = $nval; + } + elseif (is_array($val)) { + // array of single hydrated mappers, raw ID value or mixed + $isMongo = ($this->dbsType == 'mongo'); + foreach ($val as &$item) { + if (is_object($item) && + !($isMongo && $item instanceof \MongoId)) { + if (!$item instanceof Cortex || $item->dry()) + trigger_error(self::E_INVALID_RELATION_OBJECT); + else $item = $item->get($rel_field,true); + } + if ($isMongo && $rel_field == '_id' && is_string($item)) + $item = new \MongoId($item); + if (is_numeric($item)) + $item = (int) $item; + unset($item); + } + } + return $val; + } + + /** + * creates and caches related mapper objects + * @param string $model + * @param array $relConf + * @param string $key + * @param bool $pushFilter + * @return Cortex + */ + protected function getRelInstance($model=null,$relConf=null,$key='',$pushFilter=false) + { + if (!$model && !$relConf) + trigger_error(self::E_MISSING_REL_CONF); + $relConf = $model ? $model::resolveConfiguration() : $relConf; + $relName = ($model?:'Cortex').'\\'.$relConf['db']->uuid(). + '\\'.$relConf['table'].'\\'.$key; + if (\Registry::exists($relName)) { + $rel = \Registry::get($relName); + $rel->reset(); + } else { + $rel = $model ? new $model : new Cortex($relConf['db'], $relConf['table']); + if (!$rel instanceof Cortex) + trigger_error(self::E_WRONG_RELATION_CLASS); + \Registry::set($relName, $rel); + } + // restrict fields of related mapper + if(!empty($key) && isset($this->relWhitelist[$key])) { + if (isset($this->relWhitelist[$key][0])) + $rel->fields($this->relWhitelist[$key][0],false); + if (isset($this->relWhitelist[$key][1])) + $rel->fields($this->relWhitelist[$key][1],true); + } + if ($pushFilter && !empty($key)) { + if (isset($this->relFilter[$key.'.'])) { + foreach($this->relFilter[$key.'.'] as $fkey=>$conf) + $rel->filter($fkey,$conf[0],$conf[1]); + } + if (isset($this->hasCond[$key.'.'])) { + foreach($this->hasCond[$key.'.'] as $fkey=>$conf) + $rel->has($fkey,$conf[0],$conf[1]); + } + } + return $rel; + } + + /** + * get relation model from config + * @param $fieldConf + * @param $key + * @return Cortex + */ + protected function getRelFromConf(&$fieldConf, $key) { + if (!is_array($fieldConf)) + $fieldConf = array($fieldConf, '_id'); + $rel = $this->getRelInstance($fieldConf[0],null,$key,true); + if($this->dbsType=='sql' && $fieldConf[1] == '_id') + $fieldConf[1] = $rel->primary; + return $rel; + } + + /** + * returns a clean/dry model from a relation + * @param string $key + * @return Cortex + */ + public function rel($key) + { + $rt = $this->fieldConf[$key]['relType']; + $rc = $this->fieldConf[$key][$rt]; + if (!is_array($rc)) + $rc = array($rc,'_id'); + return $this->getRelInstance($rc[0],null,$key); + } + + /** + * Return fields of mapper object as an associative array + * @return array + * @param bool|Cortex $obj + * @param int|array $rel_depths depths to resolve relations + */ + public function cast($obj = NULL, $rel_depths = 1) + { + $fields = $this->mapper->cast( ($obj) ? $obj->mapper : null ); + if (!empty($this->vFields)) + foreach(array_keys($this->vFields) as $key) + $fields[$key]=$this->get($key); + if (is_int($rel_depths)) + $rel_depths = array('*'=>$rel_depths-1); + elseif (is_array($rel_depths)) + $rel_depths['*'] = isset($rel_depths['*'])?--$rel_depths['*']:-1; + if (!empty($this->fieldConf)) { + $fields += array_fill_keys(array_keys($this->fieldConf),NULL); + if($this->whitelist) + $fields = array_intersect_key($fields, array_flip($this->whitelist)); + $mp = $obj ? : $this; + foreach ($fields as $key => &$val) { + // post process configured fields + if (isset($this->fieldConf[$key]) && is_array($this->fieldConf[$key])) { + // handle relations + $rd = isset($rel_depths[$key]) ? $rel_depths[$key] : $rel_depths['*']; + if ((is_array($rd) || $rd >= 0) && $type=preg_grep('/[belongs|has]-(to-)*[one|many]/', + array_keys($this->fieldConf[$key]))) { + $relType=current($type); + // cast relations + $val = (($relType == 'belongs-to-one' || $relType == 'belongs-to-many') + && !$mp->exists($key)) ? NULL : $mp->get($key); + if ($val instanceof Cortex) + $val = $val->cast(null, $rd); + elseif ($val instanceof CortexCollection) + $val = $val->castAll($rd); + } + // extract array fields + elseif (isset($this->fieldConf[$key]['type'])) { + if ($this->dbsType == 'sql') { + if ($this->fieldConf[$key]['type'] == self::DT_SERIALIZED) + $val=unserialize($mp->mapper->{$key}); + elseif ($this->fieldConf[$key]['type'] == self::DT_JSON) + $val=json_decode($mp->mapper->{$key}, true); + } + if ($this->exists($key) + && preg_match('/BOOL/i',$this->fieldConf[$key]['type'])) { + $val = (bool) $mp->mapper->{$key}; + } + } + } + if ($this->dbsType == 'mongo' && $key == '_id') + $val = (string) $val; + if ($this->dbsType == 'sql' && $key == 'id' && $this->standardiseID) { + $fields['_id'] = $val; + unset($fields[$key]); + } + unset($val); + } + } + // custom getter + foreach ($fields as $key => &$val) { + $val = $this->emit('get_'.$key, $val); + unset($val); + } + return $fields; + } + + /** + * cast a related collection of mappers + * @param string $key field name + * @param int $rel_depths depths to resolve relations + * @return array array of associative arrays + */ + function castField($key, $rel_depths=0) + { + if (!$key) + return NULL; + $mapper_arr = $this->get($key); + if(!$mapper_arr) + return NULL; + $out = array(); + foreach ($mapper_arr as $mp) + $out[] = $mp->cast(null,$rel_depths); + return $out; + } + + /** + * wrap result mapper + * @param Cursor|array $mapper + * @return Cortex + */ + protected function factory($mapper) + { + if (is_array($mapper)) { + $mp = clone($this->mapper); + $mp->reset(); + $cx = $this->factory($mp); + $cx->copyfrom($mapper); + } else { + $cx = clone($this); + $cx->reset(false); + $cx->mapper = $mapper; + } + $cx->emit('load'); + return $cx; + } + + public function dry() { + return $this->mapper->dry(); + } + + /** + * hydrate the mapper from hive key or given array + * @param string|array $key + * @param callback|array|string $fields + * @return NULL + */ + public function copyfrom($key, $fields = null) + { + $f3 = \Base::instance(); + $srcfields = is_array($key) ? $key : $f3->get($key); + if ($fields) + if (is_callable($fields)) + $srcfields = $fields($srcfields); + else { + if (is_string($fields)) + $fields = $f3->split($fields); + $srcfields = array_intersect_key($srcfields, array_flip($fields)); + } + foreach ($srcfields as $key => $val) { + if (isset($this->fieldConf[$key]) && isset($this->fieldConf[$key]['type'])) { + if ($this->fieldConf[$key]['type'] == self::DT_JSON && is_string($val)) + $val = json_decode($val); + elseif ($this->fieldConf[$key]['type'] == self::DT_SERIALIZED && is_string($val)) + $val = unserialize($val); + } + $this->set($key, $val); + } + } + + /** + * copy mapper values into hive key + * @param string $key the hive key to copy into + * @param int $relDepth the depth of relations to resolve + * @return NULL|void + */ + public function copyto($key, $relDepth=0) { + \Base::instance()->set($key, $this->cast(null,$relDepth)); + } + + public function skip($ofs = 1) + { + $this->reset(false); + if ($this->mapper->skip($ofs)) + return $this; + else + $this->reset(false); + } + + public function first() + { + $this->reset(false); + $this->mapper->first(); + return $this; + } + + public function last() + { + $this->reset(false); + $this->mapper->last(); + return $this; + } + + /** + * reset and re-initialize the mapper + * @param bool $mapper + * @return NULL|void + */ + public function reset($mapper = true) + { + if ($mapper) + $this->mapper->reset(); + $this->fieldsCache=array(); + $this->saveCsd=array(); + $this->countFields=array(); + $this->preBinds=array(); + $this->grp_stack=null; + // set default values + if (($this->dbsType == 'jig' || $this->dbsType == 'mongo') + && !empty($this->fieldConf)) + foreach($this->fieldConf as $field_key => $field_conf) + if (array_key_exists('default',$field_conf)) { + $val = ($field_conf['default'] === \DB\SQL\Schema::DF_CURRENT_TIMESTAMP) + ? date('Y-m-d H:i:s') : $field_conf['default']; + $this->set($field_key, $val); + } + } + + /** + * check if a certain field exists in the mapper or + * or is a virtual relation field + * @param string $key + * @param bool $relField + * @return bool + */ + function exists($key, $relField = false) { + if (!$this->dry() && $key == '_id') return true; + return $this->mapper->exists($key) || + ($relField && isset($this->fieldConf[$key]['relType'])); + } + + /** + * clear any mapper field or relation + * @param string $key + * @return NULL|void + */ + function clear($key) { + unset($this->fieldsCache[$key]); + if (isset($this->fieldConf[$key]['relType'])) + $this->set($key,null); + $this->mapper->clear($key); + } + + function insert() { + $res = $this->mapper->insert(); + if (is_array($res)) + $res = $this->mapper; + if (is_object($res)) + $res = $this->factory($res); + return is_int($res) ? $this : $res; + } + + function update() { + $res = $this->mapper->update(); + if (is_array($res)) + $res = $this->mapper; + if (is_object($res)) + $res = $this->factory($res); + return is_int($res) ? $this : $res; + } + + function dbtype() { + return $this->mapper->dbtype(); + } + + public function __clone() { + $this->mapper = clone($this->mapper); + } + + function getiterator() { +// return new \ArrayIterator($this->cast(null,false)); + return new \ArrayIterator(array()); + } +} + + +class CortexQueryParser extends \Prefab { + + const + E_BRACKETS = 'Invalid query: unbalanced brackets found', + E_INBINDVALUE = 'Bind value for IN operator must be a populated array', + E_ENGINEERROR = 'Engine not supported', + E_MISSINGBINDKEY = 'Named bind parameter `%s` does not exist in filter arguments'; + + protected + $queryCache = array(); + + /** + * converts the given filter array to fit the used DBS + * + * example filter: + * array('text = ? AND num = ?','bar',5) + * array('num > ? AND num2 <= ?',5,10) + * array('num1 > num2') + * array('text like ?','%foo%') + * array('(text like ? OR text like ?) AND num != ?','foo%','%bar',23) + * + * @param array $cond + * @param string $engine + * @param object $db + * @param null $fieldConf + * @return array|bool|null + */ + public function prepareFilter($cond, $engine, $db, $fieldConf=null) + { + if (is_null($cond)) return $cond; + if (is_string($cond)) + $cond = array($cond); + $f3 = \Base::instance(); + $cacheHash = $f3->hash($f3->stringify($cond)).'.'.$engine; + if ($engine=='sql') + $cacheHash.='-'.$db->driver(); + if (isset($this->queryCache[$cacheHash])) + // load from memory + return $this->queryCache[$cacheHash]; + elseif ($f3->exists('CORTEX.queryParserCache') + && ($ttl = (int) $f3->get('CORTEX.queryParserCache'))) { + $cache = \Cache::instance(); + // load from cache + if ($f3->get('CACHE') && $ttl && ($cached = $cache->exists($cacheHash, $ncond)) + && $cached[0] + $ttl > microtime(TRUE)) { + $this->queryCache[$cacheHash] = $ncond; + return $ncond; + } + } + $where = array_shift($cond); + $args = $cond; + $where = str_replace(array('&&', '||'), array('AND', 'OR'), $where); + // prepare IN condition + $where = preg_replace('/\bIN\b\s*\(\s*(\?|:\w+)?\s*\)/i', 'IN $1', $where); + switch ($engine) { + case 'jig': + $ncond = $this->_jig_parse_filter($where, $args); + break; + case 'mongo': + $parts = $this->splitLogical($where); + if (is_int(strpos($where, ':'))) + list($parts, $args) = $this->convertNamedParams($parts, $args); + foreach ($parts as &$part) { + $part = $this->_mongo_parse_relational_op($part, $args, $fieldConf); + unset($part); + } + $ncond = $this->_mongo_parse_logical_op($parts); + break; + case 'sql': + if (!$f3->exists('CORTEX.quoteConditions',$qc) || $qc) + $where = $this->sql_quoteCondition($where,$db); + // preserve identifier + $where = preg_replace('/(?!\B)_id/', 'id', $where); + if ($db->driver() == 'pgsql') + $where = preg_replace('/\s+like\s+/i', ' ILIKE ', $where); + $parts = $this->splitLogical($where); + // ensure positional bind params + if (is_int(strpos($where, ':'))) + list($parts, $args) = $this->convertNamedParams($parts, $args); + $ncond = array(); + foreach ($parts as &$part) { + // enhanced IN handling + if (is_int(strpos($part, '?'))) { + $val = array_shift($args); + if (is_int($pos = strpos($part, 'IN ?'))) { + if (!is_array($val) || empty($val)) + trigger_error(self::E_INBINDVALUE); + $bindMarks = str_repeat('?,', count($val) - 1).'?'; + $part = substr($part, 0, $pos).'IN ('.$bindMarks.')'; + $ncond = array_merge($ncond, $val); + } elseif($val === null && preg_match('/(\w+)\s*([!=<>]+)\s*\?/i',$part,$match)) { + $part = $match[1].' IS '.($match[2]=='='||$match[2]=='=='?'':'NOT ').'NULL'; + } else + $ncond[] = $val; + } + unset($part); + } + array_unshift($ncond, implode($parts)); +// array_unshift($ncond, array_reduce($parts,function($out,$part){ +// return $out.((!$out||in_array($part,array('(',')')) +// ||preg_match('/\($/',$out))?'':' ').$part; +// },'')); + break; + default: + trigger_error(self::E_ENGINEERROR); + } + $this->queryCache[$cacheHash] = $ncond; + if(isset($ttl) && $f3->get('CACHE')) { + // save to cache + $cache = \Cache::instance(); + $cache->set($cacheHash,$ncond,$ttl); + } + return $ncond; + } + + /** + * split where criteria string into logical chunks + * @param $cond + * @return array + */ + protected function splitLogical($cond) + { + return preg_split('/(\s*(?=!)]|$))/i', + function($match) use($table,$db) { + if (!isset($match[2])) + return $match[1]; + if (preg_match('/\b(AND|OR|IN|LIKE|NOT)\b/i',$match[2])) + return $match[2]; + return $db->quotekey(($table?$table.'.':'').$match[2]); + }, $cond); + } + + /** + * convert filter array to jig syntax + * @param $where + * @param $args + * @return array + */ + protected function _jig_parse_filter($where, $args) + { + $parts = $this->splitLogical($where); + if (is_int(strpos($where, ':'))) + list($parts, $args) = $this->convertNamedParams($parts, $args); + $ncond = array(); + foreach ($parts as &$part) { + if (preg_match('/\s*\b(AND|OR)\b\s*/i',$part)) + continue; + // prefix field names + $part = preg_replace('/([a-z_-]+)/i', '@$1', $part, -1, $count); + // value comparison + if (is_int(strpos($part, '?'))) { + $val = array_shift($args); + preg_match('/(@\w+)/i', $part, $match); + $skipVal=false; + // find like operator + if (is_int(strpos($upart = strtoupper($part), ' @LIKE '))) { + if ($not = is_int($npos = strpos($upart, '@NOT'))) + $pos = $npos; + $val = $this->_likeValueToRegEx($val); + $part = ($not ? '!' : '').'preg_match(?,'.$match[0].')'; + } // find IN operator + elseif (is_int($pos = strpos($upart, ' @IN '))) { + if ($not = is_int($npos = strpos($upart, '@NOT'))) + $pos = $npos; + $part = ($not ? '!' : '').'in_array('.substr($part, 0, $pos). + ',array(\''.implode('\',\'', $val).'\'))'; + $skipVal=true; + } + elseif($val===null && preg_match('/(\w+)\s*([!=<>]+)\s*\?/i',$part,$nmatch) + && ($nmatch[2]=='=' || $nmatch[2]=='==')){ + $part = '(!array_key_exists(\''.ltrim($nmatch[1],'@').'\',$_row))'; + unset($part); + continue; + } + // add existence check + $part = ($val===null && !$skipVal) + ? '(array_key_exists(\''.ltrim($match[0],'@').'\',$_row) && '.$part.')' + : '(isset('.$match[0].') && '.$part.')'; + if (!$skipVal) + $ncond[] = $val; + } elseif ($count >= 1) { + // field comparison + preg_match_all('/(@\w+)/i', $part, $matches); + $chks = array(); + foreach ($matches[0] as $field) + $chks[] = 'isset('.$field.')'; + $part = '('.implode(' && ',$chks).' && ('.$part.'))'; + } + unset($part); + } + array_unshift($ncond, implode(' ', $parts)); + return $ncond; + } + + /** + * find and wrap logical operators AND, OR, (, ) + * @param $parts + * @return array + */ + protected function _mongo_parse_logical_op($parts) + { + $b_offset = 0; + $ncond = array(); + $child = array(); + for ($i = 0, $max = count($parts); $i < $max; $i++) { + $part = $parts[$i]; + if ($part == '(') { + // add sub-bracket to parse array + if ($b_offset > 0) + $child[] = $part; + $b_offset++; + } elseif ($part == ')') { + $b_offset--; + // found closing bracket + if ($b_offset == 0) { + $ncond[] = ($this->_mongo_parse_logical_op($child)); + $child = array(); + } elseif ($b_offset < 0) + trigger_error(self::E_BRACKETS); + else + // add sub-bracket to parse array + $child[] = $part; + } // add to parse array + elseif ($b_offset > 0) + $child[] = $part; + // condition type + elseif (!is_array($part)) { + if (strtoupper(trim($part)) == 'AND') + $add = true; + elseif (strtoupper(trim($part)) == 'OR') + $or = true; + } else // skip + $ncond[] = $part; + } + if ($b_offset > 0) + trigger_error(self::E_BRACKETS); + if (isset($add)) + return array('$and' => $ncond); + elseif (isset($or)) + return array('$or' => $ncond); + else + return $ncond[0]; + } + + /** + * find and convert relational operators + * @param $part + * @param $args + * @param null $fieldConf + * @return array|null + */ + protected function _mongo_parse_relational_op($part, &$args, $fieldConf=null) + { + if (is_null($part)) + return $part; + if (preg_match('/\<\=|\>\=|\<\>|\<|\>|\!\=|\=\=|\=|like|not like|in|not in/i', $part, $match)) { + $var = is_int(strpos($part, '?')) ? array_shift($args) : null; + $exp = explode($match[0], $part); + $key = trim($exp[0]); + // unbound value + if (is_numeric($exp[1])) + $var = $exp[1]; + // field comparison + elseif (!is_int(strpos($exp[1], '?'))) + return array('$where' => 'this.'.$key.' '.$match[0].' this.'.trim($exp[1])); + $upart = strtoupper($match[0]); + // MongoID shorthand + if ($key == '_id' || (isset($fieldConf[$key]) && isset($fieldConf[$key]['relType']))) { + if (is_array($var)) + foreach ($var as &$id) { + if (!$id instanceof \MongoId) + $id = new \MongoId($id); + unset($id); + } + elseif(!$var instanceof \MongoId) + $var = new \MongoId($var); + } + // find LIKE operator + if (in_array($upart, array('LIKE','NOT LIKE'))) { + $rgx = $this->_likeValueToRegEx($var); + $var = new \MongoRegex($rgx); + if ($upart == 'NOT LIKE') + $var = array('$not' => $var); + } // find IN operator + elseif (in_array($upart, array('IN','NOT IN'))) { + $var = array(($upart=='NOT IN')?'$nin':'$in' => array_values($var)); + } // translate operators + elseif (!in_array($match[0], array('==', '='))) { + $opr = str_replace(array('<>', '<', '>', '!', '='), + array('$ne', '$lt', '$gt', '$n', 'e'), $match[0]); + $var = array($opr => (strtolower($var) == 'null') ? null : + (is_object($var) ? $var : (is_numeric($var) ? $var + 0 : $var))); + } + return array($key => $var); + } + return $part; + } + + /** + * @param string $var + * @return string + */ + protected function _likeValueToRegEx($var) + { + $lC = substr($var, -1, 1); + // %var% -> /var/ + if ($var[0] == '%' && $lC == '%') + $var = substr($var, 1, -1); + // var% -> /^var/ + elseif ($lC == '%') + $var = '^'.substr($var, 0, -1); + // %var -> /var$/ + elseif ($var[0] == '%') + $var = substr($var, 1).'$'; + return '/'.$var.'/iu'; + } + + /** + * convert options array syntax to given engine type + * + * example: + * array('order'=>'location') // default direction is ASC + * array('order'=>'num1 desc, num2 asc') + * + * @param array $options + * @param string $engine + * @return array|null + */ + public function prepareOptions($options, $engine) + { + if (empty($options) || !is_array($options)) + return null; + switch ($engine) { + case 'jig': + if (array_key_exists('order', $options)) + $options['order'] = str_replace(array('asc', 'desc'), + array('SORT_ASC', 'SORT_DESC'), strtolower($options['order'])); + break; + case 'mongo': + if (array_key_exists('order', $options)) { + $sorts = explode(',', $options['order']); + $sorting = array(); + foreach ($sorts as $sort) { + $sp = explode(' ', trim($sort)); + $sorting[$sp[0]] = (array_key_exists(1, $sp) && + strtoupper($sp[1]) == 'DESC') ? -1 : 1; + } + $options['order'] = $sorting; + } + if (array_key_exists('group', $options) && is_string($options['group'])) { + $keys = explode(',',$options['group']); + $options['group']=array('keys'=>array(),'initial'=>array(), + 'reduce'=>'function (obj, prev) {}','finalize'=>''); + $keys = array_combine($keys,array_fill(0,count($keys),1)); + $options['group']['keys']=$keys; + $options['group']['initial']=$keys; + } + break; + } + return $options; + } +} + +class CortexCollection extends \ArrayIterator { + + protected + $relSets = array(), + $pointer = 0, + $changed = false, + $cid; + + const + E_UnknownCID = 'This Collection does not exist: %s', + E_SubsetKeysValue = '$keys must be an array or split-able string, but %s was given.'; + + public function __construct() { + $this->cid = uniqid('cortex_collection_'); + parent::__construct(); + } + + //! Prohibit cloning to ensure an existing relation cache + private function __clone() { } + + /** + * set a collection of models + * @param $models + */ + function setModels($models,$init=true) { + array_map(array($this,'add'),$models); + if ($init) + $this->changed = false; + } + + /** + * add single model to collection + * @param $model + */ + function add(Cortex $model) { + $model->addToCollection($this); + $this->append($model); + } + + public function offsetSet($i, $val) { + $this->changed=true; + parent::offsetSet($i,$val); + } + + public function hasChanged() { + return $this->changed; + } + + /** + * get a related collection + * @param $key + * @return null + */ + public function getRelSet($key) { + return (isset($this->relSets[$key])) ? $this->relSets[$key] : null; + } + + /** + * set a related collection for caching it for the lifetime of this collection + * @param $key + * @param $set + */ + public function setRelSet($key,$set) { + $this->relSets[$key] = $set; + } + + /** + * check if a related collection exists in runtime cache + * @param $key + * @return bool + */ + public function hasRelSet($key) { + return array_key_exists($key,$this->relSets); + } + + public function expose() { + return $this->getArrayCopy(); + } + + /** + * get an intersection from a cached relation-set, based on given keys + * @param string $prop + * @param array|string $keys + * @return array + */ + public function getSubset($prop,$keys) { + if (is_string($keys)) + $keys = \Base::instance()->split($keys); + if (!is_array($keys)) + trigger_error(sprintf(self::E_SubsetKeysValue,gettype($keys))); + if (!$this->hasRelSet($prop) || !($relSet = $this->getRelSet($prop))) + return null; + foreach ($keys as &$key) { + if ($key instanceof \MongoId) + $key = (string) $key; + unset($key); + } + return array_values(array_intersect_key($relSet, array_flip($keys))); + } + + /** + * returns all values of a specified property from all models + * @param string $prop + * @param bool $raw + * @return array + */ + public function getAll($prop, $raw = false) + { + $out = array(); + foreach ($this->getArrayCopy() as $model) { + if ($model instanceof Cortex && $model->exists($prop,true)) { + $val = $model->get($prop, $raw); + if (!empty($val)) + $out[] = $val; + } elseif($raw) + $out[] = $model; + } + return $out; + } + + /** + * cast all contained mappers to a nested array + * @param int|array $rel_depths depths to resolve relations + * @return array + */ + public function castAll($rel_depths=1) { + $out = array(); + foreach ($this->getArrayCopy() as $model) + $out[] = $model->cast(null,$rel_depths); + return $out; + } + + /** + * return all models keyed by a specified index key + * @param string $index + * @param bool $nested + * @return array + */ + public function getBy($index, $nested = false) + { + $out = array(); + foreach ($this->getArrayCopy() as $model) + if ($model->exists($index)) { + $val = $model->get($index, true); + if (!empty($val)) + if($nested) $out[(string) $val][] = $model; + else $out[(string) $val] = $model; + } + return $out; + } + + /** + * re-assort the current collection using a sql-like syntax + * @param $cond + */ + public function orderBy($cond){ + $cols=\Base::instance()->split($cond); + $this->uasort(function($val1,$val2) use($cols) { + foreach ($cols as $col) { + $parts=explode(' ',$col,2); + $order=empty($parts[1])?'ASC':$parts[1]; + $col=$parts[0]; + list($v1,$v2)=array($val1[$col],$val2[$col]); + if ($out=strnatcmp($v1,$v2)* + ((strtoupper($order)=='ASC')*2-1)) + return $out; + } + return 0; + }); + } + + /** + * slice the collection + * @param $offset + * @param null $limit + */ + public function slice($offset,$limit=null) { + $this->rewind(); + $i=0; + $del=array(); + while ($this->valid()) { + if ($i < $offset) + $del[]=$this->key(); + elseif ($i >= $offset && $limit && $i >= ($offset+$limit)) + $del[]=$this->key(); + $i++; + $this->next(); + } + foreach ($del as $ii) + unset($this[$ii]); + } + + static public function factory($records) { + $cc = new self(); + $cc->setModels($records); + return $cc; + } + +} \ No newline at end of file diff --git a/lib/f3/db/cursor.php b/lib/f3/db/cursor.php new file mode 100755 index 0000000..6a02e51 --- /dev/null +++ b/lib/f3/db/cursor.php @@ -0,0 +1,246 @@ +query[$this->ptr]); + } + + /** + * Return first record (mapper object) that matches criteria + * @return object|FALSE + * @param $filter string|array + * @param $options array + * @param $ttl int + **/ + function findone($filter=NULL,array $options=NULL,$ttl=0) { + return ($data=$this->find($filter,$options,$ttl))?$data[0]:FALSE; + } + + /** + * Return array containing subset of records matching criteria, + * total number of records in superset, specified limit, number of + * subsets available, and actual subset position + * @return array + * @param $pos int + * @param $size int + * @param $filter string|array + * @param $options array + **/ + function paginate($pos=0,$size=10,$filter=NULL,array $options=NULL) { + $total=$this->count($filter); + $count=ceil($total/$size); + $pos=max(0,min($pos,$count-1)); + return array( + 'subset'=>$this->find($filter, + array_merge( + $options?:array(), + array('limit'=>$size,'offset'=>$pos*$size) + ) + ), + 'total'=>$total, + 'limit'=>$size, + 'count'=>$count, + 'pos'=>$pos<$count?$pos:0 + ); + } + + /** + * Map to first record that matches criteria + * @return array|FALSE + * @param $filter string|array + * @param $options array + * @param $ttl int + **/ + function load($filter=NULL,array $options=NULL,$ttl=0) { + return ($this->query=$this->find($filter,$options,$ttl)) && + $this->skip(0)?$this->query[$this->ptr=0]:FALSE; + } + + /** + * Map to first record in cursor + * @return mixed + **/ + function first() { + return $this->skip(-$this->ptr); + } + + /** + * Map to last record in cursor + * @return mixed + **/ + function last() { + return $this->skip(($ofs=count($this->query)-$this->ptr)?$ofs-1:0); + } + + /** + * Map to nth record relative to current cursor position + * @return mixed + * @param $ofs int + **/ + function skip($ofs=1) { + $this->ptr+=$ofs; + return $this->ptr>-1 && $this->ptrquery)? + $this->query[$this->ptr]:FALSE; + } + + /** + * Map next record + * @return mixed + **/ + function next() { + return $this->skip(); + } + + /** + * Map previous record + * @return mixed + **/ + function prev() { + return $this->skip(-1); + } + + /** + * Save mapped record + * @return mixed + **/ + function save() { + return $this->query?$this->update():$this->insert(); + } + + /** + * Delete current record + * @return int|bool + **/ + function erase() { + $this->query=array_slice($this->query,0,$this->ptr,TRUE)+ + array_slice($this->query,$this->ptr,NULL,TRUE); + $this->ptr=0; + } + + /** + * Define onload trigger + * @return closure + **/ + function onload($func) { + return $this->trigger['load']=$func; + } + + /** + * Define oninsert trigger + * @return closure + **/ + function oninsert($func) { + return $this->trigger['insert']=$func; + } + + /** + * Define onupdate trigger + * @return closure + **/ + function onupdate($func) { + return $this->trigger['update']=$func; + } + + /** + * Define onerase trigger + * @return closure + **/ + function onerase($func) { + return $this->trigger['erase']=$func; + } + + /** + * Reset cursor + * @return NULL + **/ + function reset() { + $this->query=array(); + $this->ptr=0; + } + +} diff --git a/lib/f3/db/jig.php b/lib/f3/db/jig.php new file mode 100755 index 0000000..16f2255 --- /dev/null +++ b/lib/f3/db/jig.php @@ -0,0 +1,133 @@ +dir.$file)) + return array(); + $raw=$fw->read($dst); + switch ($this->format) { + case self::FORMAT_JSON: + $data=json_decode($raw,TRUE); + break; + case self::FORMAT_Serialized: + $data=$fw->unserialize($raw); + break; + } + return $data; + } + + /** + * Write data to file + * @return int + * @param $file string + * @param $data array + **/ + function write($file,array $data=NULL) { + $fw=\Base::instance(); + switch ($this->format) { + case self::FORMAT_JSON: + $out=json_encode($data,@constant('JSON_PRETTY_PRINT')); + break; + case self::FORMAT_Serialized: + $out=$fw->serialize($data); + break; + } + return $fw->write($this->dir.$file,$out); + } + + /** + * Return directory + * @return string + **/ + function dir() { + return $this->dir; + } + + /** + * Return UUID + * @return string + **/ + function uuid() { + return $this->uuid; + } + + /** + * Return SQL profiler results + * @return string + **/ + function log() { + return $this->log; + } + + /** + * Jot down log entry + * @return NULL + * @param $frame string + **/ + function jot($frame) { + if ($frame) + $this->log.=date('r').' '.$frame.PHP_EOL; + } + + /** + * Clean storage + * @return NULL + **/ + function drop() { + if ($glob=@glob($this->dir.'/*',GLOB_NOSORT)) + foreach ($glob as $file) + @unlink($file); + } + + /** + * Instantiate class + * @param $dir string + * @param $format int + **/ + function __construct($dir,$format=self::FORMAT_JSON) { + if (!is_dir($dir)) + mkdir($dir,\Base::MODE,TRUE); + $this->uuid=\Base::instance()->hash($this->dir=$dir); + $this->format=$format; + } + +} diff --git a/lib/f3/db/jig/mapper.php b/lib/f3/db/jig/mapper.php new file mode 100755 index 0000000..9e2aba7 --- /dev/null +++ b/lib/f3/db/jig/mapper.php @@ -0,0 +1,442 @@ +document); + } + + /** + * Assign value to field + * @return scalar|FALSE + * @param $key string + * @param $val scalar + **/ + function set($key,$val) { + return ($key=='_id')?FALSE:($this->document[$key]=$val); + } + + /** + * Retrieve value of field + * @return scalar|FALSE + * @param $key string + **/ + function get($key) { + if ($key=='_id') + return $this->id; + if (array_key_exists($key,$this->document)) + return $this->document[$key]; + user_error(sprintf(self::E_Field,$key)); + return FALSE; + } + + /** + * Delete field + * @return NULL + * @param $key string + **/ + function clear($key) { + if ($key!='_id') + unset($this->document[$key]); + } + + /** + * Convert array to mapper object + * @return object + * @param $id string + * @param $row array + **/ + protected function factory($id,$row) { + $mapper=clone($this); + $mapper->reset(); + $mapper->id=$id; + foreach ($row as $field=>$val) + $mapper->document[$field]=$val; + $mapper->query=array(clone($mapper)); + if (isset($mapper->trigger['load'])) + \Base::instance()->call($mapper->trigger['load'],$mapper); + return $mapper; + } + + /** + * Return fields of mapper object as an associative array + * @return array + * @param $obj object + **/ + function cast($obj=NULL) { + if (!$obj) + $obj=$this; + return $obj->document+array('_id'=>$this->id); + } + + /** + * Convert tokens in string expression to variable names + * @return string + * @param $str string + **/ + function token($str) { + $self=$this; + $str=preg_replace_callback( + '/(?stringify(substr($expr[1],1)): + (preg_match('/^\w+/', + $mix=$self->token($expr[2]))? + $fw->stringify($mix): + $mix)). + ']'; + }, + $token[1] + ); + }, + $str + ); + return trim($str); + } + + /** + * Return records that match criteria + * @return array|FALSE + * @param $filter array + * @param $options array + * @param $ttl int + * @param $log bool + **/ + function find($filter=NULL,array $options=NULL,$ttl=0,$log=TRUE) { + if (!$options) + $options=array(); + $options+=array( + 'order'=>NULL, + 'limit'=>0, + 'offset'=>0 + ); + $fw=\Base::instance(); + $cache=\Cache::instance(); + $db=$this->db; + $now=microtime(TRUE); + $data=array(); + if (!$fw->get('CACHE') || !$ttl || !($cached=$cache->exists( + $hash=$fw->hash($this->db->dir(). + $fw->stringify(array($filter,$options))).'.jig',$data)) || + $cached[0]+$ttlread($this->file); + if (is_null($data)) + return FALSE; + foreach ($data as $id=>&$doc) { + $doc['_id']=$id; + unset($doc); + } + if ($filter) { + if (!is_array($filter)) + return FALSE; + // Normalize equality operator + $expr=preg_replace('/(?<=[^<>!=])=(?!=)/','==',$filter[0]); + // Prepare query arguments + $args=isset($filter[1]) && is_array($filter[1])? + $filter[1]: + array_slice($filter,1,NULL,TRUE); + $args=is_array($args)?$args:array(1=>$args); + $keys=$vals=array(); + $tokens=array_slice( + token_get_all('token($expr)),1); + $data=array_filter($data, + function($_row) use($fw,$args,$tokens) { + $_expr=''; + $ctr=0; + $named=FALSE; + foreach ($tokens as $token) { + if (is_string($token)) + if ($token=='?') { + // Positional + $ctr++; + $key=$ctr; + } + else { + if ($token==':') + $named=TRUE; + else + $_expr.=$token; + continue; + } + elseif ($named && + token_name($token[0])=='T_STRING') { + $key=':'.$token[1]; + $named=FALSE; + } + else { + $_expr.=$token[1]; + continue; + } + $_expr.=$fw->stringify( + is_string($args[$key])? + addcslashes($args[$key],'\''): + $args[$key]); + } + // Avoid conflict with user code + unset($fw,$tokens,$args,$ctr,$token,$key,$named); + extract($_row); + // Evaluate pseudo-SQL expression + return eval('return '.$_expr.';'); + } + ); + } + if (isset($options['order'])) { + $cols=$fw->split($options['order']); + uasort( + $data, + function($val1,$val2) use($cols) { + foreach ($cols as $col) { + $parts=explode(' ',$col,2); + $order=empty($parts[1])? + SORT_ASC: + constant($parts[1]); + $col=$parts[0]; + if (!array_key_exists($col,$val1)) + $val1[$col]=NULL; + if (!array_key_exists($col,$val2)) + $val2[$col]=NULL; + list($v1,$v2)=array($val1[$col],$val2[$col]); + if ($out=strnatcmp($v1,$v2)* + (($order==SORT_ASC)*2-1)) + return $out; + } + return 0; + } + ); + } + $data=array_slice($data, + $options['offset'],$options['limit']?:NULL,TRUE); + if ($fw->get('CACHE') && $ttl) + // Save to cache backend + $cache->set($hash,$data,$ttl); + } + $out=array(); + foreach ($data as $id=>&$doc) { + unset($doc['_id']); + $out[]=$this->factory($id,$doc); + unset($doc); + } + if ($log && isset($args)) { + if ($filter) + foreach ($args as $key=>$val) { + $vals[]=$fw->stringify(is_array($val)?$val[0]:$val); + $keys[]='/'.(is_numeric($key)?'\?':preg_quote($key)).'/'; + } + $db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. + $this->file.' [find] '. + ($filter?preg_replace($keys,$vals,$filter[0],1):'')); + } + return $out; + } + + /** + * Count records that match criteria + * @return int + * @param $filter array + * @param $ttl int + **/ + function count($filter=NULL,$ttl=0) { + $now=microtime(TRUE); + $out=count($this->find($filter,NULL,$ttl,FALSE)); + $this->db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. + $this->file.' [count] '.($filter?json_encode($filter):'')); + return $out; + } + + /** + * Return record at specified offset using criteria of previous + * load() call and make it active + * @return array + * @param $ofs int + **/ + function skip($ofs=1) { + $this->document=($out=parent::skip($ofs))?$out->document:array(); + $this->id=$out?$out->id:NULL; + if ($this->document && isset($this->trigger['load'])) + \Base::instance()->call($this->trigger['load'],$this); + return $out; + } + + /** + * Insert new record + * @return array + **/ + function insert() { + if ($this->id) + return $this->update(); + $db=$this->db; + $now=microtime(TRUE); + while (($id=uniqid(NULL,TRUE)) && + ($data=$db->read($this->file)) && isset($data[$id]) && + !connection_aborted()) + usleep(mt_rand(0,100)); + $this->id=$id; + $data[$id]=$this->document; + $pkey=array('_id'=>$this->id); + $db->write($this->file,$data); + parent::reset(); + $db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. + $this->file.' [insert] '.json_encode($this->document)); + if (isset($this->trigger['insert'])) + \Base::instance()->call($this->trigger['insert'], + array($this,$pkey)); + return $this->document; + } + + /** + * Update current record + * @return array + **/ + function update() { + $db=$this->db; + $now=microtime(TRUE); + $data=$db->read($this->file); + $data[$this->id]=$this->document; + $db->write($this->file,$data); + $db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. + $this->file.' [update] '.json_encode($this->document)); + if (isset($this->trigger['update'])) + \Base::instance()->call($this->trigger['update'], + array($this,array('_id'=>$this->id))); + return $this->document; + } + + /** + * Delete current record + * @return bool + * @param $filter array + **/ + function erase($filter=NULL) { + $db=$this->db; + $now=microtime(TRUE); + $data=$db->read($this->file); + if ($filter) { + foreach ($this->find($filter,NULL,FALSE) as $mapper) + if (!$mapper->erase()) + return FALSE; + return TRUE; + } + elseif (isset($this->id)) { + $pkey=array('_id'=>$this->id); + unset($data[$this->id]); + parent::erase(); + $this->skip(0); + } + else + return FALSE; + $db->write($this->file,$data); + if ($filter) { + $args=isset($filter[1]) && is_array($filter[1])? + $filter[1]: + array_slice($filter,1,NULL,TRUE); + $args=is_array($args)?$args:array(1=>$args); + foreach ($args as $key=>$val) { + $vals[]=\Base::instance()-> + stringify(is_array($val)?$val[0]:$val); + $keys[]='/'.(is_numeric($key)?'\?':preg_quote($key)).'/'; + } + } + $db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. + $this->file.' [erase] '. + ($filter?preg_replace($keys,$vals,$filter[0],1):'')); + if (isset($this->trigger['erase'])) + \Base::instance()->call($this->trigger['erase'], + array($this,$pkey)); + return TRUE; + } + + /** + * Reset cursor + * @return NULL + **/ + function reset() { + $this->id=NULL; + $this->document=array(); + parent::reset(); + } + + /** + * Hydrate mapper object using hive array variable + * @return NULL + * @param $key string + * @param $func callback + **/ + function copyfrom($key,$func=NULL) { + $var=\Base::instance()->get($key); + if ($func) + $var=$func($var); + foreach ($var as $key=>$val) + $this->document[$key]=$val; + } + + /** + * Populate hive array variable with mapper fields + * @return NULL + * @param $key string + **/ + function copyto($key) { + $var=&\Base::instance()->ref($key); + foreach ($this->document as $key=>$field) + $var[$key]=$field; + } + + /** + * Return field names + * @return array + **/ + function fields() { + return array_keys($this->document); + } + + /** + * Instantiate class + * @return void + * @param $db object + * @param $file string + **/ + function __construct(\DB\Jig $db,$file) { + $this->db=$db; + $this->file=$file; + $this->reset(); + } + +} diff --git a/lib/f3/db/jig/session.php b/lib/f3/db/jig/session.php new file mode 100755 index 0000000..c1460e4 --- /dev/null +++ b/lib/f3/db/jig/session.php @@ -0,0 +1,184 @@ +load(array('@session_id=?',$id)); + return $this->dry()?FALSE:$this->get('data'); + } + + /** + * Write session data + * @return TRUE + * @param $id string + * @param $data string + **/ + function write($id,$data) { + $fw=\Base::instance(); + $sent=headers_sent(); + $headers=$fw->get('HEADERS'); + $this->load(array('@session_id=?',$id)); + $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash(mt_rand()); + $this->set('session_id',$id); + $this->set('data',$data); + $this->set('csrf',$sent?$this->csrf():$csrf); + $this->set('ip',$fw->get('IP')); + $this->set('agent', + isset($headers['User-Agent'])?$headers['User-Agent']:''); + $this->set('stamp',time()); + $this->save(); + if (!$sent) { + if (isset($_COOKIE['_'])) + setcookie('_','',strtotime('-1 year')); + call_user_func_array('setcookie', + array('_',$csrf)+$fw->get('JAR')); + } + return TRUE; + } + + /** + * Destroy session + * @return TRUE + * @param $id string + **/ + function destroy($id) { + $this->erase(array('@session_id=?',$id)); + setcookie(session_name(),'',strtotime('-1 year')); + unset($_COOKIE[session_name()]); + header_remove('Set-Cookie'); + return TRUE; + } + + /** + * Garbage collector + * @return TRUE + * @param $max int + **/ + function cleanup($max) { + $this->erase(array('@stamp+?load(array('@session_id=?',$id?:session_id())); + return $this->dry()?FALSE:$this->get('csrf'); + } + + /** + * Return IP address associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function ip($id=NULL) { + $this->load(array('@session_id=?',$id?:session_id())); + return $this->dry()?FALSE:$this->get('ip'); + } + + /** + * Return Unix timestamp associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function stamp($id=NULL) { + $this->load(array('@session_id=?',$id?:session_id())); + return $this->dry()?FALSE:$this->get('stamp'); + } + + /** + * Return HTTP user agent associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function agent($id=NULL) { + $this->load(array('@session_id=?',$id?:session_id())); + return $this->dry()?FALSE:$this->get('agent'); + } + + /** + * Instantiate class + * @param $db object + * @param $table string + **/ + function __construct(\DB\Jig $db,$table='sessions') { + parent::__construct($db,'sessions'); + session_set_save_handler( + array($this,'open'), + array($this,'close'), + array($this,'read'), + array($this,'write'), + array($this,'destroy'), + array($this,'cleanup') + ); + register_shutdown_function('session_commit'); + @session_start(); + $fw=\Base::instance(); + $headers=$fw->get('HEADERS'); + if (($csrf=$this->csrf()) && + ((!isset($_COOKIE['_']) || $_COOKIE['_']!=$csrf) || + ($ip=$this->ip()) && $ip!=$fw->get('IP') || + ($agent=$this->agent()) && !isset($headers['User-Agent']) || + $agent!=$headers['User-Agent'])) { + $jar=$fw->get('JAR'); + $jar['expire']=strtotime('-1 year'); + call_user_func_array('setcookie', + array_merge(array('_',''),$jar)); + unset($_COOKIE['_']); + session_destroy(); + \Base::instance()->error(403); + } + $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash(mt_rand()); + if ($this->load(array('@session_id=?',session_id()))) { + $this->set('csrf',$csrf); + $this->save(); + call_user_func_array('setcookie', + array('_',$csrf)+$fw->get('JAR')); + } + } + +} diff --git a/lib/f3/db/mongo.php b/lib/f3/db/mongo.php new file mode 100755 index 0000000..31efd72 --- /dev/null +++ b/lib/f3/db/mongo.php @@ -0,0 +1,92 @@ +dsn; + } + + /** + * Return UUID + * @return string + **/ + function uuid() { + return $this->uuid; + } + + /** + * Return MongoDB profiler results + * @return string + **/ + function log() { + $cursor=$this->selectcollection('system.profile')->find(); + foreach (iterator_to_array($cursor) as $frame) + if (!preg_match('/\.system\..+$/',$frame['ns'])) + $this->log.=date('r',$frame['ts']->sec).' ('. + sprintf('%.1f',$frame['millis']).'ms) '. + $frame['ns'].' ['.$frame['op'].'] '. + (empty($frame['query'])? + '':json_encode($frame['query'])). + (empty($frame['command'])? + '':json_encode($frame['command'])). + PHP_EOL; + return $this->log; + } + + /** + * Intercept native call to re-enable profiler + * @return int + **/ + function drop() { + $out=parent::drop(); + $this->setprofilinglevel(2); + return $out; + } + + /** + * Instantiate class + * @param $dsn string + * @param $dbname string + * @param $options array + **/ + function __construct($dsn,$dbname,array $options=NULL) { + $this->uuid=\Base::instance()->hash($this->dsn=$dsn); + $class=class_exists('\MongoClient')?'\MongoClient':'\Mongo'; + parent::__construct(new $class($dsn,$options?:array()),$dbname); + $this->setprofilinglevel(2); + } + +} diff --git a/lib/f3/db/mongo/mapper.php b/lib/f3/db/mongo/mapper.php new file mode 100755 index 0000000..3e33afd --- /dev/null +++ b/lib/f3/db/mongo/mapper.php @@ -0,0 +1,328 @@ +document); + } + + /** + * Assign value to field + * @return scalar|FALSE + * @param $key string + * @param $val scalar + **/ + function set($key,$val) { + return $this->document[$key]=$val; + } + + /** + * Retrieve value of field + * @return scalar|FALSE + * @param $key string + **/ + function get($key) { + if ($this->exists($key)) + return $this->document[$key]; + user_error(sprintf(self::E_Field,$key)); + return FALSE; + } + + /** + * Delete field + * @return NULL + * @param $key string + **/ + function clear($key) { + unset($this->document[$key]); + } + + /** + * Convert array to mapper object + * @return object + * @param $row array + **/ + protected function factory($row) { + $mapper=clone($this); + $mapper->reset(); + foreach ($row as $key=>$val) + $mapper->document[$key]=$val; + $mapper->query=array(clone($mapper)); + if (isset($mapper->trigger['load'])) + \Base::instance()->call($mapper->trigger['load'],$mapper); + return $mapper; + } + + /** + * Return fields of mapper object as an associative array + * @return array + * @param $obj object + **/ + function cast($obj=NULL) { + if (!$obj) + $obj=$this; + return $obj->document; + } + + /** + * Build query and execute + * @return array + * @param $fields string + * @param $filter array + * @param $options array + * @param $ttl int + **/ + function select($fields=NULL,$filter=NULL,array $options=NULL,$ttl=0) { + if (!$options) + $options=array(); + $options+=array( + 'group'=>NULL, + 'order'=>NULL, + 'limit'=>0, + 'offset'=>0 + ); + $fw=\Base::instance(); + $cache=\Cache::instance(); + if (!($cached=$cache->exists($hash=$fw->hash($this->db->dsn(). + $fw->stringify(array($fields,$filter,$options))).'.mongo', + $result)) || !$ttl || $cached[0]+$ttlcollection->group( + $options['group']['keys'], + $options['group']['initial'], + $options['group']['reduce'], + array( + 'condition'=>$filter, + 'finalize'=>$options['group']['finalize'] + ) + ); + $tmp=$this->db->selectcollection( + $fw->get('HOST').'.'.$fw->get('BASE').'.'. + uniqid(NULL,TRUE).'.tmp' + ); + $tmp->batchinsert($grp['retval'],array('safe'=>TRUE)); + $filter=array(); + $collection=$tmp; + } + else { + $filter=$filter?:array(); + $collection=$this->collection; + } + $this->cursor=$collection->find($filter,$fields?:array()); + if ($options['order']) + $this->cursor=$this->cursor->sort($options['order']); + if ($options['limit']) + $this->cursor=$this->cursor->limit($options['limit']); + if ($options['offset']) + $this->cursor=$this->cursor->skip($options['offset']); + $result=array(); + while ($this->cursor->hasnext()) + $result[]=$this->cursor->getnext(); + if ($options['group']) + $tmp->drop(); + if ($fw->get('CACHE') && $ttl) + // Save to cache backend + $cache->set($hash,$result,$ttl); + } + $out=array(); + foreach ($result as $doc) + $out[]=$this->factory($doc); + return $out; + } + + /** + * Return records that match criteria + * @return array + * @param $filter array + * @param $options array + * @param $ttl int + **/ + function find($filter=NULL,array $options=NULL,$ttl=0) { + if (!$options) + $options=array(); + $options+=array( + 'group'=>NULL, + 'order'=>NULL, + 'limit'=>0, + 'offset'=>0 + ); + return $this->select(NULL,$filter,$options,$ttl); + } + + /** + * Count records that match criteria + * @return int + * @param $filter array + * @param $ttl int + **/ + function count($filter=NULL,$ttl=0) { + $fw=\Base::instance(); + $cache=\Cache::instance(); + if (!($cached=$cache->exists($hash=$fw->hash($fw->stringify( + array($filter))).'.mongo',$result)) || !$ttl || + $cached[0]+$ttlcollection->count($filter); + if ($fw->get('CACHE') && $ttl) + // Save to cache backend + $cache->set($hash,$result,$ttl); + } + return $result; + } + + /** + * Return record at specified offset using criteria of previous + * load() call and make it active + * @return array + * @param $ofs int + **/ + function skip($ofs=1) { + $this->document=($out=parent::skip($ofs))?$out->document:array(); + if ($this->document && isset($this->trigger['load'])) + \Base::instance()->call($this->trigger['load'],$this); + return $out; + } + + /** + * Insert new record + * @return array + **/ + function insert() { + if (isset($this->document['_id'])) + return $this->update(); + $this->collection->insert($this->document); + $pkey=array('_id'=>$this->document['_id']); + if (isset($this->trigger['insert'])) + \Base::instance()->call($this->trigger['insert'], + array($this,$pkey)); + return $this->document; + } + + /** + * Update current record + * @return array + **/ + function update() { + $this->collection->update( + $pkey=array('_id'=>$this->document['_id']), + $this->document, + array('upsert'=>TRUE) + ); + if (isset($this->trigger['update'])) + \Base::instance()->call($this->trigger['update'], + array($this,$pkey)); + return $this->document; + } + + /** + * Delete current record + * @return bool + * @param $filter array + **/ + function erase($filter=NULL) { + if ($filter) + return $this->collection->remove($filter); + $pkey=array('_id'=>$this->document['_id']); + $result=$this->collection-> + remove(array('_id'=>$this->document['_id'])); + parent::erase(); + $this->skip(0); + if (isset($this->trigger['erase'])) + \Base::instance()->call($this->trigger['erase'], + array($this,$pkey)); + return $result; + } + + /** + * Reset cursor + * @return NULL + **/ + function reset() { + $this->document=array(); + parent::reset(); + } + + /** + * Hydrate mapper object using hive array variable + * @return NULL + * @param $key string + * @param $func callback + **/ + function copyfrom($key,$func=NULL) { + $var=\Base::instance()->get($key); + if ($func) + $var=$func($var); + foreach ($var as $key=>$val) + $this->document[$key]=$val; + } + + /** + * Populate hive array variable with mapper fields + * @return NULL + * @param $key string + **/ + function copyto($key) { + $var=&\Base::instance()->ref($key); + foreach ($this->document as $key=>$field) + $var[$key]=$field; + } + + /** + * Return field names + * @return array + **/ + function fields() { + return array_keys($this->document); + } + + /** + * Return the cursor from last query + * @return object|NULL + **/ + function cursor() { + return $this->cursor; + } + + /** + * Instantiate class + * @return void + * @param $db object + * @param $collection string + **/ + function __construct(\DB\Mongo $db,$collection) { + $this->db=$db; + $this->collection=$db->{$collection}; + $this->reset(); + } + +} diff --git a/lib/f3/db/mongo/session.php b/lib/f3/db/mongo/session.php new file mode 100755 index 0000000..9ff4497 --- /dev/null +++ b/lib/f3/db/mongo/session.php @@ -0,0 +1,184 @@ +load(array('session_id'=>$id)); + return $this->dry()?FALSE:$this->get('data'); + } + + /** + * Write session data + * @return TRUE + * @param $id string + * @param $data string + **/ + function write($id,$data) { + $fw=\Base::instance(); + $sent=headers_sent(); + $headers=$fw->get('HEADERS'); + $this->load(array('session_id'=>$id)); + $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash(mt_rand()); + $this->set('session_id',$id); + $this->set('data',$data); + $this->set('csrf',$sent?$this->csrf():$csrf); + $this->set('ip',$fw->get('IP')); + $this->set('agent', + isset($headers['User-Agent'])?$headers['User-Agent']:''); + $this->set('stamp',time()); + $this->save(); + if (!$sent) { + if (isset($_COOKIE['_'])) + setcookie('_','',strtotime('-1 year')); + call_user_func_array('setcookie', + array('_',$csrf)+$fw->get('JAR')); + } + return TRUE; + } + + /** + * Destroy session + * @return TRUE + * @param $id string + **/ + function destroy($id) { + $this->erase(array('session_id'=>$id)); + setcookie(session_name(),'',strtotime('-1 year')); + unset($_COOKIE[session_name()]); + header_remove('Set-Cookie'); + return TRUE; + } + + /** + * Garbage collector + * @return TRUE + * @param $max int + **/ + function cleanup($max) { + $this->erase(array('$where'=>'this.stamp+'.$max.'<'.time())); + return TRUE; + } + + /** + * Return anti-CSRF tokan associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function csrf($id=NULL) { + $this->load(array('session_id'=>$id?:session_id())); + return $this->dry()?FALSE:$this->get('csrf'); + } + + /** + * Return IP address associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function ip($id=NULL) { + $this->load(array('session_id'=>$id?:session_id())); + return $this->dry()?FALSE:$this->get('ip'); + } + + /** + * Return Unix timestamp associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function stamp($id=NULL) { + $this->load(array('session_id'=>$id?:session_id())); + return $this->dry()?FALSE:$this->get('stamp'); + } + + /** + * Return HTTP user agent associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function agent($id=NULL) { + $this->load(array('session_id'=>$id?:session_id())); + return $this->dry()?FALSE:$this->get('agent'); + } + + /** + * Instantiate class + * @param $db object + * @param $table string + **/ + function __construct(\DB\Mongo $db,$table='sessions') { + parent::__construct($db,$table); + session_set_save_handler( + array($this,'open'), + array($this,'close'), + array($this,'read'), + array($this,'write'), + array($this,'destroy'), + array($this,'cleanup') + ); + register_shutdown_function('session_commit'); + @session_start(); + $fw=\Base::instance(); + $headers=$fw->get('HEADERS'); + if (($csrf=$this->csrf()) && + ((!isset($_COOKIE['_']) || $_COOKIE['_']!=$csrf) || + ($ip=$this->ip()) && $ip!=$fw->get('IP') || + ($agent=$this->agent()) && !isset($headers['User-Agent']) || + $agent!=$headers['User-Agent'])) { + $jar=$fw->get('JAR'); + $jar['expire']=strtotime('-1 year'); + call_user_func_array('setcookie', + array_merge(array('_',''),$jar)); + unset($_COOKIE['_']); + session_destroy(); + \Base::instance()->error(403); + } + $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash(mt_rand()); + if ($this->load(array('session_id'=>session_id()))) { + $this->set('csrf',$csrf); + $this->save(); + call_user_func_array('setcookie', + array('_',$csrf)+$fw->get('JAR')); + } + } + +} diff --git a/lib/f3/db/sql.php b/lib/f3/db/sql.php new file mode 100755 index 0000000..c659e9d --- /dev/null +++ b/lib/f3/db/sql.php @@ -0,0 +1,381 @@ +trans=TRUE; + return $out; + } + + /** + * Rollback SQL transaction + * @return bool + **/ + function rollback() { + $out=parent::rollback(); + $this->trans=FALSE; + return $out; + } + + /** + * Commit SQL transaction + * @return bool + **/ + function commit() { + $out=parent::commit(); + $this->trans=FALSE; + return $out; + } + + /** + * Map data type of argument to a PDO constant + * @return int + * @param $val scalar + **/ + function type($val) { + switch (gettype($val)) { + case 'NULL': + return \PDO::PARAM_NULL; + case 'boolean': + return \PDO::PARAM_BOOL; + case 'integer': + return \PDO::PARAM_INT; + default: + return \PDO::PARAM_STR; + } + } + + + /** + * Execute SQL statement(s) + * @return array|int|FALSE + * @param $cmds string|array + * @param $args string|array + * @param $ttl int + * @param $log bool + **/ + function exec($cmds,$args=NULL,$ttl=0,$log=TRUE) { + $auto=FALSE; + if (is_null($args)) + $args=array(); + elseif (is_scalar($args)) + $args=array(1=>$args); + if (is_array($cmds)) { + if (count($args)<($count=count($cmds))) + // Apply arguments to SQL commands + $args=array_fill(0,$count,$args); + if (!$this->trans) { + $this->begin(); + $auto=TRUE; + } + } + else { + $cmds=array($cmds); + $args=array($args); + } + $fw=\Base::instance(); + $cache=\Cache::instance(); + foreach (array_combine($cmds,$args) as $cmd=>$arg) { + if (!preg_replace('/(^\s+|[\s;]+$)/','',$cmd)) + continue; + $now=microtime(TRUE); + $keys=$vals=array(); + if ($fw->get('CACHE') && $ttl && ($cached=$cache->exists( + $hash=$fw->hash($this->dsn.$cmd. + $fw->stringify($arg)).'.sql',$result)) && + $cached[0]+$ttl>microtime(TRUE)) { + foreach ($arg as $key=>$val) { + $vals[]=$fw->stringify(is_array($val)?$val[0]:$val); + $keys[]='/'.(is_numeric($key)?'\?':preg_quote($key)).'/'; + } + } + elseif (is_object($query=$this->prepare($cmd))) { + foreach ($arg as $key=>$val) { + if (is_array($val)) { + // User-specified data type + $query->bindvalue($key,$val[0],$val[1]); + $vals[]=$fw->stringify($val[0]); + } + else { + // Convert to PDO data type + $query->bindvalue($key,$val,$this->type($val)); + $vals[]=$fw->stringify($val); + } + $keys[]='/'.(is_numeric($key)?'\?':preg_quote($key)).'/'; + } + $query->execute(); + $error=$query->errorinfo(); + if ($error[0]!=\PDO::ERR_NONE) { + // Statement-level error occurred + if ($this->trans) + $this->rollback(); + user_error('PDOStatement: '.$error[2]); + } + if (preg_match('/^\s*'. + '(?:CALL|EXPLAIN|SELECT|PRAGMA|SHOW|RETURNING)\b/is', + $cmd)) { + $result=$query->fetchall(\PDO::FETCH_ASSOC); + $this->rows=count($result); + if ($fw->get('CACHE') && $ttl) + // Save to cache backend + $cache->set($hash,$result,$ttl); + } + else + $this->rows=$result=$query->rowcount(); + $query->closecursor(); + unset($query); + } + else { + $error=$this->errorinfo(); + if ($error[0]!=\PDO::ERR_NONE) { + // PDO-level error occurred + if ($this->trans) + $this->rollback(); + user_error('PDO: '.$error[2]); + } + } + if ($log) + $this->log.=date('r').' ('. + sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. + (empty($cached)?'':'[CACHED] '). + preg_replace($keys,$vals,$cmd,1).PHP_EOL; + } + if ($this->trans && $auto) + $this->commit(); + return $result; + } + + /** + * Return number of rows affected by last query + * @return int + **/ + function count() { + return $this->rows; + } + + /** + * Return SQL profiler results + * @return string + **/ + function log() { + return $this->log; + } + + /** + * Retrieve schema of SQL table + * @return array|FALSE + * @param $table string + * @param $fields array|string + * @param $ttl int + **/ + function schema($table,$fields=NULL,$ttl=0) { + // Supported engines + $cmd=array( + 'sqlite2?'=>array( + 'PRAGMA table_info("'.$table.'");', + 'name','type','dflt_value','notnull',0,'pk',TRUE), + 'mysql'=>array( + 'SHOW columns FROM `'.$this->dbname.'`.`'.$table.'`;', + 'Field','Type','Default','Null','YES','Key','PRI'), + 'mssql|sqlsrv|sybase|dblib|pgsql|odbc'=>array( + 'SELECT '. + 'c.column_name AS field,'. + 'c.data_type AS type,'. + 'c.column_default AS defval,'. + 'c.is_nullable AS nullable,'. + 't.constraint_type AS pkey '. + 'FROM information_schema.columns AS c '. + 'LEFT OUTER JOIN '. + 'information_schema.key_column_usage AS k '. + 'ON '. + 'c.table_name=k.table_name AND '. + 'c.column_name=k.column_name '. + ($this->dbname? + ('AND '. + ($this->engine=='pgsql'? + 'c.table_catalog=k.table_catalog': + 'c.table_schema=k.table_schema').' '):''). + 'LEFT OUTER JOIN '. + 'information_schema.table_constraints AS t ON '. + 'k.table_name=t.table_name AND '. + 'k.constraint_name=t.constraint_name '. + ($this->dbname? + ('AND '. + ($this->engine=='pgsql'? + 'k.table_catalog=t.table_catalog': + 'k.table_schema=t.table_schema').' '):''). + 'WHERE '. + 'c.table_name='.$this->quote($table).' '. + ($this->dbname? + ('AND '. + ($this->engine=='pgsql'? + 'c.table_catalog':'c.table_schema'). + '='.$this->quote($this->dbname)):''). + ';', + 'field','type','defval','nullable','YES','pkey','PRIMARY KEY'), + 'oci'=>array( + 'SELECT c.column_name AS field, '. + 'c.data_type AS type, '. + 'c.data_default AS defval, '. + 'c.nullable AS nullable, '. + '(SELECT t.constraint_type '. + 'FROM all_cons_columns acc '. + 'LEFT OUTER JOIN all_constraints t '. + 'ON acc.constraint_name=t.constraint_name '. + 'WHERE acc.table_name='.$this->quote($table).' '. + 'AND acc.column_name=c.column_name '. + 'AND constraint_type='.$this->quote('P').') AS pkey '. + 'FROM all_tab_cols c '. + 'WHERE c.table_name='.$this->quote($table), + 'FIELD','TYPE','DEFVAL','NULLABLE','Y','PKEY','P') + ); + if (is_string($fields)) + $fields=\Base::instance()->split($fields); + foreach ($cmd as $key=>$val) + if (preg_match('/'.$key.'/',$this->engine)) { + // Improve InnoDB performance on MySQL with + // SET GLOBAL innodb_stats_on_metadata=0; + // This requires SUPER privilege! + $rows=array(); + foreach ($this->exec($val[0],NULL,$ttl) as $row) + if (!$fields || in_array($row[$val[1]],$fields)) + $rows[$row[$val[1]]]=array( + 'type'=>$row[$val[2]], + 'pdo_type'=> + preg_match('/int\b|int(?=eger)|bool/i', + $row[$val[2]],$parts)? + constant('\PDO::PARAM_'. + strtoupper($parts[0])): + \PDO::PARAM_STR, + 'default'=>$row[$val[3]], + 'nullable'=>$row[$val[4]]==$val[5], + 'pkey'=>$row[$val[6]]==$val[7] + ); + return $rows; + } + return FALSE; + } + + /** + * Quote string + * @return string + * @param $val mixed + * @param $type int + **/ + function quote($val,$type=\PDO::PARAM_STR) { + return $this->engine=='odbc'? + (is_string($val)? + \Base::instance()->stringify(str_replace('\'','\'\'',$val)): + $val): + parent::quote($val,$type); + } + + /** + * Return UUID + * @return string + **/ + function uuid() { + return $this->uuid; + } + + /** + * Return database engine + * @return string + **/ + function driver() { + return $this->engine; + } + + /** + * Return server version + * @return string + **/ + function version() { + return parent::getattribute(parent::ATTR_SERVER_VERSION); + } + + /** + * Return database name + * @return string + **/ + function name() { + return $this->dbname; + } + + /** + * Return quoted identifier name + * @return string + * @param $key + **/ + function quotekey($key) { + if ($this->engine=='mysql') + $key="`".implode('`.`',explode('.',$key))."`"; + elseif (preg_match('/sybase|dblib/',$this->engine)) + $key="'".implode("'.'",explode('.',$key))."'"; + elseif (preg_match('/sqlite2?|pgsql|oci/',$this->engine)) + $key='"'.implode('"."',explode('.',$key)).'"'; + elseif (preg_match('/mssql|sqlsrv|odbc/',$this->engine)) + $key="[".implode('].[',explode('.',$key))."]"; + return $key; + } + + /** + * Instantiate class + * @param $dsn string + * @param $user string + * @param $pw string + * @param $options array + **/ + function __construct($dsn,$user=NULL,$pw=NULL,array $options=NULL) { + $fw=\Base::instance(); + $this->uuid=$fw->hash($this->dsn=$dsn); + if (preg_match('/^.+?(?:dbname|database)=(.+?)(?=;|$)/i',$dsn,$parts)) + $this->dbname=$parts[1]; + if (!$options) + $options=array(); + if (isset($parts[0]) && strstr($parts[0],':',TRUE)=='mysql') + // $options+=array(\PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES '. + // strtolower(str_replace('-','',$fw->get('ENCODING'))).';'); + $options+=array(\PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES utf8mb4;'); + parent::__construct($dsn,$user,$pw,$options); + $this->engine=parent::getattribute(parent::ATTR_DRIVER_NAME); + } + +} diff --git a/lib/f3/db/sql/mapper.php b/lib/f3/db/sql/mapper.php new file mode 100755 index 0000000..b0ecb35 --- /dev/null +++ b/lib/f3/db/sql/mapper.php @@ -0,0 +1,534 @@ +fields+$this->adhoc); + } + + /** + * Assign value to field + * @return scalar + * @param $key string + * @param $val scalar + **/ + function set($key,$val) { + if (array_key_exists($key,$this->fields)) { + $val=is_null($val) && $this->fields[$key]['nullable']? + NULL:$this->value($this->fields[$key]['pdo_type'],$val); + if ($this->fields[$key]['value']!==$val || + $this->fields[$key]['default']!==$val) + $this->fields[$key]['changed']=TRUE; + return $this->fields[$key]['value']=$val; + } + // Parenthesize expression in case it's a subquery + $this->adhoc[$key]=array('expr'=>'('.$val.')','value'=>NULL); + return $val; + } + + /** + * Retrieve value of field + * @return scalar + * @param $key string + **/ + function get($key) { + if ($key=='_id') + return $this->_id; + elseif (array_key_exists($key,$this->fields)) + return $this->fields[$key]['value']; + elseif (array_key_exists($key,$this->adhoc)) + return $this->adhoc[$key]['value']; + user_error(sprintf(self::E_Field,$key)); + } + + /** + * Clear value of field + * @return NULL + * @param $key string + **/ + function clear($key) { + if (array_key_exists($key,$this->adhoc)) + unset($this->adhoc[$key]); + } + + /** + * Get PHP type equivalent of PDO constant + * @return string + * @param $pdo string + **/ + function type($pdo) { + switch ($pdo) { + case \PDO::PARAM_NULL: + return 'unset'; + case \PDO::PARAM_INT: + return 'int'; + case \PDO::PARAM_BOOL: + return 'bool'; + case \PDO::PARAM_STR: + return 'string'; + } + } + + /** + * Cast value to PHP type + * @return scalar + * @param $type string + * @param $val scalar + **/ + function value($type,$val) { + switch ($type) { + case \PDO::PARAM_NULL: + return (unset)$val; + case \PDO::PARAM_INT: + return (int)$val; + case \PDO::PARAM_BOOL: + return (bool)$val; + case \PDO::PARAM_STR: + return (string)$val; + } + } + + /** + * Convert array to mapper object + * @return object + * @param $row array + **/ + protected function factory($row) { + $mapper=clone($this); + $mapper->reset(); + foreach ($row as $key=>$val) { + if (array_key_exists($key,$this->fields)) + $var='fields'; + elseif (array_key_exists($key,$this->adhoc)) + $var='adhoc'; + else + continue; + $mapper->{$var}[$key]['value']=$val; + if ($var=='fields' && $mapper->{$var}[$key]['pkey']) + $mapper->{$var}[$key]['previous']=$val; + } + $mapper->query=array(clone($mapper)); + if (isset($mapper->trigger['load'])) + \Base::instance()->call($mapper->trigger['load'],$mapper); + return $mapper; + } + + /** + * Return fields of mapper object as an associative array + * @return array + * @param $obj object + **/ + function cast($obj=NULL) { + if (!$obj) + $obj=$this; + return array_map( + function($row) { + return $row['value']; + }, + $obj->fields+$obj->adhoc + ); + } + + /** + * Build query string and execute + * @return array + * @param $fields string + * @param $filter string|array + * @param $options array + * @param $ttl int + **/ + function select($fields,$filter=NULL,array $options=NULL,$ttl=0) { + if (!$options) + $options=array(); + $options+=array( + 'group'=>NULL, + 'order'=>NULL, + 'limit'=>0, + 'offset'=>0 + ); + $sql='SELECT '.$fields.' FROM '.$this->table; + $args=array(); + if ($filter) { + if (is_array($filter)) { + $args=isset($filter[1]) && is_array($filter[1])? + $filter[1]: + array_slice($filter,1,NULL,TRUE); + $args=is_array($args)?$args:array(1=>$args); + list($filter)=$filter; + } + $sql.=' WHERE '.$filter; + } + if ($options['group']) + $sql.=' GROUP BY '.implode(',',array_map( + array($this->db,'quotekey'), + explode(',',$options['group']))); + if ($options['order']) { + $db=$this->db; + $sql.=' ORDER BY '.implode(',',array_map( + function($str) use($db) { + return preg_match('/(\w+)(?:\h+(ASC|DESC))?/i', + $str,$parts)? + ($db->quotekey($parts[1]). + (isset($parts[2])?(' '.$parts[2]):'')):$str; + }, + explode(',',$options['order']))); + } + if ($options['limit']) + $sql.=' LIMIT '.(int)$options['limit']; + if ($options['offset']) + $sql.=' OFFSET '.(int)$options['offset']; + $result=$this->db->exec($sql,$args,$ttl); + $out=array(); + foreach ($result as &$row) { + foreach ($row as $field=>&$val) { + if (array_key_exists($field,$this->fields)) { + if (!is_null($val) || !$this->fields[$field]['nullable']) + $val=$this->value( + $this->fields[$field]['pdo_type'],$val); + } + elseif (array_key_exists($field,$this->adhoc)) + $this->adhoc[$field]['value']=$val; + unset($val); + } + $out[]=$this->factory($row); + unset($row); + } + return $out; + } + + /** + * Return records that match criteria + * @return array + * @param $filter string|array + * @param $options array + * @param $ttl int + **/ + function find($filter=NULL,array $options=NULL,$ttl=0) { + if (!$options) + $options=array(); + $options+=array( + 'group'=>NULL, + 'order'=>NULL, + 'limit'=>0, + 'offset'=>0 + ); + $adhoc=''; + foreach ($this->adhoc as $key=>$field) + $adhoc.=','.$field['expr'].' AS '.$this->db->quotekey($key); + return $this->select(implode(',', + array_map(array($this->db,'quotekey'),array_keys($this->fields))). + $adhoc,$filter,$options,$ttl); + } + + /** + * Count records that match criteria + * @return int + * @param $filter string|array + * @param $ttl int + **/ + function count($filter=NULL,$ttl=0) { + $sql='SELECT COUNT(*) AS '. + $this->db->quotekey('rows').' FROM '.$this->table; + $args=array(); + if ($filter) { + if (is_array($filter)) { + $args=isset($filter[1]) && is_array($filter[1])? + $filter[1]: + array_slice($filter,1,NULL,TRUE); + $args=is_array($args)?$args:array(1=>$args); + list($filter)=$filter; + } + $sql.=' WHERE '.$filter; + } + $result=$this->db->exec($sql,$args,$ttl); + return $result[0]['rows']; + } + + /** + * Return record at specified offset using same criteria as + * previous load() call and make it active + * @return array + * @param $ofs int + **/ + function skip($ofs=1) { + $out=parent::skip($ofs); + $dry=$this->dry(); + foreach ($this->fields as $key=>&$field) { + $field['value']=$dry?NULL:$out->fields[$key]['value']; + $field['changed']=FALSE; + if ($field['pkey']) + $field['previous']=$dry?NULL:$out->fields[$key]['value']; + unset($field); + } + foreach ($this->adhoc as $key=>&$field) { + $field['value']=$dry?NULL:$out->adhoc[$key]['value']; + unset($field); + } + if (isset($this->trigger['load'])) + \Base::instance()->call($this->trigger['load'],$this); + return $out; + } + + /** + * Insert new record + * @return object + **/ + function insert() { + $args=array(); + $ctr=0; + $fields=''; + $values=''; + $pkeys=array(); + $inc=NULL; + foreach ($this->fields as $key=>&$field) { + if ($field['pkey']) { + $pkeys[$key]=$field['previous']; + $field['previous']=$field['value']; + if (!$inc && $field['pdo_type']==\PDO::PARAM_INT && + empty($field['value']) && !$field['nullable']) + $inc=$key; + } + if ($field['changed'] && $key!=$inc) { + $fields.=($ctr?',':'').$this->db->quotekey($key); + $values.=($ctr?',':'').'?'; + $args[$ctr+1]=array($field['value'],$field['pdo_type']); + $ctr++; + } + $field['changed']=FALSE; + unset($field); + } + if ($fields) + $this->db->exec( + 'INSERT INTO '.$this->table.' ('.$fields.') '. + 'VALUES ('.$values.')',$args + ); + $seq=NULL; + if ($this->engine=='pgsql') { + $names=array_keys($pkeys); + $seq=$this->source.'_'.end($names).'_seq'; + } + if ($this->engine!='oci') + $this->_id=$this->db->lastinsertid($seq); + if ($inc) + // Reload to obtain default and auto-increment field values + $this->load(array($inc.'=?', + $this->value($this->fields[$inc]['pdo_type'],$this->_id))); + if (isset($this->trigger['insert'])) + \Base::instance()->call($this->trigger['insert'], + array($this,$pkeys)); + return $this; + } + + /** + * Update current record + * @return object + **/ + function update() { + $args=array(); + $ctr=0; + $pairs=''; + $filter=''; + foreach ($this->fields as $key=>$field) + if ($field['changed']) { + $pairs.=($pairs?',':'').$this->db->quotekey($key).'=?'; + $args[$ctr+1]=array($field['value'],$field['pdo_type']); + $ctr++; + } + $pkeys=array(); + foreach ($this->fields as $key=>$field) + if ($field['pkey']) { + $filter.=($filter?' AND ':'').$this->db->quotekey($key).'=?'; + $args[$ctr+1]=array($field['previous'],$field['pdo_type']); + $pkeys[$key]=$field['previous']; + $ctr++; + } + if ($pairs) { + $sql='UPDATE '.$this->table.' SET '.$pairs; + if ($filter) + $sql.=' WHERE '.$filter; + $this->db->exec($sql,$args); + if (isset($this->trigger['update'])) + \Base::instance()->call($this->trigger['update'], + array($this,$pkeys)); + } + return $this; + } + + /** + * Delete current record + * @return int + * @param $filter string|array + **/ + function erase($filter=NULL) { + if ($filter) { + $args=array(); + if (is_array($filter)) { + $args=isset($filter[1]) && is_array($filter[1])? + $filter[1]: + array_slice($filter,1,NULL,TRUE); + $args=is_array($args)?$args:array(1=>$args); + list($filter)=$filter; + } + return $this->db-> + exec('DELETE FROM '.$this->table.' WHERE '.$filter.';',$args); + } + $args=array(); + $ctr=0; + $filter=''; + $pkeys=array(); + foreach ($this->fields as $key=>&$field) { + if ($field['pkey']) { + $filter.=($filter?' AND ':'').$this->db->quotekey($key).'=?'; + $args[$ctr+1]=array($field['previous'],$field['pdo_type']); + $pkeys[$key]=$field['previous']; + $ctr++; + } + $field['value']=NULL; + $field['changed']=(bool)$field['default']; + if ($field['pkey']) + $field['previous']=NULL; + unset($field); + } + foreach ($this->adhoc as &$field) { + $field['value']=NULL; + unset($field); + } + parent::erase(); + $this->skip(0); + $out=$this->db-> + exec('DELETE FROM '.$this->table.' WHERE '.$filter.';',$args); + if (isset($this->trigger['erase'])) + \Base::instance()->call($this->trigger['erase'], + array($this,$pkeys)); + return $out; + } + + /** + * Reset cursor + * @return NULL + **/ + function reset() { + foreach ($this->fields as &$field) { + $field['value']=NULL; + $field['changed']=FALSE; + if ($field['pkey']) + $field['previous']=NULL; + unset($field); + } + foreach ($this->adhoc as &$field) { + $field['value']=NULL; + unset($field); + } + parent::reset(); + } + + /** + * Hydrate mapper object using hive array variable + * @return NULL + * @param $key string + * @param $func callback + **/ + function copyfrom($key,$func=NULL) { + $var=\Base::instance()->get($key); + if ($func) + $var=$func($var); + foreach ($var as $key=>$val) + if (in_array($key,array_keys($this->fields))) { + $field=&$this->fields[$key]; + if ($field['value']!==$val) { + $field['value']=$val; + $field['changed']=TRUE; + } + unset($field); + } + } + + /** + * Populate hive array variable with mapper fields + * @return NULL + * @param $key string + **/ + function copyto($key) { + $var=&\Base::instance()->ref($key); + foreach ($this->fields as $key=>$field) + $var[$key]=$field['value']; + } + + /** + * Return schema + * @return array + **/ + function schema() { + return $this->fields; + } + + /** + * Return field names + * @return array + * @param $adhoc bool + **/ + function fields($adhoc=TRUE) { + return array_keys($this->fields+($adhoc?$this->adhoc:array())); + } + + /** + * Instantiate class + * @param $db object + * @param $table string + * @param $fields array|string + * @param $ttl int + **/ + function __construct(\DB\SQL $db,$table,$fields=NULL,$ttl=60) { + $this->db=$db; + $this->engine=$db->driver(); + if ($this->engine=='oci') + $table=strtoupper($table); + $this->source=$table; + $this->table=$this->db->quotekey($table); + $this->fields=$db->schema($table,$fields,$ttl); + $this->reset(); + } + +} diff --git a/lib/f3/db/sql/schema.php b/lib/f3/db/sql/schema.php new file mode 100644 index 0000000..eae536b --- /dev/null +++ b/lib/f3/db/sql/schema.php @@ -0,0 +1,1186 @@ + + * https://github.com/ikkez/F3-Sugar/ + * + * @package DB + * @version 2.1.1 + **/ + + +namespace DB\SQL; + +use DB\SQL; + +class Schema extends DB_Utils { + + public + $dataTypes = array( + 'BOOLEAN' => array('mysql|sqlite2?|pgsql' => 'BOOLEAN', + 'mssql|sybase|dblib|odbc|sqlsrv' => 'bit', + 'ibm' => 'numeric(1,0)', + ), + 'INT1' => array('mysql' => 'TINYINT UNSIGNED', + 'sqlite2?' => 'integer', + 'mssql|sybase|dblib|odbc|sqlsrv' => 'tinyint', + 'pgsql|ibm' => 'smallint', + ), + 'INT2' => array('mysql' => 'SMALLINT', + 'sqlite2?' => 'integer', + 'pgsql|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'smallint', + ), + 'INT4' => array('sqlite2?|pgsql|sybase|odbc|sqlsrv|imb' => 'integer', + 'mysql|mssql|dblib' => 'int', + ), + 'INT8' => array('sqlite2?' => 'integer', + 'pgsql|mysql|mssql|sybase|dblib|odbc|sqlsrv|imb' => 'bigint', + ), + 'FLOAT' => array('mysql|sqlite2?' => 'FLOAT', + 'pgsql' => 'double precision', + 'mssql|sybase|dblib|odbc|sqlsrv' => 'float', + 'imb' => 'decfloat' + ), + 'DOUBLE' => array('mysql|sqlite2?|ibm' => 'DOUBLE', + 'pgsql|sybase|odbc|sqlsrv' => 'double precision', + 'mssql|dblib' => 'decimal', + ), + 'VARCHAR128' => array('mysql|pgsql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(128)', + ), + 'VARCHAR256' => array('mysql|pgsql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(255)', + ), + 'VARCHAR512' => array('mysql|pgsql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(512)', + ), + 'TEXT' => array('mysql|sqlite2?|pgsql|mssql' => 'text', + 'sybase|dblib|odbc|sqlsrv' => 'nvarchar(max)', + 'ibm' => 'BLOB SUB_TYPE TEXT', + ), + 'LONGTEXT' => array('mysql' => 'LONGTEXT', + 'sqlite2?|pgsql|mssql' => 'text', + 'sybase|dblib|odbc|sqlsrv' => 'nvarchar(max)', + 'ibm' => 'CLOB(2000000000)', + ), + 'DATE' => array('mysql|sqlite2?|pgsql|mssql|sybase|dblib|odbc|sqlsrv|ibm' => 'date', + ), + 'DATETIME' => array('pgsql' => 'timestamp without time zone', + 'mysql|sqlite2?|mssql|sybase|dblib|odbc|sqlsrv' => 'datetime', + 'ibm' => 'timestamp', + ), + 'TIMESTAMP' => array('mysql|ibm' => 'timestamp', + 'pgsql|odbc' => 'timestamp without time zone', + 'sqlite2?|mssql|sybase|dblib|sqlsrv'=>'DATETIME', + ), + 'BLOB' => array('mysql|odbc|sqlite2?|ibm' => 'blob', + 'pgsql' => 'bytea', + 'mssql|sybase|dblib' => 'image', + 'sqlsrv' => 'varbinary(max)', + ), + ), + $defaultTypes = array( + 'CUR_STAMP' => array('mysql' => 'CURRENT_TIMESTAMP', + 'mssql|sybase|dblib|odbc|sqlsrv' => 'getdate()', + 'pgsql' => 'LOCALTIMESTAMP(0)', + 'sqlite2?' => "(datetime('now','localtime'))", + ), + ); + + public + $name; + + /** @var \Base */ + protected $fw; + + const + // DataTypes and Aliases + DT_BOOL = 'BOOLEAN', + DT_BOOLEAN = 'BOOLEAN', + DT_INT1 = 'INT1', + DT_TINYINT = 'INT1', + DT_INT2 = 'INT2', + DT_SMALLINT = 'INT2', + DT_INT4 = 'INT4', + DT_INT = 'INT4', + DT_INT8 = 'INT8', + DT_BIGINT = 'INT8', + DT_FLOAT = 'FLOAT', + DT_DOUBLE = 'DOUBLE', + DT_DECIMAL = 'DOUBLE', + DT_VARCHAR128 = 'VARCHAR128', + DT_VARCHAR256 = 'VARCHAR256', + DT_VARCHAR512 = 'VARCHAR512', + DT_TEXT = 'TEXT', + DT_LONGTEXT = 'LONGTEXT', + DT_DATE = 'DATE', + DT_DATETIME = 'DATETIME', + DT_TIMESTAMP = 'TIMESTAMP', + DT_BLOB = 'BLOB', + DT_BINARY = 'BLOB', + + // column default values + DF_CURRENT_TIMESTAMP = 'CUR_STAMP'; + + + public function __construct(\DB\SQL $db) + { + $this->fw = \Base::instance(); + parent::__construct($db); + } + + /** + * get a list of all databases + * @return array|bool + */ + public function getDatabases() + { + $cmd = array( + 'mysql' => 'SHOW DATABASES', + 'pgsql' => 'SELECT datname FROM pg_catalog.pg_database', + 'mssql|sybase|dblib|sqlsrv|odbc' => 'EXEC SP_HELPDB', + ); + $query = $this->findQuery($cmd); + if (!$query) return false; + $result = $this->db->exec($query); + if (!is_array($result)) return false; + foreach($result as &$db) + if (is_array($db)) $db = array_shift($db); + return $result; + } + + /** + * get all tables of current DB + * @return bool|array list of tables, or false + */ + public function getTables() + { + $cmd = array( + 'mysql' => array( + "show tables"), + 'sqlite2?' => array( + "SELECT name FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"), + 'pgsql|sybase|dblib' => array( + "select table_name from information_schema.tables where table_schema = 'public'"), + 'mssql|sqlsrv|odbc' => array( + "select table_name from information_schema.tables"), + 'ibm' => array("select TABLE_NAME from sysibm.tables"), + ); + $query = $this->findQuery($cmd); + if (!$query[0]) return false; + $tables = $this->db->exec($query[0]); + if ($tables && is_array($tables) && count($tables) > 0) + foreach ($tables as &$table) + $table = array_shift($table); + return $tables; + } + + /** + * returns a table object for creation + * @param $name + * @return bool|TableCreator + */ + public function createTable($name) + { + return new TableCreator($name,$this); + } + + /** + * returns a table object for altering operations + * @param $name + * @return bool|TableModifier + */ + public function alterTable($name) + { + return new TableModifier($name,$this); + } + + /** + * rename a table + * @param string $name + * @param string $new_name + * @param bool $exec + * @return bool + */ + public function renameTable($name, $new_name, $exec = true) + { + $name = $this->db->quotekey($name); + $new_name = $this->db->quotekey($new_name); + if (preg_match('/odbc/', $this->db->driver())) { + $queries = array(); + $queries[] = "SELECT * INTO $new_name FROM $name;"; + $queries[] = $this->dropTable($name, false); + return ($exec) ? $this->db->exec($queries) : implode("\n",$queries); + } else { + $cmd = array( + 'sqlite2?|pgsql' => + "ALTER TABLE $name RENAME TO $new_name;", + 'mysql|ibm' => + "RENAME TABLE $name TO $new_name;", + 'mssql|sqlsrv|sybase|dblib|odbc' => + "sp_rename {$name}, $new_name" + ); + $query = $this->findQuery($cmd); + if (!$exec) return $query; + return (preg_match('/mssql|sybase|dblib|sqlsrv/', $this->db->driver())) + ? @$this->db->exec($query) : $this->db->exec($query); + } + } + + /** + * drop a table + * @param \DB\SQL\TableBuilder|string $name + * @param bool $exec + * @return bool + */ + public function dropTable($name, $exec = true) + { + if (is_object($name) && $name instanceof TableBuilder) + $name = $name->name; + $cmd = array( + 'mysql|ibm|sqlite2?|pgsql|sybase|dblib' => + 'DROP TABLE IF EXISTS '.$this->db->quotekey($name).';', + 'mssql|sqlsrv|odbc' => + "IF OBJECT_ID('[$name]', 'U') IS NOT NULL DROP TABLE [$name];" + ); + $query = $this->findQuery($cmd); + return ($exec) ? $this->db->exec($query) : $query; + } + +} + +abstract class TableBuilder extends DB_Utils { + + protected $columns, $pkeys, $queries, $increments, $rebuild_cmd, $suppress; + public $name, $schema; + + const + TEXT_NoDefaultForTEXT = "Column `%s` of type TEXT can't have a default value.", + TEXT_ColumnExists = "Cannot add the column `%s`. It already exists."; + + /** + * @param string $name + * @param Schema $schema + * @return \DB\SQL\TableBuilder + */ + public function __construct($name, Schema $schema) + { + $this->name = $name; + $this->schema = $schema; + $this->columns = array(); + $this->queries = array(); + $this->pkeys = array('id'); + $this->increments = 'id'; + parent::__construct($schema->db); + } + + /** + * generate SQL query and execute it if $exec is true + * @param bool $exec + */ + abstract public function build($exec = TRUE); + + /** + * add a new column to this table + * @param string|Column $key column name or object + * @param null|array $args optional config array + * @return \DB\SQL\Column + */ + public function addColumn($key,$args = null) + { + if ($key instanceof Column) { + $args = $key->getColumnArray(); + $key = $key->name; + } + if (array_key_exists($key,$this->columns)) + trigger_error(sprintf(self::TEXT_ColumnExists,$key)); + $column = new Column($key, $this); + if ($args) + foreach ($args as $arg => $val) + $column->{$arg} = $val; + // skip default pkey field + if (count($this->pkeys) == 1 && in_array($key,$this->pkeys)) + return $column; + return $this->columns[$key] =& $column; + } + + /** + * create index on one or more columns + * @param string|array $index_cols Column(s) to be indexed + * @param $search_cols + * @param bool $unique Unique index + * @param int $length index length for text fields in mysql + */ + protected function _addIndex($index_cols, $search_cols, $unique, $length) + { + if (!is_array($index_cols)) + $index_cols = array($index_cols); + $quotedCols = array_map(array($this->db, 'quotekey'), $index_cols); + if (preg_match('/mysql/', $this->db->driver())) + foreach($quotedCols as $i=>&$col) + if(strtoupper($search_cols[$index_cols[$i]]['type']) == 'TEXT') + $col.='('.$length.')'; + $cols = implode(',', $quotedCols); + $name = $this->db->quotekey($this->name.'___'.implode('__', $index_cols)); + $table = $this->db->quotekey($this->name); + $index = $unique ? 'UNIQUE INDEX' : 'INDEX'; + $cmd = array( + 'pgsql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => + "CREATE $index $name ON $table ($cols);", + 'mysql' => //ALTER TABLE is used because of MySQL bug #48875 + "ALTER TABLE $table ADD $index $name ($cols);", + ); + $query = $this->findQuery($cmd); + $this->queries[] = $query; + } + + /** + * set primary / composite key to table + * @param string|array $pkeys + * @return bool + */ + public function primary($pkeys) { + if (empty($pkeys)) + return false; + if (!is_array($pkeys)) + $pkeys = array($pkeys); + // single pkey + $this->increments = $pkeys[0]; + $this->pkeys = $pkeys; + // drop duplicate pkey definition + if (array_key_exists($this->increments,$this->columns)) + unset($this->columns[$this->increments]); + // set flag on new fields + foreach ($pkeys as $name) + if(array_key_exists($name,$this->columns)) + $this->columns[$name]->pkey = true; + // composite key + if (count($pkeys) > 1) { + $pkeys_quoted = array_map(array($this->db,'quotekey'), $pkeys); + $pk_string = implode(', ', $pkeys_quoted); + if (preg_match('/sqlite2?/', $this->db->driver())) { + // rebuild table with new primary keys + $this->rebuild_cmd['pkeys'] = $pkeys; + return; + } else { + $table = $this->db->quotekey($this->name); + $table_key = $this->db->quotekey($this->name.'_pkey'); + $cmd = array( + 'odbc' => + "CREATE INDEX $table_key ON $table ( $pk_string );", + 'mysql' => + "ALTER TABLE $table DROP PRIMARY KEY, ADD PRIMARY KEY ( $pk_string );", + 'mssql|sybase|dblib|sqlsrv' => array( + "ALTER TABLE $table DROP CONSTRAINT PK_".$this->name."_ID;", + "ALTER TABLE $table ADD CONSTRAINT $table_key PRIMARY KEY ( $pk_string );", + ), + 'pgsql' => array( + "ALTER TABLE $table DROP CONSTRAINT $table_key;", + "ALTER TABLE $table ADD CONSTRAINT $table_key PRIMARY KEY ( $pk_string );", + ), + ); + $query = $this->findQuery($cmd); + if (!is_array($query)) + $query = array($query); + foreach ($query as $q) + $this->queries[] = $q; + } + } + } + +} + +class TableCreator extends TableBuilder { + + const + TEXT_TableAlreadyExists = "Table `%s` already exists. Cannot create it."; + + /** + * generate SQL query for creating a basic table, containing an ID serial field + * and execute it if $exec is true, otherwise just return the generated query string + * @param bool $exec + * @return bool|TableModifier|string + */ + public function build($exec = TRUE) + { + // check if already existing + if ($exec && in_array($this->name, $this->schema->getTables())) { + trigger_error(sprintf(self::TEXT_TableAlreadyExists,$this->name)); + return false; + } + $cols = ''; + if (!empty($this->columns)) + foreach ($this->columns as $cname => $column) { + // no defaults for TEXT type + if ($column->default !== false && is_int(strpos(strtoupper($column->type),'TEXT'))) { + trigger_error(sprintf(self::TEXT_NoDefaultForTEXT, $column->name)); + return false; + } + $cols .= ', '.$column->getColumnQuery(); + } + $table = $this->db->quotekey($this->name); + $id = $this->db->quotekey($this->increments); + $cmd = array( + 'sqlite2?|sybase|dblib' => + "CREATE TABLE $table ($id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT".$cols.");", + 'mysql' => + "CREATE TABLE $table ($id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT".$cols.") DEFAULT CHARSET=utf8 COLLATE utf8_unicode_ci;", + 'pgsql' => + "CREATE TABLE $table ($id SERIAL PRIMARY KEY".$cols.");", + 'mssql|odbc|sqlsrv' => + "CREATE TABLE $table ($id INT IDENTITY CONSTRAINT PK_".$this->name."_ID PRIMARY KEY".$cols.");", + 'ibm' => + "CREATE TABLE $table ($id INTEGER AS IDENTITY NOT NULL $cols, PRIMARY KEY($id));", + ); + $query = $this->findQuery($cmd); + // composite key for sqlite + if (count($this->pkeys) > 1 && preg_match('/sqlite2?/', $this->db->driver())) { + $pk_string = implode(', ', $this->pkeys); + $query = "CREATE TABLE $table ($id INTEGER NULL".$cols.", PRIMARY KEY ($pk_string) );"; + $newTable = new TableModifier($this->name, $this->schema); + // auto-incrementation in composite primary keys + $pk_queries = $newTable->_sqlite_increment_trigger($this->increments); + $this->queries = array_merge($this->queries, $pk_queries); + } + array_unshift($this->queries, $query); + // indexes + foreach ($this->columns as $cname => $column) + if ($column->index) + $this->addIndex($cname, $column->unique); + if (!$exec) + return $this->queries; + $this->db->exec($this->queries); + return isset($newTable) ? $newTable : new TableModifier($this->name,$this->schema); + } + + /** + * create index on one or more columns + * @param string|array $columns Column(s) to be indexed + * @param bool $unique Unique index + * @param int $length index length for text fields in mysql + */ + public function addIndex($columns, $unique = FALSE, $length = 20) + { + if (!is_array($columns)) + $columns = array($columns); + $cols = $this->columns; + foreach ($cols as &$col) + $col = $col->getColumnArray(); + parent::_addIndex($columns,$cols,$unique,$length); + } + +} + + +class TableModifier extends TableBuilder { + + protected + $colTypes, $rebuild_cmd; + + const + // error messages + TEXT_TableNotExisting = "Unable to alter table `%s`. It does not exist.", + TEXT_NotNullFieldNeedsDefault = 'You cannot add the not nullable column `%s` without specifying a default value', + TEXT_ENGINE_NOT_SUPPORTED = 'DB Engine `%s` is not supported for this action.'; + + /** + * generate SQL queries for altering the table and execute it if $exec is true, + * otherwise return the generated query string + */ + public function build($exec = TRUE) + { + // check if table exists + if (!in_array($this->name, $this->schema->getTables())) + trigger_error(sprintf(self::TEXT_TableNotExisting, $this->name)); + + if ($sqlite = preg_match('/sqlite2?/', $this->db->driver())) { + $sqlite_queries = array(); + } + $rebuild = false; + $additional_queries = $this->queries; + $this->queries = array(); + // add new columns + foreach ($this->columns as $cname => $column) { + // not nullable fields should have a default value, when altering a table + if ($column->default === false && $column->nullable === false) { + trigger_error(sprintf(self::TEXT_NotNullFieldNeedsDefault, $column->name)); + return false; + } + // no defaults for TEXT type + if($column->default !== false && is_int(strpos(strtoupper($column->type),'TEXT'))) { + trigger_error(sprintf(self::TEXT_NoDefaultForTEXT, $column->name)); + return false; + } + $table = $this->db->quotekey($this->name); + $col_query = $column->getColumnQuery(); + if ($sqlite) { + // sqlite: dynamic column default only works when rebuilding the table + if($column->default === Schema::DF_CURRENT_TIMESTAMP) { + $rebuild = true; + break; + } else + $sqlite_queries[] = "ALTER TABLE $table ADD $col_query;"; + } else { + $cmd = array( + 'mysql|pgsql|mssql|sybase|dblib|odbc|sqlsrv' => + "ALTER TABLE $table ADD $col_query;", + 'ibm' => + "ALTER TABLE $table ADD COLUMN $col_query;", + ); + $this->queries[] = $this->findQuery($cmd); + } + } + if ($sqlite) + if ($rebuild || !empty($this->rebuild_cmd)) $this->_sqlite_rebuild($exec); + else $this->queries += $sqlite_queries; + $this->queries = array_merge($this->queries,$additional_queries); + // add new indexes + foreach ($this->columns as $cname => $column) + if ($column->index) + $this->addIndex($cname, $column->unique); + if (empty($this->queries)) + return false; + if (is_array($this->queries) && count($this->queries) == 1) + $this->queries = $this->queries[0]; + if (!$exec) return $this->queries; + $result = ($this->suppress) + ? @$this->db->exec($this->queries) : $this->db->exec($this->queries); + $this->queries = $this->columns = $this->rebuild_cmd = array(); + return $result; + } + + /** + * rebuild a sqlite table with additional schema changes + */ + protected function _sqlite_rebuild($exec=true) + { + $new_columns = $this->columns; + $existing_columns = $this->getCols(true); + // find after sorts + $after = array(); + foreach ($new_columns as $cname => $column) + if(!empty($column->after)) + $after[$column->after][] = $cname; + // find rename commands + $rename = (!empty($this->rebuild_cmd) && array_key_exists('rename',$this->rebuild_cmd)) + ? $this->rebuild_cmd['rename'] : array(); + // get primary-key fields + foreach ($existing_columns as $key => $col) + if ($col['pkey']) + $pkeys[array_key_exists($key,$rename) ? $rename[$key] : $key] = $col; + foreach ($new_columns as $key => $col) + if ($col->pkey) + $pkeys[$key] = $col; + // indexes + $indexes = $this->listIndex(); + // drop fields + if (!empty($this->rebuild_cmd) && array_key_exists('drop', $this->rebuild_cmd)) + foreach ($this->rebuild_cmd['drop'] as $name) + if (array_key_exists($name, $existing_columns)) { + if (array_key_exists($name, $pkeys)) { + unset($pkeys[$name]); + // drop composite key + if(count($pkeys) == 1) { + $incrementTrigger = $this->db->quotekey($this->name.'_insert'); + $this->queries[] = 'DROP TRIGGER IF EXISTS '.$incrementTrigger; + } + } + unset($existing_columns[$name]); + // drop index + foreach (array_keys($indexes) as $col) { + // for backward compatibility + if ($col == $name) + unset($indexes[$name]); + // new index names + if ($col == $this->name.'___'.$name) + unset($indexes[$this->name.'___'.$name]); + // check if column is part of an existing combined index + if (is_int(strpos($col, '__'))) { + if (is_int(strpos($col, '___'))) { + $col = explode('___', $col); + $ci = explode('__', $col[1]); + $col = implode('___',$col); + } else // for backward compatibility + $ci = explode('__', $col); + // drop combined index + if (in_array($name, $ci)) + unset($indexes[$col]); + } + } + } + // create new table + $oname = $this->name; + $this->queries[] = $this->rename($oname.'_temp', false); + $newTable = $this->schema->createTable($oname); + // add existing fields + foreach ($existing_columns as $name => $col) { + $colName = array_key_exists($name, $rename) ? $rename[$name] : $name; + // update column datatype + if (array_key_exists('update',$this->rebuild_cmd) + && in_array($name,array_keys($this->rebuild_cmd['update']))) + $col['type']=$this->rebuild_cmd['update'][$name]; + $newTable->addColumn($colName, $col)->passThrough(); + // add new fields with after flag + if (array_key_exists($name,$after)) + foreach (array_reverse($after[$name]) as $acol) { + $newTable->addColumn($new_columns[$acol]); + unset($new_columns[$acol]); + } + } + // add remaining new fields + foreach ($new_columns as $ncol) + $newTable->addColumn($ncol); + $newTable->primary(array_keys($pkeys)); + // add existing indexes + foreach (array_reverse($indexes) as $name=>$conf) { + if (is_int(strpos($name, '___'))) + list($tname,$name) = explode('___', $name); + if (is_int(strpos($name, '__'))) + $name = explode('__', $name); + if ($exec) { + $t = $this->schema->alterTable($oname); + $t->dropIndex($name); + $t->build(); + } + $newTable->addIndex($name,$conf['unique']); + } + // build new table + $newTableQueries = $newTable->build(false); + $this->queries = array_merge($this->queries,$newTableQueries); + // copy data + if (!empty($existing_columns)) { + foreach (array_keys($existing_columns) as $name) { + $fields_from[] = $this->db->quotekey($name); + $toName = array_key_exists($name, $rename) ? $rename[$name] : $name; + $fields_to[] = $this->db->quotekey($toName); + } + $this->queries[] = + 'INSERT INTO '.$this->db->quotekey($newTable->name).' ('.implode(', ', $fields_to).') '. + 'SELECT '.implode(', ', $fields_from).' FROM '.$this->db->quotekey($this->name).';'; + } + $this->queries[] = $this->drop(false); + $this->name = $oname; + } + + /** + * create an insert trigger to work-a-round auto-incrementation in composite primary keys + * @param $pkey + * @return array + */ + public function _sqlite_increment_trigger($pkey) { + $table = $this->db->quotekey($this->name); + $pkey = $this->db->quotekey($pkey); + $triggerName = $this->db->quotekey($this->name.'_insert'); + $queries[] = "DROP TRIGGER IF EXISTS $triggerName;"; + $queries[] = 'CREATE TRIGGER '.$triggerName.' AFTER INSERT ON '.$table. + ' WHEN (NEW.'.$pkey.' IS NULL) BEGIN'. + ' UPDATE '.$table.' SET '.$pkey.' = ('. + ' select coalesce( max( '.$pkey.' ), 0 ) + 1 from '.$table. + ') WHERE ROWID = NEW.ROWID;'. + ' END;'; + return $queries; + } + + /** + * get columns of a table + * @param bool $types + * @return array + */ + public function getCols($types = false) + { + $schema = $this->db->schema($this->name, null, 0); + if (!$types) + return array_keys($schema); + else + foreach ($schema as $name => &$cols) { + $default = ($cols['default'] === '') ? null : $cols['default']; + if (!is_null($default) && ( + (is_int(strpos($curdef=$this->findQuery($this->schema->defaultTypes['CUR_STAMP']), + $default)) || is_int(strpos($default,$curdef))) + || $default == "('now'::text)::timestamp(0) without time zone")) + { + $default = 'CUR_STAMP'; + } elseif (!is_null($default)) { + // remove single-qoutes + if (preg_match('/sqlite2?/', $this->db->driver())) + $default=preg_replace('/^\s*([\'"])(.*)\1\s*$/','\2',$default); + elseif (preg_match('/mssql|sybase|dblib|odbc|sqlsrv/', $this->db->driver())) + $default=preg_replace('/^\s*(\(\')(.*)(\'\))\s*$/','\2',$default); + // extract value from character_data in postgre + elseif (preg_match('/pgsql/', $this->db->driver())) + if (is_int(strpos($default, 'nextval'))) + $default = null; // drop autoincrement default + elseif (preg_match("/^\'*(.*)\'*::(\s*\w)+/", $default, $match)) + $default = $match[1]; + } else + $default=false; + $cols['default'] = $default; + } + return $schema; + } + + /** + * removes a column from a table + * @param string $name + * @return bool + */ + public function dropColumn($name) + { + $colTypes = $this->getCols(true); + // check if column exists + if (!in_array($name, array_keys($colTypes))) return true; + if (preg_match('/sqlite2?/', $this->db->driver())) { + // SQlite does not support drop column directly + $this->rebuild_cmd['drop'][] = $name; + } else { + $quotedTable = $this->db->quotekey($this->name); + $quotedColumn = $this->db->quotekey($name); + $cmd = array( + 'mysql' => + "ALTER TABLE $quotedTable DROP $quotedColumn;", + 'pgsql|odbc|ibm|mssql|sybase|dblib|sqlsrv' => + "ALTER TABLE $quotedTable DROP COLUMN $quotedColumn;", + ); + if (preg_match('/mssql|sybase|dblib|sqlsrv/', $this->db->driver())) + $this->suppress=true; + $this->queries[] = $this->findQuery($cmd); + } + } + + /** + * rename a column + * @param $name + * @param $new_name + * @return void + */ + public function renameColumn($name, $new_name) + { + $existing_columns = $this->getCols(true); + // check if column is already existing + if (!in_array($name, array_keys($existing_columns))) + trigger_error('cannot rename column. it does not exist.'); + if (in_array($new_name, array_keys($existing_columns))) + trigger_error('cannot rename column. new column already exist.'); + + if (preg_match('/sqlite2?/', $this->db->driver())) + // SQlite does not support drop or rename column directly + $this->rebuild_cmd['rename'][$name] = $new_name; + elseif (preg_match('/odbc/', $this->db->driver())) { + // no rename column for odbc, create temp column + $this->addColumn($new_name, $existing_columns[$name])->passThrough(); + $this->queries[] = "UPDATE $this->name SET $new_name = $name"; + $this->dropColumn($name); + } else { + $existing_columns = $this->getCols(true); + $quotedTable = $this->db->quotekey($this->name); + $quotedColumn = $this->db->quotekey($name); + $quotedColumnNew = $this->db->quotekey($new_name); + $cmd = array( + 'mysql' => + "ALTER TABLE $quotedTable CHANGE $quotedColumn $quotedColumnNew ".$existing_columns[$name]['type'].";", + 'pgsql|ibm' => + "ALTER TABLE $quotedTable RENAME COLUMN $quotedColumn TO $quotedColumnNew;", + 'mssql|sybase|dblib|sqlsrv' => + "sp_rename [$this->name.$name], '$new_name', 'Column'", + ); + if (preg_match('/mssql|sybase|dblib|sqlsrv/', $this->db->driver())) + $this->suppress = true; + $this->queries[] = $this->findQuery($cmd); + } + } + + /** + * modifies column datatype + * @param $name + * @param $datatype + * @param bool $force + * @return bool + */ + public function updateColumn($name, $datatype, $force = false) + { + if(!$force) + $datatype = $this->findQuery($this->schema->dataTypes[strtoupper($datatype)]); + $table = $this->db->quotekey($this->name); + $column = $this->db->quotekey($name); + if (preg_match('/sqlite2?/', $this->db->driver())){ + $this->rebuild_cmd['update'][$name] = $datatype; + } else { + $cmd = array( + 'mysql' => + "ALTER TABLE $table MODIFY COLUMN $column $datatype;", + 'pgsql' => + "ALTER TABLE $table ALTER COLUMN $column TYPE $datatype;", + 'sqlsrv|mssql|sybase|dblib|ibm' => + "ALTER TABLE $table ALTER COLUMN $column $datatype;", + ); + $this->queries[] = $this->findQuery($cmd); + } + } + + /** + * create index on one or more columns + * @param string|array $columns Column(s) to be indexed + * @param bool $unique Unique index + * @param int $length index length for text fields in mysql + */ + public function addIndex($columns, $unique = FALSE, $length = 20) + { + if (!is_array($columns)) + $columns = array($columns); + $existingCol = $this->columns; + foreach ($existingCol as &$col) + $col = $col->getColumnArray(); + $allCols = array_merge($this->getCols(true), $existingCol); + parent::_addIndex($columns, $allCols, $unique, $length); + } + + /** + * drop a column index + * @param string|array $name + */ + public function dropIndex($name) + { + if (is_array($name)) + $name = $this->name.'___'.implode('__', $name); + elseif(!is_int(strpos($name,'___'))) + $name = $this->name.'___'.$name; + $name = $this->db->quotekey($name); + $table = $this->db->quotekey($this->name); + $cmd = array( + 'pgsql|sqlite2?|ibm' => + "DROP INDEX $name;", + 'mssql|sybase|dblib|odbc|sqlsrv' => + "DROP INDEX $table.$name;", + 'mysql'=> + "ALTER TABLE $table DROP INDEX $name;", + ); + $query = $this->findQuery($cmd); + $this->queries[] = $query; + } + + /** + * returns table indexes as assoc array + * @return array + */ + public function listIndex() + { + $table = $this->db->quotekey($this->name); + $cmd = array( + 'sqlite2?' => + "PRAGMA index_list($table);", + 'mysql' => + "SHOW INDEX FROM $table;", + 'mssql|sybase|dblib|sqlsrv' => + "select * from sys.indexes ". + "where object_id = (select object_id from sys.objects where name = '$this->name')", + 'pgsql' => + "select i.relname as name, ix.indisunique as unique ". + "from pg_class t, pg_class i, pg_index ix ". + "where t.oid = ix.indrelid and i.oid = ix.indexrelid ". + "and t.relkind = 'r' and t.relname = '$this->name'". + "group by t.relname, i.relname, ix.indisunique;", + ); + $result = $this->db->exec($this->findQuery($cmd)); + $indexes = array(); + if (preg_match('/pgsql|sqlite2?/', $this->db->driver())) { + foreach($result as $row) + $indexes[$row['name']] = array('unique' => $row['unique']); + } elseif (preg_match('/mssql|sybase|dblib|sqlsrv/', $this->db->driver())) { + foreach ($result as $row) + $indexes[$row['name']] = array('unique' => $row['is_unique']); + } elseif (preg_match('/mysql/', $this->db->driver())) { + foreach($result as $row) + $indexes[$row['Key_name']] = array('unique' => !(bool)$row['Non_unique']); + } else + trigger_error(sprintf(self::TEXT_ENGINE_NOT_SUPPORTED, $this->db->driver())); + return $indexes; + } + + /** + * rename this table + * @param string $new_name + * @param bool $exec + * @return $this|bool + */ + public function rename($new_name, $exec = true) { + $query = $this->schema->renameTable($this->name, $new_name, $exec); + $this->name = $new_name; + return ($exec) ? $this : $query; + } + + /** + * drop this table + * @param bool $exec + * @return mixed + */ + public function drop($exec = true) { + return $this->schema->dropTable($this,$exec); + } + +} + +/** + * defines a table column configuration + * Class Column + * @package DB\SQL + */ +class Column extends DB_Utils { + + public $name, $type, $nullable, $default, $after, $index, $unique, $passThrough, $pkey; + protected $table, $schema; + + const + TEXT_NoDataType = 'The specified datatype %s is not defined in %s driver', + TEXT_CurrentStampDataType = 'Current timestamp as column default is only possible for TIMESTAMP datatype'; + + /** + * @param string $name + * @param TableBuilder $table + */ + public function __construct($name, TableBuilder $table) { + $this->name = $name; + $this->nullable = true; + $this->default = false; + $this->after = false; + $this->index = false; + $this->unique = false; + $this->passThrough = false; + $this->pkey = false; + + $this->table = $table; + $this->schema = $table->schema; + parent::__construct($this->schema->db); + } + + /** + * @param string $datatype + * @param bool $force don't match datatype against DT array + * @return $this + */ + public function type($datatype, $force = FALSE) { + $this->type = $datatype; + $this->passThrough = $force; + return $this; + } + + public function type_tinyint() { + $this->type = Schema::DT_INT1; + return $this; + } + + public function type_smallint() { + $this->type = Schema::DT_INT2; + return $this; + } + + public function type_int() { + $this->type = Schema::DT_INT4; + return $this; + } + + public function type_bigint() { + $this->type = Schema::DT_INT8; + return $this; + } + + public function type_float() { + $this->type = Schema::DT_FLOAT; + return $this; + } + + public function type_decimal() { + $this->type = Schema::DT_DOUBLE; + return $this; + } + + public function type_text() { + $this->type = Schema::DT_TEXT; + return $this; + } + + public function type_longtext() { + $this->type = Schema::DT_LONGTEXT; + return $this; + } + + public function type_varchar($length = 255) { + $this->type = "varchar($length)"; + $this->passThrough = true; + return $this; + } + + public function type_date() { + $this->type = Schema::DT_DATE; + return $this; + } + + public function type_datetime() { + $this->type = Schema::DT_DATETIME; + return $this; + } + + public function type_timestamp($asDefault=false) { + $this->type = Schema::DT_TIMESTAMP; + if ($asDefault) + $this->default = Schema::DF_CURRENT_TIMESTAMP; + return $this; + } + + public function type_blob() { + $this->type = Schema::DT_BLOB; + return $this; + } + + public function type_bool() { + $this->type = Schema::DT_BOOLEAN; + return $this; + } + + public function passThrough($state = TRUE) { + $this->passThrough = $state; + return $this; + } + + public function nullable($nullable) { + $this->nullable = $nullable; + return $this; + } + + public function defaults($default) { + $this->default = $default; + return $this; + } + + public function after($name) { + $this->after = $name; + return $this; + } + + public function index($unique = FALSE) { + $this->index = true; + $this->unique = $unique; + return $this; + } + + /** + * returns an array of this column configuration + * @return array + */ + public function getColumnArray() + { + $fields = array('name','type','passThrough','default','nullable', + 'index','unique','after','pkey'); + $fields = array_flip($fields); + foreach($fields as $key => &$val) + $val = $this->{$key}; + unset($val); + return $fields; + } + + /** + * generate SQL column definition query + * @return bool|string + */ + public function getColumnQuery() + { + if (!$this->type) + trigger_error(sprintf('Cannot build a column query for `%s`: no column type set',$this->name)); + // prepare column types + if ($this->passThrough) + $type_val = $this->type; + else { + $type_val = $this->findQuery($this->schema->dataTypes[strtoupper($this->type)]); + if (!$type_val) { + trigger_error(sprintf(self::TEXT_NoDataType, strtoupper($this->type), + $this->db->driver())); + return FALSE; + } + } + // build query + $query = $this->db->quotekey($this->name).' '.$type_val.' '. + ($this->nullable ? 'NULL' : 'NOT NULL'); + // default value + if ($this->default !== false) { + $def_cmds = array( + 'sqlite2?|mysql|pgsql|mssql|sybase|dblib|odbc|sqlsrv' => 'DEFAULT', + 'ibm' => 'WITH DEFAULT', + ); + $def_cmd = $this->findQuery($def_cmds).' '; + // timestamp default + if ($this->default === Schema::DF_CURRENT_TIMESTAMP) { + // check for right datatpye + $stamp_type = $this->findQuery($this->schema->dataTypes['TIMESTAMP']); + if ($this->type != 'TIMESTAMP' && // TODO: check that condition + ($this->passThrough && strtoupper($this->type) != strtoupper($stamp_type)) + ) + trigger_error(self::TEXT_CurrentStampDataType); + $def_cmd .= $this->findQuery($this->schema->defaultTypes[strtoupper($this->default)]); + } else { + // static defaults + $pdo_type = preg_match('/int|bool/i', $type_val, $parts) ? + constant('\PDO::PARAM_'.strtoupper($parts[0])) : \PDO::PARAM_STR; + $def_cmd .= ($this->default === NULL ? 'NULL' : + $this->db->quote(htmlspecialchars($this->default, ENT_QUOTES, + $this->f3->get('ENCODING')), $pdo_type)); + } + $query .= ' '.$def_cmd; + } + if (!empty($this->after)) { + // `after` feature only works for mysql + if (preg_match('/mysql/', $this->db->driver())) { + $after_cmd = 'AFTER '.$this->db->quotekey($this->after); + $query .= ' '.$after_cmd; + } + } + return $query; + } +} + + +class DB_Utils { + + /** @var \DB\SQL */ + protected $db; + + /** @var \BASE */ + protected $f3; + + const + TEXT_ENGINE_NOT_SUPPORTED = 'DB Engine `%s` is not supported for this action.'; + + /** + * parse command array and return backend specific query + * @param $cmd + * @param $cmd array + * @return bool|string + */ + protected function findQuery($cmd) + { + $match = FALSE; + foreach ($cmd as $backend => $val) + if (preg_match('/'.$backend.'/', $this->db->driver())) { + $match = TRUE; + break; + } + if (!$match) { + trigger_error(sprintf(self::TEXT_ENGINE_NOT_SUPPORTED, $this->db->driver())); + return FALSE; + } + return $val; + } + + public function __construct(SQL $db) { + $this->db = $db; + $this->f3 = \Base::instance(); + } +} \ No newline at end of file diff --git a/lib/f3/db/sql/session.php b/lib/f3/db/sql/session.php new file mode 100755 index 0000000..093c07e --- /dev/null +++ b/lib/f3/db/sql/session.php @@ -0,0 +1,201 @@ +load(array('session_id=?',$id)); + return $this->dry()?FALSE:$this->get('data'); + } + + /** + * Write session data + * @return TRUE + * @param $id string + * @param $data string + **/ + function write($id,$data) { + $fw=\Base::instance(); + $sent=headers_sent(); + $headers=$fw->get('HEADERS'); + $this->load(array('session_id=?',$id)); + $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash(mt_rand()); + $this->set('session_id',$id); + $this->set('data',$data); + $this->set('csrf',$sent?$this->csrf():$csrf); + $this->set('ip',$fw->get('IP')); + $this->set('agent', + isset($headers['User-Agent'])?$headers['User-Agent']:''); + $this->set('stamp',time()); + $this->save(); + if (!$sent) { + if (isset($_COOKIE['_'])) + setcookie('_','',strtotime('-1 year')); + call_user_func_array('setcookie', + array('_',$csrf)+$fw->get('JAR')); + } + return TRUE; + } + + /** + * Destroy session + * @return TRUE + * @param $id string + **/ + function destroy($id) { + $this->erase(array('session_id=?',$id)); + setcookie(session_name(),'',strtotime('-1 year')); + unset($_COOKIE[session_name()]); + header_remove('Set-Cookie'); + return TRUE; + } + + /** + * Garbage collector + * @return TRUE + * @param $max int + **/ + function cleanup($max) { + $this->erase(array('stamp+?load(array('session_id=?',$id?:session_id())); + return $this->dry()?FALSE:$this->get('csrf'); + } + + /** + * Return IP address associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function ip($id=NULL) { + $this->load(array('session_id=?',$id?:session_id())); + return $this->dry()?FALSE:$this->get('ip'); + } + + /** + * Return Unix timestamp associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function stamp($id=NULL) { + $this->load(array('session_id=?',$id?:session_id())); + return $this->dry()?FALSE:$this->get('stamp'); + } + + /** + * Return HTTP user agent associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function agent($id=NULL) { + $this->load(array('session_id=?',$id?:session_id())); + return $this->dry()?FALSE:$this->get('agent'); + } + + /** + * Instantiate class + * @param $db object + * @param $table string + **/ + function __construct(\DB\SQL $db,$table='sessions') { + $db->exec( + (preg_match('/mssql|sqlsrv|sybase/',$db->driver())? + ('IF NOT EXISTS (SELECT * FROM sysobjects WHERE '. + 'name='.$db->quote($table).' AND xtype=\'U\') '. + 'CREATE TABLE dbo.'): + ('CREATE TABLE IF NOT EXISTS '. + (($name=$db->name())?($name.'.'):''))). + $table.' ('. + 'session_id VARCHAR(40),'. + 'data TEXT,'. + 'csrf TEXT,'. + 'ip VARCHAR(40),'. + 'agent VARCHAR(255),'. + 'stamp INTEGER,'. + 'PRIMARY KEY(session_id)'. + ');' + ); + parent::__construct($db,$table); + session_set_save_handler( + array($this,'open'), + array($this,'close'), + array($this,'read'), + array($this,'write'), + array($this,'destroy'), + array($this,'cleanup') + ); + register_shutdown_function('session_commit'); + @session_start(); + $fw=\Base::instance(); + $headers=$fw->get('HEADERS'); + if (($csrf=$this->csrf()) && + ((!isset($_COOKIE['_']) || $_COOKIE['_']!=$csrf) || + ($ip=$this->ip()) && $ip!=$fw->get('IP') || + ($agent=$this->agent()) && !isset($headers['User-Agent']) || + $agent!=$headers['User-Agent'])) { + $jar=$fw->get('JAR'); + $jar['expire']=strtotime('-1 year'); + call_user_func_array('setcookie', + array_merge(array('_',''),$jar)); + unset($_COOKIE['_']); + session_destroy(); + \Base::instance()->error(403); + } + $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash(mt_rand()); + if ($this->load(array('session_id=?',session_id()))) { + $this->set('csrf',$csrf); + $this->save(); + call_user_func_array('setcookie', + array('_',$csrf)+$fw->get('JAR')); + } + } + +} diff --git a/lib/f3/f3.php b/lib/f3/f3.php new file mode 100755 index 0000000..4788d58 --- /dev/null +++ b/lib/f3/f3.php @@ -0,0 +1,35 @@ +6) + user_error(sprintf(self::E_Color,'0x'.$hex)); + $color=str_split($hex,$len/3); + foreach ($color as &$hue) { + $hue=hexdec(str_repeat($hue,6/$len)); + unset($hue); + } + return $color; + } + + /** + * Invert image + * @return object + **/ + function invert() { + imagefilter($this->data,IMG_FILTER_NEGATE); + return $this->save(); + } + + /** + * Adjust brightness (range:-255 to 255) + * @return object + * @param $level int + **/ + function brightness($level) { + imagefilter($this->data,IMG_FILTER_BRIGHTNESS,$level); + return $this->save(); + } + + /** + * Adjust contrast (range:-100 to 100) + * @return object + * @param $level int + **/ + function contrast($level) { + imagefilter($this->data,IMG_FILTER_CONTRAST,$level); + return $this->save(); + } + + /** + * Convert to grayscale + * @return object + **/ + function grayscale() { + imagefilter($this->data,IMG_FILTER_GRAYSCALE); + return $this->save(); + } + + /** + * Adjust smoothness + * @return object + * @param $level int + **/ + function smooth($level) { + imagefilter($this->data,IMG_FILTER_SMOOTH,$level); + return $this->save(); + } + + /** + * Emboss the image + * @return object + **/ + function emboss() { + imagefilter($this->data,IMG_FILTER_EMBOSS); + return $this->save(); + } + + /** + * Apply sepia effect + * @return object + **/ + function sepia() { + imagefilter($this->data,IMG_FILTER_GRAYSCALE); + imagefilter($this->data,IMG_FILTER_COLORIZE,90,60,45); + return $this->save(); + } + + /** + * Pixelate the image + * @return object + * @param $size int + **/ + function pixelate($size) { + imagefilter($this->data,IMG_FILTER_PIXELATE,$size,TRUE); + return $this->save(); + } + + /** + * Blur the image using Gaussian filter + * @return object + * @param $selective bool + **/ + function blur($selective=FALSE) { + imagefilter($this->data, + $selective?IMG_FILTER_SELECTIVE_BLUR:IMG_FILTER_GAUSSIAN_BLUR); + return $this->save(); + } + + /** + * Apply sketch effect + * @return object + **/ + function sketch() { + imagefilter($this->data,IMG_FILTER_MEAN_REMOVAL); + return $this->save(); + } + + /** + * Flip on horizontal axis + * @return object + **/ + function hflip() { + $tmp=imagecreatetruecolor( + $width=$this->width(),$height=$this->height()); + imagesavealpha($tmp,TRUE); + imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); + imagecopyresampled($tmp,$this->data, + 0,0,$width-1,0,$width,$height,-$width,$height); + imagedestroy($this->data); + $this->data=$tmp; + return $this->save(); + } + + /** + * Flip on vertical axis + * @return object + **/ + function vflip() { + $tmp=imagecreatetruecolor( + $width=$this->width(),$height=$this->height()); + imagesavealpha($tmp,TRUE); + imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); + imagecopyresampled($tmp,$this->data, + 0,0,0,$height-1,$width,$height,$width,-$height); + imagedestroy($this->data); + $this->data=$tmp; + return $this->save(); + } + + /** + * Crop the image + * @return object + * @param $x1 int + * @param $y1 int + * @param $x2 int + * @param $y2 int + **/ + function crop($x1,$y1,$x2,$y2) { + $tmp=imagecreatetruecolor($width=$x2-$x1+1,$height=$y2-$y1+1); + imagesavealpha($tmp,TRUE); + imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); + imagecopyresampled($tmp,$this->data, + 0,0,$x1,$y1,$width,$height,$width,$height); + imagedestroy($this->data); + $this->data=$tmp; + return $this->save(); + } + + /** + * Resize image (Maintain aspect ratio); Crop relative to center + * if flag is enabled; Enlargement allowed if flag is enabled + * @return object + * @param $width int + * @param $height int + * @param $crop bool + * @param $enlarge bool + **/ + function resize($width,$height,$crop=TRUE,$enlarge=TRUE) { + // Adjust dimensions; retain aspect ratio + $ratio=($origw=imagesx($this->data))/($origh=imagesy($this->data)); + if (!$crop) + if ($width/$ratio<=$height) + $height=$width/$ratio; + else + $width=$height*$ratio; + if (!$enlarge) { + $width=min($origw,$width); + $height=min($origh,$height); + } + // Create blank image + $tmp=imagecreatetruecolor($width,$height); + imagesavealpha($tmp,TRUE); + imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); + // Resize + if ($crop) { + if ($width/$ratio<=$height) { + $cropw=$origh*$width/$height; + imagecopyresampled($tmp,$this->data, + 0,0,($origw-$cropw)/2,0,$width,$height,$cropw,$origh); + } + else { + $croph=$origw*$height/$width; + imagecopyresampled($tmp,$this->data, + 0,0,0,($origh-$croph)/2,$width,$height,$origw,$croph); + } + } + else + imagecopyresampled($tmp,$this->data, + 0,0,0,0,$width,$height,$origw,$origh); + imagedestroy($this->data); + $this->data=$tmp; + return $this->save(); + } + + /** + * Rotate image + * @return object + * @param $angle int + **/ + function rotate($angle) { + $this->data=imagerotate($this->data,$angle, + imagecolorallocatealpha($this->data,0,0,0,127)); + imagesavealpha($this->data,TRUE); + return $this->save(); + } + + /** + * Apply an image overlay + * @return object + * @param $img object + * @param $align int + **/ + function overlay(Image $img,$align=NULL) { + if (is_null($align)) + $align=self::POS_Right|self::POS_Bottom; + $ovr=imagecreatefromstring($img->dump()); + imagesavealpha($ovr,TRUE); + $imgw=$this->width(); + $imgh=$this->height(); + $ovrw=imagesx($ovr); + $ovrh=imagesy($ovr); + if ($align & self::POS_Left) + $posx=0; + if ($align & self::POS_Center) + $posx=($imgw-$ovrw)/2; + if ($align & self::POS_Right) + $posx=$imgw-$ovrw; + if ($align & self::POS_Top) + $posy=0; + if ($align & self::POS_Middle) + $posy=($imgh-$ovrh)/2; + if ($align & self::POS_Bottom) + $posy=$imgh-$ovrh; + if (empty($posx)) + $posx=0; + if (empty($posy)) + $posy=0; + imagecopy($this->data,$ovr,$posx,$posy,0,0,$ovrw,$ovrh); + return $this->save(); + } + + /** + * Generate identicon + * @return object + * @param $str string + * @param $size int + * @param $blocks int + **/ + function identicon($str,$size=64,$blocks=4) { + $sprites=array( + array(.5,1,1,0,1,1), + array(.5,0,1,0,.5,1,0,1), + array(.5,0,1,0,1,1,.5,1,1,.5), + array(0,.5,.5,0,1,.5,.5,1,.5,.5), + array(0,.5,1,0,1,1,0,1,1,.5), + array(1,0,1,1,.5,1,1,.5,.5,.5), + array(0,0,1,0,1,.5,0,0,.5,1,0,1), + array(0,0,.5,0,1,.5,.5,1,0,1,.5,.5), + array(.5,0,.5,.5,1,.5,1,1,.5,1,.5,.5,0,.5), + array(0,0,1,0,.5,.5,1,.5,.5,1,.5,.5,0,1), + array(0,.5,.5,1,1,.5,.5,0,1,0,1,1,0,1), + array(.5,0,1,0,1,1,.5,1,1,.75,.5,.5,1,.25), + array(0,.5,.5,0,.5,.5,1,0,1,.5,.5,1,.5,.5,0,1), + array(0,0,1,0,1,1,0,1,1,.5,.5,.25,.5,.75,0,.5,.5,.25), + array(0,.5,.5,.5,.5,0,1,0,.5,.5,1,.5,.5,1,.5,.5,0,1), + array(0,0,1,0,.5,.5,.5,0,0,.5,1,.5,.5,1,.5,.5,0,1) + ); + $hash=sha1($str); + $this->data=imagecreatetruecolor($size,$size); + list($r,$g,$b)=$this->rgb(hexdec(substr($hash,-3))); + $fg=imagecolorallocate($this->data,$r,$g,$b); + imagefill($this->data,0,0,IMG_COLOR_TRANSPARENT); + $ctr=count($sprites); + $dim=$blocks*floor($size/$blocks)*2/$blocks; + for ($j=0,$y=ceil($blocks/2);$j<$y;$j++) + for ($i=$j,$x=$blocks-1-$j;$i<$x;$i++) { + $sprite=imagecreatetruecolor($dim,$dim); + imagefill($sprite,0,0,IMG_COLOR_TRANSPARENT); + if ($block=$sprites[ + hexdec($hash[($j*$blocks+$i)*2])%$ctr]) { + for ($k=0,$pts=count($block);$k<$pts;$k++) + $block[$k]*=$dim; + imagefilledpolygon($sprite,$block,$pts/2,$fg); + } + $sprite=imagerotate($sprite, + 90*(hexdec($hash[($j*$blocks+$i)*2+1])%4), + imagecolorallocatealpha($sprite,0,0,0,127)); + for ($k=0;$k<4;$k++) { + imagecopyresampled($this->data,$sprite, + $i*$dim/2,$j*$dim/2,0,0,$dim/2,$dim/2,$dim,$dim); + $this->data=imagerotate($this->data,90, + imagecolorallocatealpha($this->data,0,0,0,127)); + } + imagedestroy($sprite); + } + imagesavealpha($this->data,TRUE); + return $this->save(); + } + + /** + * Generate CAPTCHA image + * @return object|FALSE + * @param $font string + * @param $size int + * @param $len int + * @param $key string + * @param $path string + * @param $fg int + * @param $bg int + **/ + function captcha($font,$size=24,$len=5, + $key=NULL,$path='',$fg=0xFFFFFF,$bg=0x000000) { + if ((!$ssl=extension_loaded('openssl')) && ($len<4 || $len>13)) { + user_error(sprintf(self::E_Length,$len)); + return FALSE; + } + $fw=Base::instance(); + foreach ($fw->split($path?:$fw->get('UI').';./') as $dir) + if (is_file($path=$dir.$font)) { + $seed=strtoupper(substr( + $ssl?bin2hex(openssl_random_pseudo_bytes($len)):uniqid(), + -$len)); + $block=$size*3; + $tmp=array(); + for ($i=0,$width=0,$height=0;$i<$len;$i++) { + // Process at 2x magnification + $box=imagettfbbox($size*2,0,$path,$seed[$i]); + $w=$box[2]-$box[0]; + $h=$box[1]-$box[5]; + $char=imagecreatetruecolor($block,$block); + imagefill($char,0,0,$bg); + imagettftext($char,$size*2,0, + ($block-$w)/2,$block-($block-$h)/2, + $fg,$path,$seed[$i]); + $char=imagerotate($char,mt_rand(-30,30), + imagecolorallocatealpha($char,0,0,0,127)); + // Reduce to normal size + $tmp[$i]=imagecreatetruecolor( + ($w=imagesx($char))/2,($h=imagesy($char))/2); + imagefill($tmp[$i],0,0,IMG_COLOR_TRANSPARENT); + imagecopyresampled($tmp[$i],$char,0,0,0,0,$w/2,$h/2,$w,$h); + imagedestroy($char); + $width+=$i+1<$len?$block/2:$w/2; + $height=max($height,$h/2); + } + $this->data=imagecreatetruecolor($width,$height); + imagefill($this->data,0,0,IMG_COLOR_TRANSPARENT); + for ($i=0;$i<$len;$i++) { + imagecopy($this->data,$tmp[$i], + $i*$block/2,($height-imagesy($tmp[$i]))/2,0,0, + imagesx($tmp[$i]),imagesy($tmp[$i])); + imagedestroy($tmp[$i]); + } + imagesavealpha($this->data,TRUE); + if ($key) + $fw->set($key,$seed); + return $this->save(); + } + user_error(self::E_Font); + return FALSE; + } + + /** + * Return image width + * @return int + **/ + function width() { + return imagesx($this->data); + } + + /** + * Return image height + * @return int + **/ + function height() { + return imagesy($this->data); + } + + /** + * Send image to HTTP client + * @return NULL + **/ + function render() { + $args=func_get_args(); + $format=$args?array_shift($args):'png'; + if (PHP_SAPI!='cli') { + header('Content-Type: image/'.$format); + header('X-Powered-By: '.Base::instance()->get('PACKAGE')); + } + call_user_func_array('image'.$format, + array_merge(array($this->data),$args)); + } + + /** + * Return image as a string + * @return string + **/ + function dump() { + $args=func_get_args(); + $format=$args?array_shift($args):'png'; + ob_start(); + call_user_func_array('image'.$format, + array_merge(array($this->data),$args)); + return ob_get_clean(); + } + + /** + * Save current state + * @return object + **/ + function save() { + $fw=Base::instance(); + if ($this->flag) { + if (!is_dir($dir=$fw->get('TEMP'))) + mkdir($dir,Base::MODE,TRUE); + $this->count++; + $fw->write($dir.'/'. + $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash($this->file).'-'.$this->count.'.png', + $this->dump()); + } + return $this; + } + + /** + * Revert to specified state + * @return object + * @param $state int + **/ + function restore($state=1) { + $fw=Base::instance(); + if ($this->flag && is_file($file=($path=$fw->get('TEMP'). + $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash($this->file).'-').$state.'.png')) { + if (is_resource($this->data)) + imagedestroy($this->data); + $this->data=imagecreatefromstring($fw->read($file)); + imagesavealpha($this->data,TRUE); + foreach (glob($path.'*.png',GLOB_NOSORT) as $match) + if (preg_match('/-(\d+)\.png/',$match,$parts) && + $parts[1]>$state) + @unlink($match); + $this->count=$state; + } + return $this; + } + + /** + * Undo most recently applied filter + * @return object + **/ + function undo() { + if ($this->flag) { + if ($this->count) + $this->count--; + return $this->restore($this->count); + } + return $this; + } + + /** + * Load string + * @return object + * @param $str string + **/ + function load($str) { + $this->data=imagecreatefromstring($str); + imagesavealpha($this->data,TRUE); + $this->save(); + return $this; + } + + /** + * Instantiate image + * @param $file string + * @param $flag bool + * @param $path string + **/ + function __construct($file=NULL,$flag=FALSE,$path='') { + $this->flag=$flag; + if ($file) { + $fw=Base::instance(); + // Create image from file + $this->file=$file; + foreach ($fw->split($path?:$fw->get('UI').';./') as $dir) + if (is_file($dir.$file)) + return $this->load($fw->read($dir.$file)); + } + } + + /** + * Wrap-up + * @return NULL + **/ + function __destruct() { + if (is_resource($this->data)) { + imagedestroy($this->data); + $fw=Base::instance(); + $path=$fw->get('TEMP'). + $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash($this->file); + if ($glob=@glob($path.'*.png',GLOB_NOSORT)) + foreach ($glob as $match) + if (preg_match('/-(\d+)\.png/',$match)) + @unlink($match); + } + } + +} diff --git a/lib/f3/license.txt b/lib/f3/license.txt new file mode 100755 index 0000000..3c7236c --- /dev/null +++ b/lib/f3/license.txt @@ -0,0 +1,621 @@ +GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + +The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + +Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and +modification follow. + +TERMS AND CONDITIONS + +0. Definitions. + +"This License" refers to version 3 of the GNU General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based +on the Program. + +To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +1. Source Code. + +The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + +A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +The Corresponding Source for a work in source code form is that +same work. + +2. Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +a) The work must carry prominent notices stating that you modified +it, and giving a relevant date. + +b) The work must carry prominent notices stating that it is +released under this License and any conditions added under section +7. This requirement modifies the requirement in section 4 to +"keep intact all notices". + +c) You must license the entire work, as a whole, under this +License to anyone who comes into possession of a copy. This +License will therefore apply, along with any applicable section 7 +additional terms, to the whole of the work, and all its parts, +regardless of how they are packaged. This License gives no +permission to license the work in any other way, but it does not +invalidate such permission if you have separately received it. + +d) If the work has interactive user interfaces, each must display +Appropriate Legal Notices; however, if the Program has interactive +interfaces that do not display Appropriate Legal Notices, your +work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +a) Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by the +Corresponding Source fixed on a durable physical medium +customarily used for software interchange. + +b) Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by a +written offer, valid for at least three years and valid for as +long as you offer spare parts or customer support for that product +model, to give anyone who possesses the object code either (1) a +copy of the Corresponding Source for all the software in the +product that is covered by this License, on a durable physical +medium customarily used for software interchange, for a price no +more than your reasonable cost of physically performing this +conveying of source, or (2) access to copy the +Corresponding Source from a network server at no charge. + +c) Convey individual copies of the object code with a copy of the +written offer to provide the Corresponding Source. This +alternative is allowed only occasionally and noncommercially, and +only if you received the object code with such an offer, in accord +with subsection 6b. + +d) Convey the object code by offering access from a designated +place (gratis or for a charge), and offer equivalent access to the +Corresponding Source in the same way through the same place at no +further charge. You need not require recipients to copy the +Corresponding Source along with the object code. If the place to +copy the object code is a network server, the Corresponding Source +may be on a different server (operated by you or a third party) +that supports equivalent copying facilities, provided you maintain +clear directions next to the object code saying where to find the +Corresponding Source. Regardless of what server hosts the +Corresponding Source, you remain obligated to ensure that it is +available for as long as needed to satisfy these requirements. + +e) Convey the object code using peer-to-peer transmission, provided +you inform other peers where the object code and Corresponding +Source of the work are being offered to the general public at no +charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +a) Disclaiming warranty or limiting liability differently from the +terms of sections 15 and 16 of this License; or + +b) Requiring preservation of specified reasonable legal notices or +author attributions in that material or in the Appropriate Legal +Notices displayed by works containing it; or + +c) Prohibiting misrepresentation of the origin of that material, or +requiring that modified versions of such material be marked in +reasonable ways as different from the original version; or + +d) Limiting the use for publicity purposes of names of licensors or +authors of the material; or + +e) Declining to grant rights under trademark law for use of some +trade names, trademarks, or service marks; or + +f) Requiring indemnification of licensors and authors of that +material by anyone who conveys the material (or modified versions of +it) with contractual assumptions of liability to the recipient, for +any liability that these contractual assumptions directly impose on +those licensors and authors. + +All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +8. Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +11. Patents. + +A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +13. Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS diff --git a/lib/f3/log.php b/lib/f3/log.php new file mode 100755 index 0000000..7ec78c0 --- /dev/null +++ b/lib/f3/log.php @@ -0,0 +1,60 @@ +write( + $this->file, + date($format). + (isset($_SERVER['REMOTE_ADDR'])? + (' ['.$_SERVER['REMOTE_ADDR'].']'):'').' '. + trim($text).PHP_EOL, + TRUE + ); + } + + /** + * Erase log + * @return NULL + **/ + function erase() { + @unlink($this->file); + } + + /** + * Instantiate class + * @param $file string + **/ + function __construct($file) { + $fw=Base::instance(); + if (!is_dir($dir=$fw->get('LOGS'))) + mkdir($dir,Base::MODE,TRUE); + $this->file=$dir.$file; + } + +} diff --git a/lib/f3/magic.php b/lib/f3/magic.php new file mode 100755 index 0000000..d17d180 --- /dev/null +++ b/lib/f3/magic.php @@ -0,0 +1,140 @@ +isprivate(); + unset($ref); + return $out; + } + return FALSE; + } + + /** + * Convenience method for checking property value + * @return mixed + * @param $key string + **/ + function offsetexists($key) { + return $this->visible($key)?isset($this->$key):$this->exists($key); + } + + /** + * Alias for offsetexists() + * @return mixed + * @param $key string + **/ + function __isset($key) { + return $this->offsetexists($key); + } + + /** + * Convenience method for assigning property value + * @return mixed + * @param $key string + * @param $val scalar + **/ + function offsetset($key,$val) { + return $this->visible($key)?($this->key=$val):$this->set($key,$val); + } + + /** + * Alias for offsetset() + * @return mixed + * @param $key string + * @param $val scalar + **/ + function __set($key,$val) { + return $this->offsetset($key,$val); + } + + /** + * Convenience method for retrieving property value + * @return mixed + * @param $key string + **/ + function offsetget($key) { + return $this->visible($key)?$this->$key:$this->get($key); + } + + /** + * Alias for offsetget() + * @return mixed + * @param $key string + **/ + function __get($key) { + return $this->offsetget($key); + } + + /** + * Convenience method for checking property value + * @return NULL + * @param $key string + **/ + function offsetunset($key) { + if ($this->visible($key)) + unset($this->$key); + else + $this->clear($key); + } + + /** + * Alias for offsetunset() + * @return NULL + * @param $key string + **/ + function __unset($key) { + $this->offsetunset($key); + } + +} diff --git a/lib/f3/markdown.php b/lib/f3/markdown.php new file mode 100755 index 0000000..bc6cfd4 --- /dev/null +++ b/lib/f3/markdown.php @@ -0,0 +1,570 @@ +\h?(.*?(?:\n+|$))/','\1',$str); + return strlen($str)? + ('
'.$this->build($str).'
'."\n\n"):''; + } + + /** + * Process whitespace-prefixed code block + * @return string + * @param $str string + **/ + protected function _pre($str) { + $str=preg_replace('/(?<=^|\n)(?: {4}|\t)(.+?(?:\n+|$))/','\1', + $this->esc($str)); + return strlen($str)? + ('
'.
+				$this->esc($this->snip($str)).
+			'
'."\n\n"): + ''; + } + + /** + * Process fenced code block + * @return string + * @param $hint string + * @param $str string + **/ + protected function _fence($hint,$str) { + $str=$this->snip($str); + $fw=Base::instance(); + if ($fw->get('HIGHLIGHT')) { + switch (strtolower($hint)) { + case 'php': + $str=$fw->highlight($str); + break; + case 'apache': + preg_match_all('/(?<=^|\n)(\h*)'. + '(?:(<\/?)(\w+)((?:\h+[^>]+)*)(>)|'. + '(?:(\w+)(\h.+?)))(\h*(?:\n+|$))/', + $str,$matches,PREG_SET_ORDER); + $out=''; + foreach ($matches as $match) + $out.=$match[1]. + ($match[3]? + (''. + $this->esc($match[2]).$match[3]. + ''. + ($match[4]? + (''. + $this->esc($match[4]). + ''): + ''). + ''. + $this->esc($match[5]). + ''): + (''. + $match[6]. + ''. + ''. + $this->esc($match[7]). + '')). + $match[8]; + $str=''.$out.''; + break; + case 'html': + preg_match_all( + '/(?:(?:<(\/?)(\w+)'. + '((?:\h+(?:\w+\h*=\h*)?".+?"|[^>]+)*|'. + '\h+.+?)(\h*\/?)>)|(.+?))/s', + $str,$matches,PREG_SET_ORDER + ); + $out=''; + foreach ($matches as $match) { + if ($match[2]) { + $out.='<'. + $match[1].$match[2].''; + if ($match[3]) { + preg_match_all( + '/(?:\h+(?:(?:(\w+)\h*=\h*)?'. + '(".+?")|(.+)))/', + $match[3],$parts,PREG_SET_ORDER + ); + foreach ($parts as $part) + $out.=' '. + (empty($part[3])? + ((empty($part[1])? + '': + (''. + $part[1].'=')). + ''. + $part[2].''): + (''. + $part[3].'')); + } + $out.=''. + $match[4].'>'; + } + else + $out.=$this->esc($match[5]); + } + $str=''.$out.''; + break; + case 'ini': + preg_match_all( + '/(?<=^|\n)(?:'. + '(;[^\n]*)|(?:<\?php.+?\?>?)|'. + '(?:\[(.+?)\])|'. + '(.+?)\h*=\h*'. + '((?:\\\\\h*\r?\n|.+?)*)'. + ')((?:\r?\n)+|$)/', + $str,$matches,PREG_SET_ORDER + ); + $out=''; + foreach ($matches as $match) { + if ($match[1]) + $out.=''.$match[1]. + ''; + elseif ($match[2]) + $out.='['.$match[2].']'. + ''; + elseif ($match[3]) + $out.=''.$match[3]. + '='. + ($match[4]? + (''. + $match[4].''):''); + else + $out.=$match[0]; + if (isset($match[5])) + $out.=$match[5]; + } + $str=''.$out.''; + break; + default: + $str=''.$this->esc($str).''; + break; + } + } + else + $str=''.$this->esc($str).''; + return '
'.$str.'
'."\n\n"; + } + + /** + * Process horizontal rule + * @return string + **/ + protected function _hr() { + return '
'."\n\n"; + } + + /** + * Process atx-style heading + * @return string + * @param $type string + * @param $str string + **/ + protected function _atx($type,$str) { + $level=strlen($type); + return ''. + $this->scan($str).''."\n\n"; + } + + /** + * Process setext-style heading + * @return string + * @param $str string + * @param $type string + **/ + protected function _setext($str,$type) { + $level=strpos('=-',$type)+1; + return ''. + $this->scan($str).''."\n\n"; + } + + /** + * Process ordered/unordered list + * @return string + * @param $str string + **/ + protected function _li($str) { + // Initialize list parser + $len=strlen($str); + $ptr=0; + $dst=''; + $first=TRUE; + $tight=TRUE; + $type='ul'; + // Main loop + while ($ptr<$len) { + if (preg_match('/^\h*[*-](?:\h?[*-]){2,}(?:\n+|$)/', + substr($str,$ptr),$match)) { + $ptr+=strlen($match[0]); + // Embedded horizontal rule + return (strlen($dst)? + ('<'.$type.'>'."\n".$dst.''."\n\n"):''). + '
'."\n\n".$this->build(substr($str,$ptr)); + } + elseif (preg_match('/(?<=^|\n)([*+-]|\d+\.)\h'. + '(.+?(?:\n+|$))((?:(?: {4}|\t)+.+?(?:\n+|$))*)/s', + substr($str,$ptr),$match)) { + $match[3]=preg_replace('/(?<=^|\n)(?: {4}|\t)/','',$match[3]); + $found=FALSE; + foreach (array_slice($this->blocks,0,-1) as $regex) + if (preg_match($regex,$match[3])) { + $found=TRUE; + break; + } + // List + if ($first) { + // First pass + if (is_numeric($match[1])) + $type='ol'; + if (preg_match('/\n{2,}$/',$match[2]. + ($found?'':$match[3]))) + // Loose structure; Use paragraphs + $tight=FALSE; + $first=FALSE; + } + // Strip leading whitespaces + $ptr+=strlen($match[0]); + $tmp=$this->snip($match[2].$match[3]); + if ($tight) { + if ($found) + $tmp=$match[2].$this->build($this->snip($match[3])); + } + else + $tmp=$this->build($tmp); + $dst.='
  • '.$this->scan(trim($tmp)).'
  • '."\n"; + } + } + return strlen($dst)? + ('<'.$type.'>'."\n".$dst.''."\n\n"):''; + } + + /** + * Ignore raw HTML + * @return string + * @param $str string + **/ + protected function _raw($str) { + return $str; + } + + /** + * Process paragraph + * @return string + * @param $str string + **/ + protected function _p($str) { + $str=trim($str); + if (strlen($str)) { + if (preg_match('/^(.+?\n)([>#].+)$/s',$str,$parts)) + return $this->_p($parts[1]).$this->build($parts[2]); + $self=$this; + $str=preg_replace_callback( + '/([^<>\[]+)?(<[\?%].+?[\?%]>|<.+?>|\[.+?\]\s*\(.+?\))|'. + '(.+)/s', + function($expr) use($self) { + $tmp=''; + if (isset($expr[4])) + $tmp.=$self->esc($expr[4]); + else { + if (isset($expr[1])) + $tmp.=$self->esc($expr[1]); + $tmp.=$expr[2]; + if (isset($expr[3])) + $tmp.=$self->esc($expr[3]); + } + return $tmp; + }, + $str + ); + return '

    '.$this->scan($str).'

    '."\n\n"; + } + return ''; + } + + /** + * Process strong/em/strikethrough spans + * @return string + * @param $str string + **/ + protected function _text($str) { + $tmp=''; + while ($str!=$tmp) + $str=preg_replace_callback( + '/(?'.$expr[2].'
    '; + case 2: + return ''.$expr[2].''; + case 3: + return ''.$expr[2].''; + } + }, + preg_replace( + '/(?\1', + $tmp=$str + ) + ); + return $str; + } + + /** + * Process image span + * @return string + * @param $str string + **/ + protected function _img($str) { + $self=$this; + return preg_replace_callback( + '/!(?:\[(.+?)\])?\h*\(?(?:\h*"(.*?)"\h*)?\)/', + function($expr) use($self) { + return ''.$self->esc($expr[1]).''; + }, + $str + ); + } + + /** + * Process anchor span + * @return string + * @param $str string + **/ + protected function _a($str) { + $self=$this; + return preg_replace_callback( + '/(??(?:\h*"(.*?)"\h*)?\)/', + function($expr) use($self) { + return '
    '.$self->scan($expr[1]).''; + }, + $str + ); + } + + /** + * Auto-convert links + * @return string + * @param $str string + **/ + protected function _auto($str) { + $self=$this; + return preg_replace_callback( + '/`.*?<(.+?)>.*?`|<(.+?)>/', + function($expr) use($self) { + if (empty($expr[1]) && parse_url($expr[2],PHP_URL_SCHEME)) { + $expr[2]=$self->esc($expr[2]); + return ''.$expr[2].''; + } + return $expr[0]; + }, + $str + ); + } + + /** + * Process code span + * @return string + * @param $str string + **/ + protected function _code($str) { + $self=$this; + return preg_replace_callback( + '/`` (.+?) ``|(?'. + $self->esc(empty($expr[1])?$expr[2]:$expr[1]).''; + }, + $str + ); + } + + /** + * Convert characters to HTML entities + * @return string + * @param $str string + **/ + function esc($str) { + if (!$this->special) + $this->special=array( + '...'=>'…', + '(tm)'=>'™', + '(r)'=>'®', + '(c)'=>'©' + ); + foreach ($this->special as $key=>$val) + $str=preg_replace('/'.preg_quote($key,'/').'/i',$val,$str); + return htmlspecialchars($str,ENT_COMPAT, + Base::instance()->get('ENCODING'),FALSE); + } + + /** + * Reduce multiple line feeds + * @return string + * @param $str string + **/ + protected function snip($str) { + return preg_replace('/(?:(?<=\n)\n+)|\n+$/',"\n",$str); + } + + /** + * Scan line for convertible spans + * @return string + * @param $str string + **/ + function scan($str) { + $inline=array('img','a','text','auto','code'); + foreach ($inline as $func) + $str=$this->{'_'.$func}($str); + return $str; + } + + /** + * Assemble blocks + * @return string + * @param $str string + **/ + protected function build($str) { + if (!$this->blocks) { + // Regexes for capturing entire blocks + $this->blocks=array( + 'blockquote'=>'/^(?:\h?>\h?.*?(?:\n+|$))+/', + 'pre'=>'/^(?:(?: {4}|\t).+?(?:\n+|$))+/', + 'fence'=>'/^`{3}\h*(\w+)?.*?[^\n]*\n+(.+?)`{3}[^\n]*'. + '(?:\n+|$)/s', + 'hr'=>'/^\h*[*_-](?:\h?[\*_-]){2,}\h*(?:\n+|$)/', + 'atx'=>'/^\h*(#{1,6})\h?(.+?)\h*(?:#.*)?(?:\n+|$)/', + 'setext'=>'/^\h*(.+?)\h*\n([=-])+\h*(?:\n+|$)/', + 'li'=>'/^(?:(?:[*+-]|\d+\.)\h.+?(?:\n+|$)'. + '(?:(?: {4}|\t)+.+?(?:\n+|$))*)+/s', + 'raw'=>'/^((?:|'. + '<(address|article|aside|audio|blockquote|canvas|dd|'. + 'div|dl|fieldset|figcaption|figure|footer|form|h\d|'. + 'header|hgroup|hr|noscript|object|ol|output|p|pre|'. + 'section|table|tfoot|ul|video).*?'. + '(?:\/>|>(?:(?>[^><]+)|(?R))*<\/\2>))'. + '\h*(?:\n{2,}|\n*$)|<[\?%].+?[\?%]>\h*(?:\n?$|\n*))/s', + 'p'=>'/^(.+?(?:\n{2,}|\n*$))/s' + ); + } + $self=$this; + // Treat lines with nothing but whitespaces as empty lines + $str=preg_replace('/\n\h+(?=\n)/',"\n",$str); + // Initialize block parser + $len=strlen($str); + $ptr=0; + $dst=''; + // Main loop + while ($ptr<$len) { + if (preg_match('/^ {0,3}\[([^\[\]]+)\]:\s*?\s*'. + '(?:"([^\n]*)")?(?:\n+|$)/s',substr($str,$ptr),$match)) { + // Reference-style link; Backtrack + $ptr+=strlen($match[0]); + $tmp=''; + // Catch line breaks in title attribute + $ref=preg_replace('/\h/','\s',preg_quote($match[1],'/')); + while ($dst!=$tmp) { + $dst=preg_replace_callback( + '/(?esc($match[2]).'"'. + (empty($match[3])? + '': + (' title="'. + $self->esc($match[3]).'"')).'>'. + // Link + $self->scan( + empty($expr[3])? + (empty($expr[1])? + $expr[4]: + $expr[1]): + $expr[3] + ).''): + // Image + (''.
+										$self->esc($expr[3]).''); + }, + $tmp=$dst + ); + } + } + else + foreach ($this->blocks as $func=>$regex) + if (preg_match($regex,substr($str,$ptr),$match)) { + $ptr+=strlen($match[0]); + $dst.=call_user_func_array( + array($this,'_'.$func), + count($match)>1?array_slice($match,1):$match + ); + break; + } + } + return $dst; + } + + /** + * Render HTML equivalent of markdown + * @return string + * @param $txt string + **/ + function convert($txt) { + $txt=preg_replace_callback( + '/(.+?<\/code>|'. + '<[^>\n]+>|\([^\n\)]+\)|"[^"\n]+")|'. + '\\\\(.)/s', + function($expr) { + // Process escaped characters + return empty($expr[1])?$expr[2]:$expr[1]; + }, + $this->build(preg_replace('/\r\n|\r/',"\n",$txt)) + ); + return $this->snip($txt); + } + +} diff --git a/lib/f3/matrix.php b/lib/f3/matrix.php new file mode 100755 index 0000000..70ae3de --- /dev/null +++ b/lib/f3/matrix.php @@ -0,0 +1,101 @@ +$cols) + foreach ($cols as $keyy=>$valy) + $out[$keyy][$keyx]=$valy; + $var=$out; + } + + /** + * Sort a multi-dimensional array variable on a specified column + * @return bool + * @param $var array + * @param $col mixed + * @param $order int + **/ + function sort(array &$var,$col,$order=SORT_ASC) { + uasort( + $var, + function($val1,$val2) use($col,$order) { + list($v1,$v2)=array($val1[$col],$val2[$col]); + $out=is_numeric($v1) && is_numeric($v2)? + Base::instance()->sign($v1-$v2):strcmp($v1,$v2); + if ($order==SORT_DESC) + $out=-$out; + return $out; + } + ); + $var=array_values($var); + } + + /** + * Change the key of a two-dimensional array element + * @return NULL + * @param $var array + * @param $old string + * @param $new string + **/ + function changekey(array &$var,$old,$new) { + $keys=array_keys($var); + $vals=array_values($var); + $keys[array_search($old,$keys)]=$new; + $var=array_combine($keys,$vals); + } + + /** + * Return month calendar of specified date, with optional setting for + * first day of week (0 for Sunday) + * @return array + * @param $date string + * @param $first int + **/ + function calendar($date='now',$first=0) { + $parts=getdate(strtotime($date)); + $days=cal_days_in_month(CAL_GREGORIAN,$parts['mon'],$parts['year']); + $ref=date('w',strtotime(date('Y-m',$parts[0]).'-01'))+(7-$first)%7; + $out=array(); + for ($i=0;$i<$days;$i++) + $out[floor(($ref+$i)/7)][($ref+$i)%7]=$i+1; + return $out; + } + +} diff --git a/lib/f3/pagination.php b/lib/f3/pagination.php new file mode 100644 index 0000000..6e7eea4 --- /dev/null +++ b/lib/f3/pagination.php @@ -0,0 +1,257 @@ + + + @version 1.4.1 + **/ + +class Pagination { + + private $items_count; + private $items_per_page; + private $range = 2; + private $current_page; + private $template = 'pagebrowser.html'; + private $routeKey; + private $routeKeyPrefix; + private $linkPath; + private $fw; + + const + TEXT_MissingItemsAttr='You need to specify items attribute for a pagination.'; + /** + * create new pagination + * @param $items array|integer max items or array to count + * @param $limit int max items per page + * @param $routeKey string the key for pagination in your routing + */ + public function __construct( $items, $limit = 10, $routeKey = 'page' ) { + $this->fw = \Base::instance(); + $this->items_count = is_array($items)?count($items):$items; + $this->routeKey = $routeKey; + $this->setLimit($limit); + } + + /** + * set maximum items shown on one page + * @param $limit int + */ + public function setLimit($limit) { + if(is_numeric($limit)) + $this->items_per_page = $limit; + $this->setCurrent( self::findCurrentPage($this->routeKey)); + } + + /** + * set token name used in your route pattern for pagination + * @param string $key + */ + public function setRouteKey($key) { + $this->routeKey = $key; + } + + /** + * set a prefix that is added to your page links + * @param string $prefix + */ + public function setRouteKeyPrefix($prefix) { + $this->routeKeyPrefix = $prefix; + } + + /** + * set path for the template file + * @param $template string + */ + public function setTemplate($template) { + $this->template = $template; + } + + /** + * set the range of pages, that are displayed prev and next to current page + * @param $range int + */ + public function setRange($range) { + if(is_numeric($range)) $this->range = $range; + } + + /** + * set the current page number + * @param $current int + */ + public function setCurrent($current) { + if(!$this->routeKeyPrefix) + $current = str_replace($this->routeKeyPrefix,'',$current); + if(!is_numeric($current)) return; + if($current <= $this->getMax()) $this->current_page = $current; + else $this->current_page = $this->getMax(); + } + + /** + * set path to current routing for link building + * @param $linkPath + */ + public function setLinkPath($linkPath) { + $this->linkPath = (substr($linkPath,0,1) != '/') ? '/'.$linkPath:$linkPath; + if(substr($this->linkPath,-1) != '/') $this->linkPath .= '/'; + } + + /** + * extract the current page number from the route parameter token + * @param string $key + * @return int|mixed + */ + static public function findCurrentPage($key='page') { + $f3 = \Base::instance(); + return $f3->exists('PARAMS.'.$key) ? + preg_replace("/[^0-9]/", "", $f3->get('PARAMS.'.$key)) : 1; + } + + /** + * returns the current page number + * @return int + */ + public function getCurrent() { + return $this->current_page; + } + + /** + * returns the maximum count of items to display in pages + * @return int + */ + public function getItemCount() { + return $this->items_count; + } + + /** + * get maximum pages needed to display all items + * @return int + */ + public function getMax() { + return ceil($this->items_count / $this->items_per_page); + } + + + /** + * get next page number + * @return int|bool + */ + public function getNext() { + $nextPage = $this->current_page + 1; + if( $nextPage > $this->getMax() ) return false; + return $nextPage; + } + + /** + * get previous page number + * @return int|bool + */ + public function getPrev() { + $prevPage = $this->current_page - 1; + if( $prevPage < 1 ) return false; + return $prevPage; + } + + /** + * return last page number, if current page is not in range + * @return bool|int + */ + public function getLast() { + return ($this->current_page < $this->getMax() - $this->range ) ? $this->getMax() : false; + } + + /** + * return first page number, if current page is not in range + * @return bool|int + */ + public function getFirst() { + return ($this->current_page > 3) ? 1 : false; + } + + /** + * return all page numbers within the given range + * @param $range int + * @return array page numbers in range + */ + public function getInRange($range = null) { + if(is_null($range)) + $range = $this->range; + $current_range = array( ($this->current_page-$range < 1 ? 1 : $this->current_page-$range), + ($this->current_page+$range > $this->getMax() ? $this->getMax() : $this->current_page+$range)); + $rangeIDs = array(); + for($x = $current_range[0]; $x <= $current_range[1]; ++$x) { + $rangeIDs[] = $x; + } + return $rangeIDs; + } + + /** + * returns the number of items left behind for current page + * @return int + */ + public function getItemOffset() { + return ($this->current_page - 1) * $this->items_per_page; + } + + /** + * generates the pagination output + * @return string + */ + public function serve() { + if(is_null($this->linkPath)) { + $route = $this->fw->get('PARAMS.0'); + if($this->fw->exists('PARAMS.'.$this->routeKey)) + $route = preg_replace("/".$this->fw->get('PARAMS.'.$this->routeKey)."$/",'',$route); + elseif(substr($route,-1) != '/') + $route.= '/'; + } else + $route = $this->linkPath; + $this->fw->set('pg.route',$route); + $this->fw->set('pg.prefix',$this->routeKeyPrefix); + $this->fw->set('pg.currentPage',$this->current_page); + $this->fw->set('pg.nextPage',$this->getNext()); + $this->fw->set('pg.prevPage',$this->getPrev()); + $this->fw->set('pg.firstPage',$this->getFirst()); + $this->fw->set('pg.lastPage',$this->getLast()); + $this->fw->set('pg.rangePages',$this->getInRange()); + $output = \View::instance()->render($this->template); + $this->fw->clear('pg'); + return $output; + } + + /** + * magic render function for custom tags + * @static + * @param $args + * @return string + */ + static public function renderTag($args){ + $attr = $args['@attrib']; + $tmp = Template::instance(); + foreach($attr as &$att) + $att = $tmp->token($att); + $pn_code = '$pn = new Pagination('.$attr['items'].');'; + if(array_key_exists('limit',$attr)) + $pn_code .= '$pn->setLimit('.$attr['limit'].');'; + if(array_key_exists('range',$attr)) + $pn_code .= '$pn->setRange('.$attr['range'].');'; + if(array_key_exists('src',$attr)) + $pn_code .= '$pn->setTemplate("'.$attr['src'].'");'; + if(array_key_exists('token',$attr)) + $pn_code .= '$pn->setRouteKey("'.$attr['token'].'");'; + if(array_key_exists('link-path',$attr)) + $pn_code .= '$pn->setLinkPath("'.$attr['link-path'].'");'; + if(array_key_exists('token-prefix',$attr)) + $pn_code .= '$pn->setRouteKeyPrefix("'.$attr['token-prefix'].'");'; + $pn_code .= 'echo $pn->serve();'; + return ''; + } +} \ No newline at end of file diff --git a/lib/f3/session.php b/lib/f3/session.php new file mode 100755 index 0000000..5320ea8 --- /dev/null +++ b/lib/f3/session.php @@ -0,0 +1,184 @@ +exists($id.'.@',$data)?$data['data']:FALSE; + } + + /** + * Write session data + * @return TRUE + * @param $id string + * @param $data string + **/ + function write($id,$data) { + $fw=Base::instance(); + $sent=headers_sent(); + $headers=$fw->get('HEADERS'); + $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash(mt_rand()); + $jar=$fw->get('JAR'); + Cache::instance()->set($id.'.@', + array( + 'data'=>$data, + 'csrf'=>$sent?$this->csrf():$csrf, + 'ip'=>$fw->get('IP'), + 'agent'=>isset($headers['User-Agent'])? + $headers['User-Agent']:'', + 'stamp'=>time() + ), + $jar['expire']?($jar['expire']-time()):0 + ); + if (!$sent) { + if (isset($_COOKIE['_'])) + setcookie('_','',strtotime('-1 year')); + call_user_func_array('setcookie',array('_',$csrf)+$jar); + } + return TRUE; + } + + /** + * Destroy session + * @return TRUE + * @param $id string + **/ + function destroy($id) { + Cache::instance()->clear($id.'.@'); + setcookie(session_name(),'',strtotime('-1 year')); + unset($_COOKIE[session_name()]); + header_remove('Set-Cookie'); + return TRUE; + } + + /** + * Garbage collector + * @return TRUE + * @param $max int + **/ + function cleanup($max) { + Cache::instance()->reset('.@',$max); + return TRUE; + } + + /** + * Return anti-CSRF tokan associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function csrf($id=NULL) { + return Cache::instance()->exists(($id?:session_id()).'.@',$data)? + $data['csrf']:FALSE; + } + + /** + * Return IP address associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function ip($id=NULL) { + return Cache::instance()->exists(($id?:session_id()).'.@',$data)? + $data['ip']:FALSE; + } + + /** + * Return Unix timestamp associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function stamp($id=NULL) { + return Cache::instance()->exists(($id?:session_id()).'.@',$data)? + $data['stamp']:FALSE; + } + + /** + * Return HTTP user agent associated with specified session ID + * @return string|FALSE + * @param $id string + **/ + function agent($id=NULL) { + return Cache::instance()->exists(($id?:session_id()).'.@',$data)? + $data['agent']:FALSE; + } + + /** + * Instantiate class + * @return object + **/ + function __construct() { + session_set_save_handler( + array($this,'open'), + array($this,'close'), + array($this,'read'), + array($this,'write'), + array($this,'destroy'), + array($this,'cleanup') + ); + register_shutdown_function('session_commit'); + @session_start(); + $fw=\Base::instance(); + $headers=$fw->get('HEADERS'); + if (($csrf=$this->csrf()) && + ((!isset($_COOKIE['_']) || $_COOKIE['_']!=$csrf) || + ($ip=$this->ip()) && $ip!=$fw->get('IP') || + ($agent=$this->agent()) && !isset($headers['User-Agent']) || + $agent!=$headers['User-Agent'])) { + $jar=$fw->get('JAR'); + $jar['expire']=strtotime('-1 year'); + call_user_func_array('setcookie', + array_merge(array('_',''),$jar)); + unset($_COOKIE['_']); + session_destroy(); + \Base::instance()->error(403); + } + $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash(mt_rand()); + $jar=$fw->get('JAR'); + if (Cache::instance()->exists($id=session_id().'.@',$data)) { + $data['csrf']=$csrf; + Cache::instance()->set($id.'.@', + $data, + $jar['expire']?($jar['expire']-time()):0 + ); + call_user_func_array('setcookie',array('_',$csrf)+$jar); + } + } + +} diff --git a/lib/f3/smtp.php b/lib/f3/smtp.php new file mode 100755 index 0000000..2337745 --- /dev/null +++ b/lib/f3/smtp.php @@ -0,0 +1,268 @@ +fixheader($key); + return isset($this->headers[$key]); + } + + /** + * Bind value to e-mail header + * @return string + * @param $key string + * @param $val string + **/ + function set($key,$val) { + $key=$this->fixheader($key); + return $this->headers[$key]=$val; + } + + /** + * Return value of e-mail header + * @return string|NULL + * @param $key string + **/ + function get($key) { + $key=$this->fixheader($key); + return isset($this->headers[$key])?$this->headers[$key]:NULL; + } + + /** + * Remove header + * @return NULL + * @param $key string + **/ + function clear($key) { + $key=$this->fixheader($key); + unset($this->headers[$key]); + } + + /** + * Return client-server conversation history + * @return string + **/ + function log() { + return str_replace("\n",PHP_EOL,$this->log); + } + + /** + * Send SMTP command and record server response + * @return NULL + * @param $cmd string + * @param $log bool + **/ + protected function dialog($cmd=NULL,$log=TRUE) { + $socket=&$this->socket; + if (!is_null($cmd)) + fputs($socket,$cmd."\r\n"); + $reply=''; + while (!feof($socket) && ($info=stream_get_meta_data($socket)) && + !$info['timed_out'] && $str=fgets($socket,4096)) { + $reply.=$str; + if (preg_match('/(?:^|\n)\d{3} .+?\r\n/s',$reply)) + break; + } + if ($log) { + $this->log.=$cmd."\n"; + $this->log.=str_replace("\r",'',$reply); + } + } + + /** + * Add e-mail attachment + * @return NULL + * @param $file + **/ + function attach($file) { + if (!is_file($file)) + user_error(sprintf(self::E_Attach,$file)); + $this->attachments[]=$file; + } + + /** + * Transmit message + * @return bool + * @param $message string + * @param $log bool + **/ + function send($message,$log=TRUE) { + if ($this->scheme=='ssl' && !extension_loaded('openssl')) + return FALSE; + $fw=Base::instance(); + // Connect to the server + $socket=&$this->socket; + $socket=@fsockopen($this->host,$this->port); + if (!$socket) + return FALSE; + stream_set_blocking($socket,TRUE); + // Get server's initial response + $this->dialog(NULL,FALSE); + // Announce presence + $this->dialog('EHLO '.$fw->get('HOST')); + if (strtolower($this->scheme)=='tls') { + $this->dialog('STARTTLS'); + stream_socket_enable_crypto( + $socket,TRUE,STREAM_CRYPTO_METHOD_TLS_CLIENT); + $this->dialog('EHLO '.$fw->get('HOST')); + } + if ($this->user && $this->pw) { + // Authenticate + $this->dialog('AUTH LOGIN'); + $this->dialog(base64_encode($this->user)); + $this->dialog(base64_encode($this->pw)); + } + // Required headers + $reqd=array('From','To','Subject'); + // Retrieve headers + $headers=$this->headers; + foreach ($reqd as $id) + if (empty($headers[$id])) + user_error(sprintf(self::E_Header,$id)); + // Message should not be blank + if (!$message) + user_error(self::E_Blank); + $eol="\r\n"; + $str=''; + // Stringify headers + foreach ($headers as $key=>$val) + if (!in_array($key,$reqd)) + $str.=$key.': '.$val.$eol; + // Start message dialog + $this->dialog('MAIL FROM: '.strstr($headers['From'],'<')); + foreach ($fw->split($headers['To']. + (isset($headers['Cc'])?(';'.$headers['Cc']):''). + (isset($headers['Bcc'])?(';'.$headers['Bcc']):'')) as $dst) + $this->dialog('RCPT TO: '.strstr($dst,'<')); + $this->dialog('DATA'); + if ($this->attachments) { + // Replace Content-Type + $hash=uniqid(NULL,TRUE); + $type=$headers['Content-Type']; + $headers['Content-Type']='multipart/mixed; '. + 'boundary="'.$hash.'"'; + // Send mail headers + $out=''; + foreach ($headers as $key=>$val) + if ($key!='Bcc') + $out.=$key.': '.$val.$eol; + $out.=$eol; + $out.='This is a multi-part message in MIME format'.$eol; + $out.=$eol; + $out.='--'.$hash.$eol; + $out.='Content-Type: '.$type.$eol; + $out.=$eol; + $out.=$message.$eol; + foreach ($this->attachments as $attachment) { + $out.='--'.$hash.$eol; + $out.='Content-Type: application/octet-stream'.$eol; + $out.='Content-Transfer-Encoding: base64'.$eol; + $out.='Content-Disposition: attachment; '. + 'filename="'.basename($attachment).'"'.$eol; + $out.=$eol; + $out.=chunk_split( + base64_encode(file_get_contents($attachment))).$eol; + } + $out.=$eol; + $out.='--'.$hash.'--'.$eol; + $out.='.'; + $this->dialog($out); + } + else { + // Send mail headers + $out=''; + foreach ($headers as $key=>$val) + if ($key!='Bcc') + $out.=$key.': '.$val.$eol; + $out.=$eol; + $out.=$message.$eol; + $out.='.'; + // Send message + $this->dialog($out); + } + $this->dialog('QUIT'); + if ($socket) + fclose($socket); + return TRUE; + } + + /** + * Instantiate class + * @param $host string + * @param $port int + * @param $scheme string + * @param $user string + * @param $pw string + **/ + function __construct($host,$port,$scheme,$user,$pw) { + $this->headers=array( + 'MIME-Version'=>'1.0', + 'Content-Type'=>'text/plain; '. + 'charset='.Base::instance()->get('ENCODING'), + 'Content-Transfer-Encoding'=>'8bit' + ); + $this->host=$host; + if (strtolower($this->scheme=strtolower($scheme))=='ssl') + $this->host='ssl://'.$host; + $this->port=$port; + $this->user=$user; + $this->pw=$pw; + } + +} diff --git a/lib/f3/template.php b/lib/f3/template.php new file mode 100755 index 0000000..59ccb97 --- /dev/null +++ b/lib/f3/template.php @@ -0,0 +1,335 @@ +$val) + $out.='$'.$key.'='. + (preg_match('/\{\{(.+?)\}\}/',$val)? + $this->token($val): + Base::instance()->stringify($val)).'; '; + return ''; + } + + /** + * Template -include- tag handler + * @return string + * @param $node array + **/ + protected function _include(array $node) { + $attrib=$node['@attrib']; + return + 'token($attrib['if']).') '):''). + ('echo $this->render('. + (preg_match('/\{\{(.+?)\}\}/',$attrib['href'])? + $this->token($attrib['href']): + Base::instance()->stringify($attrib['href'])).','. + '$this->mime,get_defined_vars()); ?>'); + } + + /** + * Template -exclude- tag handler + * @return string + **/ + protected function _exclude() { + return ''; + } + + /** + * Template -ignore- tag handler + * @return string + * @param $node array + **/ + protected function _ignore(array $node) { + return $node[0]; + } + + /** + * Template -loop- tag handler + * @return string + * @param $node array + **/ + protected function _loop(array $node) { + $attrib=$node['@attrib']; + unset($node['@attrib']); + return + 'token($attrib['from']).';'. + $this->token($attrib['to']).';'. + $this->token($attrib['step']).'): ?>'. + $this->build($node). + ''; + } + + /** + * Template -repeat- tag handler + * @return string + * @param $node array + **/ + protected function _repeat(array $node) { + $attrib=$node['@attrib']; + unset($node['@attrib']); + return + 'token($attrib['counter'])).'=0; '):''). + 'foreach (('. + $this->token($attrib['group']).'?:array()) as '. + (isset($attrib['key'])? + ($this->token($attrib['key']).'=>'):''). + $this->token($attrib['value']).'):'. + (isset($ctr)?(' '.$ctr.'++;'):'').' ?>'. + $this->build($node). + ''; + } + + /** + * Template -check- tag handler + * @return string + * @param $node array + **/ + protected function _check(array $node) { + $attrib=$node['@attrib']; + unset($node['@attrib']); + // Grab and blocks + foreach ($node as $pos=>$block) + if (isset($block['true'])) + $true=array($pos,$block); + elseif (isset($block['false'])) + $false=array($pos,$block); + if (isset($true,$false) && $true[0]>$false[0]) + // Reverse and blocks + list($node[$true[0]],$node[$false[0]])=array($false[1],$true[1]); + return + 'token($attrib['if']).'): ?>'. + $this->build($node). + ''; + } + + /** + * Template -true- tag handler + * @return string + * @param $node array + **/ + protected function _true(array $node) { + return $this->build($node); + } + + /** + * Template -false- tag handler + * @return string + * @param $node array + **/ + protected function _false(array $node) { + return ''.$this->build($node); + } + + /** + * Template -switch- tag handler + * @return string + * @param $node array + **/ + protected function _switch(array $node) { + $attrib=$node['@attrib']; + unset($node['@attrib']); + foreach ($node as $pos=>$block) + if (is_string($block) && !preg_replace('/\s+/','',$block)) + unset($node[$pos]); + return + 'token($attrib['expr']).'): ?>'. + $this->build($node). + ''; + } + + /** + * Template -case- tag handler + * @return string + * @param $node array + **/ + protected function _case(array $node) { + $attrib=$node['@attrib']; + unset($node['@attrib']); + return + 'token($attrib['value']): + Base::instance()->stringify($attrib['value'])).': ?>'. + $this->build($node). + 'token($attrib['break']).') ':''). + 'break; ?>'; + } + + /** + * Template -default- tag handler + * @return string + * @param $node array + **/ + protected function _default(array $node) { + return + ''. + $this->build($node). + ''; + } + + /** + * Assemble markup + * @return string + * @param $node array|string + **/ + protected function build($node) { + if (is_string($node)) + return parent::build($node); + $out=''; + foreach ($node as $key=>$val) + $out.=is_int($key)?$this->build($val):$this->{'_'.$key}($val); + return $out; + } + + /** + * Extend template with custom tag + * @return NULL + * @param $tag string + * @param $func callback + **/ + function extend($tag,$func) { + $this->tags.='|'.$tag; + $this->custom['_'.$tag]=$func; + } + + /** + * Call custom tag handler + * @return string|FALSE + * @param $func callback + * @param $args array + **/ + function __call($func,array $args) { + if ($func[0]=='_') + return call_user_func_array($this->custom[$func],$args); + if (method_exists($this,$func)) + return call_user_func_array(array($this,$func),$args); + user_error(sprintf(self::E_Method,$func)); + } + + /** + * Parse string for template directives and tokens + * @return string|array + * @param $text string + **/ + function parse($text) { + // Build tree structure + for ($ptr=0,$len=strlen($text),$tree=array(),$node=&$tree, + $stack=array(),$depth=0,$tmp='';$ptr<$len;) + if (preg_match('/^<(\/?)(?:F3:)?'. + '('.$this->tags.')\b((?:\h+[\w-]+'. + '(?:\h*=\h*(?:"(?:.+?)"|\'(?:.+?)\'))?|'. + '\h*\{\{.+?\}\})*)\h*(\/?)>/is', + substr($text,$ptr),$match)) { + if (strlen($tmp)) + $node[]=$tmp; + // Element node + if ($match[1]) { + // Find matching start tag + $save=$depth; + $found=FALSE; + while ($depth>0) { + $depth--; + foreach ($stack[$depth] as $item) + if (is_array($item) && isset($item[$match[2]])) { + // Start tag found + $found=TRUE; + break 2; + } + } + if (!$found) + // Unbalanced tag + $depth=$save; + $node=&$stack[$depth]; + } + else { + // Start tag + $stack[$depth]=&$node; + $node=&$node[][$match[2]]; + if ($match[3]) { + // Process attributes + preg_match_all( + '/(?:\b([\w-]+)\h*'. + '(?:=\h*(?:"(.+?)"|\'(.+?)\'))?|'. + '(\{\{.+?\}\}))/s', + $match[3],$attr,PREG_SET_ORDER); + foreach ($attr as $kv) + if (isset($kv[4])) + $node['@attrib'][]=$kv[4]; + else + $node['@attrib'][$kv[1]]= + (empty($kv[2])? + (empty($kv[3])?NULL:$kv[3]):$kv[2]); + } + if ($match[4]) + // Empty tag + $node=&$stack[$depth]; + else + $depth++; + } + $tmp=''; + $ptr+=strlen($match[0]); + } + else { + // Text node + $tmp.=substr($text,$ptr,1); + $ptr++; + } + if (strlen($tmp)) + // Append trailing text + $node[]=$tmp; + // Break references + unset($node); + unset($stack); + return $tree; + } + + /** + * Class constructor + * return object + **/ + function __construct() { + $ref=new ReflectionClass(__CLASS__); + $this->tags=''; + foreach ($ref->getmethods() as $method) + if (preg_match('/^_(?=[[:alpha:]])/',$method->name)) + $this->tags.=(strlen($this->tags)?'|':''). + substr($method->name,1); + } + +} diff --git a/lib/f3/test.php b/lib/f3/test.php new file mode 100755 index 0000000..459d54e --- /dev/null +++ b/lib/f3/test.php @@ -0,0 +1,77 @@ +data; + } + + /** + * Evaluate condition and save test result + * @return object + * @param $cond bool + * @param $text string + **/ + function expect($cond,$text=NULL) { + $out=(bool)$cond; + if ($this->level==$out || $this->level==self::FLAG_Both) { + $data=array('status'=>$out,'text'=>$text,'source'=>NULL); + foreach (debug_backtrace() as $frame) + if (isset($frame['file'])) { + $data['source']=Base::instance()-> + fixslashes($frame['file']).':'.$frame['line']; + break; + } + $this->data[]=$data; + } + return $this; + } + + /** + * Append message to test results + * @return NULL + * @param $text string + **/ + function message($text) { + $this->expect(TRUE,$text); + } + + /** + * Class constructor + * @return NULL + * @param $level int + **/ + function __construct($level=self::FLAG_Both) { + $this->level=$level; + } + +} diff --git a/lib/f3/utf.php b/lib/f3/utf.php new file mode 100755 index 0000000..63dcb3a --- /dev/null +++ b/lib/f3/utf.php @@ -0,0 +1,192 @@ +strpos($stack,$needle,$ofs,TRUE); + } + + /** + * Find position of first occurrence of a string + * @return int|FALSE + * @param $stack string + * @param $needle string + * @param $ofs int + * @param $case bool + **/ + function strpos($stack,$needle,$ofs=0,$case=FALSE) { + return preg_match('/^(.{'.$ofs.'}.*?)'. + preg_quote($needle,'/').'/us'.($case?'i':''),$stack,$match)? + $this->strlen($match[1]):FALSE; + } + + /** + * Returns part of haystack string from the first occurrence of + * needle to the end of haystack (case-insensitive) + * @return string|FALSE + * @param $stack string + * @param $needle string + * @param $before bool + **/ + function stristr($stack,$needle,$before=FALSE) { + return $this->strstr($stack,$needle,$before,TRUE); + } + + /** + * Returns part of haystack string from the first occurrence of + * needle to the end of haystack + * @return string|FALSE + * @param $stack string + * @param $needle string + * @param $before bool + * @param $case bool + **/ + function strstr($stack,$needle,$before=FALSE,$case=FALSE) { + if (!$needle) + return FALSE; + preg_match('/^(.*?)'.preg_quote($needle,'/').'/us'.($case?'i':''), + $stack,$match); + return isset($match[1])? + ($before? + $match[1]: + $this->substr($stack,$this->strlen($match[1]))): + FALSE; + } + + /** + * Return part of a string + * @return string|FALSE + * @param $str string + * @param $start int + * @param $len int + **/ + function substr($str,$start,$len=0) { + if ($start<0) + $start=$this->strlen($str)+$start; + if (!$len) + $len=$this->strlen($str)-$start; + return preg_match('/^.{'.$start.'}(.{0,'.$len.'})/us',$str,$match)? + $match[1]:FALSE; + } + + /** + * Count the number of substring occurrences + * @return int + * @param $stack string + * @param $needle string + **/ + function substr_count($stack,$needle) { + preg_match_all('/'.preg_quote($needle,'/').'/us',$stack, + $matches,PREG_SET_ORDER); + return count($matches); + } + + /** + * Strip whitespaces from the beginning of a string + * @return string + * @param $str string + **/ + function ltrim($str) { + return preg_replace('/^[\pZ\pC]+/u','',$str); + } + + /** + * Strip whitespaces from the end of a string + * @return string + * @param $str string + **/ + function rtrim($str) { + return preg_replace('/[\pZ\pC]+$/u','',$str); + } + + /** + * Strip whitespaces from the beginning and end of a string + * @return string + * @param $str string + **/ + function trim($str) { + return preg_replace('/^[\pZ\pC]+|[\pZ\pC]+$/u','',$str); + } + + /** + * Return UTF-8 byte order mark + * @return string + **/ + function bom() { + return chr(0xef).chr(0xbb).chr(0xbf); + } + + /** + * Convert code points to Unicode symbols + * @return string + * @param $str string + **/ + function translate($str) { + return html_entity_decode( + preg_replace('/\\\\u([[:xdigit:]]+)/i','&#x\1;',$str)); + } + + /** + * Translate emoji tokens to Unicode font-supported symbols + * @return string + * @param $str string + **/ + function emojify($str) { + $map=array( + ':('=>'\u2639', // frown + ':)'=>'\u263a', // smile + '<3'=>'\u2665', // heart + ':D'=>'\u1f603', // grin + 'XD'=>'\u1f606', // laugh + ';)'=>'\u1f609', // wink + ':P'=>'\u1f60b', // tongue + ':,'=>'\u1f60f', // think + ':/'=>'\u1f623', // skeptic + '8O'=>'\u1f632', // oops + )+Base::instance()->get('EMOJI'); + return $this->translate(str_replace(array_keys($map), + array_values($map),$str)); + } + +} diff --git a/lib/f3/web.php b/lib/f3/web.php new file mode 100755 index 0000000..42e1ed9 --- /dev/null +++ b/lib/f3/web.php @@ -0,0 +1,838 @@ +'audio/basic', + 'avi'=>'video/avi', + 'bmp'=>'image/bmp', + 'bz2'=>'application/x-bzip2', + 'css'=>'text/css', + 'dtd'=>'application/xml-dtd', + 'doc'=>'application/msword', + 'gif'=>'image/gif', + 'gz'=>'application/x-gzip', + 'hqx'=>'application/mac-binhex40', + 'html?'=>'text/html', + 'jar'=>'application/java-archive', + 'jpe?g'=>'image/jpeg', + 'js'=>'application/x-javascript', + 'midi'=>'audio/x-midi', + 'mp3'=>'audio/mpeg', + 'mpe?g'=>'video/mpeg', + 'ogg'=>'audio/vorbis', + 'pdf'=>'application/pdf', + 'png'=>'image/png', + 'ppt'=>'application/vnd.ms-powerpoint', + 'ps'=>'application/postscript', + 'qt'=>'video/quicktime', + 'ram?'=>'audio/x-pn-realaudio', + 'rdf'=>'application/rdf', + 'rtf'=>'application/rtf', + 'sgml?'=>'text/sgml', + 'sit'=>'application/x-stuffit', + 'svg'=>'image/svg+xml', + 'swf'=>'application/x-shockwave-flash', + 'tgz'=>'application/x-tar', + 'tiff'=>'image/tiff', + 'txt'=>'text/plain', + 'wav'=>'audio/wav', + 'xls'=>'application/vnd.ms-excel', + 'xml'=>'application/xml', + 'zip'=>'application/x-zip-compressed' + ); + foreach ($map as $key=>$val) + if (preg_match('/'.$key.'/',strtolower($ext[0]))) + return $val; + } + return 'application/octet-stream'; + } + + /** + * Return the MIME types stated in the HTTP Accept header as an array; + * If a list of MIME types is specified, return the best match; or + * FALSE if none found + * @return array|string|FALSE + * @param $list string|array + **/ + function acceptable($list=NULL) { + $accept=array(); + foreach (explode(',',str_replace(' ','',$_SERVER['HTTP_ACCEPT'])) + as $mime) + if (preg_match('/(.+?)(?:;q=([\d\.]+)|$)/',$mime,$parts)) + $accept[$parts[1]]=isset($parts[2])?$parts[2]:1; + if (!$accept) + $accept['*/*']=1; + else { + krsort($accept); + arsort($accept); + } + if ($list) { + if (is_string($list)) + $list=explode(',',$list); + foreach ($accept as $mime=>$q) + if ($q && $out=preg_grep('/'. + str_replace('\*','.*',preg_quote($mime,'/')).'/',$list)) + return current($out); + return FALSE; + } + return $accept; + } + + /** + * Transmit file to HTTP client; Return file size if successful, + * FALSE otherwise + * @return int|FALSE + * @param $file string + * @param $mime string + * @param $kbps int + * @param $force bool + **/ + function send($file,$mime=NULL,$kbps=0,$force=TRUE) { + if (!is_file($file)) + return FALSE; + if (PHP_SAPI!='cli') { + header('Content-Type: '.($mime?:$this->mime($file))); + if ($force) + header('Content-Disposition: attachment; '. + 'filename='.basename($file)); + header('Accept-Ranges: bytes'); + header('Content-Length: '.$size=filesize($file)); + header('X-Powered-By: '.Base::instance()->get('PACKAGE')); + } + $ctr=0; + $handle=fopen($file,'rb'); + $start=microtime(TRUE); + while (!feof($handle) && + ($info=stream_get_meta_data($handle)) && + !$info['timed_out'] && !connection_aborted()) { + if ($kbps) { + // Throttle output + $ctr++; + if ($ctr/$kbps>$elapsed=microtime(TRUE)-$start) + usleep(1e6*($ctr/$kbps-$elapsed)); + } + // Send 1KiB and reset timer + echo fread($handle,1024); + } + fclose($handle); + return $size; + } + + /** + * Receive file(s) from HTTP client + * @return array|bool + * @param $func callback + * @param $overwrite bool + * @param $slug callback|bool + **/ + function receive($func=NULL,$overwrite=FALSE,$slug=TRUE) { + $fw=Base::instance(); + $dir=$fw->get('UPLOADS'); + if (!is_dir($dir)) + mkdir($dir,Base::MODE,TRUE); + if ($fw->get('VERB')=='PUT') { + $tmp=$fw->get('TEMP'). + $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash(uniqid()); + if (!$fw->get('RAW')) + $fw->write($tmp,$fw->get('BODY')); + else { + $src=@fopen('php://input','r'); + $dst=@fopen($tmp,'w'); + if (!$src || !$dst) + return FALSE; + while (!feof($src) && + ($info=stream_get_meta_data($src)) && + !$info['timed_out'] && $str=fgets($src,4096)) + fputs($dst,$str,strlen($str)); + fclose($dst); + fclose($src); + } + $base=basename($fw->get('URI')); + $file=array( + 'name'=>$dir. + ($slug && preg_match('/(.+?)(\.\w+)?$/',$base,$parts)? + (is_callable($slug)? + $slug($base): + ($this->slug($parts[1]). + (isset($parts[2])?$parts[2]:''))): + $base), + 'tmp_name'=>$tmp, + 'type'=>$this->mime($base), + 'size'=>filesize($tmp) + ); + return (!file_exists($file['name']) || $overwrite) && + (!$func || $fw->call($func,array($file))!==FALSE) && + rename($tmp,$file['name']); + } + $out=array(); + foreach ($_FILES as $item) { + if (is_array($item['name'])) { + // Transpose array + $tmp=array(); + foreach ($item as $keyx=>$cols) + foreach ($cols as $keyy=>$valy) + $tmp[$keyy][$keyx]=$valy; + $item=$tmp; + } + else + $item=array($item); + foreach ($item as $file) { + if (empty($file['name'])) + continue; + $base=basename($file['name']); + $file['name']=$dir. + ($slug && preg_match('/(.+?)(\.\w+)?$/',$base,$parts)? + (is_callable($slug)? + $slug($base): + ($this->slug($parts[1]). + (isset($parts[2])?$parts[2]:''))): + $base); + $out[$file['name']]=!$file['error'] && + is_uploaded_file($file['tmp_name']) && + (!file_exists($file['name']) || $overwrite) && + (!$func || $fw->call($func,array($file))!==FALSE) && + move_uploaded_file($file['tmp_name'],$file['name']); + } + } + return $out; + } + + /** + * Return upload progress in bytes, FALSE on failure + * @return int|FALSE + * @param $id string + **/ + function progress($id) { + // ID returned by session.upload_progress.name + return ini_get('session.upload_progress.enabled') && + isset($_SESSION[$id]['bytes_processed'])? + $_SESSION[$id]['bytes_processed']:FALSE; + } + + /** + * HTTP request via cURL + * @return array + * @param $url string + * @param $options array + **/ + protected function _curl($url,$options) { + $curl=curl_init($url); + curl_setopt($curl,CURLOPT_FOLLOWLOCATION, + $options['follow_location']); + curl_setopt($curl,CURLOPT_MAXREDIRS, + $options['max_redirects']); + curl_setopt($curl,CURLOPT_CUSTOMREQUEST,$options['method']); + if (isset($options['header'])) + curl_setopt($curl,CURLOPT_HTTPHEADER,$options['header']); + if (isset($options['user_agent'])) + curl_setopt($curl,CURLOPT_USERAGENT,$options['user_agent']); + if (isset($options['content'])) + curl_setopt($curl,CURLOPT_POSTFIELDS,$options['content']); + curl_setopt($curl,CURLOPT_ENCODING,'gzip,deflate'); + $timeout=isset($options['timeout'])? + $options['timeout']: + ini_get('default_socket_timeout'); + curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,$timeout); + curl_setopt($curl,CURLOPT_TIMEOUT,$timeout); + $headers=array(); + curl_setopt($curl,CURLOPT_HEADERFUNCTION, + // Callback for response headers + function($curl,$line) use(&$headers) { + if ($trim=trim($line)) + $headers[]=$trim; + return strlen($line); + } + ); + curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,FALSE); + ob_start(); + curl_exec($curl); + curl_close($curl); + $body=ob_get_clean(); + return array( + 'body'=>$body, + 'headers'=>$headers, + 'engine'=>'cURL', + 'cached'=>FALSE + ); + } + + /** + * HTTP request via PHP stream wrapper + * @return array + * @param $url string + * @param $options array + **/ + protected function _stream($url,$options) { + $eol="\r\n"; + $options['header']=implode($eol,$options['header']); + $body=@file_get_contents($url,FALSE, + stream_context_create(array('http'=>$options))); + $headers=isset($http_response_header)? + $http_response_header:array(); + $match=NULL; + foreach ($headers as $header) + if (preg_match('/Content-Encoding: (.+)/',$header,$match)) + break; + if ($match) + switch ($match[1]) { + case 'gzip': + $body=gzdecode($body); + break; + case 'deflate': + $body=gzuncompress($body); + break; + } + return array( + 'body'=>$body, + 'headers'=>$headers, + 'engine'=>'stream', + 'cached'=>FALSE + ); + } + + /** + * HTTP request via low-level TCP/IP socket + * @return array + * @param $url string + * @param $options array + **/ + protected function _socket($url,$options) { + $eol="\r\n"; + $headers=array(); + $body=''; + $parts=parse_url($url); + $empty=empty($parts['port']); + if ($parts['scheme']=='https') { + $parts['host']='ssl://'.$parts['host']; + if ($empty) + $parts['port']=443; + } + elseif ($empty) + $parts['port']=80; + if (empty($parts['path'])) + $parts['path']='/'; + if (empty($parts['query'])) + $parts['query']=''; + $socket=@fsockopen($parts['host'],$parts['port']); + if (!$socket) + return FALSE; + stream_set_blocking($socket,TRUE); + fputs($socket,$options['method'].' '.$parts['path']. + ($parts['query']?('?'.$parts['query']):'').' HTTP/1.0'.$eol + ); + fputs($socket,implode($eol,$options['header']).$eol.$eol); + if (isset($options['content'])) + fputs($socket,$options['content'].$eol); + // Get response + $content=''; + while (!feof($socket) && + ($info=stream_get_meta_data($socket)) && + !$info['timed_out'] && $str=fgets($socket,4096)) + $content.=$str; + fclose($socket); + $html=explode($eol.$eol,$content,2); + $body=isset($html[1])?$html[1]:''; + $headers=array_merge($headers,$current=explode($eol,$html[0])); + $match=NULL; + foreach ($current as $header) + if (preg_match('/Content-Encoding: (.+)/',$header,$match)) + break; + if ($match) + switch ($match[1]) { + case 'gzip': + $body=gzdecode($body); + break; + case 'deflate': + $body=gzuncompress($body); + break; + } + if ($options['follow_location'] && + preg_match('/Location: (.+?)'.preg_quote($eol).'/', + $html[0],$loc)) { + $options['max_redirects']--; + return $this->request($loc[1],$options); + } + return array( + 'body'=>$body, + 'headers'=>$headers, + 'engine'=>'socket', + 'cached'=>FALSE + ); + } + + /** + * Specify the HTTP request engine to use; If not available, + * fall back to an applicable substitute + * @return string + * @param $arg string + **/ + function engine($arg='curl') { + $arg=strtolower($arg); + $flags=array( + 'curl'=>extension_loaded('curl'), + 'stream'=>ini_get('allow_url_fopen'), + 'socket'=>function_exists('fsockopen') + ); + if ($flags[$arg]) + return $this->wrapper=$arg; + foreach ($flags as $key=>$val) + if ($val) + return $this->wrapper=$key; + user_error(E_Request); + } + + /** + * Replace old headers with new elements + * @return NULL + * @param $old array + * @param $new string|array + **/ + function subst(array &$old,$new) { + if (is_string($new)) + $new=array($new); + foreach ($new as $hdr) { + $old=preg_grep('/'.preg_quote(strstr($hdr,':',TRUE),'/').':.+/', + $old,PREG_GREP_INVERT); + array_push($old,$hdr); + } + } + + /** + * Submit HTTP request; Use HTTP context options (described in + * http://www.php.net/manual/en/context.http.php) if specified; + * Cache the page as instructed by remote server + * @return array|FALSE + * @param $url string + * @param $options array + **/ + function request($url,array $options=NULL) { + $fw=Base::instance(); + $parts=parse_url($url); + if (empty($parts['scheme'])) { + // Local URL + $url=$fw->get('SCHEME').'://'. + $fw->get('HOST'). + ($url[0]!='/'?($fw->get('BASE').'/'):'').$url; + $parts=parse_url($url); + } + elseif (!preg_match('/https?/',$parts['scheme'])) + return FALSE; + if (!is_array($options)) + $options=array(); + if (empty($options['header'])) + $options['header']=array(); + elseif (is_string($options['header'])) + $options['header']=array($options['header']); + if (!$this->wrapper) + $this->engine(); + if ($this->wrapper!='stream') { + // PHP streams can't cope with redirects when Host header is set + foreach ($options['header'] as &$header) + if (preg_match('/^Host:/',$header)) { + $header='Host: '.$parts['host']; + unset($header); + break; + } + $this->subst($options['header'],'Host: '.$parts['host']); + } + $this->subst($options['header'], + array( + 'Accept-Encoding: gzip,deflate', + 'User-Agent: Mozilla/5.0 (compatible; '.php_uname('s').')', + 'Connection: close' + ) + ); + if (isset($options['content'])) { + if ($options['method']=='POST') + $this->subst($options['header'], + 'Content-Type: application/x-www-form-urlencoded'); + $this->subst($options['header'], + 'Content-Length: '.strlen($options['content'])); + } + if (isset($parts['user'],$parts['pass'])) + $this->subst($options['header'], + 'Authorization: Basic '. + base64_encode($parts['user'].':'.$parts['pass']) + ); + $options+=array( + 'method'=>'GET', + 'header'=>$options['header'], + 'follow_location'=>TRUE, + 'max_redirects'=>20, + 'ignore_errors'=>FALSE + ); + $eol="\r\n"; + if ($fw->get('CACHE') && + preg_match('/GET|HEAD/',$options['method'])) { + $cache=Cache::instance(); + if ($cache->exists( + $hash=$fw->hash($options['method'].' '.$url).'.url',$data)) { + if (preg_match('/Last-Modified: (.+?)'.preg_quote($eol).'/', + implode($eol,$data['headers']),$mod)) + $this->subst($options['header'], + 'If-Modified-Since: '.$mod[1]); + } + } + $result=$this->{'_'.$this->wrapper}($url,$options); + if ($result && isset($cache)) { + if (preg_match('/HTTP\/1\.\d 304/', + implode($eol,$result['headers']))) { + $result=$cache->get($hash); + $result['cached']=TRUE; + } + elseif (preg_match('/Cache-Control: max-age=(.+?)'. + preg_quote($eol).'/',implode($eol,$result['headers']),$exp)) + $cache->set($hash,$result,$exp[1]); + } + return $result; + } + + /** + * Strip Javascript/CSS files of extraneous whitespaces and comments; + * Return combined output as a minified string + * @return string + * @param $files string|array + * @param $mime string + * @param $header bool + * @param $path string + **/ + function minify($files,$mime=NULL,$header=TRUE,$path='') { + $fw=Base::instance(); + if (is_string($files)) + $files=$fw->split($files); + if (!$mime) + $mime=$this->mime($files[0]); + preg_match('/\w+$/',$files[0],$ext); + $cache=Cache::instance(); + $dst=''; + foreach ($fw->split($path?:$fw->get('UI').';./') as $dir) + foreach ($files as $file) + if (is_file($save=$fw->fixslashes($dir.$file))) { + if ($fw->get('CACHE') && + ($cached=$cache->exists( + $hash=$fw->hash($save).'.'.$ext[0],$data)) && + $cached[0]>filemtime($save)) + $dst.=$data; + else { + $data=''; + $src=$fw->read($save); + for ($ptr=0,$len=strlen($src);$ptr<$len;) { + if (preg_match('/^@import\h+url'. + '\(\h*([\'"])(.+?)\1\h*\)[^;]*;/', + substr($src,$ptr),$parts)) { + $path=dirname($file); + $data.=$this->minify( + ($path?($path.'/'):'').$parts[2], + $mime,$header + ); + $ptr+=strlen($parts[0]); + continue; + } + if ($src[$ptr]=='/') { + if ($src[$ptr+1]=='*') { + // Multiline comment + $str=strstr( + substr($src,$ptr+2),'*/',TRUE); + $ptr+=strlen($str)+4; + } + elseif ($src[$ptr+1]=='/') { + // Single-line comment + $str=strstr( + substr($src,$ptr+2),"\n",TRUE); + $ptr+=strlen($str)+2; + } + else { + // Presume it's a regex pattern + $regex=TRUE; + // Backtrack and validate + for ($ofs=$ptr;$ofs;$ofs--) { + // Pattern should be preceded by + // open parenthesis, colon, + // object property or operator + if (preg_match( + '/(return|[(:=!+\-*&|])$/', + substr($src,0,$ofs))) { + $data.='/'; + $ptr++; + while ($ptr<$len) { + $data.=$src[$ptr]; + $ptr++; + if ($src[$ptr-1]=='\\') { + $data.=$src[$ptr]; + $ptr++; + } + elseif ($src[$ptr-1]=='/') + break; + } + break; + } + elseif (!ctype_space($src[$ofs-1])) { + // Not a regex pattern + $regex=FALSE; + break; + } + } + if (!$regex) { + // Division operator + $data.=$src[$ptr]; + $ptr++; + } + } + continue; + } + if (in_array($src[$ptr],array('\'','"'))) { + $match=$src[$ptr]; + $data.=$match; + $ptr++; + // String literal + while ($ptr<$len) { + $data.=$src[$ptr]; + $ptr++; + if ($src[$ptr-1]=='\\') { + $data.=$src[$ptr]; + $ptr++; + } + elseif ($src[$ptr-1]==$match) + break; + } + continue; + } + if (ctype_space($src[$ptr])) { + if ($ptr+1get('CACHE')) + $cache->set($hash,$data); + $dst.=$data; + } + } + if (PHP_SAPI!='cli' && $header) + header('Content-Type: '.$mime.'; charset='.$fw->get('ENCODING')); + return $dst; + } + + /** + * Retrieve RSS feed and return as an array + * @return array|FALSE + * @param $url string + * @param $max int + * @param $tags string + **/ + function rss($url,$max=10,$tags=NULL) { + if (!$data=$this->request($url)) + return FALSE; + // Suppress errors caused by invalid XML structures + libxml_use_internal_errors(TRUE); + $xml=simplexml_load_string($data['body'], + NULL,LIBXML_NOBLANKS|LIBXML_NOERROR); + if (!is_object($xml)) + return FALSE; + $out=array(); + if (isset($xml->channel)) { + $out['source']=(string)$xml->channel->title; + $max=min($max,count($xml->channel->item)); + for ($i=0;$i<$max;$i++) { + $item=$xml->channel->item[$i]; + $list=array(''=>NULL)+$item->getnamespaces(TRUE); + $fields=array(); + foreach ($list as $ns=>$uri) + foreach ($item->children($uri) as $key=>$val) + $fields[$ns.($ns?':':'').$key]=(string)$val; + $out['feed'][]=$fields; + } + } + else + return FALSE; + Base::instance()->scrub($out,$tags); + return $out; + } + + /** + * Retrieve information from whois server + * @return string|FALSE + * @param $addr string + * @param $server string + **/ + function whois($addr,$server='whois.internic.net') { + $socket=@fsockopen($server,43,$errno,$errstr); + if (!$socket) + // Can't establish connection + return FALSE; + // Set connection timeout parameters + stream_set_blocking($socket,TRUE); + stream_set_timeout($socket,ini_get('default_socket_timeout')); + // Send request + fputs($socket,$addr."\r\n"); + $info=stream_get_meta_data($socket); + // Get response + $response=''; + while (!feof($socket) && !$info['timed_out']) { + $response.=fgets($socket,4096); // MDFK97 + $info=stream_get_meta_data($socket); + } + fclose($socket); + return $info['timed_out']?FALSE:trim($response); + } + + /** + * Return a URL/filesystem-friendly version of string + * @return string + * @param $text string + **/ + function slug($text) { + return trim(strtolower(preg_replace('/([^\pL\pN])+/u','-', + trim(strtr(str_replace('\'','',$text), + array( + 'Ǎ'=>'A','А'=>'A','Ā'=>'A','Ă'=>'A','Ą'=>'A','Å'=>'A', + 'Ǻ'=>'A','Ä'=>'Ae','Á'=>'A','À'=>'A','Ã'=>'A','Â'=>'A', + 'Æ'=>'AE','Ǽ'=>'AE','Б'=>'B','Ç'=>'C','Ć'=>'C','Ĉ'=>'C', + 'Č'=>'C','Ċ'=>'C','Ц'=>'C','Ч'=>'Ch','Ð'=>'Dj','Đ'=>'Dj', + 'Ď'=>'Dj','Д'=>'Dj','É'=>'E','Ę'=>'E','Ё'=>'E','Ė'=>'E', + 'Ê'=>'E','Ě'=>'E','Ē'=>'E','È'=>'E','Е'=>'E','Э'=>'E', + 'Ë'=>'E','Ĕ'=>'E','Ф'=>'F','Г'=>'G','Ģ'=>'G','Ġ'=>'G', + 'Ĝ'=>'G','Ğ'=>'G','Х'=>'H','Ĥ'=>'H','Ħ'=>'H','Ï'=>'I', + 'Ĭ'=>'I','İ'=>'I','Į'=>'I','Ī'=>'I','Í'=>'I','Ì'=>'I', + 'И'=>'I','Ǐ'=>'I','Ĩ'=>'I','Î'=>'I','IJ'=>'IJ','Ĵ'=>'J', + 'Й'=>'J','Я'=>'Ja','Ю'=>'Ju','К'=>'K','Ķ'=>'K','Ĺ'=>'L', + 'Л'=>'L','Ł'=>'L','Ŀ'=>'L','Ļ'=>'L','Ľ'=>'L','М'=>'M', + 'Н'=>'N','Ń'=>'N','Ñ'=>'N','Ņ'=>'N','Ň'=>'N','Ō'=>'O', + 'О'=>'O','Ǿ'=>'O','Ǒ'=>'O','Ơ'=>'O','Ŏ'=>'O','Ő'=>'O', + 'Ø'=>'O','Ö'=>'Oe','Õ'=>'O','Ó'=>'O','Ò'=>'O','Ô'=>'O', + 'Œ'=>'OE','П'=>'P','Ŗ'=>'R','Р'=>'R','Ř'=>'R','Ŕ'=>'R', + 'Ŝ'=>'S','Ş'=>'S','Š'=>'S','Ș'=>'S','Ś'=>'S','С'=>'S', + 'Ш'=>'Sh','Щ'=>'Shch','Ť'=>'T','Ŧ'=>'T','Ţ'=>'T','Ț'=>'T', + 'Т'=>'T','Ů'=>'U','Ű'=>'U','Ŭ'=>'U','Ũ'=>'U','Ų'=>'U', + 'Ū'=>'U','Ǜ'=>'U','Ǚ'=>'U','Ù'=>'U','Ú'=>'U','Ü'=>'Ue', + 'Ǘ'=>'U','Ǖ'=>'U','У'=>'U','Ư'=>'U','Ǔ'=>'U','Û'=>'U', + 'В'=>'V','Ŵ'=>'W','Ы'=>'Y','Ŷ'=>'Y','Ý'=>'Y','Ÿ'=>'Y', + 'Ź'=>'Z','З'=>'Z','Ż'=>'Z','Ž'=>'Z','Ж'=>'Zh','á'=>'a', + 'ă'=>'a','â'=>'a','à'=>'a','ā'=>'a','ǻ'=>'a','å'=>'a', + 'ä'=>'ae','ą'=>'a','ǎ'=>'a','ã'=>'a','а'=>'a','ª'=>'a', + 'æ'=>'ae','ǽ'=>'ae','б'=>'b','č'=>'c','ç'=>'c','ц'=>'c', + 'ċ'=>'c','ĉ'=>'c','ć'=>'c','ч'=>'ch','ð'=>'dj','ď'=>'dj', + 'д'=>'dj','đ'=>'dj','э'=>'e','é'=>'e','ё'=>'e','ë'=>'e', + 'ê'=>'e','е'=>'e','ĕ'=>'e','è'=>'e','ę'=>'e','ě'=>'e', + 'ė'=>'e','ē'=>'e','ƒ'=>'f','ф'=>'f','ġ'=>'g','ĝ'=>'g', + 'ğ'=>'g','г'=>'g','ģ'=>'g','х'=>'h','ĥ'=>'h','ħ'=>'h', + 'ǐ'=>'i','ĭ'=>'i','и'=>'i','ī'=>'i','ĩ'=>'i','į'=>'i', + 'ı'=>'i','ì'=>'i','î'=>'i','í'=>'i','ï'=>'i','ij'=>'ij', + 'ĵ'=>'j','й'=>'j','я'=>'ja','ю'=>'ju','ķ'=>'k','к'=>'k', + 'ľ'=>'l','ł'=>'l','ŀ'=>'l','ĺ'=>'l','ļ'=>'l','л'=>'l', + 'м'=>'m','ņ'=>'n','ñ'=>'n','ń'=>'n','н'=>'n','ň'=>'n', + 'ʼn'=>'n','ó'=>'o','ò'=>'o','ǒ'=>'o','ő'=>'o','о'=>'o', + 'ō'=>'o','º'=>'o','ơ'=>'o','ŏ'=>'o','ô'=>'o','ö'=>'oe', + 'õ'=>'o','ø'=>'o','ǿ'=>'o','œ'=>'oe','п'=>'p','р'=>'r', + 'ř'=>'r','ŕ'=>'r','ŗ'=>'r','ſ'=>'s','ŝ'=>'s','ș'=>'s', + 'š'=>'s','ś'=>'s','с'=>'s','ş'=>'s','ш'=>'sh','щ'=>'shch', + 'ß'=>'ss','ţ'=>'t','т'=>'t','ŧ'=>'t','ť'=>'t','ț'=>'t', + 'у'=>'u','ǘ'=>'u','ŭ'=>'u','û'=>'u','ú'=>'u','ų'=>'u', + 'ù'=>'u','ű'=>'u','ů'=>'u','ư'=>'u','ū'=>'u','ǚ'=>'u', + 'ǜ'=>'u','ǔ'=>'u','ǖ'=>'u','ũ'=>'u','ü'=>'ue','в'=>'v', + 'ŵ'=>'w','ы'=>'y','ÿ'=>'y','ý'=>'y','ŷ'=>'y','ź'=>'z', + 'ž'=>'z','з'=>'z','ż'=>'z','ж'=>'zh' + )+Base::instance()->get('DIACRITICS'))))),'-'); + } + + /** + * Return chunk of text from standard Lorem Ipsum passage + * @return string + * @param $count int + * @param $max int + * @param $std bool + **/ + function filler($count=1,$max=20,$std=TRUE) { + $out=''; + if ($std) + $out='Lorem ipsum dolor sit amet, consectetur adipisicing elit, '. + 'sed do eiusmod tempor incididunt ut labore et dolore magna '. + 'aliqua.'; + $rnd=explode(' ', + 'a ab ad accusamus adipisci alias aliquam amet animi aperiam '. + 'architecto asperiores aspernatur assumenda at atque aut beatae '. + 'blanditiis cillum commodi consequatur corporis corrupti culpa '. + 'cum cupiditate debitis delectus deleniti deserunt dicta '. + 'dignissimos distinctio dolor ducimus duis ea eaque earum eius '. + 'eligendi enim eos error esse est eum eveniet ex excepteur '. + 'exercitationem expedita explicabo facere facilis fugiat harum '. + 'hic id illum impedit in incidunt ipsa iste itaque iure iusto '. + 'laborum laudantium libero magnam maiores maxime minim minus '. + 'modi molestiae mollitia nam natus necessitatibus nemo neque '. + 'nesciunt nihil nisi nobis non nostrum nulla numquam occaecati '. + 'odio officia omnis optio pariatur perferendis perspiciatis '. + 'placeat porro possimus praesentium proident quae quia quibus '. + 'quo ratione recusandae reiciendis rem repellat reprehenderit '. + 'repudiandae rerum saepe sapiente sequi similique sint soluta '. + 'suscipit tempora tenetur totam ut ullam unde vel veniam vero '. + 'vitae voluptas'); + for ($i=0,$add=$count-(int)$std;$i<$add;$i++) { + shuffle($rnd); + $words=array_slice($rnd,0,mt_rand(3,$max)); + $out.=' '.ucfirst(implode(' ',$words)).'.'; + } + return $out; + } + +} + +if (!function_exists('gzdecode')) { + + /** + * Decode gzip-compressed string + * @param $str string + **/ + function gzdecode($str) { + $fw=Base::instance(); + if (!is_dir($tmp=$fw->get('TEMP'))) + mkdir($tmp,Base::MODE,TRUE); + file_put_contents($file=$tmp.'/'. + $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash(uniqid(NULL,TRUE)).'.gz',$str,LOCK_EX); + ob_start(); + readgzfile($file); + $out=ob_get_clean(); + @unlink($file); + return $out; + } + +} diff --git a/lib/f3/web/geo.php b/lib/f3/web/geo.php new file mode 100755 index 0000000..c1b915e --- /dev/null +++ b/lib/f3/web/geo.php @@ -0,0 +1,101 @@ +getLocation(); + $trn=$ref->getTransitions($now=time(),$now); + $out=array( + 'offset'=>$ref-> + getOffset(new \DateTime('now',new \DateTimeZone('GMT')))/3600, + 'country'=>$loc['country_code'], + 'latitude'=>$loc['latitude'], + 'longitude'=>$loc['longitude'], + 'dst'=>$trn[0]['isdst'] + ); + unset($ref); + return $out; + } + + /** + * Return geolocation data based on specified/auto-detected IP address + * @return array|FALSE + * @param $ip string + **/ + function location($ip=NULL) { + $fw=\Base::instance(); + $web=\Web::instance(); + if (!$ip) + $ip=$fw->get('IP'); + $public=filter_var($ip,FILTER_VALIDATE_IP, + FILTER_FLAG_IPV4|FILTER_FLAG_IPV6| + FILTER_FLAG_NO_RES_RANGE|FILTER_FLAG_NO_PRIV_RANGE); + if (function_exists('geoip_db_avail') && + geoip_db_avail(GEOIP_CITY_EDITION_REV1) && + $out=@geoip_record_by_name($ip)) { + $out['request']=$ip; + $out['region_code']=$out['region']; + $out['region_name']=geoip_region_name_by_code( + $out['country_code'],$out['region']); + unset($out['country_code3'],$out['region'],$out['postal_code']); + return $out; + } + if (($req=$web->request('http://www.geoplugin.net/json.gp'. + ($public?('?ip='.$ip):''))) && + $data=json_decode($req['body'],TRUE)) { + $out=array(); + foreach ($data as $key=>$val) + if (!strpos($key,'currency') && $key!=='geoplugin_status' + && $key!=='geoplugin_region') + $out[$fw->snakecase(substr($key, 10))]=$val; + return $out; + } + return FALSE; + } + + /** + * Return weather data based on specified latitude/longitude + * @return array|FALSE + * @param $latitude float + * @param $longitude float + **/ + function weather($latitude,$longitude) { + $fw=\Base::instance(); + $web=\Web::instance(); + $query=array( + 'lat'=>$latitude, + 'lng'=>$longitude, + 'username'=>$fw->hash($fw->get('IP')) + ); + return ($req=$web->request( + 'http://ws.geonames.org/findNearByWeatherJSON?'. + http_build_query($query))) && + ($data=json_decode($req['body'],TRUE)) && + isset($data['weatherObservation'])? + $data['weatherObservation']: + FALSE; + } + +} diff --git a/lib/f3/web/google/staticmap.php b/lib/f3/web/google/staticmap.php new file mode 100755 index 0000000..8d8a5fc --- /dev/null +++ b/lib/f3/web/google/staticmap.php @@ -0,0 +1,58 @@ +query[]=array($func,$args[0]); + return $this; + } + + /** + * Generate map + * @return string + **/ + function dump() { + $fw=\Base::instance(); + $web=\Web::instance(); + $out=''; + return ($req=$web->request( + self::URL_Static.'?'.array_reduce( + $this->query, + function($out,$item) { + return ($out.=($out?'&':''). + urlencode($item[0]).'='.urlencode($item[1])); + } + ))) && $req['body']?$req['body']:FALSE; + } + +} diff --git a/lib/f3/web/openid.php b/lib/f3/web/openid.php new file mode 100755 index 0000000..a6c302f --- /dev/null +++ b/lib/f3/web/openid.php @@ -0,0 +1,236 @@ +args['identity'])) + $this->args['identity']='http://'.$this->args['identity']; + $url=parse_url($this->args['identity']); + // Remove fragment; reconnect parts + $this->args['identity']=$url['scheme'].'://'. + (isset($url['user'])? + ($url['user']. + (isset($url['pass'])?(':'.$url['pass']):'').'@'):''). + strtolower($url['host']).(isset($url['path'])?$url['path']:'/'). + (isset($url['query'])?('?'.$url['query']):''); + // HTML-based discovery of OpenID provider + $req=\Web::instance()-> + request($this->args['identity'],array('proxy'=>$proxy)); + if (!$req) + return FALSE; + $type=array_values(preg_grep('/Content-Type:/',$req['headers'])); + if ($type && + preg_match('/application\/xrds\+xml|text\/xml/',$type[0]) && + ($sxml=simplexml_load_string($req['body'])) && + ($xrds=json_decode(json_encode($sxml),TRUE)) && + isset($xrds['XRD'])) { + // XRDS document + $svc=$xrds['XRD']['Service']; + if (isset($svc[0])) + $svc=$svc[0]; + if (preg_grep('/http:\/\/specs\.openid\.net\/auth\/2.0\/'. + '(?:server|signon)/',$svc['Type'])) { + $this->args['provider']=$svc['URI']; + if (isset($svc['LocalID'])) + $this->args['localidentity']=$svc['LocalID']; + elseif (isset($svc['CanonicalID'])) + $this->args['localidentity']=$svc['CanonicalID']; + } + $this->args['server']=$svc['URI']; + if (isset($svc['Delegate'])) + $this->args['delegate']=$svc['Delegate']; + } + else { + $len=strlen($req['body']); + $ptr=0; + // Parse document + while ($ptr<$len) + if (preg_match( + '/^/is', + substr($req['body'],$ptr),$parts)) { + if ($parts[1] && + // Process attributes + preg_match_all('/\b(rel|href)\h*=\h*'. + '(?:"(.+?)"|\'(.+?)\')/s',$parts[1],$attr, + PREG_SET_ORDER)) { + $node=array(); + foreach ($attr as $kv) + $node[$kv[1]]=isset($kv[2])?$kv[2]:$kv[3]; + if (isset($node['rel']) && + preg_match('/openid2?\.(\w+)/', + $node['rel'],$var) && + isset($node['href'])) + $this->args[$var[1]]=$node['href']; + + } + $ptr+=strlen($parts[0]); + } + else + $ptr++; + } + // Get OpenID provider's endpoint URL + if (isset($this->args['provider'])) { + // OpenID 2.0 + $this->args['ns']='http://specs.openid.net/auth/2.0'; + if (isset($this->args['localidentity'])) + $this->args['identity']=$this->args['localidentity']; + if (isset($this->args['trust_root'])) + $this->args['realm']=$this->args['trust_root']; + } + elseif (isset($this->args['server'])) { + // OpenID 1.1 + $this->args['ns']='http://openid.net/signon/1.1'; + if (isset($this->args['delegate'])) + $this->args['identity']=$this->args['delegate']; + } + if (isset($this->args['provider'])) { + // OpenID 2.0 + if (empty($this->args['claimed_id'])) + $this->args['claimed_id']=$this->args['identity']; + return $this->args['provider']; + } + elseif (isset($this->args['server'])) + // OpenID 1.1 + return $this->args['server']; + else + return FALSE; + } + + /** + * Initiate OpenID authentication sequence; Return FALSE on failure + * or redirect to OpenID provider URL + * @return bool + * @param $proxy string + * @param $attr array + * @param $reqd string|array + **/ + function auth($proxy=NULL,$attr=array(),array $reqd=NULL) { + $fw=\Base::instance(); + $root=$fw->get('SCHEME').'://'.$fw->get('HOST'); + if (empty($this->args['trust_root'])) + $this->args['trust_root']=$root.$fw->get('BASE').'/'; + if (empty($this->args['return_to'])) + $this->args['return_to']=$root.$_SERVER['REQUEST_URI']; + $this->args['mode']='checkid_setup'; + if ($this->url=$this->discover($proxy)) { + if ($attr) { + $this->args['ns.ax']='http://openid.net/srv/ax/1.0'; + $this->args['ax.mode']='fetch_request'; + foreach ($attr as $key=>$val) + $this->args['ax.type.'.$key]=$val; + $this->args['ax.required']=is_string($reqd)? + $reqd:implode(',',$reqd); + } + $var=array(); + foreach ($this->args as $key=>$val) + $var['openid.'.$key]=$val; + $fw->reroute($this->url.'?'.http_build_query($var)); + } + return FALSE; + } + + /** + * Return TRUE if OpenID verification was successful + * @return bool + * @param $proxy string + **/ + function verified($proxy=NULL) { + preg_match_all('/(?<=^|&)openid\.([^=]+)=([^&]+)/', + $_SERVER['QUERY_STRING'],$matches,PREG_SET_ORDER); + foreach ($matches as $match) + $this->args[$match[1]]=urldecode($match[2]); + if ($this->args['mode']!='error' && + $this->url=$this->discover($proxy)) { + $this->args['mode']='check_authentication'; + $var=array(); + foreach ($this->args as $key=>$val) + $var['openid.'.$key]=$val; + $req=\Web::instance()->request( + $this->url, + array( + 'method'=>'POST', + 'content'=>http_build_query($var), + 'proxy'=>$proxy + ) + ); + return (bool)preg_match('/is_valid:true/i',$req['body']); + } + return FALSE; + } + + /** + * Return OpenID response fields + * @return array + **/ + function response() { + return $this->args; + } + + /** + * Return TRUE if OpenID request parameter exists + * @return bool + * @param $key string + **/ + function exists($key) { + return isset($this->args[$key]); + } + + /** + * Bind value to OpenID request parameter + * @return string + * @param $key string + * @param $val string + **/ + function set($key,$val) { + return $this->args[$key]=$val; + } + + /** + * Return value of OpenID request parameter + * @return mixed + * @param $key string + **/ + function get($key) { + return isset($this->args[$key])?$this->args[$key]:NULL; + } + + /** + * Remove OpenID request parameter + * @return NULL + * @param $key + **/ + function clear($key) { + unset($this->args[$key]); + } + +} + diff --git a/lib/f3/web/pingback.php b/lib/f3/web/pingback.php new file mode 100755 index 0000000..c7d9f93 --- /dev/null +++ b/lib/f3/web/pingback.php @@ -0,0 +1,170 @@ +request($url); + $found=FALSE; + if ($req && $req['body']) { + // Look for pingback header + foreach ($req['headers'] as $header) + if (preg_match('/^X-Pingback:\h*(.+)/',$header,$href)) { + $found=$href[1]; + break; + } + if (!$found && + // Scan page for pingback link tag + preg_match('//i',$req['body'],$parts) && + preg_match('/rel\h*=\h*"pingback"/i',$parts[1]) && + preg_match('/href\h*=\h*"\h*(.+?)\h*"/i',$parts[1],$href)) + $found=$href[1]; + } + return $found; + } + + /** + * Load local page contents, parse HTML anchor tags, find permalinks, + * and send XML-RPC calls to corresponding pingback servers + * @return NULL + * @param $source string + **/ + function inspect($source) { + $fw=\Base::instance(); + $web=\Web::instance(); + $parts=parse_url($source); + if (empty($parts['scheme']) || empty($parts['host']) || + $parts['host']==$fw->get('HOST')) { + $req=$web->request($source); + $doc=new \DOMDocument('1.0',$fw->get('ENCODING')); + $doc->stricterrorchecking=FALSE; + $doc->recover=TRUE; + if ($req && @$doc->loadhtml($req['body'])) { + // Parse anchor tags + $links=$doc->getelementsbytagname('a'); + foreach ($links as $link) { + $permalink=$link->getattribute('href'); + // Find pingback-enabled resources + if ($permalink && $found=$this->enabled($permalink)) { + $req=$web->request($found, + array( + 'method'=>'POST', + 'header'=>'Content-Type: application/xml', + 'content'=>xmlrpc_encode_request( + 'pingback.ping', + array($source,$permalink), + array('encoding'=>$fw->get('ENCODING')) + ) + ) + ); + if ($req && $req['body']) + $this->log.=date('r').' '. + $permalink.' [permalink:'.$found.']'.PHP_EOL. + $req['body'].PHP_EOL; + } + } + } + unset($doc); + } + } + + /** + * Receive ping, check if local page is pingback-enabled, verify + * source contents, and return XML-RPC response + * @return string + * @param $func callback + * @param $path string + **/ + function listen($func,$path=NULL) { + $fw=\Base::instance(); + if (PHP_SAPI!='cli') { + header('X-Powered-By: '.$fw->get('PACKAGE')); + header('Content-Type: application/xml; '. + 'charset='.$charset=$fw->get('ENCODING')); + } + if (!$path) + $path=$fw->get('BASE'); + $web=\Web::instance(); + $args=xmlrpc_decode_request($fw->get('BODY'),$method,$charset); + $options=array('encoding'=>$charset); + if ($method=='pingback.ping' && isset($args[0],$args[1])) { + list($source,$permalink)=$args; + $doc=new \DOMDocument('1.0',$fw->get('ENCODING')); + // Check local page if pingback-enabled + $parts=parse_url($permalink); + if ((empty($parts['scheme']) || + $parts['host']==$fw->get('HOST')) && + preg_match('/^'.preg_quote($path,'/').'/'. + ($fw->get('CASELESS')?'i':''),$parts['path']) && + $this->enabled($permalink)) { + // Check source + $parts=parse_url($source); + if ((empty($parts['scheme']) || + $parts['host']==$fw->get('HOST')) && + ($req=$web->request($source)) && + $doc->loadhtml($req['body'])) { + $links=$doc->getelementsbytagname('a'); + foreach ($links as $link) { + if ($link->getattribute('href')==$permalink) { + call_user_func_array($func, + array($source,$req['body'])); + // Success + die(xmlrpc_encode_request(NULL,$source,$options)); + } + } + // No link to local page + die(xmlrpc_encode_request(NULL,0x11,$options)); + } + // Source failure + die(xmlrpc_encode_request(NULL,0x10,$options)); + } + // Doesn't exist (or not pingback-enabled) + die(xmlrpc_encode_request(NULL,0x21,$options)); + } + // Access denied + die(xmlrpc_encode_request(NULL,0x31,$options)); + } + + /** + * Return transaction history + * @return string + **/ + function log() { + return $this->log; + } + + /** + * Instantiate class + * @return object + **/ + function __construct() { + // Suppress errors caused by invalid HTML structures + libxml_use_internal_errors(TRUE); + } + +} diff --git a/lib/faker/.gitignore b/lib/faker/.gitignore new file mode 100755 index 0000000..7579f74 --- /dev/null +++ b/lib/faker/.gitignore @@ -0,0 +1,2 @@ +vendor +composer.lock diff --git a/lib/faker/.travis.yml b/lib/faker/.travis.yml new file mode 100755 index 0000000..80bebb2 --- /dev/null +++ b/lib/faker/.travis.yml @@ -0,0 +1,21 @@ +language: php + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - hhvm + +sudo: false + +cache: + directories: + - $HOME/.composer/cache + +before_script: + - travis_retry composer self-update + - travis_retry composer install --no-interaction --prefer-dist + +script: make sniff test diff --git a/lib/faker/CHANGELOG.md b/lib/faker/CHANGELOG.md new file mode 100755 index 0000000..b251047 --- /dev/null +++ b/lib/faker/CHANGELOG.md @@ -0,0 +1,295 @@ +CHANGELOG +========= + +2015-05-29, v1.5.0 +------------------ + +* Added ability to print custom text on the images fetched by the Image provider [\#583](https://github.com/fzaninotto/Faker/pull/583) ([fzaninotto](https://github.com/fzaninotto)) +* Fixed typos in Preuvian (es\_PE) Person provider [\#581](https://github.com/fzaninotto/Faker/pull/581) [\#580](https://github.com/fzaninotto/Faker/pull/580) ([ysramirez](https://github.com/ysramirez)) +* Added instructions for installing with composer to readme.md [\#572](https://github.com/fzaninotto/Faker/pull/572) ([totophe](https://github.com/totophe)) +* Added Kazakh (kk\_KZ) locale [\#569](https://github.com/fzaninotto/Faker/pull/569) ([YerlenZhubangaliyev](https://github.com/YerlenZhubangaliyev)) +* Added Korean (ko\_KR) locale [\#566](https://github.com/fzaninotto/Faker/pull/566) ([pearlc](https://github.com/pearlc)) +* Fixed file provider to ignore unreadable and special files [\#565](https://github.com/fzaninotto/Faker/pull/565) ([svrnm](https://github.com/svrnm)) +* Fixed Dutch (nl\_NL) Address and Person providers [\#560](https://github.com/fzaninotto/Faker/pull/560) ([killerog](https://github.com/killerog)) +* Fixed Dutch (nl\_NL) Person provider [\#559](https://github.com/fzaninotto/Faker/pull/559) ([pauledenburg](https://github.com/pauledenburg)) +* Added Russian (ru\_RU) Bank names provider [\#553](https://github.com/fzaninotto/Faker/pull/553) ([wizardjedi](https://github.com/wizardjedi)) +* Added mobile phone function in French (fr\_FR) provider [\#552](https://github.com/fzaninotto/Faker/pull/552) ([kletellier](https://github.com/kletellier)) +* Added phpdoc for new magic methods in Generator to help IntelliSense completion [\#550](https://github.com/fzaninotto/Faker/pull/550) ([stof](https://github.com/stof)) +* Fixed File provider bug 'The first argument to copy() function cannot be a directory' [\#547](https://github.com/fzaninotto/Faker/pull/547) ([svrnm](https://github.com/svrnm)) +* Added new Brazilian (pt\_BR) Providers [\#545](https://github.com/fzaninotto/Faker/pull/545) ([igorsantos07](https://github.com/igorsantos07)) +* Fixed ability to seed the generator [\#543](https://github.com/fzaninotto/Faker/pull/543) ([schmengler](https://github.com/schmengler)) +* Added streetAddress formatter to Russian (ru\_RU) provider [\#542](https://github.com/fzaninotto/Faker/pull/542) ([ZAYEC77](https://github.com/ZAYEC77)) +* Fixed Internet provider warning "Could not create transliterator"* [\#541](https://github.com/fzaninotto/Faker/pull/541) ([fonsecas72](https://github.com/fonsecas72)) +* Fixed Spanish for Argentina (es\_AR) Address provider [\#540](https://github.com/fzaninotto/Faker/pull/540) ([ivanmirson](https://github.com/ivanmirson)) +* Fixed region names in French for Belgium (fr\_BE) address provider [\#536](https://github.com/fzaninotto/Faker/pull/536) ([miclf](https://github.com/miclf)) +* Fixed broken Doctrine2 link in README [\#534](https://github.com/fzaninotto/Faker/pull/534) ([JonathanKryza](https://github.com/JonathanKryza)) +* Added link to faker-context Behat extension in readme [\#532](https://github.com/fzaninotto/Faker/pull/532) ([denheck](https://github.com/denheck)) +* Added PHP 7.0 nightly to Travis build targets [\#525](https://github.com/fzaninotto/Faker/pull/525) ([TomasVotruba](https://github.com/TomasVotruba)) +* Added Dutch (nl\_NL) color names [\#523](https://github.com/fzaninotto/Faker/pull/523) ([belendel](https://github.com/belendel)) +* Fixed Chinese (zh\_CN) Address provider (remove Taipei) [\#522](https://github.com/fzaninotto/Faker/pull/522) ([asika32764](https://github.com/asika32764)) +* Fixed phonenumber formats in Dutch (nl\_NL) PhoneNumber provider [\#521](https://github.com/fzaninotto/Faker/pull/521) ([SpaceK33z](https://github.com/SpaceK33z)) +* Fixed Russian (ru\_RU) Address provider [\#518](https://github.com/fzaninotto/Faker/pull/518) ([glagola](https://github.com/glagola)) +* Added Italian (it\_IT) Text provider [\#517](https://github.com/fzaninotto/Faker/pull/517) ([endelwar](https://github.com/endelwar)) +* Added Norwegian (no\_NO) locale [\#515](https://github.com/fzaninotto/Faker/pull/515) ([phaza](https://github.com/phaza)) +* Added VAT number to Bulgarian (bg\_BG) Payment provider [\#512](https://github.com/fzaninotto/Faker/pull/512) ([ronanguilloux](https://github.com/ronanguilloux)) +* Fixed UserAgent provider outdated user agents [\#511](https://github.com/fzaninotto/Faker/pull/511) ([ajbdev](https://github.com/ajbdev)) +* Fixed `image()` formatter to make it work with temp dir of any (decent) OS [\#507](https://github.com/fzaninotto/Faker/pull/507) ([ronanguilloux](https://github.com/ronanguilloux)) +* Added Persian (fa\_IR) locale [\#500](https://github.com/fzaninotto/Faker/pull/500) ([zoli](https://github.com/zoli)) +* Added Currency Code formatter [\#497](https://github.com/fzaninotto/Faker/pull/497) ([stelgenhof](https://github.com/stelgenhof)) +* Added VAT number to Belgium (be_BE) Payment provider [\#495](https://github.com/fzaninotto/Faker/pull/495) ([ronanguilloux](https://github.com/ronanguilloux)) +* Fixed `imageUrl` formatter bug where it would always return the same image [\#494](https://github.com/fzaninotto/Faker/pull/494) ([fzaninotto](https://github.com/fzaninotto)) +* Added more Indonesian (id\_ID) providers [\#493](https://github.com/fzaninotto/Faker/pull/493) ([deerawan](https://github.com/deerawan)) +* Added Indonesian (id\_ID) locale [\#492](https://github.com/fzaninotto/Faker/pull/492) ([stoutZero](https://github.com/stoutZero)) +* Fixed unique generator performance [\#491](https://github.com/fzaninotto/Faker/pull/491) ([ikwattro](https://github.com/ikwattro)) +* Added transliterator to `email` and `username` [\#490](https://github.com/fzaninotto/Faker/pull/490) ([fzaninotto](https://github.com/fzaninotto)) +* Added Hungarian (hu\_HU) Text provider [\#486](https://github.com/fzaninotto/Faker/pull/486) ([lintaba](https://github.com/lintaba)) +* Fixed CakePHP Entity Popolator (some cases where no entities prev. inserted) [\#483](https://github.com/fzaninotto/Faker/pull/483) ([jadb](https://github.com/jadb)) +* Added Color and DateTime Turkish (tr\_TR) Providers [\#481](https://github.com/fzaninotto/Faker/pull/481) ([behramcelen](https://github.com/behramcelen)) +* Added Latvian (lv\_LV) `personalIdentityNumber` formatter [\#472](https://github.com/fzaninotto/Faker/pull/472) ([MatissJanis](https://github.com/MatissJanis)) +* Added VAT number to Austrian (at_AT) Payment provider [\#470](https://github.com/fzaninotto/Faker/pull/470) ([ronanguilloux](https://github.com/ronanguilloux)) +* Fixed missing @return phpDoc in Payment provider [\#469](https://github.com/fzaninotto/Faker/pull/469) ([ronanguilloux](https://github.com/ronanguilloux)) +* Added SWIFT/BIC payment type formatter to the Payment provider [\#465](https://github.com/fzaninotto/Faker/pull/465) ([ronanguilloux](https://github.com/ronanguilloux)) +* Fixed small typo in Base provider exception [\#460](https://github.com/fzaninotto/Faker/pull/460) ([miclf](https://github.com/miclf)) +* Added Georgian (ka\_Ge) locale [\#457](https://github.com/fzaninotto/Faker/pull/457) ([lperto](https://github.com/lperto)) +* Added PSR-4 Autoloading [\#455](https://github.com/fzaninotto/Faker/pull/455) ([GrahamCampbell](https://github.com/GrahamCampbell)) +* Added Uganda (en_UG) locale [\#454](https://github.com/fzaninotto/Faker/pull/454) ([tharoldD](https://github.com/tharoldD)) +* Added `regexify` formatter, generating a random string based on a regular expression [\#453](https://github.com/fzaninotto/Faker/pull/453) ([fzaninotto](https://github.com/fzaninotto)) +* Added shuffle formatter, to shuffle an array or a string [\#452](https://github.com/fzaninotto/Faker/pull/452) ([fzaninotto](https://github.com/fzaninotto)) +* Added ISBN-10 & ISBN-13 codes formatters to Barcode provider [\#451](https://github.com/fzaninotto/Faker/pull/451) ([gietos](https://github.com/gietos)) +* Fixed Russian (ru\_RU) middle names (different for different genders) [\#450](https://github.com/fzaninotto/Faker/pull/450) ([gietos](https://github.com/gietos)) +* Fixed Ukranian (uk\_UA) Person provider [\#448](https://github.com/fzaninotto/Faker/pull/448) ([aivus](https://github.com/aivus)) +* Added Vietnamese (vi\_VN) locale [\#447](https://github.com/fzaninotto/Faker/pull/447) ([huy95](https://github.com/huy95)) +* Added type hint to the Documentor constructor [\#446](https://github.com/fzaninotto/Faker/pull/446) ([JeroenDeDauw](https://github.com/JeroenDeDauw)) +* Fixed Russian (ru\_RU) Person provider (joined names) [\#445](https://github.com/fzaninotto/Faker/pull/445) ([aivus](https://github.com/aivus)) +* Added English (en\_GB) `mobileNumber` methods [\#438](https://github.com/fzaninotto/Faker/pull/438) ([daveblake](https://github.com/daveblake)) +* Added Traditional Chinese (zh\_TW) Realtext provider [\#434](https://github.com/fzaninotto/Faker/pull/434) ([tzhuan](https://github.com/tzhuan)) +* Fixed first name in Spanish for Argentina (es\_AR) Person provider [\#433](https://github.com/fzaninotto/Faker/pull/433) ([fzaninotto](https://github.com/fzaninotto)) +* Fixed Canadian (en_CA) state abbreviation for Nunavut [\#430](https://github.com/fzaninotto/Faker/pull/430) ([julien-c](https://github.com/julien-c)) +* Added CakePHP ORM entity populator [\#428](https://github.com/fzaninotto/Faker/pull/428) ([jadb](https://github.com/jadb)) +* Added Traditional Chinese (zh\_TW) locale [\#427](https://github.com/fzaninotto/Faker/pull/427) ([tzhuan](https://github.com/tzhuan)) +* Fixed typo in Doctrine Populator phpDoc [\#425](https://github.com/fzaninotto/Faker/pull/425) ([ihsanudin](https://github.com/ihsanudin)) +* Added Chinese (zh_CN) Internet provider [\#424](https://github.com/fzaninotto/Faker/pull/424) ([Lisso-Me](https://github.com/Lisso-Me)) +* Added Country ISO 3166-1 alpha-3 code to the Miscellaneous provider[\#422](https://github.com/fzaninotto/Faker/pull/422) ([gido](https://github.com/gido)) +* Added English (en\_GB) Person provider [\#421](https://github.com/fzaninotto/Faker/pull/421) ([AlexCutts](https://github.com/AlexCutts)) +* Added missing tests for the Color Provider [\#420](https://github.com/fzaninotto/Faker/pull/420) ([bessl](https://github.com/bessl)) +* Added Nepali (ne\_NP) locale [\#419](https://github.com/fzaninotto/Faker/pull/419) ([ankitpokhrel](https://github.com/ankitpokhrel)) +* Fixed latitude and longitude formatters bug (numeric value out of range for 32bits) [\#416](https://github.com/fzaninotto/Faker/pull/416) ([fzaninotto](https://github.com/fzaninotto)) +* Added a dedicated calculator Luhn calculator service [\#414](https://github.com/fzaninotto/Faker/pull/414) ([fzaninotto](https://github.com/fzaninotto)) +* Fixed Russian (ru_RU) Person provider (removed lowercase duplications) [\#413](https://github.com/fzaninotto/Faker/pull/413) ([Ragazzo](https://github.com/Ragazzo)) +* Fixed barcode formatter (improved speed, added tests) [\#412](https://github.com/fzaninotto/Faker/pull/412) ([fzaninotto](https://github.com/fzaninotto)) +* Added ipv4 and barcode formatters tests [\#410](https://github.com/fzaninotto/Faker/pull/410) ([bessl](https://github.com/bessl)) +* Fixed typos in various comments blocks [\#409](https://github.com/fzaninotto/Faker/pull/409) ([bessl](https://github.com/bessl)) +* Fixed InternetTest (replaced regex with PHP filter) [\#406](https://github.com/fzaninotto/Faker/pull/406) ([bessl](https://github.com/bessl)) +* Added password formatter to the Internet provider[\#402](https://github.com/fzaninotto/Faker/pull/402) ([fzaninotto](https://github.com/fzaninotto)) +* Added Company and Internet Austrian (de\_AT) Providers [\#400](https://github.com/fzaninotto/Faker/pull/400) ([bessl](https://github.com/bessl)) +* Added third-party libraries section in README [\#399](https://github.com/fzaninotto/Faker/pull/399) ([fzaninotto](https://github.com/fzaninotto)) +* Added Spanish for Venezuela (es\_VE) locale [\#398](https://github.com/fzaninotto/Faker/pull/398) ([DIOHz0r](https://github.com/DIOHz0r)) +* Added PhoneNumber Autrian (de\_AT) Provider, and missing test for the 'locale' method. [\#395](https://github.com/fzaninotto/Faker/pull/395) ([bessl](https://github.com/bessl)) +* Removed wrongly localized Lorem provider [\#394](https://github.com/fzaninotto/Faker/pull/394) ([fzaninotto](https://github.com/fzaninotto)) +* Fixed Miscellaneous provider (made the `locale` formatter static) [\#390](https://github.com/fzaninotto/Faker/pull/390) ([bessl](https://github.com/bessl)) +* Added a unit test file for the Miscellaneous Provider [\#389](https://github.com/fzaninotto/Faker/pull/389) ([bessl](https://github.com/bessl)) +* Added warning in README about using `rand()`` and the seed functions [\#386](https://github.com/fzaninotto/Faker/pull/386) ([paulvalla](https://github.com/paulvalla)) +* Fixed French (fr\_FR) Person provider (Uppercased a first name) [\#385](https://github.com/fzaninotto/Faker/pull/385) ([netcarver](https://github.com/netcarver)) +* Added Russian (ru\_RU) and Ukrainian (uk\_UA) Text providers [\#383](https://github.com/fzaninotto/Faker/pull/383) ([terion-name](https://github.com/terion-name)) +* Added more street prefixes to French (fr\_FR) Address provider [\#381](https://github.com/fzaninotto/Faker/pull/381) ([ronanguilloux](https://github.com/ronanguilloux)) +* Added PHP 5.6 to CI targets [\#378](https://github.com/fzaninotto/Faker/pull/378) ([GrahamCampbell](https://github.com/GrahamCampbell)) +* Fixed spaces remaining at the end of liine in various files [\#377](https://github.com/fzaninotto/Faker/pull/377) ([GrahamCampbell](https://github.com/GrahamCampbell)) +* Fixed UserAgent provider (added space before processor on linux platform) [\#374](https://github.com/fzaninotto/Faker/pull/374) ([TomK](https://github.com/TomK)) +* Added Company generator for Russian (ru\_RU) locale [\#371](https://github.com/fzaninotto/Faker/pull/371) ([kix](https://github.com/kix)) +* Fixed Russian (ru\_RU) Color provider (uppercase letters) [\#370](https://github.com/fzaninotto/Faker/pull/370) ([semanser](https://github.com/semanser)) +* Added more Polish (pl\_PL) phone numbers [\#369](https://github.com/fzaninotto/Faker/pull/369) ([piotrantosik](https://github.com/piotrantosik)) +* Fixed Ruby Faker link in readme [\#368](https://github.com/fzaninotto/Faker/pull/368) ([philsturgeon](https://github.com/philsturgeon)) +* Added more Japanese (ja\_JP) names in Person provider [\#366](https://github.com/fzaninotto/Faker/pull/366) ([kumamidori](https://github.com/kumamidori)) +* Added Slovenian (sl\_SL) locale [\#363](https://github.com/fzaninotto/Faker/pull/363) ([alesf](https://github.com/alesf)) +* Fixed German (de\_DE) Person provider (first names) [\#362](https://github.com/fzaninotto/Faker/pull/362) ([mikehaertl](https://github.com/mikehaertl)) +* Fixed Ukrainian (uk\_UA) Person providr (there is no such letter "ы" in Ukrainian) [\#359](https://github.com/fzaninotto/Faker/pull/359) ([nazar-pc](https://github.com/nazar-pc)) +* Fixed Chinese (zh\_CN) PhoneNumber provider (the length of mobile phone number is 11) [\#358](https://github.com/fzaninotto/Faker/pull/358) ([byan](https://github.com/byan)) +* Added Arabic (ar_\JO) Locale [\#357](https://github.com/fzaninotto/Faker/pull/357) ([zrashwani](https://github.com/zrashwani)) +* Fixed Czech (cs\_CZ) Person provider (missing lowercase in last name) [\#355](https://github.com/fzaninotto/Faker/pull/355) ([halaxa](https://github.com/halaxa)) +* Fixed French for Belgium (fr\_BE) Address Provider (doubled city names) [\#354](https://github.com/fzaninotto/Faker/pull/354) ([miclf](https://github.com/miclf)) +* Added Biased Integer Provider [\#332](https://github.com/fzaninotto/Faker/pull/332) ([TimWolla](https://github.com/TimWolla)) +* Added Swedish (sv\_SE) locale [\#316](https://github.com/fzaninotto/Faker/pull/316) ([ulrikjohansson](https://github.com/ulrikjohansson)) +* Added English for New Zealand (en\_NZ) locale [\#283](https://github.com/fzaninotto/Faker/pull/283) ([JasonMortonNZ](https://github.com/JasonMortonNZ)) +* Added mention of external Provider for cron expressions to readme[\#498](https://github.com/fzaninotto/Faker/pull/498) ([swekaj](https://github.com/swekaj)) + +2014-06-04, v1.4.0 +------------------ + +* Fixed typo in Slovak person names (cinan) +* Added tests for uk_UA providers (serge-kuharev) +* Fixed numerify() performance by making it 30% faster (fzaninotto) +* Added strict option to randomNumber to force number of digits (fzaninotto) +* Fixed randomNumber usage duplicating numberBetween (fzaninotto) +* Fixed address provider for latvian language (MatissJA) +* Added Czech Republic (cs_CZ) address, company, datetime and text providers (Mikulas) +* Fixed da_DK Person provider data containing an 'unnamed' person (tolnem) +* Added slug provider (fzaninotto) +* Fixed IDE insights for new local IP and MAC address providers (hugofonseca) +* Added firstname gender method to all Person providers (csanquer) +* Fixed tr_TR email service, city name, person, and phone number formats (ogunkarakus) +* Fixed US_en state list (fzaninotto) +* Fixed en_US address provider so state abbr are ISO 3166 codes (Garbee) +* Added local IP and MAC address providers (kielabokkie) +* Fixed typo in century list affecting the century provider (fzaninotto) +* Added default value to optional modifier (joshuajabbour) +* Fixed Portuguese phonenumbers have 9 digits (hugofonseca) +* Added fileCopy to File provider to simulate file upload (stefanosala) +* Added pt_PT providers (hugofonseca) +* Fixed dead code in text provider (hugofonseca) +* Fixed IDE insights for magic properties (hugofonseca) +* Added tin (NIF) generator for pt_PT provider (hugofonseca) +* Fixed numberBetween max default value handling (fzaninotto) +* Added pt_PT phone number provider (hugofonseca) +* Fixed PSR-2 standards and add make task to force it on Travis (terite) +* Added new ro_RO Personal Numerical Code (CNP) and phone number providers (avataru) +* Fixed Internet provider for sk_SK locale (cinan) +* Fixed typo in en_ZA Internet provider (bjorntheart) +* Fixed phpdoc for DateTime magic methods (stof) +* Added doc about seeding with maximum timestamp using dateTime formatters (fzaninotto) +* Added Maximum Timestamp option to get always same unix timestamp when using a fixed seed (csanquer) +* Added Montenegrian (me_ME) providers (ognjenm) +* Added ean barcode provider (nineinchnick) +* Added fullPath parameter to Image provider (stefanosala) +* Added more Polish company formats (nineinchnick) +* Added Polish realText provider (nineinchnick) +* Fixed remaining non-seedable random generators (terite) +* Added randomElements provider (terite) +* Added French realText provider (fzaninotto) +* Fixed realText provider bootstrap slowness (fzaninotto) +* Added realText provider for English and German, based on Markov Chains Generator (TimWolla) +* Fixed address format in nl_NL provider (doenietzomoeilijk) +* Fixed potentially offensive word from last name list (joshuajabbour) +* Fixed reamde documentation about the optional modifier (cryode) +* Fixed Image provider and documentor routine (fzaninotto) +* Fixed IDE insights for methods (PedroTroller) +* Fixed missing data in en_US Address provider (Garbee) +* Added Bengali (bn_BD) providers (masnun) +* Fixed warning on test file when short tags are on (bateller) +* Fixed Doctrine populator undefined index warning (dbojdo) +* Added French Canadian (fr_CA) Address and Person providers (marcaube) +* Fixed typo in NullGenerator (mhanson01) +* Fixed Doctrine populator issue with one-to-one nullable relationship (jpetitcolas) +* Added Canadian English (en_CA) address and phone number providers (cviebrock) +* Fixed duplicated Payment example in readme (Garbee) +* Fixed Polish (pl_PL) Person provider data (czogori) +* Added Hungarian (hu_HU) providers (sagikazarmark) +* Added 'kana' (ja_JP) name formatters (kzykhys) +* Added allow_failure for hhvm to travis-ci and test against php 5.5 (toin0u) + +2013-12-16, v1.3.0 +------------------ + +* Fixed state generator in Australian (en_AU) provider (sebklaus) +* Fixed IDE insights for locale specific providers (ulrikjohansson) +* Added English (South Africa) (en_ZA) person, address, Internet and phone number providers (dmfaux) +* Fixed integer values overflowing on signed INTEGER columns on Doctrine populator (Thinkscape) +* Fixed spelling error in French (fr_FR) address provider (leihog) +* Added improvements based on SensioLabsInsights analysis +* Fixed Italian (it_IT) email provider (garak) +* Added Spanish (es_ES) Internet provider (eusonlito) +* Added English Philippines (en_PH) address provider (kamote) +* Added Brazilian (pt_BR) email provider data (KennedyTedesco) +* Fixed UK country code (pgscandeias) +* Added Peruvian (es_PE) person, address, phone number, and company providers (cslucano) +* Added Ukrainian (uk_UA) color provider (ruden) +* Fixed Ukrainian (uk_UA) namespace and email translitteration (ruden) +* Added Romanian (Moldova) (ro_MD) person, address, and phone number providers (AlexanderC) +* Added IBAN generator for every currently known locale that uses it (nineinchnick) +* Added Image generation powered by LoremPixel (weotch) +* Fixed missing timezone with dateTimeBetween (baldurrensch) +* Fixed call to undefined method cardType in Payment (WMeldon) +* Added Romanian (ro_RO) address and person providers (calina-c) +* Fixed Doctrine populator to use ObjectManager instead of EntityManagerInterface (mgiustiniani) +* Fixed docblock for Provider\Base::unique() (pschultz) +* Added Payment providers (creditCardType, creditCardNumber, creditCardExpirationDate, creditCardExpirationDateString) (pomaxa) +* Added unique() modifier +* Added IDE insights to allow better intellisense/phpStorm autocompletion (thallisphp) +* Added Polish (pl_PL) address provider, personal identity number and pesel number generator (nineinchnick) +* Added Turkish (tr_TR) address provider, and improved internet provider (hasandz) +* Fixed Propel column number guesser to use signed range of values (gunnarlium) +* Added Greek (el_GR) person, address, and phone number providers (georgeharito) +* Added Austrian (en_AU) address, Internet, and phone number providers (rcuddy) +* Fixed phpDoc in Doctrine Entity populator (rogamoore) +* Added French (fr_FR) phone number formats (vchabot) +* Added optional() modifier (weotch) +* Fixed typo in the Person provider documentation (jtreminio) +* Fixed Russian (ru_RU) person format (alexshadow007) +* Added Japanese (ja_JP) person, address, Internet, phone number, and company providers (kumamidori) +* Added color providers, driver license and passport number formats for the ru_RU locale (pomaxa) +* Added Latvian (lv_LV) person, address, Internet, and phone number providers (pomaxa) +* Added Brazilian (pt_BR) Internet provider (vjnrv) +* Added more Czech (cs_CZ) lastnames (petrkle) +* Added Chinese Simplified (zh_CN) person, address, Internet, and phone number providers (tlikai) +* Fixed Typos (pborelli) +* Added Color provider with hexColor, rgbColor, rgbColorAsArray, rgbCssColor, safeColorName, and colorName formatters (lsv) +* Added support for associative arrays in `randomElement` (aRn0D) + + +2013-06-09, v1.2.0 +------------------ + +* Added new provider for fr_BE locale (jflefebvre) +* Updated locale provider to use a static locale list (spawn-guy) +* Fixed invalid UTF-8 sequence in domain provider with the Bulgarian provider (Dynom) +* Fixed the nl_NL Person provider (Dynom) +* Removed all requires and added the autoload definition to composer (Dynom) +* Fixed encoding problems in nl_NL Address provider (Dynom) +* Added icelandic provider (is_IS) (birkir) +* Added en_CA address and phone numbers (cviebrock) +* Updated safeEmail provider to be really safe (TimWolla) +* Documented alternative randomNumber usage (Seldaek) +* Added basic file provider (anroots) +* Fixed use of fourth argument on Doctrine addEntity (ecentinela) +* Added nl_BE provider (wimvds) +* Added Random Float provider (csanquer) +* Fixed bug in Faker\ORM\Doctrine\Populator (mmf-amarcos) +* Updated ru_RU provider (rmrevin) +* Added safe email domain provider (csanquer) +* Fixed latitude provider (rumpl) +* Fixed unpredictability of fake data generated by Faker\Provider\Base::numberBetween() (goatherd) +* Added uuid provider (goatherd) +* Added possibility to call methods on Doctrine entities, possibility to generate unique id (nenadalm) +* Fixed prefixes typos in 'pl_PL' Person provider (krymen) +* Added more fake data to the Ukraininan providers (lysenkobv) +* Added more fake data to the Italian providers (EmanueleMinotto) +* Fixed spaces appearing in generated emails (alchy58) +* Added Armenian (hy_AM) provider (artash) +* Added Generation of valid SIREN & SIRET codes to French providers (alexsegura) +* Added Dutch (nl_NL) provider (WouterJ) +* Fixed missing typehint in Base::__construct() (benja-M-1) +* Fixed typo in README (benja-M-1) +* Added Ukrainian (ua_UA) provider (rsvasilyev) +* Added Turkish (tr_TR) Provider (faridmovsumov) +* Fixed executable bit in some PHP files (siwinski) +* Added Brazilian Portuguese (pt_BR) provider (oliveiraev) +* Added Spanish (es_ES) provider (ivannis) +* Fixed Doctrine populator to allow for the population of entity data that has associations to other entities (afishnamedsquish) +* Added Danish (da_DK) providers (toin0u) +* Cleaned up whitespaces (toin0u) +* Fixed utf-8 bug with lowercase generators (toin0u) +* Fixed composer.json (Seldaek) +* Fixed bug in Doctrine EntityPopulator (beberlei) +* Added Finnish (fi_FI) provider (drodil) + +2012-10-29, v1.1.0 +------------------ + +* Updated text provider to return paragraphs as a string instead of array. Great for populating markdown textarea fields (Seldaek) +* Updated dateTimeBetween to accept DateTime instances (Seldaek) +* Added random number generator between a and b, simply like rand() (Seldaek) +* Fixed spaces in generated emails (blaugueux) +* Fixed Person provider in Russian locale (Isamashii) +* Added new UserAgent provider (blaugueux) +* Added locale generator to Miscellaneous provider (blaugueux) +* Added timezone generator to DateTime provider (blaugueux) +* Added new generators to French Address providers (departments, regions) (geoffrey-brier) +* Added new generators to French Company provider (catch phrase, SIREN, and SIRET numbers) (geoffrey-brier) +* Added state generator to German Address provider (Powerhamster) +* Added Slovak provider (bazo) +* Added latitude and longitude formatters to Address provider (fixe) +* Added Serbian provider (umpirsky) + +2012-07-10, v1.0.0 +----------------- + +* Initial Version diff --git a/lib/faker/CONTRIBUTING.md b/lib/faker/CONTRIBUTING.md new file mode 100755 index 0000000..804bf79 --- /dev/null +++ b/lib/faker/CONTRIBUTING.md @@ -0,0 +1,22 @@ +Contributing +============ + +If you've written a new formatter, adapted Faker to a new locale, or fixed a bug, your contribution is welcome! + +Before proposing a pull request, check the following: + +* Your code should follow the [PSR-2 coding standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md). Run `make sniff` to check that the coding standards are followed, and use [php-cs-fixer](https://github.com/fabpot/PHP-CS-Fixer) to fix inconsistencies. +* Unit tests should still pass after your patch. Run the tests on your dev server (with `make test`) or check the continuous integration status for your pull request. +* As much as possible, add unit tests for your code +* Never use `rand()` in your providers. Faker uses the Mersenne Twister Randomizer, so use `mt_rand()` or any of the base generators (`randomNumber`, `randomElement`, etc.) instead. +* If you add new providers (or new locales) and that they embed a lot of data for random generation (e.g. first names in a new language), please add a `@link` to the reference you used for this list (example [in the ru_RU locale](https://github.com/fzaninotto/Faker/blob/master/src/Faker/Provider/ru_RU/Person.php#L13)). This will ease future updates of the list and debates about the most relevant data for this provider. +* If you add long list of random data, please split the list into several lines. This makes diffs easier to read, and facilitates core review. +* If you add new formatters, please include documentation for it in the README. Don't forget to add a line about new formatters in the `@property` or `@method` phpDoc entries in [Generator.php](https://github.com/fzaninotto/Faker/blob/master/src/Faker/Generator.php#L6-L118) to help IDEs auto-complete your formatters. +* If your new formatters are specific to a certain locale, document them in the [Language-specific formatters](https://github.com/fzaninotto/Faker#language-specific-formatters) list instead. +* Avoid changing existing sets of data. Some developers use Faker with seeding for unit tests ; changing the data makes their tests fail. +* Speed is important in all Faker usages. Make sure your code is optimized to generate thousands of fake items in no time, without consuming too much memory or CPU. +* If you commit a new feature, be prepared to help maintaining it. Watch the project on GitHub, and please comment on issues or PRs regarding the feature you contributed. + +Once your code is merged, it is available for free to everybody under the MIT License. Publishing your Pull Request on the Faker GitHub repository means that you agree with this license for your contribution. + +Thank you for your contribution! Faker wouldn't be so great without you. diff --git a/lib/faker/LICENSE b/lib/faker/LICENSE new file mode 100755 index 0000000..99ed007 --- /dev/null +++ b/lib/faker/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011 François Zaninotto +Portions Copyright (c) 2008 Caius Durling +Portions Copyright (c) 2008 Adam Royle +Portions Copyright (c) 2008 Fiona Burrows + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/lib/faker/Makefile b/lib/faker/Makefile new file mode 100755 index 0000000..ad0bb40 --- /dev/null +++ b/lib/faker/Makefile @@ -0,0 +1,10 @@ +vendor/autoload.php: + composer install --no-interaction --prefer-source + +.PHONY: sniff +sniff: vendor/autoload.php + vendor/bin/phpcs --standard=PSR2 src -n + +.PHONY: test +test: vendor/autoload.php + vendor/bin/phpunit --verbose diff --git a/lib/faker/composer.json b/lib/faker/composer.json new file mode 100755 index 0000000..8d432f7 --- /dev/null +++ b/lib/faker/composer.json @@ -0,0 +1,35 @@ +{ + "name": "fzaninotto/faker", + "type": "library", + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": ["faker", "fixtures", "data"], + "license": "MIT", + "authors": [ + { + "name": "François Zaninotto" + } + ], + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5", + "ext-intl": "*" + }, + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "autoload-dev": { + "psr-4": { + "Faker\\PHPUnit\\": "test/Faker/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + } +} diff --git a/lib/faker/phpunit.xml.dist b/lib/faker/phpunit.xml.dist new file mode 100755 index 0000000..4ffa17f --- /dev/null +++ b/lib/faker/phpunit.xml.dist @@ -0,0 +1,12 @@ + + + + + + ./test/Faker/ + + + diff --git a/lib/faker/readme.md b/lib/faker/readme.md new file mode 100755 index 0000000..a80bda2 --- /dev/null +++ b/lib/faker/readme.md @@ -0,0 +1,1176 @@ +# Faker + +Faker is a PHP library that generates fake data for you. Whether you need to bootstrap your database, create good-looking XML documents, fill-in your persistence to stress test it, or anonymize data taken from a production service, Faker is for you. + +Faker is heavily inspired by Perl's [Data::Faker](http://search.cpan.org/~jasonk/Data-Faker-0.07/), and by ruby's [Faker](https://rubygems.org/gems/faker). + +Faker requires PHP >= 5.3.3. + +[![Monthly Downloads](https://poser.pugx.org/fzaninotto/faker/d/monthly.png)](https://packagist.org/packages/fzaninotto/faker) [![Build Status](https://travis-ci.org/fzaninotto/Faker.svg?branch=master)](https://travis-ci.org/fzaninotto/Faker) [![SensioLabsInsight](https://insight.sensiolabs.com/projects/eceb78a9-38d4-4ad5-8b6b-b52f323e3549/mini.png)](https://insight.sensiolabs.com/projects/eceb78a9-38d4-4ad5-8b6b-b52f323e3549) + +# Table of Contents + +- [Installation](#installation) +- [Basic Usage](#basic-usage) +- [Formatters](#formatters) + - [Base](#fakerproviderbase) + - [Lorem Ipsum Text](#fakerproviderlorem) + - [Person](#fakerprovideren_usperson) + - [Address](#fakerprovideren_usaddress) + - [Phone Number](#fakerprovideren_usphonenumber) + - [Company](#fakerprovideren_uscompany) + - [Real Text](#fakerprovideren_ustext) + - [Date and Time](#fakerproviderdatetime) + - [Internet](#fakerproviderinternet) + - [User Agent](#fakerprovideruseragent) + - [Payment](#fakerproviderpayment) + - [Color](#fakerprovidercolor) + - [File](#fakerproviderfile) + - [Image](#fakerproviderimage) + - [Uuid](#fakerprovideruuid) + - [Barcode](#fakerproviderbarcode) + - [Miscellaneous](#fakerprovidermiscellaneous) + - [Biased](#fakerproviderbiased) +- [Unique and Optional modifiers](#unique-and-optional-modifiers) +- [Localization](#localization) +- [Populating Entities Using an ORM or an ODM](#populating-entities-using-an-orm-or-an-odm) +- [Seeding the Generator](#seeding-the-generator) +- [Faker Internals: Understanding Providers](#faker-internals-understanding-providers) +- [Real Life Usage](#real-life-usage) +- [Language specific formatters](#language-specific-formatters) +- [Third-Party Libraries Extending/Based On Faker](#third-party-libraries-extendingbased-on-faker) +- [License](#license) + + +## Installation + +```sh +composer require fzaninotto/faker +``` + +## Basic Usage + +Use `Faker\Factory::create()` to create and initialize a faker generator, which can generate data by accessing properties named after the type of data you want. + +```php +name; + // 'Lucy Cechtelar'; +echo $faker->address; + // "426 Jordy Lodge + // Cartwrightshire, SC 88120-6700" +echo $faker->text; + // Dolores sit sint laboriosam dolorem culpa et autem. Beatae nam sunt fugit + // et sit et mollitia sed. + // Fuga deserunt tempora facere magni omnis. Omnis quia temporibus laudantium + // sit minima sint. +``` + +Even if this example shows a property access, each call to `$faker->name` yields a different (random) result. This is because Faker uses `__get()` magic, and forwards `Faker\Generator->$property` calls to `Faker\Generator->format($property)`. + +```php +name, "\n"; +} + // Adaline Reichel + // Dr. Santa Prosacco DVM + // Noemy Vandervort V + // Lexi O'Conner + // Gracie Weber + // Roscoe Johns + // Emmett Lebsack + // Keegan Thiel + // Wellington Koelpin II + // Ms. Karley Kiehn V +``` + +**Tip**: For a quick generation of fake data, you can also use Faker as a command line tool thanks to [faker-cli](https://github.com/bit3/faker-cli). + +## Formatters + +Each of the generator properties (like `name`, `address`, and `lorem`) are called "formatters". A faker generator has many of them, packaged in "providers". Here is a list of the bundled formatters in the default locale. + +### `Faker\Provider\Base` + + randomDigit // 7 + randomDigitNotNull // 5 + randomNumber($nbDigits = NULL) // 79907610 + randomFloat($nbMaxDecimals = NULL, $min = 0, $max = NULL) // 48.8932 + numberBetween($min = 1000, $max = 9000) // 8567 + randomLetter // 'b' + randomElements($array = array ('a','b','c'), $count = 1) // array('c') + randomElement($array = array ('a','b','c')) // 'b' + shuffle('hello, world') // 'rlo,h eoldlw' + shuffle(array(1, 2, 3)) // array(2, 1, 3) + numerify('Hello ###') // 'Hello 609' + lexify('Hello ???') // 'Hello wgt' + bothify('Hello ##??') // 'Hello 42jz' + asciify('Hello ***') // 'Hello R6+' + regexify('[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'); // sm0@y8k96a.ej + +### `Faker\Provider\Lorem` + + word // 'aut' + words($nb = 3) // array('porro', 'sed', 'magni') + sentence($nbWords = 6) // 'Sit vitae voluptas sint non voluptates.' + sentences($nb = 3) // array('Optio quos qui illo error.', 'Laborum vero a officia id corporis.', 'Saepe provident esse hic eligendi.') + paragraph($nbSentences = 3) // 'Ut ab voluptas sed a nam. Sint autem inventore aut officia aut aut blanditiis. Ducimus eos odit amet et est ut eum.' + paragraphs($nb = 3) // array('Quidem ut sunt et quidem est accusamus aut. Fuga est placeat rerum ut. Enim ex eveniet facere sunt.', 'Aut nam et eum architecto fugit repellendus illo. Qui ex esse veritatis.', 'Possimus omnis aut incidunt sunt. Asperiores incidunt iure sequi cum culpa rem. Rerum exercitationem est rem.') + text($maxNbChars = 200) // 'Fuga totam reiciendis qui architecto fugiat nemo. Consequatur recusandae qui cupiditate eos quod.' + +### `Faker\Provider\en_US\Person` + + title($gender = null|'male'|'female') // 'Ms.' + titleMale // 'Mr.' + titleFemale // 'Ms.' + suffix // 'Jr.' + name($gender = null|'male'|'female') // 'Dr. Zane Stroman' + firstName($gender = null|'male'|'female') // 'Maynard' + firstNameMale // 'Maynard' + firstNameFemale // 'Rachel' + lastName // 'Zulauf' + +### `Faker\Provider\en_US\Address` + + cityPrefix // 'Lake' + secondaryAddress // 'Suite 961' + state // 'NewMexico' + stateAbbr // 'OH' + citySuffix // 'borough' + streetSuffix // 'Keys' + buildingNumber // '484' + city // 'West Judge' + streetName // 'Keegan Trail' + streetAddress // '439 Karley Loaf Suite 897' + postcode // '17916' + address // '8888 Cummings Vista Apt. 101, Susanbury, NY 95473' + country // 'Falkland Islands (Malvinas)' + latitude // 77.147489 + longitude // 86.211205 + +### `Faker\Provider\en_US\PhoneNumber` + + phoneNumber // '201-886-0269 x3767' + tollFreePhoneNumber // '(888) 937-7238' + +### `Faker\Provider\en_US\Company` + + catchPhrase // 'Monitored regional contingency' + bs // 'e-enable robust architectures' + company // 'Bogan-Treutel' + companySuffix // 'and Sons' + +### `Faker\Provider\en_US\Text` + + realText($maxNbChars = 200, $indexSize = 2) // "And yet I wish you could manage it?) 'And what are they made of?' Alice asked in a shrill, passionate voice. 'Would YOU like cats if you were never even spoke to Time!' 'Perhaps not,' Alice replied." + +### `Faker\Provider\DateTime` + + unixTime($max = 'now') // 58781813 + dateTime($max = 'now') // DateTime('2008-04-25 08:37:17') + dateTimeAD($max = 'now') // DateTime('1800-04-29 20:38:49') + iso8601($max = 'now') // '1978-12-09T10:10:29+0000' + date($format = 'Y-m-d', $max = 'now') // '1979-06-09' + time($format = 'H:i:s', $max = 'now') // '20:49:42' + dateTimeBetween($startDate = '-30 years', $endDate = 'now') // DateTime('2003-03-15 02:00:49') + dateTimeInInterval($startDate = '-30 years', $interval = '+ 5 days') // DateTime('2003-03-15 02:00:49') + dateTimeThisCentury($max = 'now') // DateTime('1915-05-30 19:28:21') + dateTimeThisDecade($max = 'now') // DateTime('2007-05-29 22:30:48') + dateTimeThisYear($max = 'now') // DateTime('2011-02-27 20:52:14') + dateTimeThisMonth($max = 'now') // DateTime('2011-10-23 13:46:23') + amPm($max = 'now') // 'pm' + dayOfMonth($max = 'now') // '04' + dayOfWeek($max = 'now') // 'Friday' + month($max = 'now') // '06' + monthName($max = 'now') // 'January' + year($max = 'now') // '1993' + century // 'VI' + timezone // 'Europe/Paris' + +### `Faker\Provider\Internet` + + email // 'tkshlerin@collins.com' + safeEmail // 'king.alford@example.org' + freeEmail // 'bradley72@gmail.com' + companyEmail // 'russel.durward@mcdermott.org' + freeEmailDomain // 'yahoo.com' + safeEmailDomain // 'example.org' + userName // 'wade55' + password // 'k&|X+a45*2[' + domainName // 'wolffdeckow.net' + domainWord // 'feeney' + tld // 'biz' + url // 'http://www.skilesdonnelly.biz/aut-accusantium-ut-architecto-sit-et.html' + slug // 'aut-repellat-commodi-vel-itaque-nihil-id-saepe-nostrum' + ipv4 // '109.133.32.252' + localIpv4 // '10.242.58.8' + ipv6 // '8e65:933d:22ee:a232:f1c1:2741:1f10:117c' + macAddress // '43:85:B7:08:10:CA' + +### `Faker\Provider\UserAgent` + + userAgent // 'Mozilla/5.0 (Windows CE) AppleWebKit/5350 (KHTML, like Gecko) Chrome/13.0.888.0 Safari/5350' + chrome // 'Mozilla/5.0 (Macintosh; PPC Mac OS X 10_6_5) AppleWebKit/5312 (KHTML, like Gecko) Chrome/14.0.894.0 Safari/5312' + firefox // 'Mozilla/5.0 (X11; Linuxi686; rv:7.0) Gecko/20101231 Firefox/3.6' + safari // 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_7_1 rv:3.0; en-US) AppleWebKit/534.11.3 (KHTML, like Gecko) Version/4.0 Safari/534.11.3' + opera // 'Opera/8.25 (Windows NT 5.1; en-US) Presto/2.9.188 Version/10.00' + internetExplorer // 'Mozilla/5.0 (compatible; MSIE 7.0; Windows 98; Win 9x 4.90; Trident/3.0)' + +### `Faker\Provider\Payment` + + creditCardType // 'MasterCard' + creditCardNumber // '4485480221084675' + creditCardExpirationDate // 04/13 + creditCardExpirationDateString // '04/13' + creditCardDetails // array('MasterCard', '4485480221084675', 'Aleksander Nowak', '04/13') + // Generates a random IBAN. Set $countryCode to null for a random country + iban($countryCode) // 'IT31A8497112740YZ575DJ28BP4' + swiftBicNumber // RZTIAT22263 + +### `Faker\Provider\Color` + + hexcolor // '#fa3cc2' + rgbcolor // '0,255,122' + rgbColorAsArray // array(0,255,122) + rgbCssColor // 'rgb(0,255,122)' + safeColorName // 'fuchsia' + colorName // 'Gainsbor' + +### `Faker\Provider\File` + + fileExtension // 'avi' + mimeType // 'video/x-msvideo' + // Copy a random file from the source to the target directory and returns the fullpath or filename + file($sourceDir = '/tmp', $targetDir = '/tmp') // '/path/to/targetDir/13b73edae8443990be1aa8f1a483bc27.jpg' + file($sourceDir, $targetDir, false) // '13b73edae8443990be1aa8f1a483bc27.jpg' + +### `Faker\Provider\Image` + + // Image generation provided by LoremPixel (http://lorempixel.com/) + imageUrl($width = 640, $height = 480) // 'http://lorempixel.com/640/480/' + imageUrl($width, $height, 'cats') // 'http://lorempixel.com/800/600/cats/' + imageUrl($width, $height, 'cats', true, 'Faker') // 'http://lorempixel.com/800/400/cats/Faker' + image($dir = '/tmp', $width = 640, $height = 480) // '/tmp/13b73edae8443990be1aa8f1a483bc27.jpg' + image($dir, $width, $height, 'cats') // 'tmp/13b73edae8443990be1aa8f1a483bc27.jpg' it's a cat! + image($dir, $width, $height, 'cats', true, 'Faker') // 'tmp/13b73edae8443990be1aa8f1a483bc27.jpg' it's a cat with Faker text + +### `Faker\Provider\Uuid` + + uuid // '7e57d004-2b97-0e7a-b45f-5387367791cd' + +### `Faker\Provider\Barcode` + + ean13 // '4006381333931' + ean8 // '73513537' + isbn13 // '9790404436093' + isbn10 // '4881416324' + +### `Faker\Provider\Miscellaneous` + + boolean($chanceOfGettingTrue = 50) // true + md5 // 'de99a620c50f2990e87144735cd357e7' + sha1 // 'f08e7f04ca1a413807ebc47551a40a20a0b4de5c' + sha256 // '0061e4c60dac5c1d82db0135a42e00c89ae3a333e7c26485321f24348c7e98a5' + locale // en_UK + countryCode // UK + languageCode // en + currencyCode // EUR + +### `Faker\Provider\Biased` + + // get a random number between 10 and 20, + // with more chances to be close to 20 + biasedNumberBetween($min = 10, $max = 20, $function = 'sqrt') + +## Unique and Optional modifiers + +Faker provides two special providers, `unique()` and `optional()`, to be called before any provider. `optional()` can be useful for seeding non-required fields, like a mobile telephone number; `unique()` is required to populate fields that cannot accept twice the same value, like primary identifiers. + +```php +// unique() forces providers to return unique values +$values = array(); +for ($i=0; $i < 10; $i++) { + // get a random digit, but always a new one, to avoid duplicates + $values []= $faker->unique()->randomDigit; +} +print_r($values); // [4, 1, 8, 5, 0, 2, 6, 9, 7, 3] + +// providers with a limited range will throw an exception when no new unique value can be generated +$values = array(); +try { + for ($i=0; $i < 10; $i++) { + $values []= $faker->unique()->randomDigitNotNull; + } +} catch (\OverflowException $e) { + echo "There are only 9 unique digits not null, Faker can't generate 10 of them!"; +} + +// you can reset the unique modifier for all providers by passing true as first argument +$faker->unique($reset = true)->randomDigitNotNull; // will not throw OverflowException since unique() was reset +// tip: unique() keeps one array of values per provider + +// optional() sometimes bypasses the provider to return a default value instead (which defaults to NULL) +$values = array(); +for ($i=0; $i < 10; $i++) { + // get a random digit, but also null sometimes + $values []= $faker->optional()->randomDigit; +} +print_r($values); // [1, 4, null, 9, 5, null, null, 4, 6, null] + +// optional() accepts a weight argument to specify the probability of receiving the default value. +// 0 will always return the default value; 1 will always return the provider. Default weight is 0.5. +$faker->optional($weight = 0.1)->randomDigit; // 90% chance of NULL +$faker->optional($weight = 0.9)->randomDigit; // 10% chance of NULL + +// optional() accepts a default argument to specify the default value to return. +// Defaults to NULL. +$faker->optional($weight = 0.5, $default = false)->randomDigit; // 50% chance of FALSE +$faker->optional($weight = 0.9, $default = 'abc')->word; // 10% chance of 'abc' +``` + +## Localization + +`Faker\Factory` can take a locale as an argument, to return localized data. If no localized provider is found, the factory fallbacks to the default locale (en_EN). + +```php +name, "\n"; +} + // Luce du Coulon + // Auguste Dupont + // Roger Le Voisin + // Alexandre Lacroix + // Jacques Humbert-Roy + // Thérèse Guillet-Andre + // Gilles Gros-Bodin + // Amélie Pires + // Marcel Laporte + // Geneviève Marchal +``` + +You can check available Faker locales in the source code, [under the `Provider` directory](https://github.com/fzaninotto/Faker/tree/master/src/Faker/Provider). The localization of Faker is an ongoing process, for which we need your help. Don't hesitate to create localized providers to your own locale and submit a PR! + +## Populating Entities Using an ORM or an ODM + +Faker provides adapters for Object-Relational and Object-Document Mappers (currently, [Propel](http://www.propelorm.org), [Doctrine2](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/), [CakePHP](http://cakephp.org) and [Mandango](https://github.com/mandango/mandango) are supported). These adapters ease the population of databases through the Entity classes provided by an ORM library (or the population of document stores using Document classes provided by an ODM library). + +To populate entities, create a new populator class (using a generator instance as parameter), then list the class and number of all the entities that must be generated. To launch the actual data population, call the `execute()` method. + +Here is an example showing how to populate 5 `Author` and 10 `Book` objects: + +```php +addEntity('Author', 5); +$populator->addEntity('Book', 10); +$insertedPKs = $populator->execute(); +``` + +The populator uses name and column type guessers to populate each column with relevant data. For instance, Faker populates a column named `first_name` using the `firstName` formatter, and a column with a `TIMESTAMP` type using the `dateTime` formatter. The resulting entities are therefore coherent. If Faker misinterprets a column name, you can still specify a custom closure to be used for populating a particular column, using the third argument to `addEntity()`: + +```php +addEntity('Book', 5, array( + 'ISBN' => function() use ($generator) { return $generator->ean13(); } +)); +``` + +In this example, Faker will guess a formatter for all columns except `ISBN`, for which the given anonymous function will be used. + +**Tip**: To ignore some columns, specify `null` for the column names in the third argument of `addEntity()`. This is usually necessary for columns added by a behavior: + +```php +addEntity('Book', 5, array( + 'CreatedAt' => null, + 'UpdatedAt' => null, +)); +``` + +Of course, Faker does not populate autoincremented primary keys. In addition, `Faker\ORM\Propel\Populator::execute()` returns the list of inserted PKs, indexed by class: + +```php + (34, 35, 36, 37, 38), +// 'Book' => (456, 457, 458, 459, 470, 471, 472, 473, 474, 475) +// ) +``` + +In the previous example, the `Book` and `Author` models share a relationship. Since `Author` entities are populated first, Faker is smart enough to relate the populated `Book` entities to one of the populated `Author` entities. + +Lastly, if you want to execute an arbitrary function on an entity before insertion, use the fourth argument of the `addEntity()` method: + +```php +addEntity('Book', 5, array(), array( + function($book) { $book->publish(); }, +)); +``` + +## Seeding the Generator + +You may want to get always the same generated data - for instance when using Faker for unit testing purposes. The generator offers a `seed()` method, which seeds the random number generator. Calling the same script twice with the same seed produces the same results. + +```php +seed(1234); + +echo $faker->name; // 'Jess Mraz I'; +``` + +> **Tip**: DateTime formatters won't reproduce the same fake data if you don't fix the `$max` value: +> +> ```php +> // even when seeded, this line will return different results because $max varies +> $faker->dateTime(); // equivalent to $faker->dateTime($max = 'now') +> // make sure you fix the $max parameter +> $faker->dateTime('2014-02-25 08:37:17'); // will return always the same date when seeded +> ``` +> +> **Tip**: Formatters won't reproduce the same fake data if you use the `rand()` php function. Use `$faker` or `mt_rand()` instead: +> +> ```php +> // bad +> $faker->realText(rand(10,20)); +> // good +> $faker->realText($faker->numberBetween(10,20)); +> ``` + + + +## Faker Internals: Understanding Providers + +A `Faker\Generator` alone can't do much generation. It needs `Faker\Provider` objects to delegate the data generation to them. `Faker\Factory::create()` actually creates a `Faker\Generator` bundled with the default providers. Here is what happens under the hood: + +```php +addProvider(new Faker\Provider\en_US\Person($faker)); +$faker->addProvider(new Faker\Provider\en_US\Address($faker)); +$faker->addProvider(new Faker\Provider\en_US\PhoneNumber($faker)); +$faker->addProvider(new Faker\Provider\en_US\Company($faker)); +$faker->addProvider(new Faker\Provider\Lorem($faker)); +$faker->addProvider(new Faker\Provider\Internet($faker)); +```` + +Whenever you try to access a property on the `$faker` object, the generator looks for a method with the same name in all the providers attached to it. For instance, calling `$faker->name` triggers a call to `Faker\Provider\Person::name()`. And since Faker starts with the last provider, you can easily override existing formatters: just add a provider containing methods named after the formatters you want to override. + +That means that you can easily add your own providers to a `Faker\Generator` instance. A provider is usually a class extending `\Faker\Provider\Base`. This parent class allows you to use methods like `lexify()` or `randomNumber()`; it also gives you access to formatters of other providers, through the protected `$generator` property. The new formatters are the public methods of the provider class. + +Here is an example provider for populating Book data: + +```php +generator->sentence($nbWords); + return substr($sentence, 0, strlen($sentence) - 1); + } + + public function ISBN() + { + return $this->generator->ean13(); + } +} +``` + +To register this provider, just add a new instance of `\Faker\Provider\Book` to an existing generator: + +```php +addProvider(new \Faker\Provider\Book($faker)); +``` + +Now you can use the two new formatters like any other Faker formatter: + +```php +setTitle($faker->title); +$book->setISBN($faker->ISBN); +$book->setSummary($faker->text); +$book->setPrice($faker->randomNumber(2)); +``` + +**Tip**: A provider can also be a Plain Old PHP Object. In that case, all the public methods of the provider become available to the generator. + +## Real Life Usage + +The following script generates a valid XML document: + +```php + + + + + + +boolean(25)): ?> + + +
    + streetAddress ?> + city ?> + postcode ?> + state ?> +
    + +boolean(33)): ?> + bs ?> + +boolean(33)): ?> + + + +boolean(15)): ?> +
    +text(400) ?> +]]> +
    + +
    + +
    +``` + +Running this script produces a document looking like: + +```xml + + + + +
    + 182 Harrison Cove + North Lloyd + 45577 + Alabama +
    + + orchestrate compelling web-readiness + +
    + +
    +
    + + +
    + 90111 Hegmann Inlet + South Geovanymouth + 69961-9311 + Colorado +
    + + +
    + + +
    + 9791 Nona Corner + Harberhaven + 74062-8191 + RhodeIsland +
    + + +
    + + +
    + 11161 Schultz Via + Feilstad + 98019 + NewJersey +
    + + + +
    + +
    +
    + + +
    + 6106 Nader Village Suite 753 + McLaughlinstad + 43189-8621 + Missouri +
    + + expedite viral synergies + + +
    + + +
    + 7546 Kuvalis Plaza + South Wilfrid + 77069 + Georgia +
    + + +
    + + + +
    + 478 Daisha Landing Apt. 510 + West Lizethhaven + 30566-5362 + WestVirginia +
    + + orchestrate dynamic networks + + +
    + +
    +
    + + +
    + 1251 Koelpin Mission + North Revastad + 81620 + Maryland +
    + + +
    + + +
    + 6396 Langworth Hills Apt. 446 + New Carlos + 89399-0268 + Wyoming +
    + + + +
    + + + +
    + 2246 Kreiger Station Apt. 291 + Kaydenmouth + 11397-1072 + Wyoming +
    + + grow sticky portals + +
    + +
    +
    +
    +``` + +## Language specific formatters + +### `Faker\Provider\ar_SA\Person` +```php +idNumber; // ID number +echo $faker->nationalIdNumber // Citizen ID number +echo $faker->foreignerIdNumber // Foreigner ID number + +``` + +### `Faker\Provider\at_AT\Payment` +```php +vat; // "AT U12345678" - Austrian Value Added Tax number +echo $faker->vat(false); // "ATU12345678" - unspaced Austrian Value Added Tax number + +``` + +### `Faker\Provider\be_BE\Payment` +```php +vat; // "BE 0123456789" - Belgian Value Added Tax number +echo $faker->vat(false); // "BE0123456789" - unspaced Belgian Value Added Tax number + +``` + +### `Faker\Provider\bg_BG\Payment` +```php +vat; // "BG 0123456789" - Bulgarian Value Added Tax number +echo $faker->vat(false); // "BG0123456789" - unspaced Bulgarian Value Added Tax number + +``` + +### `Faker\Provider\cs_CZ\Address` +```php +region; // "Liberecký kraj" + +``` + +### `Faker\Provider\cs_CZ\Company` +```php +ico; // "69663963" + +``` + +### `Faker\Provider\cs_CZ\DateTime` +```php +monthNameGenitive; // "prosince" +echo $faker->formattedDate; // "12. listopadu 2015" + +``` + +### `Faker\Provider\cs_CZ\Person` +```php +birthNumber; // "7304243452" + +``` + +### `Faker\Provider\da_DK\Person` + +```php +cpr; // "051280-2387" + +``` + +### `Faker\Provider\da_DK\Address` + +```php +kommune; // "Frederiksberg" + +// Generates a random region name +echo $faker->region; // "Region Sjælland" + +``` + +### `Faker\Provider\da_DK\Company` + +```php +cvr; // "32458723" + +// Generates a random P number +echo $faker->p; // "5398237590" + +``` + +### `Faker\Provider\fr_FR\Company` + +```php +siren; // 082 250 104 + +// Generates a random SIRET number +echo $faker->siret; // 347 355 708 00224 +``` + +### `Faker\Provider\fr_FR\Address` + +```php +departmentName; // "Haut-Rhin" + +// Generates a random department number +echo $faker->departmentNumber; // "2B" + +// Generates a random department info (department number => department name) +$faker->department; // array('18' => 'Cher'); + +// Generates a random region +echo $faker->region; // "Saint-Pierre-et-Miquelon" + +``` + +### `Faker\Provider\hu_HU\Payment` + +```php +bankAccountNumber; // "HU09904437680048220079300783" + +``` + +### `Faker\Provider\ja_JP\Person` + +```php +kanaName; // "アオタ ミノル" + +// Generates a 'kana' first name +echo $faker->firstKanaName; // "ハルカ" + +// Generates a 'kana' last name +echo $faker->lastKanaName; // "ナカジマ" +``` + +### `Faker\Provider\ka_GE\Payment` + +```php +bankAccountNumber; // "GE33ZV9773853617253389" + +``` + +### `Faker\Provider\kk_KZ\Company` + +```php +businessIdentificationNumber; // "150140000019" + +``` + +### `Faker\Provider\kk_KZ\Payment` + +```php +bank; // "Қазкоммерцбанк" + +// Generates a random bank account number +echo $faker->bankAccountNumber; // "KZ1076321LO4H6X41I37" + +``` + +### `Faker\Provider\kk_KZ\Person` + +```php +individualIdentificationNumber; // "780322300455" + +``` + +### `Faker\Provider\ko_KR\Address` + +```php +metropolitanCity; // "서울특별시" + +// Generates a borough +echo $faker->borough; // "강남구" + +``` + + +### `Faker\Provider\lv_LV\Person` + +```php +personalIdentityNumber; // "140190-12301" + +``` + +### `Faker\Provider\no_NO\Payment` + +```php +bankAccountNumber; // "NO3246764709816" + +``` + +### `Faker\Provider\pl_PL\Person` + +```php +pesel; // "40061451555" +// Generates a random personal identity card number +echo $faker->personalIdentityNumber; // "AKX383360" +// Generates a random taxpayer identification number (NIP) +echo $faker->taxpayerIdentificationNumber; // '8211575109' + +``` + +### `Faker\Provider\pl_PL\Company` + +```php +regon; // "714676680" +// Generates a random local REGON number +echo $faker->regonLocal; // "15346111382836" + +``` + +### `Faker\Provider\pl_PL\Payment` + +```php +bank; // "Narodowy Bank Polski" +// Generates a random bank account number +echo $faker->bankAccountNumber; // "PL14968907563953822118075816" + +``` + +### `Faker\Provider\pt_PT\Person` + +```php +taxpayerIdentificationNumber; // '165249277' + +``` + +### `Faker\Provider\pt_BR\PhoneNumber` + +```php +areaCode; // 21 +echo $faker->cellphone; // 9432-5656 +echo $faker->landline; // 2654-3445 +echo $faker->phone; // random landline, 8-digit or 9-digit cellphone number + +// Using the phone functions with a false argument returns unformatted numbers +echo $faker->cellphone(false); // 74336667 + +// cellphone() has a special second argument to add the 9th digit. Ignored if generated a Radio number +echo $faker->cellphone(true, true); // 98983-3945 or 7343-1290 + +// Using the "Number" suffix adds area code to the phone +echo $faker->cellphoneNumber; // (11) 98309-2935 +echo $faker->landlineNumber(false); // 3522835934 +echo $faker->phoneNumber; // formatted, random landline or cellphone (obbeying the 9th digit rule) +echo $faker->phoneNumberCleared; // not formatted, random landline or cellphone (obbeying the 9th digit rule) +``` + +### `Faker\Provider\pt_BR\Person` + +```php +name; // 'Sr. Luis Adriano Sepúlveda Filho' + +// Valid document generators have a boolean argument to remove formatting +echo $faker->cpf; // '145.343.345-76' +echo $faker->cpf(false); // '45623467866' +echo $faker->rg; // '84.405.736-3' +echo $faker->cnpj; // '23.663.478/0001-24' +``` + +### `Faker\Provider\ro_MD\Payment` + +```php +bankAccountNumber; // "MD83BQW1CKMUW34HBESDP3A8" + +``` + +### `Faker\Provider\ro_RO\Payment` + +```php +bankAccountNumber; // "RO55WRJE3OE8X3YQI7J26U1E" + +``` + +### `Faker\Provider\ro_RO\Person` + +```php +prefixMale; // "ing." +// Generates a random female name prefix/title +echo $faker->prefixFemale; // "d-na." +// Generates a random male fist name +echo $faker->firstNameMale; // "Adrian" +// Generates a random female fist name +echo $faker->firstNameFemale; // "Miruna" + +// Generates a random Personal Numerical Code (CNP) +echo $faker->cnp; // "2800523081231" +echo $faker->cnp($gender = NULL, $century = NULL, $county = NULL); + +// Valid option values: +// $gender: m, f, 1, 2 +// $century: 1800, 1900, 2000, 1, 2, 3, 4, 5, 6 +// $county: 2 letter ISO 3166-2:RO county codes and B1-B6 for Bucharest's 6 sectors +``` + +### `Faker\Provider\ro_RO\PhoneNumber` + +```php +tollFreePhoneNumber; // "0800123456" +// Generates a random premium-rate phone number +echo $faker->premiumRatePhoneNumber; // "0900123456" +``` + +### `Faker\Provider\ru_RU\Payment` + +```php +bank; // "ОТП Банк" +``` + +### `Faker\Provider\en_NZ\Phone` + +```php +cellNumber; // "021 123 4567" + +// Generates a toll free number +echo $faker->tollFreeNumber; // "0800 123 456" + +// Area Code +echo $faker->areaCode; // "03" +``` + +### `Faker\Provider\sv_SE\Payment` + +```php +bankAccountNumber; // "SE5018548608468284909192" + +``` + +### `Faker\Provider\sv_SE\Person` +```php +personalIdentityNumber() // '950910-0799' + +//Since the numbers are different for male and female persons, optionally you can specify gender. +echo $faker->personalIdentityNumber('female') // '950910-0781' + +``` + +### `Faker\Provider\ne_NP\Address` +```php +district; + +//Generates a Nepali city name +echo $faker->cityName; +``` + +## Third-Party Libraries Extending/Based On Faker + +* Symfony2 bundles: + * [BazingaFakerBundle](https://github.com/willdurand/BazingaFakerBundle): Put the awesome Faker library into the Symfony2 DIC and populate your database with fake data. + * [AliceBundle](https://github.com/hautelook/AliceBundle), [AliceFixturesBundle](https://github.com/h4cc/AliceFixturesBundle): Bundles for using [Alice](https://packagist.org/packages/nelmio/alice) and Faker with data fixtures. Able to use Doctrine ORM as well as Doctrine MongoDB ODM. +* [FakerServiceProvider](https://github.com/EmanueleMinotto/FakerServiceProvider): Faker Service Provider for Silex +* [faker-cli](https://github.com/bit3/faker-cli): Command Line Tool for the Faker PHP library +* [Factory Muffin](https://github.com/thephpleague/factory-muffin): enable the rapid creation of objects (PHP port of factory-girl) +* [CompanyNameGenerator](https://github.com/fzaninotto/CompanyNameGenerator): Generate names for English tech companies with class +* [datalea](https://github.com/spyrit/datalea) A highly customizable random test data generator web app +* [newage-ipsum](https://github.com/frequenc1/newage-ipsum): A new aged ipsum provider for the faker library inspired by http://sebpearce.com/bullshit/ +* [xml-faker](https://github.com/prewk/xml-faker): Create fake XML with Faker +* [faker-context](https://github.com/denheck/faker-context): Behat context using Faker to generate testdata +* [CronExpressionGenerator](https://github.com/swekaj/CronExpressionGenerator): Faker provider for generating random, valid cron expressions. +* [pragmafabrik/Pomm2Faker](https://github.com/pragmafabrik/Pomm2Faker): Faker client for Pomm ORM (PostgreSQL) +* [nelmio/alice](https://packagist.org/packages/nelmio/alice): Fixtures/object generator with a yaml DSL that can use Faker as data generator. +* [CakePHP 2.x Fake Seeder Plugin](https://github.com/ravage84/cakephp-fake-seeder) A CakePHP 2.x shell to seed your database with fake and/or fixed data. + +## License + +Faker is released under the MIT Licence. See the bundled LICENSE file for details. diff --git a/lib/faker/src/Faker/Calculator/Iban.php b/lib/faker/src/Faker/Calculator/Iban.php new file mode 100755 index 0000000..99c0f0e --- /dev/null +++ b/lib/faker/src/Faker/Calculator/Iban.php @@ -0,0 +1,68 @@ += 0; $i -= 2) { + $sum += $number{$i}; + } + for ($i = $length - 2; $i >= 0; $i -= 2) { + $sum += array_sum(str_split($number{$i} * 2)); + } + + return $sum % 10; + } + + /** + * @return string + */ + public static function computeCheckDigit($partialNumber) + { + $checkDigit = self::checksum($partialNumber . '0'); + if ($checkDigit === 0) { + return 0; + } + + return (string) (10 - $checkDigit); + } + + /** + * Checks whether a number (partial number + check digit) is Luhn compliant + * + * @return boolean + */ + public static function isValid($number) + { + return self::checksum($number) === 0; + } +} diff --git a/lib/faker/src/Faker/DefaultGenerator.php b/lib/faker/src/Faker/DefaultGenerator.php new file mode 100755 index 0000000..ad75ccd --- /dev/null +++ b/lib/faker/src/Faker/DefaultGenerator.php @@ -0,0 +1,27 @@ +optional(). + */ +class DefaultGenerator +{ + protected $default = null; + + public function __construct($default = null) + { + $this->default = $default; + } + + public function __get($attribute) + { + return $this->default; + } + + public function __call($method, $attributes) + { + return $this->default; + } +} diff --git a/lib/faker/src/Faker/Documentor.php b/lib/faker/src/Faker/Documentor.php new file mode 100755 index 0000000..216e208 --- /dev/null +++ b/lib/faker/src/Faker/Documentor.php @@ -0,0 +1,60 @@ +generator = $generator; + } + + public function getFormatters() + { + $formatters = array(); + $providers = array_reverse($this->generator->getProviders()); + $providers[]= new Provider\Base($this->generator); + foreach ($providers as $provider) { + $providerClass = get_class($provider); + $formatters[$providerClass] = array(); + $refl = new \ReflectionObject($provider); + foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflmethod) { + if ($reflmethod->getDeclaringClass()->getName() == 'Faker\Provider\Base' && $providerClass != 'Faker\Provider\Base') { + continue; + } + $methodName = $reflmethod->name; + if ($reflmethod->isConstructor()) { + continue; + } + $parameters = array(); + foreach ($reflmethod->getParameters() as $reflparameter) { + $parameter = '$'. $reflparameter->getName(); + if ($reflparameter->isDefaultValueAvailable()) { + $parameter .= ' = ' . var_export($reflparameter->getDefaultValue(), true); + } + $parameters []= $parameter; + } + $parameters = $parameters ? '('. join(', ', $parameters) . ')' : ''; + try { + $example = $this->generator->format($methodName); + } catch (\InvalidArgumentException $e) { + $example = ''; + } + if (is_array($example)) { + $example = "array('". join("', '", $example) . "')"; + } elseif ($example instanceof \DateTime) { + $example = "DateTime('" . $example->format('Y-m-d H:i:s') . "')"; + } elseif ($example instanceof Generator || $example instanceof UniqueGenerator) { // modifier + $example = ''; + } else { + $example = var_export($example, true); + } + $formatters[$providerClass][$methodName . $parameters] = $example; + } + } + + return $formatters; + } +} diff --git a/lib/faker/src/Faker/Factory.php b/lib/faker/src/Faker/Factory.php new file mode 100755 index 0000000..25ca9be --- /dev/null +++ b/lib/faker/src/Faker/Factory.php @@ -0,0 +1,52 @@ +addProvider(new $providerClassName($generator)); + } + + return $generator; + } + + protected static function getProviderClassname($provider, $locale = '') + { + if ($providerClass = self::findProviderClassname($provider, $locale)) { + return $providerClass; + } + // fallback to default locale + if ($providerClass = self::findProviderClassname($provider, static::DEFAULT_LOCALE)) { + return $providerClass; + } + // fallback to no locale + $providerClass = self::findProviderClassname($provider); + if (class_exists($providerClass)) { + return $providerClass; + } + throw new \InvalidArgumentException(sprintf('Unable to find provider "%s" with locale "%s"', $provider, $locale)); + } + + protected static function findProviderClassname($provider, $locale = '') + { + $providerClass = 'Faker\\' . ($locale ? sprintf('Provider\%s\%s', $locale, $provider) : sprintf('Provider\%s', $provider)); + if (class_exists($providerClass, true)) { + return $providerClass; + } + } +} diff --git a/lib/faker/src/Faker/Generator.php b/lib/faker/src/Faker/Generator.php new file mode 100755 index 0000000..3378797 --- /dev/null +++ b/lib/faker/src/Faker/Generator.php @@ -0,0 +1,240 @@ +providers, $provider); + } + + public function getProviders() + { + return $this->providers; + } + + public function seed($seed = null) + { + if ($seed === null) { + mt_srand(); + } else { + mt_srand((int) $seed); + } + } + + public function format($formatter, $arguments = array()) + { + return call_user_func_array($this->getFormatter($formatter), $arguments); + } + + /** + * @return Callable + */ + public function getFormatter($formatter) + { + if (isset($this->formatters[$formatter])) { + return $this->formatters[$formatter]; + } + foreach ($this->providers as $provider) { + if (method_exists($provider, $formatter)) { + $this->formatters[$formatter] = array($provider, $formatter); + + return $this->formatters[$formatter]; + } + } + throw new \InvalidArgumentException(sprintf('Unknown formatter "%s"', $formatter)); + } + + /** + * Replaces tokens ('{{ tokenName }}') with the result from the token method call + * + * @param string $string String that needs to bet parsed + * @return string + */ + public function parse($string) + { + return preg_replace_callback('/\{\{\s?(\w+)\s?\}\}/u', array($this, 'callFormatWithMatches'), $string); + } + + protected function callFormatWithMatches($matches) + { + return $this->format($matches[1]); + } + + public function __get($attribute) + { + return $this->format($attribute); + } + + public function __call($method, $attributes) + { + return $this->format($method, $attributes); + } +} diff --git a/lib/faker/src/Faker/Guesser/Name.php b/lib/faker/src/Faker/Guesser/Name.php new file mode 100755 index 0000000..856920f --- /dev/null +++ b/lib/faker/src/Faker/Guesser/Name.php @@ -0,0 +1,153 @@ +generator = $generator; + } + + /** + * @param string $name + * @param int|null $size Length of field, if known + * @return callable + */ + public function guessFormat($name, $size = null) + { + $name = Base::toLower($name); + $generator = $this->generator; + if (preg_match('/^is[_A-Z]/', $name)) { + return function () use ($generator) { + return $generator->boolean; + }; + } + if (preg_match('/(_a|A)t$/', $name)) { + return function () use ($generator) { + return $generator->dateTime; + }; + } + switch (str_replace('_', '', $name)) { + case 'firstname': + return function () use ($generator) { + return $generator->firstName; + }; + case 'lastname': + return function () use ($generator) { + return $generator->lastName; + }; + case 'username': + case 'login': + return function () use ($generator) { + return $generator->userName; + }; + case 'email': + case 'emailaddress': + return function () use ($generator) { + return $generator->email; + }; + case 'phonenumber': + case 'phone': + case 'telephone': + case 'telnumber': + return function () use ($generator) { + return $generator->phoneNumber; + }; + case 'address': + return function () use ($generator) { + return $generator->address; + }; + case 'city': + case 'town': + return function () use ($generator) { + return $generator->city; + }; + case 'streetaddress': + return function () use ($generator) { + return $generator->streetAddress; + }; + case 'postcode': + case 'zipcode': + return function () use ($generator) { + return $generator->postcode; + }; + case 'state': + return function () use ($generator) { + return $generator->state; + }; + case 'county': + if ($this->generator->locale == 'en_US') { + return function () use ($generator) { + return sprintf('%s County', $generator->city); + }; + } + + return function () use ($generator) { + return $generator->state; + }; + case 'country': + switch ($size) { + case 2: + return function () use ($generator) { + return $generator->countryCode; + }; + case 3: + return function () use ($generator) { + return $generator->countryISOAlpha3; + }; + case 5: + case 6: + return function () use ($generator) { + return $generator->locale; + }; + default: + return function () use ($generator) { + return $generator->country; + }; + } + break; + case 'locale': + return function () use ($generator) { + return $generator->locale; + }; + case 'currency': + case 'currencycode': + return function () use ($generator) { + return $generator->currencyCode; + }; + case 'url': + case 'website': + return function () use ($generator) { + return $generator->url; + }; + case 'company': + case 'companyname': + case 'employer': + return function () use ($generator) { + return $generator->company; + }; + case 'title': + if ($size !== null && $size <= 10) { + return function () use ($generator) { + return $generator->title; + }; + } + + return function () use ($generator) { + return $generator->sentence; + }; + case 'body': + case 'summary': + case 'article': + case 'description': + return function () use ($generator) { + return $generator->text; + }; + } + } +} diff --git a/lib/faker/src/Faker/ORM/CakePHP/ColumnTypeGuesser.php b/lib/faker/src/Faker/ORM/CakePHP/ColumnTypeGuesser.php new file mode 100755 index 0000000..0796c16 --- /dev/null +++ b/lib/faker/src/Faker/ORM/CakePHP/ColumnTypeGuesser.php @@ -0,0 +1,64 @@ +generator = $generator; + } + + public function guessFormat($column, $table) + { + $generator = $this->generator; + $schema = $table->schema(); + + switch ($schema->columnType($column)) { + case 'boolean': + return function () use ($generator) { + return $generator->boolean; + }; + case 'integer': + return function () use ($generator) { + return mt_rand(0, intval('2147483647')); + }; + case 'biginteger': + return function () use ($generator) { + return mt_rand(0, intval('9223372036854775807')); + }; + case 'decimal': + case 'float': + return function () use ($generator) { + return $generator->randomFloat(); + }; + case 'uuid': + return function () use ($generator) { + return $generator->uuid(); + }; + case 'string': + $columnData = $schema->column($column); + $length = $columnData['length']; + return function () use ($generator, $length) { + return $generator->text($length); + }; + case 'text': + return function () use ($generator) { + return $generator->text(); + }; + case 'date': + case 'datetime': + case 'timestamp': + case 'time': + return function () use ($generator) { + return $generator->datetime(); + }; + + case 'binary': + default: + return null; + } + } +} diff --git a/lib/faker/src/Faker/ORM/CakePHP/EntityPopulator.php b/lib/faker/src/Faker/ORM/CakePHP/EntityPopulator.php new file mode 100755 index 0000000..b64a1de --- /dev/null +++ b/lib/faker/src/Faker/ORM/CakePHP/EntityPopulator.php @@ -0,0 +1,152 @@ +class = $class; + } + + public function __get($name) + { + return $this->{$name}; + } + + public function __set($name, $value) + { + $this->{$name} = $value; + } + + public function mergeColumnFormattersWith($columnFormatters) + { + $this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters); + } + + public function mergeModifiersWith($modifiers) + { + $this->modifiers = array_merge($this->modifiers, $modifiers); + } + + public function guessColumnFormatters($populator) + { + $formatters = []; + $class = $this->class; + $table = $this->getTable($class); + $schema = $table->schema(); + $pk = $schema->primaryKey(); + $guessers = $populator->getGuessers() + ['ColumnTypeGuesser' => new ColumnTypeGuesser($populator->getGenerator())]; + $isForeignKey = function ($column) use ($table) { + foreach ($table->associations()->type('BelongsTo') as $assoc) { + if ($column == $assoc->foreignKey()) { + return true; + } + } + return false; + }; + + + foreach ($schema->columns() as $column) { + if ($column == $pk[0] || $isForeignKey($column)) { + continue; + } + + foreach ($guessers as $guesser) { + if ($formatter = $guesser->guessFormat($column, $table)) { + $formatters[$column] = $formatter; + break; + } + } + } + + return $formatters; + } + + public function guessModifiers($populator) + { + $modifiers = []; + $table = $this->getTable($this->class); + + $belongsTo = $table->associations()->type('BelongsTo'); + foreach ($belongsTo as $assoc) { + $modifiers['belongsTo' . $assoc->name()] = function ($data, $insertedEntities) use ($assoc) { + $table = $assoc->target(); + $foreignModel = $table->alias(); + + $foreignKeys = []; + if (!empty($insertedEntities[$foreignModel])) { + $foreignKeys = $insertedEntities[$foreignModel]; + } else { + $foreignKeys = $table->find('all') + ->select(['id']) + ->map(function ($row) { + return $row->id; + }) + ->toArray(); + } + + if (empty($foreignKeys)) { + throw new \Exception(sprintf('%s belongsTo %s, which seems empty at this point.', $this->getTable($this->class)->table(), $assoc->table())); + } + + $foreignKey = $foreignKeys[array_rand($foreignKeys)]; + $data[$assoc->foreignKey()] = $foreignKey; + return $data; + }; + } + + // TODO check if TreeBehavior attached to modify lft/rgt cols + + return $modifiers; + } + + public function execute($class, $insertedEntities, $options = []) + { + $table = $this->getTable($class); + $entity = $table->newEntity(); + + foreach ($this->columnFormatters as $column => $format) { + if (!is_null($format)) { + $entity->{$column} = is_callable($format) ? $format($insertedEntities, $table) : $format; + } + } + + foreach ($this->modifiers as $modifier) { + $entity = $modifier($entity, $insertedEntities); + } + + if (!$entity = $table->save($entity, $options)) { + throw new \RuntimeException("Failed saving $class record"); + } + + $pk = $table->primaryKey(); + if (is_string($pk)) { + return $entity->{$pk}; + } + + return $entity->{$pk[0]}; + } + + public function setConnection($name) + { + $this->connectionName = $name; + } + + protected function getTable($class) + { + $options = []; + if (!empty($this->connectionName)) { + $options['connection'] = $this->connectionName; + } + return TableRegistry::get($class, $options); + } +} diff --git a/lib/faker/src/Faker/ORM/CakePHP/Populator.php b/lib/faker/src/Faker/ORM/CakePHP/Populator.php new file mode 100755 index 0000000..cd5aa47 --- /dev/null +++ b/lib/faker/src/Faker/ORM/CakePHP/Populator.php @@ -0,0 +1,84 @@ +generator = $generator; + } + + public function getGenerator() + { + return $this->generator; + } + + public function getGuessers() + { + return $this->guessers; + } + + public function removeGuesser($name) + { + if ($this->guessers[$name]) { + unset($this->guessers[$name]); + } + return $this; + } + + public function addGuesser($class) + { + if (!is_object($class)) { + $class = new $class($this->generator); + } + + if (!method_exists($class, 'guessFormat')) { + throw new \Exception('Missing required custom guesser method: ' . get_class($class) . '::guessFormat()'); + } + + $this->guessers[get_class($class)] = $class; + return $this; + } + + public function addEntity($entity, $number, $customColumnFormatters = [], $customModifiers = []) + { + if (!$entity instanceof EntityPopulator) { + $entity = new EntityPopulator($entity); + } + + $entity->columnFormatters = $entity->guessColumnFormatters($this); + if ($customColumnFormatters) { + $entity->mergeColumnFormattersWith($customColumnFormatters); + } + + $entity->modifiers = $entity->guessModifiers($this); + if ($customModifiers) { + $entity->mergeModifiers($customModifiers); + } + + $class = $entity->class; + $this->entities[$class] = $entity; + $this->quantities[$class] = $number; + return $this; + } + + public function execute($options = []) + { + $insertedEntities = []; + + foreach ($this->quantities as $class => $number) { + for ($i = 0; $i < $number; $i++) { + $insertedEntities[$class][] = $this->entities[$class]->execute($class, $insertedEntities, $options); + } + } + + return $insertedEntities; + } +} diff --git a/lib/faker/src/Faker/ORM/Doctrine/ColumnTypeGuesser.php b/lib/faker/src/Faker/ORM/Doctrine/ColumnTypeGuesser.php new file mode 100755 index 0000000..899dc95 --- /dev/null +++ b/lib/faker/src/Faker/ORM/Doctrine/ColumnTypeGuesser.php @@ -0,0 +1,68 @@ +generator = $generator; + } + + public function guessFormat($fieldName, ClassMetadata $class) + { + $generator = $this->generator; + $type = $class->getTypeOfField($fieldName); + switch ($type) { + case 'boolean': + return function () use ($generator) { + return $generator->boolean; + }; + case 'decimal': + $size = isset($class->fieldMappings[$fieldName]['precision']) ? $class->fieldMappings[$fieldName]['precision'] : 2; + + return function () use ($generator, $size) { + return $generator->randomNumber($size + 2) / 100; + }; + case 'smallint': + return function () { + return mt_rand(0, 65535); + }; + case 'integer': + return function () { + return mt_rand(0, intval('2147483647')); + }; + case 'bigint': + return function () { + return mt_rand(0, intval('18446744073709551615')); + }; + case 'float': + return function () { + return mt_rand(0, intval('4294967295'))/mt_rand(1, intval('4294967295')); + }; + case 'string': + $size = isset($class->fieldMappings[$fieldName]['length']) ? $class->fieldMappings[$fieldName]['length'] : 255; + + return function () use ($generator, $size) { + return $generator->text($size); + }; + case 'text': + return function () use ($generator) { + return $generator->text; + }; + case 'datetime': + case 'date': + case 'time': + return function () use ($generator) { + return $generator->datetime; + }; + default: + // no smart way to guess what the user expects here + return null; + } + } +} diff --git a/lib/faker/src/Faker/ORM/Doctrine/EntityPopulator.php b/lib/faker/src/Faker/ORM/Doctrine/EntityPopulator.php new file mode 100755 index 0000000..3eab1a2 --- /dev/null +++ b/lib/faker/src/Faker/ORM/Doctrine/EntityPopulator.php @@ -0,0 +1,197 @@ +class = $class; + } + + /** + * @return string + */ + public function getClass() + { + return $this->class->getName(); + } + + public function setColumnFormatters($columnFormatters) + { + $this->columnFormatters = $columnFormatters; + } + + public function getColumnFormatters() + { + return $this->columnFormatters; + } + + public function mergeColumnFormattersWith($columnFormatters) + { + $this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters); + } + + public function setModifiers(array $modifiers) + { + $this->modifiers = $modifiers; + } + + public function getModifiers() + { + return $this->modifiers; + } + + public function mergeModifiersWith(array $modifiers) + { + $this->modifiers = array_merge($this->modifiers, $modifiers); + } + + public function guessColumnFormatters(\Faker\Generator $generator) + { + $formatters = array(); + $nameGuesser = new \Faker\Guesser\Name($generator); + $columnTypeGuesser = new ColumnTypeGuesser($generator); + foreach ($this->class->getFieldNames() as $fieldName) { + if ($this->class->isIdentifier($fieldName) || !$this->class->hasField($fieldName)) { + continue; + } + + $size = isset($this->class->fieldMappings[$fieldName]['length']) ? $this->class->fieldMappings[$fieldName]['length'] : null; + if ($formatter = $nameGuesser->guessFormat($fieldName, $size)) { + $formatters[$fieldName] = $formatter; + continue; + } + if ($formatter = $columnTypeGuesser->guessFormat($fieldName, $this->class)) { + $formatters[$fieldName] = $formatter; + continue; + } + } + + foreach ($this->class->getAssociationNames() as $assocName) { + if ($this->class->isCollectionValuedAssociation($assocName)) { + continue; + } + + $relatedClass = $this->class->getAssociationTargetClass($assocName); + + $unique = $optional = false; + $mappings = $this->class->getAssociationMappings(); + foreach ($mappings as $mapping) { + if ($mapping['targetEntity'] == $relatedClass) { + if ($mapping['type'] == ClassMetadata::ONE_TO_ONE) { + $unique = true; + $optional = isset($mapping['joinColumns'][0]['nullable']) ? $mapping['joinColumns'][0]['nullable'] : false; + break; + } + } + } + + $index = 0; + $formatters[$assocName] = function ($inserted) use ($relatedClass, &$index, $unique, $optional) { + + if (isset($inserted[$relatedClass])) { + if ($unique) { + $related = null; + if (isset($inserted[$relatedClass][$index]) || !$optional) { + $related = $inserted[$relatedClass][$index]; + } + + $index++; + + return $related; + } + + return $inserted[$relatedClass][mt_rand(0, count($inserted[$relatedClass]) - 1)]; + } + + return null; + }; + } + + return $formatters; + } + + /** + * Insert one new record using the Entity class. + */ + public function execute(ObjectManager $manager, $insertedEntities, $generateId = false) + { + $obj = $this->class->newInstance(); + + $this->fillColumns($obj, $insertedEntities); + $this->callMethods($obj, $insertedEntities); + + if ($generateId) { + $idsName = $this->class->getIdentifier(); + foreach ($idsName as $idName) { + $id = $this->generateId($obj, $idName, $manager); + $this->class->reflFields[$idName]->setValue($obj, $id); + } + } + + $manager->persist($obj); + + return $obj; + } + + private function fillColumns($obj, $insertedEntities) + { + foreach ($this->columnFormatters as $field => $format) { + if (null !== $format) { + $value = is_callable($format) ? $format($insertedEntities, $obj) : $format; + $this->class->reflFields[$field]->setValue($obj, $value); + } + } + } + + private function callMethods($obj, $insertedEntities) + { + foreach ($this->getModifiers() as $modifier) { + $modifier($obj, $insertedEntities); + } + } + + private function generateId($obj, $column, EntityManagerInterface $manager) + { + /* @var $repository \Doctrine\ORM\EntityRepository */ + $repository = $manager->getRepository(get_class($obj)); + $result = $repository->createQueryBuilder('e') + ->select(sprintf('e.%s', $column)) + ->getQuery() + ->getResult(); + $ids = array_map('current', $result); + + $id = null; + do { + $id = mt_rand(); + } while (in_array($id, $ids)); + + return $id; + } +} diff --git a/lib/faker/src/Faker/ORM/Doctrine/Populator.php b/lib/faker/src/Faker/ORM/Doctrine/Populator.php new file mode 100755 index 0000000..27114c0 --- /dev/null +++ b/lib/faker/src/Faker/ORM/Doctrine/Populator.php @@ -0,0 +1,78 @@ +generator = $generator; + $this->manager = $manager; + } + + /** + * Add an order for the generation of $number records for $entity. + * + * @param mixed $entity A Doctrine classname, or a \Faker\ORM\Doctrine\EntityPopulator instance + * @param int $number The number of entities to populate + */ + public function addEntity($entity, $number, $customColumnFormatters = array(), $customModifiers = array(), $generateId = false) + { + if (!$entity instanceof \Faker\ORM\Doctrine\EntityPopulator) { + if (null === $this->manager) { + throw new \InvalidArgumentException("No entity manager passed to Doctrine Populator."); + } + $entity = new \Faker\ORM\Doctrine\EntityPopulator($this->manager->getClassMetadata($entity)); + } + $entity->setColumnFormatters($entity->guessColumnFormatters($this->generator)); + if ($customColumnFormatters) { + $entity->mergeColumnFormattersWith($customColumnFormatters); + } + $entity->mergeModifiersWith($customModifiers); + $this->generateId[$entity->getClass()] = $generateId; + + $class = $entity->getClass(); + $this->entities[$class] = $entity; + $this->quantities[$class] = $number; + } + + /** + * Populate the database using all the Entity classes previously added. + * + * @param EntityManager $entityManager A Doctrine connection object + * + * @return array A list of the inserted PKs + */ + public function execute($entityManager = null) + { + if (null === $entityManager) { + $entityManager = $this->manager; + } + if (null === $entityManager) { + throw new \InvalidArgumentException("No entity manager passed to Doctrine Populator."); + } + + $insertedEntities = array(); + foreach ($this->quantities as $class => $number) { + $generateId = $this->generateId[$class]; + for ($i=0; $i < $number; $i++) { + $insertedEntities[$class][]= $this->entities[$class]->execute($entityManager, $insertedEntities, $generateId); + } + $entityManager->flush(); + } + + return $insertedEntities; + } +} diff --git a/lib/faker/src/Faker/ORM/Mandango/ColumnTypeGuesser.php b/lib/faker/src/Faker/ORM/Mandango/ColumnTypeGuesser.php new file mode 100755 index 0000000..e64dc75 --- /dev/null +++ b/lib/faker/src/Faker/ORM/Mandango/ColumnTypeGuesser.php @@ -0,0 +1,43 @@ +generator = $generator; + } + + public function guessFormat($field) + { + $generator = $this->generator; + switch ($field['type']) { + case 'boolean': + return function () use ($generator) { + return $generator->boolean; + }; + case 'integer': + return function () { + return mt_rand(0, intval('4294967295')); + }; + case 'float': + return function () { + return mt_rand(0, intval('4294967295'))/mt_rand(1, intval('4294967295')); + }; + case 'string': + return function () use ($generator) { + return $generator->text(255); + }; + case 'date': + return function () use ($generator) { + return $generator->datetime; + }; + default: + // no smart way to guess what the user expects here + return null; + } + } +} diff --git a/lib/faker/src/Faker/ORM/Mandango/EntityPopulator.php b/lib/faker/src/Faker/ORM/Mandango/EntityPopulator.php new file mode 100755 index 0000000..061df77 --- /dev/null +++ b/lib/faker/src/Faker/ORM/Mandango/EntityPopulator.php @@ -0,0 +1,110 @@ +class = $class; + } + + public function getClass() + { + return $this->class; + } + + public function setColumnFormatters($columnFormatters) + { + $this->columnFormatters = $columnFormatters; + } + + public function getColumnFormatters() + { + return $this->columnFormatters; + } + + public function mergeColumnFormattersWith($columnFormatters) + { + $this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters); + } + + public function guessColumnFormatters(\Faker\Generator $generator, Mandango $mandango) + { + $formatters = array(); + $nameGuesser = new \Faker\Guesser\Name($generator); + $columnTypeGuesser = new \Faker\ORM\Mandango\ColumnTypeGuesser($generator); + + $metadata = $mandango->getMetadata($this->class); + + // fields + foreach ($metadata['fields'] as $fieldName => $field) { + if ($formatter = $nameGuesser->guessFormat($fieldName)) { + $formatters[$fieldName] = $formatter; + continue; + } + if ($formatter = $columnTypeGuesser->guessFormat($field)) { + $formatters[$fieldName] = $formatter; + continue; + } + } + + // references + foreach (array_merge($metadata['referencesOne'], $metadata['referencesMany']) as $referenceName => $reference) { + if (!isset($reference['class'])) { + continue; + } + $referenceClass = $reference['class']; + + $formatters[$referenceName] = function ($insertedEntities) use ($referenceClass) { + if (isset($insertedEntities[$referenceClass])) { + return Base::randomElement($insertedEntities[$referenceClass]); + } + }; + } + + return $formatters; + } + + /** + * Insert one new record using the Entity class. + */ + public function execute(Mandango $mandango, $insertedEntities) + { + $metadata = $mandango->getMetadata($this->class); + + $obj = $mandango->create($this->class); + foreach ($this->columnFormatters as $column => $format) { + if (null !== $format) { + $value = is_callable($format) ? $format($insertedEntities, $obj) : $format; + + if (isset($metadata['fields'][$column]) || + isset($metadata['referencesOne'][$column])) { + $obj->set($column, $value); + } + + if (isset($metadata['referencesMany'][$column])) { + $adder = 'add'.ucfirst($column); + $obj->$adder($value); + } + } + } + $mandango->persist($obj); + + return $obj; + } +} diff --git a/lib/faker/src/Faker/ORM/Mandango/Populator.php b/lib/faker/src/Faker/ORM/Mandango/Populator.php new file mode 100755 index 0000000..57a06a5 --- /dev/null +++ b/lib/faker/src/Faker/ORM/Mandango/Populator.php @@ -0,0 +1,61 @@ +generator = $generator; + $this->mandango = $mandango; + } + + /** + * Add an order for the generation of $number records for $entity. + * + * @param mixed $entity A Propel ActiveRecord classname, or a \Faker\ORM\Propel\EntityPopulator instance + * @param int $number The number of entities to populate + */ + public function addEntity($entity, $number, $customColumnFormatters = array()) + { + if (!$entity instanceof \Faker\ORM\Mandango\EntityPopulator) { + $entity = new \Faker\ORM\Mandango\EntityPopulator($entity); + } + $entity->setColumnFormatters($entity->guessColumnFormatters($this->generator, $this->mandango)); + if ($customColumnFormatters) { + $entity->mergeColumnFormattersWith($customColumnFormatters); + } + $class = $entity->getClass(); + $this->entities[$class] = $entity; + $this->quantities[$class] = $number; + } + + /** + * Populate the database using all the Entity classes previously added. + * + * @return array A list of the inserted entities. + */ + public function execute() + { + $insertedEntities = array(); + foreach ($this->quantities as $class => $number) { + for ($i=0; $i < $number; $i++) { + $insertedEntities[$class][]= $this->entities[$class]->execute($this->mandango, $insertedEntities); + } + } + $this->mandango->flush(); + + return $insertedEntities; + } +} diff --git a/lib/faker/src/Faker/ORM/Propel/ColumnTypeGuesser.php b/lib/faker/src/Faker/ORM/Propel/ColumnTypeGuesser.php new file mode 100755 index 0000000..e406768 --- /dev/null +++ b/lib/faker/src/Faker/ORM/Propel/ColumnTypeGuesser.php @@ -0,0 +1,100 @@ +generator = $generator; + } + + public function guessFormat(ColumnMap $column) + { + $generator = $this->generator; + if ($column->isTemporal()) { + if ($column->isEpochTemporal()) { + return function () use ($generator) { + return $generator->dateTime; + }; + } else { + return function () use ($generator) { + return $generator->dateTimeAD; + }; + } + } + $type = $column->getType(); + switch ($type) { + case PropelColumnTypes::BOOLEAN: + case PropelColumnTypes::BOOLEAN_EMU: + return function () use ($generator) { + return $generator->boolean; + }; + case PropelColumnTypes::NUMERIC: + case PropelColumnTypes::DECIMAL: + $size = $column->getSize(); + + return function () use ($generator, $size) { + return $generator->randomNumber($size + 2) / 100; + }; + case PropelColumnTypes::TINYINT: + return function () { + return mt_rand(0, 127); + }; + case PropelColumnTypes::SMALLINT: + return function () { + return mt_rand(0, 32767); + }; + case PropelColumnTypes::INTEGER: + return function () { + return mt_rand(0, intval('2147483647')); + }; + case PropelColumnTypes::BIGINT: + return function () { + return mt_rand(0, intval('9223372036854775807')); + }; + case PropelColumnTypes::FLOAT: + return function () { + return mt_rand(0, intval('2147483647'))/mt_rand(1, intval('2147483647')); + }; + case PropelColumnTypes::DOUBLE: + case PropelColumnTypes::REAL: + return function () { + return mt_rand(0, intval('9223372036854775807'))/mt_rand(1, intval('9223372036854775807')); + }; + case PropelColumnTypes::CHAR: + case PropelColumnTypes::VARCHAR: + case PropelColumnTypes::BINARY: + case PropelColumnTypes::VARBINARY: + $size = $column->getSize(); + + return function () use ($generator, $size) { + return $generator->text($size); + }; + case PropelColumnTypes::LONGVARCHAR: + case PropelColumnTypes::LONGVARBINARY: + case PropelColumnTypes::CLOB: + case PropelColumnTypes::CLOB_EMU: + case PropelColumnTypes::BLOB: + return function () use ($generator) { + return $generator->text; + }; + case PropelColumnTypes::ENUM: + $valueSet = $column->getValueSet(); + + return function () use ($generator, $valueSet) { + return $generator->randomElement($valueSet); + }; + case PropelColumnTypes::OBJECT: + case PropelColumnTypes::PHP_ARRAY: + default: + // no smart way to guess what the user expects here + return null; + } + } +} diff --git a/lib/faker/src/Faker/ORM/Propel/EntityPopulator.php b/lib/faker/src/Faker/ORM/Propel/EntityPopulator.php new file mode 100755 index 0000000..5af6810 --- /dev/null +++ b/lib/faker/src/Faker/ORM/Propel/EntityPopulator.php @@ -0,0 +1,170 @@ +class = $class; + } + + public function getClass() + { + return $this->class; + } + + public function setColumnFormatters($columnFormatters) + { + $this->columnFormatters = $columnFormatters; + } + + public function getColumnFormatters() + { + return $this->columnFormatters; + } + + public function mergeColumnFormattersWith($columnFormatters) + { + $this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters); + } + + public function guessColumnFormatters(\Faker\Generator $generator) + { + $formatters = array(); + $class = $this->class; + $peerClass = $class::PEER; + $tableMap = $peerClass::getTableMap(); + $nameGuesser = new \Faker\Guesser\Name($generator); + $columnTypeGuesser = new \Faker\ORM\Propel\ColumnTypeGuesser($generator); + foreach ($tableMap->getColumns() as $columnMap) { + // skip behavior columns, handled by modifiers + if ($this->isColumnBehavior($columnMap)) { + continue; + } + if ($columnMap->isForeignKey()) { + $relatedClass = $columnMap->getRelation()->getForeignTable()->getClassname(); + $formatters[$columnMap->getPhpName()] = function ($inserted) use ($relatedClass) { + return isset($inserted[$relatedClass]) ? $inserted[$relatedClass][mt_rand(0, count($inserted[$relatedClass]) - 1)] : null; + }; + continue; + } + if ($columnMap->isPrimaryKey()) { + continue; + } + if ($formatter = $nameGuesser->guessFormat($columnMap->getPhpName(), $columnMap->getSize())) { + $formatters[$columnMap->getPhpName()] = $formatter; + continue; + } + if ($formatter = $columnTypeGuesser->guessFormat($columnMap)) { + $formatters[$columnMap->getPhpName()] = $formatter; + continue; + } + } + + return $formatters; + } + + protected function isColumnBehavior(ColumnMap $columnMap) + { + foreach ($columnMap->getTable()->getBehaviors() as $name => $params) { + $columnName = Base::toLower($columnMap->getName()); + switch ($name) { + case 'nested_set': + $columnNames = array($params['left_column'], $params['right_column'], $params['level_column']); + if (in_array($columnName, $columnNames)) { + return true; + } + break; + case 'timestampable': + $columnNames = array($params['create_column'], $params['update_column']); + if (in_array($columnName, $columnNames)) { + return true; + } + break; + } + } + + return false; + } + + public function setModifiers($modifiers) + { + $this->modifiers = $modifiers; + } + + public function getModifiers() + { + return $this->modifiers; + } + + public function mergeModifiersWith($modifiers) + { + $this->modifiers = array_merge($this->modifiers, $modifiers); + } + + public function guessModifiers(\Faker\Generator $generator) + { + $modifiers = array(); + $class = $this->class; + $peerClass = $class::PEER; + $tableMap = $peerClass::getTableMap(); + foreach ($tableMap->getBehaviors() as $name => $params) { + switch ($name) { + case 'nested_set': + $modifiers['nested_set'] = function ($obj, $inserted) use ($class, $generator) { + if (isset($inserted[$class])) { + $queryClass = $class . 'Query'; + $parent = $queryClass::create()->findPk($generator->randomElement($inserted[$class])); + $obj->insertAsLastChildOf($parent); + } else { + $obj->makeRoot(); + } + }; + break; + case 'sortable': + $modifiers['sortable'] = function ($obj, $inserted) use ($class, $generator) { + $maxRank = isset($inserted[$class]) ? count($inserted[$class]) : 0; + $obj->insertAtRank(mt_rand(1, $maxRank + 1)); + }; + break; + } + } + + return $modifiers; + } + + /** + * Insert one new record using the Entity class. + */ + public function execute($con, $insertedEntities) + { + $obj = new $this->class(); + foreach ($this->getColumnFormatters() as $column => $format) { + if (null !== $format) { + $obj->setByName($column, is_callable($format) ? $format($insertedEntities, $obj) : $format); + } + } + foreach ($this->getModifiers() as $modifier) { + $modifier($obj, $insertedEntities); + } + $obj->save($con); + + return $obj->getPrimaryKey(); + } +} diff --git a/lib/faker/src/Faker/ORM/Propel/Populator.php b/lib/faker/src/Faker/ORM/Propel/Populator.php new file mode 100755 index 0000000..067229b --- /dev/null +++ b/lib/faker/src/Faker/ORM/Propel/Populator.php @@ -0,0 +1,86 @@ +generator = $generator; + } + + /** + * Add an order for the generation of $number records for $entity. + * + * @param mixed $entity A Propel ActiveRecord classname, or a \Faker\ORM\Propel\EntityPopulator instance + * @param int $number The number of entities to populate + */ + public function addEntity($entity, $number, $customColumnFormatters = array(), $customModifiers = array()) + { + if (!$entity instanceof \Faker\ORM\Propel\EntityPopulator) { + $entity = new \Faker\ORM\Propel\EntityPopulator($entity); + } + $entity->setColumnFormatters($entity->guessColumnFormatters($this->generator)); + if ($customColumnFormatters) { + $entity->mergeColumnFormattersWith($customColumnFormatters); + } + $entity->setModifiers($entity->guessModifiers($this->generator)); + if ($customModifiers) { + $entity->mergeModifiersWith($customModifiers); + } + $class = $entity->getClass(); + $this->entities[$class] = $entity; + $this->quantities[$class] = $number; + } + + /** + * Populate the database using all the Entity classes previously added. + * + * @param PropelPDO $con A Propel connection object + * + * @return array A list of the inserted PKs + */ + public function execute($con = null) + { + if (null === $con) { + $con = $this->getConnection(); + } + $isInstancePoolingEnabled = \Propel::isInstancePoolingEnabled(); + \Propel::disableInstancePooling(); + $insertedEntities = array(); + $con->beginTransaction(); + foreach ($this->quantities as $class => $number) { + for ($i=0; $i < $number; $i++) { + $insertedEntities[$class][]= $this->entities[$class]->execute($con, $insertedEntities); + } + } + $con->commit(); + if ($isInstancePoolingEnabled) { + \Propel::enableInstancePooling(); + } + + return $insertedEntities; + } + + protected function getConnection() + { + // use the first connection available + $class = key($this->entities); + + if (!$class) { + throw new \RuntimeException('No class found from entities. Did you add entities to the Populator ?'); + } + + $peer = $class::PEER; + + return \Propel::getConnection($peer::DATABASE_NAME, \Propel::CONNECTION_WRITE); + } +} diff --git a/lib/faker/src/Faker/Provider/Address.php b/lib/faker/src/Faker/Provider/Address.php new file mode 100755 index 0000000..c11b5b1 --- /dev/null +++ b/lib/faker/src/Faker/Provider/Address.php @@ -0,0 +1,123 @@ +generator->parse($format); + } + + /** + * @example 'Crist Parks' + */ + public function streetName() + { + $format = static::randomElement(static::$streetNameFormats); + + return $this->generator->parse($format); + } + + /** + * @example '791 Crist Parks' + */ + public function streetAddress() + { + $format = static::randomElement(static::$streetAddressFormats); + + return $this->generator->parse($format); + } + + /** + * @example 86039-9874 + */ + public static function postcode() + { + return static::toUpper(static::bothify(static::randomElement(static::$postcode))); + } + + /** + * @example '791 Crist Parks, Sashabury, IL 86039-9874' + */ + public function address() + { + $format = static::randomElement(static::$addressFormats); + + return $this->generator->parse($format); + } + + /** + * @example 'Japan' + */ + public static function country() + { + return static::randomElement(static::$country); + } + + /** + * @example 77.147489 + * @return float Uses signed degrees format (returns a float number between -90 and 90) + */ + public static function latitude() + { + return static::randomFloat(6, 0, 180) - 90; + } + + /** + * @example 86.211205 + * @return float Uses signed degrees format (returns a float number between -180 and 180) + */ + public static function longitude() + { + return static::randomFloat(6, 0, 360) - 180; + } +} diff --git a/lib/faker/src/Faker/Provider/Barcode.php b/lib/faker/src/Faker/Provider/Barcode.php new file mode 100755 index 0000000..5281e37 --- /dev/null +++ b/lib/faker/src/Faker/Provider/Barcode.php @@ -0,0 +1,110 @@ +numerify(str_repeat('#', $length - 1)); + + return $code . static::eanChecksum($code); + } + + /** + * Utility function for computing EAN checksums + */ + protected static function eanChecksum($input) + { + $sequence = (strlen($input) - 1) == 8 ? array(3, 1) : array(1, 3); + $sums = 0; + foreach (str_split($input) as $n => $digit) { + $sums += $digit * $sequence[$n % 2]; + } + return (10 - $sums % 10) % 10; + } + + /** + * ISBN-10 check digit + * @link http://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-10_check_digits + * + * @param string $input ISBN without check-digit + * @throws \LengthException When wrong input length passed + * + * @return integer Check digit + */ + protected static function isbnChecksum($input) + { + // We're calculating check digit for ISBN-10 + // so, the length of the input should be 9 + $length = 9; + + if (strlen($input) != $length) { + throw new \LengthException(sprintf('Input length should be equal to %d', $length)); + } + + $digits = str_split($input); + array_walk( + $digits, + function (&$digit, $position) { + $digit = (10 - $position) * $digit; + } + ); + $result = (11 - array_sum($digits) % 11) % 11; + + // 10 is replaced by X + return ($result < 10)?$result:'X'; + } + + /** + * Get a random EAN13 barcode. + * @return string + * @example '4006381333931' + */ + public function ean13() + { + return $this->ean(13); + } + + /** + * Get a random EAN8 barcode. + * @return string + * @example '73513537' + */ + public function ean8() + { + return $this->ean(8); + } + + /** + * Get a random ISBN-10 code + * @link http://en.wikipedia.org/wiki/International_Standard_Book_Number + * + * @return string + * @example '4881416324' + */ + public function isbn10() + { + $code = $this->numerify(str_repeat('#', 9)); + + return $code . static::isbnChecksum($code); + } + + /** + * Get a random ISBN-13 code + * @link http://en.wikipedia.org/wiki/International_Standard_Book_Number + * + * @return string + * @example '9790404436093' + */ + public function isbn13() + { + $code = '97' . static::numberBetween(8, 9) . $this->numerify(str_repeat('#', 9)); + + return $code . static::eanChecksum($code); + } +} diff --git a/lib/faker/src/Faker/Provider/Base.php b/lib/faker/src/Faker/Provider/Base.php new file mode 100755 index 0000000..9c7aefe --- /dev/null +++ b/lib/faker/src/Faker/Provider/Base.php @@ -0,0 +1,545 @@ +generator = $generator; + } + + /** + * Returns a random number between 0 and 9 + * + * @return integer + */ + public static function randomDigit() + { + return mt_rand(0, 9); + } + + /** + * Returns a random number between 1 and 9 + * + * @return integer + */ + public static function randomDigitNotNull() + { + return mt_rand(1, 9); + } + + /** + * Generates a random digit, which cannot be $except + * + * @param int $except + * @return int + */ + public static function randomDigitNot($except) + { + $result = self::numberBetween(0, 8); + if ($result >= $except) { + $result++; + } + return $result; + } + + /** + * Returns a random integer with 0 to $nbDigits digits. + * + * The maximum value returned is mt_getrandmax() + * + * @param integer $nbDigits Defaults to a random number between 1 and 9 + * @param boolean $strict Whether the returned number should have exactly $nbDigits + * @example 79907610 + * + * @return integer + */ + public static function randomNumber($nbDigits = null, $strict = false) + { + if (!is_bool($strict)) { + throw new \InvalidArgumentException('randomNumber() generates numbers of fixed width. To generate numbers between two boundaries, use numberBetween() instead.'); + } + if (null === $nbDigits) { + $nbDigits = static::randomDigitNotNull(); + } + $max = pow(10, $nbDigits) - 1; + if ($max > mt_getrandmax()) { + throw new \InvalidArgumentException('randomNumber() can only generate numbers up to mt_getrandmax()'); + } + if ($strict) { + return mt_rand(pow(10, $nbDigits - 1), $max); + } + + return mt_rand(0, $max); + } + + /** + * Return a random float number + * + * @param int $nbMaxDecimals + * @param int|float $min + * @param int|float $max + * @example 48.8932 + * + * @return float + */ + public static function randomFloat($nbMaxDecimals = null, $min = 0, $max = null) + { + if (null === $nbMaxDecimals) { + $nbMaxDecimals = static::randomDigit(); + } + + if (null === $max) { + $max = static::randomNumber(); + } + + if ($min > $max) { + $tmp = $min; + $min = $max; + $max = $tmp; + } + + return round($min + mt_rand() / mt_getrandmax() * ($max - $min), $nbMaxDecimals); + } + + /** + * Returns a random number between $int1 and $int2 (any order) + * + * @param integer $int1 default to 0 + * @param integer $int2 defaults to 32 bit max integer, ie 2147483647 + * @example 79907610 + * + * @return integer + */ + public static function numberBetween($int1 = 0, $int2 = 2147483647) + { + $min = $int1 < $int2 ? $int1 : $int2; + $max = $int1 < $int2 ? $int2 : $int1; + return mt_rand($min, $max); + } + + /** + * Returns a random letter from a to z + * + * @return string + */ + public static function randomLetter() + { + return chr(mt_rand(97, 122)); + } + + /** + * Returns a random ASCII character (excluding accents and special chars) + */ + public static function randomAscii() + { + return chr(mt_rand(33, 126)); + } + + /** + * Returns random elements from a provided array + * + * @param array $array Array to take elements from. Defaults to a-f + * @param integer $count Number of elements to take. + * @throws \LengthException When requesting more elements than provided + * + * @return array New array with $count elements from $array + */ + public static function randomElements(array $array = array('a', 'b', 'c'), $count = 1) + { + $allKeys = array_keys($array); + $numKeys = count($allKeys); + + if ($numKeys < $count) { + throw new \LengthException(sprintf('Cannot get %d elements, only %d in array', $count, $numKeys)); + } + + $highKey = $numKeys - 1; + $keys = $elements = array(); + $numElements = 0; + + while ($numElements < $count) { + $num = mt_rand(0, $highKey); + if (isset($keys[$num])) { + continue; + } + + $keys[$num] = true; + $elements[] = $array[$allKeys[$num]]; + $numElements++; + } + + return $elements; + } + + /** + * Returns a random element from a passed array + * + * @param array $array + * @return mixed + */ + public static function randomElement($array = array('a', 'b', 'c')) + { + if (!$array) { + return null; + } + $elements = static::randomElements($array, 1); + + return $elements[0]; + } + + /** + * Returns a random key from a passed associative array + * + * @param array $array + * @return int|string|null + */ + public static function randomKey($array = array()) + { + if (!$array) { + return null; + } + $keys = array_keys($array); + $key = $keys[mt_rand(0, count($keys) - 1)]; + + return $key; + } + + /** + * Returns a shuffled version of the argument. + * + * This function accepts either an array, or a string. + * + * @example $faker->shuffle([1, 2, 3]); // [2, 1, 3] + * @example $faker->shuffle('hello, world'); // 'rlo,h eold!lw' + * + * @see shuffleArray() + * @see shuffleString() + * + * @param array|string $arg The set to shuffle + * @return array|string The shuffled set + */ + public static function shuffle($arg = '') + { + if (is_array($arg)) { + return static::shuffleArray($arg); + } + if (is_string($arg)) { + return static::shuffleString($arg); + } + throw new \InvalidArgumentException('shuffle() only supports strings or arrays'); + } + + /** + * Returns a shuffled version of the array. + * + * This function does not mutate the original array. It uses the + * Fisher–Yates algorithm, which is unbiaised, together with a Mersenne + * twister random generator. This function is therefore more random than + * PHP's shuffle() function, and it is seedable. + * + * @link http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle + * + * @example $faker->shuffleArray([1, 2, 3]); // [2, 1, 3] + * + * @param array $array The set to shuffle + * @return array The shuffled set + */ + public static function shuffleArray($array = array()) + { + $shuffledArray = array(); + $i = 0; + reset($array); + while (list($key, $value) = each($array)) { + if ($i == 0) { + $j = 0; + } else { + $j = mt_rand(0, $i); + } + if ($j == $i) { + $shuffledArray[]= $value; + } else { + $shuffledArray[]= $shuffledArray[$j]; + $shuffledArray[$j] = $value; + } + $i++; + } + return $shuffledArray; + } + + /** + * Returns a shuffled version of the string. + * + * This function does not mutate the original string. It uses the + * Fisher–Yates algorithm, which is unbiaised, together with a Mersenne + * twister random generator. This function is therefore more random than + * PHP's shuffle() function, and it is seedable. Additionally, it is + * UTF8 safe if the mb extension is available. + * + * @link http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle + * + * @example $faker->shuffleString('hello, world'); // 'rlo,h eold!lw' + * + * @param string $string The set to shuffle + * @param string $encoding The string encoding (defaults to UTF-8) + * @return string The shuffled set + */ + public static function shuffleString($string = '', $encoding = 'UTF-8') + { + if (function_exists('mb_strlen')) { + // UTF8-safe str_split() + $array = array(); + $strlen = mb_strlen($string, $encoding); + for ($i = 0; $i < $strlen; $i++) { + $array []= mb_substr($string, $i, 1, $encoding); + } + } else { + $array = str_split($string, 1); + } + return join('', static::shuffleArray($array)); + } + + private static function replaceWildcard($string, $wildcard = '#', $callback = 'static::randomDigit') + { + if (($pos = strpos($string, $wildcard)) === false) { + return $string; + } + for ($i = $pos, $last = strrpos($string, $wildcard, $pos) + 1; $i < $last; $i++) { + if ($string[$i] === $wildcard) { + $string[$i] = call_user_func($callback); + } + } + return $string; + } + + /** + * Replaces all hash sign ('#') occurrences with a random number + * Replaces all percentage sign ('%') occurrences with a not null number + * + * @param string $string String that needs to bet parsed + * @return string + */ + public static function numerify($string = '###') + { + // instead of using randomDigit() several times, which is slow, + // count the number of hashes and generate once a large number + $toReplace = array(); + if (($pos = strpos($string, '#')) !== false) { + for ($i = $pos, $last = strrpos($string, '#', $pos) + 1; $i < $last; $i++) { + if ($string[$i] === '#') { + $toReplace[] = $i; + } + } + } + if ($nbReplacements = count($toReplace)) { + $maxAtOnce = strlen((string) mt_getrandmax()) - 1; + $numbers = ''; + $i = 0; + while ($i < $nbReplacements) { + $size = min($nbReplacements - $i, $maxAtOnce); + $numbers .= str_pad(static::randomNumber($size), $size, '0', STR_PAD_LEFT); + $i += $size; + } + for ($i = 0; $i < $nbReplacements; $i++) { + $string[$toReplace[$i]] = $numbers[$i]; + } + } + $string = self::replaceWildcard($string, '%', 'static::randomDigitNotNull'); + + return $string; + } + + /** + * Replaces all question mark ('?') occurrences with a random letter + * + * @param string $string String that needs to bet parsed + * @return string + */ + public static function lexify($string = '????') + { + return self::replaceWildcard($string, '?', 'static::randomLetter'); + } + + /** + * Replaces hash signs ('#') and question marks ('?') with random numbers and letters + * An asterisk ('*') is replaced with either a random number or a random letter + * + * @param string $string String that needs to bet parsed + * @return string + */ + public static function bothify($string = '## ??') + { + $string = self::replaceWildcard($string, '*', function () { + return mt_rand(0, 1) ? '#' : '?'; + }); + return static::lexify(static::numerify($string)); + } + + /** + * Replaces * signs with random numbers and letters and special characters + * + * @example $faker->asciify(''********'); // "s5'G!uC3" + * + * @param string $string String that needs to bet parsed + * @return string + */ + public static function asciify($string = '****') + { + return preg_replace_callback('/\*/u', 'static::randomAscii', $string); + } + + /** + * Transforms a basic regular expression into a random string satisfying the expression. + * + * @example $faker->regexify('[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'); // sm0@y8k96a.ej + * + * Regex delimiters '/.../' and begin/end markers '^...$' are ignored. + * + * Only supports a small subset of the regex syntax. For instance, + * unicode, negated classes, unbouned ranges, subpatterns, back references, + * assertions, recursive patterns, and comments are not supported. Escaping + * support is extremely fragile. + * + * This method is also VERY slow. Use it only when no other formatter + * can generate the fake data you want. For instance, prefer calling + * `$faker->email` rather than `regexify` with the previous regular + * expression. + * + * Also note than `bothify` can probably do most of what this method does, + * but much faster. For instance, for a dummy email generation, try + * `$faker->bothify('?????????@???.???')`. + * + * @see https://github.com/icomefromthenet/ReverseRegex for a more robust implementation + * + * @param string $regex A regular expression (delimiters are optional) + * @return string + */ + public static function regexify($regex = '') + { + // ditch the anchors + $regex = preg_replace('/^\/?\^?/', '', $regex); + $regex = preg_replace('/\$?\/?$/', '', $regex); + // All {2} become {2,2} + $regex = preg_replace('/\{(\d+)\}/', '{\1,\1}', $regex); + // Single-letter quantifiers (?, *, +) become bracket quantifiers ({0,1}, {0,rand}, {1, rand}) + $regex = preg_replace('/(?generator; + } + + return new DefaultGenerator($default); + } + + /** + * Chainable method for making any formatter unique. + * + * + * // will never return twice the same value + * $faker->unique()->randomElement(array(1, 2, 3)); + * + * + * @param boolean $reset If set to true, resets the list of existing values + * @param integer $maxRetries Maximum number of retries to find a unique value, + * After which an OverflowException is thrown. + * @throws \OverflowException When no unique value can be found by iterating $maxRetries times + * + * @return UniqueGenerator A proxy class returning only non-existing values + */ + public function unique($reset = false, $maxRetries = 10000) + { + if ($reset || !$this->unique) { + $this->unique = new UniqueGenerator($this->generator, $maxRetries); + } + + return $this->unique; + } +} diff --git a/lib/faker/src/Faker/Provider/Biased.php b/lib/faker/src/Faker/Provider/Biased.php new file mode 100755 index 0000000..c9ebb41 --- /dev/null +++ b/lib/faker/src/Faker/Provider/Biased.php @@ -0,0 +1,64 @@ +generator->parse($format); + } + + /** + * @example 'Ltd' + */ + public static function companySuffix() + { + return static::randomElement(static::$companySuffix); + } +} diff --git a/lib/faker/src/Faker/Provider/DateTime.php b/lib/faker/src/Faker/Provider/DateTime.php new file mode 100755 index 0000000..37e1180 --- /dev/null +++ b/lib/faker/src/Faker/Provider/DateTime.php @@ -0,0 +1,263 @@ +getTimestamp(); + } + + return strtotime(empty($max) ? 'now' : $max); + } + + /** + * Get a timestamp between January 1, 1970 and now + * + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @return int + * + * @example 1061306726 + */ + public static function unixTime($max = 'now') + { + return mt_rand(0, static::getMaxTimestamp($max)); + } + + /** + * Get a datetime object for a date between January 1, 1970 and now + * + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @example DateTime('2005-08-16 20:39:21') + * @return \DateTime + */ + public static function dateTime($max = 'now') + { + return new \DateTime('@' . static::unixTime($max)); + } + + /** + * Get a datetime object for a date between January 1, 001 and now + * + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @example DateTime('1265-03-22 21:15:52') + * @return \DateTime + */ + public static function dateTimeAD($max = 'now') + { + return new \DateTime('@' . mt_rand(-62135597361, static::getMaxTimestamp($max))); + } + + /** + * get a date string formatted with ISO8601 + * + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @return string + * @example '2003-10-21T16:05:52+0000' + */ + public static function iso8601($max = 'now') + { + return static::date(\DateTime::ISO8601, $max); + } + + /** + * Get a date string between January 1, 1970 and now + * + * @param string $format + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @return string + * @example '2008-11-27' + */ + public static function date($format = 'Y-m-d', $max = 'now') + { + return static::dateTime($max)->format($format); + } + + /** + * Get a time string (24h format by default) + * + * @param string $format + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @return string + * @example '15:02:34' + */ + public static function time($format = 'H:i:s', $max = 'now') + { + return static::dateTime($max)->format($format); + } + + /** + * Get a DateTime object based on a random date between two given dates. + * Accepts date strings that can be recognized by strtotime(). + * + * @param \DateTime|string $startDate Defaults to 30 years ago + * @param \DateTime|string $endDate Defaults to "now" + * @example DateTime('1999-02-02 11:42:52') + * @return \DateTime + */ + public static function dateTimeBetween($startDate = '-30 years', $endDate = 'now') + { + $startTimestamp = $startDate instanceof \DateTime ? $startDate->getTimestamp() : strtotime($startDate); + $endTimestamp = static::getMaxTimestamp($endDate); + + if ($startTimestamp > $endTimestamp) { + throw new \InvalidArgumentException('Start date must be anterior to end date.'); + } + + $timestamp = mt_rand($startTimestamp, $endTimestamp); + + $ts = new \DateTime('@' . $timestamp); + $ts->setTimezone(new \DateTimeZone(date_default_timezone_get())); + + return $ts; + } + + /** + * Get a DateTime object based on a random date between one given date and + * an interval + * Accepts date string that can be recognized by strtotime(). + * + * @param string $date Defaults to 30 years ago + * @param string $interval Defaults to 5 days after + * @example dateTimeInInterval('1999-02-02 11:42:52', '+ 5 days') + * @return \DateTime + */ + public static function dateTimeInInterval($date = '-30 years', $interval = '+5 days') + { + $intervalObject = \DateInterval::createFromDateString($interval); + $datetime = $date instanceof \DateTime ? $date : new \DateTime($date); + $otherDatetime = clone $datetime; + $otherDatetime->add($intervalObject); + + $begin = $datetime > $otherDatetime ? $otherDatetime : $datetime; + $end = $datetime===$begin ? $otherDatetime : $datetime; + + return static::dateTimeBetween($begin, $end); + } + + /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @example DateTime('1964-04-04 11:02:02') + * @return \DateTime + */ + public static function dateTimeThisCentury($max = 'now') + { + return static::dateTimeBetween('-100 year', $max); + } + + /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @example DateTime('2010-03-10 05:18:58') + * @return \DateTime + */ + public static function dateTimeThisDecade($max = 'now') + { + return static::dateTimeBetween('-10 year', $max); + } + + /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @example DateTime('2011-09-19 09:24:37') + * @return \DateTime + */ + public static function dateTimeThisYear($max = 'now') + { + return static::dateTimeBetween('-1 year', $max); + } + + /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @example DateTime('2011-10-05 12:51:46') + * @return \DateTime + */ + public static function dateTimeThisMonth($max = 'now') + { + return static::dateTimeBetween('-1 month', $max); + } + + /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @return string + * @example 'am' + */ + public static function amPm($max = 'now') + { + return static::dateTime($max)->format('a'); + } + + /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @return string + * @example '22' + */ + public static function dayOfMonth($max = 'now') + { + return static::dateTime($max)->format('d'); + } + + /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @return string + * @example 'Tuesday' + */ + public static function dayOfWeek($max = 'now') + { + return static::dateTime($max)->format('l'); + } + + /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @return string + * @example '7' + */ + public static function month($max = 'now') + { + return static::dateTime($max)->format('m'); + } + + /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @return string + * @example 'September' + */ + public static function monthName($max = 'now') + { + return static::dateTime($max)->format('F'); + } + + /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @return int + * @example 1673 + */ + public static function year($max = 'now') + { + return static::dateTime($max)->format('Y'); + } + + /** + * @return string + * @example 'XVII' + */ + public static function century() + { + return static::randomElement(static::$century); + } + + /** + * @return string + * @example 'Europe/Paris' + */ + public static function timezone() + { + return static::randomElement(\DateTimeZone::listIdentifiers()); + } +} diff --git a/lib/faker/src/Faker/Provider/File.php b/lib/faker/src/Faker/Provider/File.php new file mode 100755 index 0000000..3897c27 --- /dev/null +++ b/lib/faker/src/Faker/Provider/File.php @@ -0,0 +1,606 @@ + file extension(s) + * @link http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types + */ + protected static $mimeTypes = array( + 'application/atom+xml' => 'atom', + 'application/ecmascript' => 'ecma', + 'application/emma+xml' => 'emma', + 'application/epub+zip' => 'epub', + 'application/java-archive' => 'jar', + 'application/java-vm' => 'class', + 'application/javascript' => 'js', + 'application/json' => 'json', + 'application/jsonml+json' => 'jsonml', + 'application/lost+xml' => 'lostxml', + 'application/mathml+xml' => 'mathml', + 'application/mets+xml' => 'mets', + 'application/mods+xml' => 'mods', + 'application/mp4' => 'mp4s', + 'application/msword' => array('doc', 'dot'), + 'application/octet-stream' => array( + 'bin', + 'dms', + 'lrf', + 'mar', + 'so', + 'dist', + 'distz', + 'pkg', + 'bpk', + 'dump', + 'elc', + 'deploy' + ), + 'application/ogg' => 'ogx', + 'application/omdoc+xml' => 'omdoc', + 'application/pdf' => 'pdf', + 'application/pgp-encrypted' => 'pgp', + 'application/pgp-signature' => array('asc', 'sig'), + 'application/pkix-pkipath' => 'pkipath', + 'application/pkixcmp' => 'pki', + 'application/pls+xml' => 'pls', + 'application/postscript' => array('ai', 'eps', 'ps'), + 'application/pskc+xml' => 'pskcxml', + 'application/rdf+xml' => 'rdf', + 'application/reginfo+xml' => 'rif', + 'application/rss+xml' => 'rss', + 'application/rtf' => 'rtf', + 'application/sbml+xml' => 'sbml', + 'application/vnd.adobe.air-application-installer-package+zip' => 'air', + 'application/vnd.adobe.xdp+xml' => 'xdp', + 'application/vnd.adobe.xfdf' => 'xfdf', + 'application/vnd.ahead.space' => 'ahead', + 'application/vnd.dart' => 'dart', + 'application/vnd.data-vision.rdz' => 'rdz', + 'application/vnd.dece.data' => array('uvf', 'uvvf', 'uvd', 'uvvd'), + 'application/vnd.dece.ttml+xml' => array('uvt', 'uvvt'), + 'application/vnd.dece.unspecified' => array('uvx', 'uvvx'), + 'application/vnd.dece.zip' => array('uvz', 'uvvz'), + 'application/vnd.denovo.fcselayout-link' => 'fe_launch', + 'application/vnd.dna' => 'dna', + 'application/vnd.dolby.mlp' => 'mlp', + 'application/vnd.dpgraph' => 'dpg', + 'application/vnd.dreamfactory' => 'dfac', + 'application/vnd.ds-keypoint' => 'kpxx', + 'application/vnd.dvb.ait' => 'ait', + 'application/vnd.dvb.service' => 'svc', + 'application/vnd.dynageo' => 'geo', + 'application/vnd.ecowin.chart' => 'mag', + 'application/vnd.enliven' => 'nml', + 'application/vnd.epson.esf' => 'esf', + 'application/vnd.epson.msf' => 'msf', + 'application/vnd.epson.quickanime' => 'qam', + 'application/vnd.epson.salt' => 'slt', + 'application/vnd.epson.ssf' => 'ssf', + 'application/vnd.ezpix-album' => 'ez2', + 'application/vnd.ezpix-package' => 'ez3', + 'application/vnd.fdf' => 'fdf', + 'application/vnd.fdsn.mseed' => 'mseed', + 'application/vnd.fdsn.seed' => array('seed', 'dataless'), + 'application/vnd.flographit' => 'gph', + 'application/vnd.fluxtime.clip' => 'ftc', + 'application/vnd.hal+xml' => 'hal', + 'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx', + 'application/vnd.ibm.minipay' => 'mpy', + 'application/vnd.ibm.secure-container' => 'sc', + 'application/vnd.iccprofile' => array('icc', 'icm'), + 'application/vnd.igloader' => 'igl', + 'application/vnd.immervision-ivp' => 'ivp', + 'application/vnd.kde.karbon' => 'karbon', + 'application/vnd.kde.kchart' => 'chrt', + 'application/vnd.kde.kformula' => 'kfo', + 'application/vnd.kde.kivio' => 'flw', + 'application/vnd.kde.kontour' => 'kon', + 'application/vnd.kde.kpresenter' => array('kpr', 'kpt'), + 'application/vnd.kde.kspread' => 'ksp', + 'application/vnd.kde.kword' => array('kwd', 'kwt'), + 'application/vnd.kenameaapp' => 'htke', + 'application/vnd.kidspiration' => 'kia', + 'application/vnd.kinar' => array('kne', 'knp'), + 'application/vnd.koan' => array('skp', 'skd', 'skt', 'skm'), + 'application/vnd.kodak-descriptor' => 'sse', + 'application/vnd.las.las+xml' => 'lasxml', + 'application/vnd.llamagraphics.life-balance.desktop' => 'lbd', + 'application/vnd.llamagraphics.life-balance.exchange+xml' => 'lbe', + 'application/vnd.lotus-1-2-3' => '123', + 'application/vnd.lotus-approach' => 'apr', + 'application/vnd.lotus-freelance' => 'pre', + 'application/vnd.lotus-notes' => 'nsf', + 'application/vnd.lotus-organizer' => 'org', + 'application/vnd.lotus-screencam' => 'scm', + 'application/vnd.mozilla.xul+xml' => 'xul', + 'application/vnd.ms-artgalry' => 'cil', + 'application/vnd.ms-cab-compressed' => 'cab', + 'application/vnd.ms-excel' => array( + 'xls', + 'xlm', + 'xla', + 'xlc', + 'xlt', + 'xlw' + ), + 'application/vnd.ms-excel.addin.macroenabled.12' => 'xlam', + 'application/vnd.ms-excel.sheet.binary.macroenabled.12' => 'xlsb', + 'application/vnd.ms-excel.sheet.macroenabled.12' => 'xlsm', + 'application/vnd.ms-excel.template.macroenabled.12' => 'xltm', + 'application/vnd.ms-fontobject' => 'eot', + 'application/vnd.ms-htmlhelp' => 'chm', + 'application/vnd.ms-ims' => 'ims', + 'application/vnd.ms-lrm' => 'lrm', + 'application/vnd.ms-officetheme' => 'thmx', + 'application/vnd.ms-pki.seccat' => 'cat', + 'application/vnd.ms-pki.stl' => 'stl', + 'application/vnd.ms-powerpoint' => array('ppt', 'pps', 'pot'), + 'application/vnd.ms-powerpoint.addin.macroenabled.12' => 'ppam', + 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'pptm', + 'application/vnd.ms-powerpoint.slide.macroenabled.12' => 'sldm', + 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'ppsm', + 'application/vnd.ms-powerpoint.template.macroenabled.12' => 'potm', + 'application/vnd.ms-project' => array('mpp', 'mpt'), + 'application/vnd.ms-word.document.macroenabled.12' => 'docm', + 'application/vnd.ms-word.template.macroenabled.12' => 'dotm', + 'application/vnd.ms-works' => array('wps', 'wks', 'wcm', 'wdb'), + 'application/vnd.ms-wpl' => 'wpl', + 'application/vnd.ms-xpsdocument' => 'xps', + 'application/vnd.mseq' => 'mseq', + 'application/vnd.musician' => 'mus', + 'application/vnd.oasis.opendocument.chart' => 'odc', + 'application/vnd.oasis.opendocument.chart-template' => 'otc', + 'application/vnd.oasis.opendocument.database' => 'odb', + 'application/vnd.oasis.opendocument.formula' => 'odf', + 'application/vnd.oasis.opendocument.formula-template' => 'odft', + 'application/vnd.oasis.opendocument.graphics' => 'odg', + 'application/vnd.oasis.opendocument.graphics-template' => 'otg', + 'application/vnd.oasis.opendocument.image' => 'odi', + 'application/vnd.oasis.opendocument.image-template' => 'oti', + 'application/vnd.oasis.opendocument.presentation' => 'odp', + 'application/vnd.oasis.opendocument.presentation-template' => 'otp', + 'application/vnd.oasis.opendocument.spreadsheet' => 'ods', + 'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots', + 'application/vnd.oasis.opendocument.text' => 'odt', + 'application/vnd.oasis.opendocument.text-master' => 'odm', + 'application/vnd.oasis.opendocument.text-template' => 'ott', + 'application/vnd.oasis.opendocument.text-web' => 'oth', + 'application/vnd.olpc-sugar' => 'xo', + 'application/vnd.oma.dd2+xml' => 'dd2', + 'application/vnd.openofficeorg.extension' => 'oxt', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx', + 'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx', + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx', + 'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx', + 'application/vnd.pvi.ptid1' => 'ptid', + 'application/vnd.quark.quarkxpress' => array( + 'qxd', + 'qxt', + 'qwd', + 'qwt', + 'qxl', + 'qxb' + ), + 'application/vnd.realvnc.bed' => 'bed', + 'application/vnd.recordare.musicxml' => 'mxl', + 'application/vnd.recordare.musicxml+xml' => 'musicxml', + 'application/vnd.rig.cryptonote' => 'cryptonote', + 'application/vnd.rim.cod' => 'cod', + 'application/vnd.rn-realmedia' => 'rm', + 'application/vnd.rn-realmedia-vbr' => 'rmvb', + 'application/vnd.route66.link66+xml' => 'link66', + 'application/vnd.sailingtracker.track' => 'st', + 'application/vnd.seemail' => 'see', + 'application/vnd.sema' => 'sema', + 'application/vnd.semd' => 'semd', + 'application/vnd.semf' => 'semf', + 'application/vnd.shana.informed.formdata' => 'ifm', + 'application/vnd.shana.informed.formtemplate' => 'itp', + 'application/vnd.shana.informed.interchange' => 'iif', + 'application/vnd.shana.informed.package' => 'ipk', + 'application/vnd.simtech-mindmapper' => array('twd', 'twds'), + 'application/vnd.smaf' => 'mmf', + 'application/vnd.stepmania.stepchart' => 'sm', + 'application/vnd.sun.xml.calc' => 'sxc', + 'application/vnd.sun.xml.calc.template' => 'stc', + 'application/vnd.sun.xml.draw' => 'sxd', + 'application/vnd.sun.xml.draw.template' => 'std', + 'application/vnd.sun.xml.impress' => 'sxi', + 'application/vnd.sun.xml.impress.template' => 'sti', + 'application/vnd.sun.xml.math' => 'sxm', + 'application/vnd.sun.xml.writer' => 'sxw', + 'application/vnd.sun.xml.writer.global' => 'sxg', + 'application/vnd.sun.xml.writer.template' => 'stw', + 'application/vnd.sus-calendar' => array('sus', 'susp'), + 'application/vnd.svd' => 'svd', + 'application/vnd.symbian.install' => array('sis', 'sisx'), + 'application/vnd.syncml+xml' => 'xsm', + 'application/vnd.syncml.dm+wbxml' => 'bdm', + 'application/vnd.syncml.dm+xml' => 'xdm', + 'application/vnd.tao.intent-module-archive' => 'tao', + 'application/vnd.tcpdump.pcap' => array('pcap', 'cap', 'dmp'), + 'application/vnd.tmobile-livetv' => 'tmo', + 'application/vnd.trid.tpt' => 'tpt', + 'application/vnd.triscape.mxs' => 'mxs', + 'application/vnd.trueapp' => 'tra', + 'application/vnd.ufdl' => array('ufd', 'ufdl'), + 'application/vnd.uiq.theme' => 'utz', + 'application/vnd.umajin' => 'umj', + 'application/vnd.unity' => 'unityweb', + 'application/vnd.uoml+xml' => 'uoml', + 'application/vnd.vcx' => 'vcx', + 'application/vnd.visio' => array('vsd', 'vst', 'vss', 'vsw'), + 'application/vnd.visionary' => 'vis', + 'application/vnd.vsf' => 'vsf', + 'application/vnd.wap.wbxml' => 'wbxml', + 'application/vnd.wap.wmlc' => 'wmlc', + 'application/vnd.wap.wmlscriptc' => 'wmlsc', + 'application/vnd.webturbo' => 'wtb', + 'application/vnd.wolfram.player' => 'nbp', + 'application/vnd.wordperfect' => 'wpd', + 'application/vnd.wqd' => 'wqd', + 'application/vnd.wt.stf' => 'stf', + 'application/vnd.xara' => 'xar', + 'application/vnd.xfdl' => 'xfdl', + 'application/voicexml+xml' => 'vxml', + 'application/widget' => 'wgt', + 'application/winhlp' => 'hlp', + 'application/wsdl+xml' => 'wsdl', + 'application/wspolicy+xml' => 'wspolicy', + 'application/x-7z-compressed' => '7z', + 'application/x-bittorrent' => 'torrent', + 'application/x-blorb' => array('blb', 'blorb'), + 'application/x-bzip' => 'bz', + 'application/x-cdlink' => 'vcd', + 'application/x-cfs-compressed' => 'cfs', + 'application/x-chat' => 'chat', + 'application/x-chess-pgn' => 'pgn', + 'application/x-conference' => 'nsc', + 'application/x-cpio' => 'cpio', + 'application/x-csh' => 'csh', + 'application/x-debian-package' => array('deb', 'udeb'), + 'application/x-dgc-compressed' => 'dgc', + 'application/x-director' => array( + 'dir', + 'dcr', + 'dxr', + 'cst', + 'cct', + 'cxt', + 'w3d', + 'fgd', + 'swa' + ), + 'application/x-font-ttf' => array('ttf', 'ttc'), + 'application/x-font-type1' => array('pfa', 'pfb', 'pfm', 'afm'), + 'application/x-font-woff' => 'woff', + 'application/x-freearc' => 'arc', + 'application/x-futuresplash' => 'spl', + 'application/x-gca-compressed' => 'gca', + 'application/x-glulx' => 'ulx', + 'application/x-gnumeric' => 'gnumeric', + 'application/x-gramps-xml' => 'gramps', + 'application/x-gtar' => 'gtar', + 'application/x-hdf' => 'hdf', + 'application/x-install-instructions' => 'install', + 'application/x-iso9660-image' => 'iso', + 'application/x-java-jnlp-file' => 'jnlp', + 'application/x-latex' => 'latex', + 'application/x-lzh-compressed' => array('lzh', 'lha'), + 'application/x-mie' => 'mie', + 'application/x-mobipocket-ebook' => array('prc', 'mobi'), + 'application/x-ms-application' => 'application', + 'application/x-ms-shortcut' => 'lnk', + 'application/x-ms-wmd' => 'wmd', + 'application/x-ms-wmz' => 'wmz', + 'application/x-ms-xbap' => 'xbap', + 'application/x-msaccess' => 'mdb', + 'application/x-msbinder' => 'obd', + 'application/x-mscardfile' => 'crd', + 'application/x-msclip' => 'clp', + 'application/x-msdownload' => array('exe', 'dll', 'com', 'bat', 'msi'), + 'application/x-msmediaview' => array( + 'mvb', + 'm13', + 'm14' + ), + 'application/x-msmetafile' => array('wmf', 'wmz', 'emf', 'emz'), + 'application/x-rar-compressed' => 'rar', + 'application/x-research-info-systems' => 'ris', + 'application/x-sh' => 'sh', + 'application/x-shar' => 'shar', + 'application/x-shockwave-flash' => 'swf', + 'application/x-silverlight-app' => 'xap', + 'application/x-sql' => 'sql', + 'application/x-stuffit' => 'sit', + 'application/x-stuffitx' => 'sitx', + 'application/x-subrip' => 'srt', + 'application/x-sv4cpio' => 'sv4cpio', + 'application/x-sv4crc' => 'sv4crc', + 'application/x-t3vm-image' => 't3', + 'application/x-tads' => 'gam', + 'application/x-tar' => 'tar', + 'application/x-tcl' => 'tcl', + 'application/x-tex' => 'tex', + 'application/x-tex-tfm' => 'tfm', + 'application/x-texinfo' => array('texinfo', 'texi'), + 'application/x-tgif' => 'obj', + 'application/x-ustar' => 'ustar', + 'application/x-wais-source' => 'src', + 'application/x-x509-ca-cert' => array('der', 'crt'), + 'application/x-xfig' => 'fig', + 'application/x-xliff+xml' => 'xlf', + 'application/x-xpinstall' => 'xpi', + 'application/x-xz' => 'xz', + 'application/x-zmachine' => 'z1', + 'application/xaml+xml' => 'xaml', + 'application/xcap-diff+xml' => 'xdf', + 'application/xenc+xml' => 'xenc', + 'application/xhtml+xml' => array('xhtml', 'xht'), + 'application/xml' => array('xml', 'xsl'), + 'application/xml-dtd' => 'dtd', + 'application/xop+xml' => 'xop', + 'application/xproc+xml' => 'xpl', + 'application/xslt+xml' => 'xslt', + 'application/xspf+xml' => 'xspf', + 'application/xv+xml' => array('mxml', 'xhvml', 'xvml', 'xvm'), + 'application/yang' => 'yang', + 'application/yin+xml' => 'yin', + 'application/zip' => 'zip', + 'audio/adpcm' => 'adp', + 'audio/basic' => array('au', 'snd'), + 'audio/midi' => array('mid', 'midi', 'kar', 'rmi'), + 'audio/mp4' => 'mp4a', + 'audio/mpeg' => array( + 'mpga', + 'mp2', + 'mp2a', + 'mp3', + 'm2a', + 'm3a' + ), + 'audio/ogg' => array('oga', 'ogg', 'spx'), + 'audio/vnd.dece.audio' => array('uva', 'uvva'), + 'audio/vnd.rip' => 'rip', + 'audio/webm' => 'weba', + 'audio/x-aac' => 'aac', + 'audio/x-aiff' => array('aif', 'aiff', 'aifc'), + 'audio/x-caf' => 'caf', + 'audio/x-flac' => 'flac', + 'audio/x-matroska' => 'mka', + 'audio/x-mpegurl' => 'm3u', + 'audio/x-ms-wax' => 'wax', + 'audio/x-ms-wma' => 'wma', + 'audio/x-pn-realaudio' => array('ram', 'ra'), + 'audio/x-pn-realaudio-plugin' => 'rmp', + 'audio/x-wav' => 'wav', + 'audio/xm' => 'xm', + 'image/bmp' => 'bmp', + 'image/cgm' => 'cgm', + 'image/g3fax' => 'g3', + 'image/gif' => 'gif', + 'image/ief' => 'ief', + 'image/jpeg' => array('jpeg', 'jpg', 'jpe'), + 'image/ktx' => 'ktx', + 'image/png' => 'png', + 'image/prs.btif' => 'btif', + 'image/sgi' => 'sgi', + 'image/svg+xml' => array('svg', 'svgz'), + 'image/tiff' => array('tiff', 'tif'), + 'image/vnd.adobe.photoshop' => 'psd', + 'image/vnd.dece.graphic' => array('uvi', 'uvvi', 'uvg', 'uvvg'), + 'image/vnd.dvb.subtitle' => 'sub', + 'image/vnd.djvu' => array('djvu', 'djv'), + 'image/vnd.dwg' => 'dwg', + 'image/vnd.dxf' => 'dxf', + 'image/vnd.fastbidsheet' => 'fbs', + 'image/vnd.fpx' => 'fpx', + 'image/vnd.fst' => 'fst', + 'image/vnd.fujixerox.edmics-mmr' => 'mmr', + 'image/vnd.fujixerox.edmics-rlc' => 'rlc', + 'image/vnd.ms-modi' => 'mdi', + 'image/vnd.ms-photo' => 'wdp', + 'image/vnd.net-fpx' => 'npx', + 'image/vnd.wap.wbmp' => 'wbmp', + 'image/vnd.xiff' => 'xif', + 'image/webp' => 'webp', + 'image/x-3ds' => '3ds', + 'image/x-cmu-raster' => 'ras', + 'image/x-cmx' => 'cmx', + 'image/x-freehand' => array('fh', 'fhc', 'fh4', 'fh5', 'fh7'), + 'image/x-icon' => 'ico', + 'image/x-mrsid-image' => 'sid', + 'image/x-pcx' => 'pcx', + 'image/x-pict' => array('pic', 'pct'), + 'image/x-portable-anymap' => 'pnm', + 'image/x-portable-bitmap' => 'pbm', + 'image/x-portable-graymap' => 'pgm', + 'image/x-portable-pixmap' => 'ppm', + 'image/x-rgb' => 'rgb', + 'image/x-tga' => 'tga', + 'image/x-xbitmap' => 'xbm', + 'image/x-xpixmap' => 'xpm', + 'image/x-xwindowdump' => 'xwd', + 'message/rfc822' => array('eml', 'mime'), + 'model/iges' => array('igs', 'iges'), + 'model/mesh' => array('msh', 'mesh', 'silo'), + 'model/vnd.collada+xml' => 'dae', + 'model/vnd.dwf' => 'dwf', + 'model/vnd.gdl' => 'gdl', + 'model/vnd.gtw' => 'gtw', + 'model/vnd.mts' => 'mts', + 'model/vnd.vtu' => 'vtu', + 'model/vrml' => array('wrl', 'vrml'), + 'model/x3d+binary' => 'x3db', + 'model/x3d+vrml' => 'x3dv', + 'model/x3d+xml' => 'x3d', + 'text/cache-manifest' => 'appcache', + 'text/calendar' => array('ics', 'ifb'), + 'text/css' => 'css', + 'text/csv' => 'csv', + 'text/html' => array('html', 'htm'), + 'text/n3' => 'n3', + 'text/plain' => array( + 'txt', + 'text', + 'conf', + 'def', + 'list', + 'log', + 'in' + ), + 'text/prs.lines.tag' => 'dsc', + 'text/richtext' => 'rtx', + 'text/sgml' => array('sgml', 'sgm'), + 'text/tab-separated-values' => 'tsv', + 'text/troff' => array( + 't', + 'tr', + 'roff', + 'man', + 'me', + 'ms' + ), + 'text/turtle' => 'ttl', + 'text/uri-list' => array('uri', 'uris', 'urls'), + 'text/vcard' => 'vcard', + 'text/vnd.curl' => 'curl', + 'text/vnd.curl.dcurl' => 'dcurl', + 'text/vnd.curl.scurl' => 'scurl', + 'text/vnd.curl.mcurl' => 'mcurl', + 'text/vnd.dvb.subtitle' => 'sub', + 'text/vnd.fly' => 'fly', + 'text/vnd.fmi.flexstor' => 'flx', + 'text/vnd.graphviz' => 'gv', + 'text/vnd.in3d.3dml' => '3dml', + 'text/vnd.in3d.spot' => 'spot', + 'text/vnd.sun.j2me.app-descriptor' => 'jad', + 'text/vnd.wap.wml' => 'wml', + 'text/vnd.wap.wmlscript' => 'wmls', + 'text/x-asm' => array('s', 'asm'), + 'text/x-fortran' => array('f', 'for', 'f77', 'f90'), + 'text/x-java-source' => 'java', + 'text/x-opml' => 'opml', + 'text/x-pascal' => array('p', 'pas'), + 'text/x-nfo' => 'nfo', + 'text/x-setext' => 'etx', + 'text/x-sfv' => 'sfv', + 'text/x-uuencode' => 'uu', + 'text/x-vcalendar' => 'vcs', + 'text/x-vcard' => 'vcf', + 'video/3gpp' => '3gp', + 'video/3gpp2' => '3g2', + 'video/h261' => 'h261', + 'video/h263' => 'h263', + 'video/h264' => 'h264', + 'video/jpeg' => 'jpgv', + 'video/jpm' => array('jpm', 'jpgm'), + 'video/mj2' => 'mj2', + 'video/mp4' => 'mp4', + 'video/mpeg' => array('mpeg', 'mpg', 'mpe', 'm1v', 'm2v'), + 'video/ogg' => 'ogv', + 'video/quicktime' => array('qt', 'mov'), + 'video/vnd.dece.hd' => array('uvh', 'uvvh'), + 'video/vnd.dece.mobile' => array('uvm', 'uvvm'), + 'video/vnd.dece.pd' => array('uvp', 'uvvp'), + 'video/vnd.dece.sd' => array('uvs', 'uvvs'), + 'video/vnd.dece.video' => array('uvv', 'uvvv'), + 'video/vnd.dvb.file' => 'dvb', + 'video/vnd.fvt' => 'fvt', + 'video/vnd.mpegurl' => array('mxu', 'm4u'), + 'video/vnd.ms-playready.media.pyv' => 'pyv', + 'video/vnd.uvvu.mp4' => array('uvu', 'uvvu'), + 'video/vnd.vivo' => 'viv', + 'video/webm' => 'webm', + 'video/x-f4v' => 'f4v', + 'video/x-fli' => 'fli', + 'video/x-flv' => 'flv', + 'video/x-m4v' => 'm4v', + 'video/x-matroska' => array('mkv', 'mk3d', 'mks'), + 'video/x-mng' => 'mng', + 'video/x-ms-asf' => array('asf', 'asx'), + 'video/x-ms-vob' => 'vob', + 'video/x-ms-wm' => 'wm', + 'video/x-ms-wmv' => 'wmv', + 'video/x-ms-wmx' => 'wmx', + 'video/x-ms-wvx' => 'wvx', + 'video/x-msvideo' => 'avi', + 'video/x-sgi-movie' => 'movie', + ); + + /** + * Get a random MIME type + * + * @return string + * @example 'video/avi' + */ + public static function mimeType() + { + return static::randomElement(array_keys(static::$mimeTypes)); + } + + /** + * Get a random file extension (without a dot) + * + * @example avi + * @return string + */ + public static function fileExtension() + { + $random_extension = static::randomElement(array_values(static::$mimeTypes)); + + return is_array($random_extension) ? static::randomElement($random_extension) : $random_extension; + } + + /** + * Copy a random file from the source directory to the target directory and returns the filename/fullpath + * + * @param string $sourceDirectory The directory to look for random file taking + * @param string $targetDirectory + * @param boolean $fullPath Whether to have the full path or just the filename + * @return string + */ + public static function file($sourceDirectory = '/tmp', $targetDirectory = '/tmp', $fullPath = true) + { + if (!is_dir($sourceDirectory)) { + throw new \InvalidArgumentException(sprintf('Source directory %s does not exist or is not a directory.', $sourceDirectory)); + } + + if (!is_dir($targetDirectory)) { + throw new \InvalidArgumentException(sprintf('Target directory %s does not exist or is not a directory.', $targetDirectory)); + } + + if ($sourceDirectory == $targetDirectory) { + throw new \InvalidArgumentException('Source and target directories must differ.'); + } + + // Drop . and .. and reset array keys + $files = array_filter(array_values(array_diff(scandir($sourceDirectory), array('.', '..'))), function ($file) use ($sourceDirectory) { + return is_file($sourceDirectory . DIRECTORY_SEPARATOR . $file) && is_readable($sourceDirectory . DIRECTORY_SEPARATOR . $file); + }); + + if (empty($files)) { + throw new \InvalidArgumentException(sprintf('Source directory %s is empty.', $sourceDirectory)); + } + + $sourceFullPath = $sourceDirectory . DIRECTORY_SEPARATOR . static::randomElement($files); + + $destinationFile = Uuid::uuid() . '.' . pathinfo($sourceFullPath, PATHINFO_EXTENSION); + $destinationFullPath = $targetDirectory . DIRECTORY_SEPARATOR . $destinationFile; + + if (false === copy($sourceFullPath, $destinationFullPath)) { + return false; + } + + return $fullPath ? $destinationFullPath : $destinationFile; + } +} diff --git a/lib/faker/src/Faker/Provider/Image.php b/lib/faker/src/Faker/Provider/Image.php new file mode 100755 index 0000000..0def137 --- /dev/null +++ b/lib/faker/src/Faker/Provider/Image.php @@ -0,0 +1,88 @@ + 'I','Ö' => 'O','Œ' => 'O','Ü' => 'U','ä' => 'a','æ' => 'a', + 'ij' => 'i','ö' => 'o','œ' => 'o','ü' => 'u','ß' => 's','ſ' => 's', + 'À' => 'A','Á' => 'A','Â' => 'A','Ã' => 'A','Ä' => 'A','Å' => 'A', + 'Æ' => 'A','Ā' => 'A','Ą' => 'A','Ă' => 'A','Ç' => 'C','Ć' => 'C', + 'Č' => 'C','Ĉ' => 'C','Ċ' => 'C','Ď' => 'D','Đ' => 'D','È' => 'E', + 'É' => 'E','Ê' => 'E','Ë' => 'E','Ē' => 'E','Ę' => 'E','Ě' => 'E', + 'Ĕ' => 'E','Ė' => 'E','Ĝ' => 'G','Ğ' => 'G','Ġ' => 'G','Ģ' => 'G', + 'Ĥ' => 'H','Ħ' => 'H','Ì' => 'I','Í' => 'I','Î' => 'I','Ï' => 'I', + 'Ī' => 'I','Ĩ' => 'I','Ĭ' => 'I','Į' => 'I','İ' => 'I','Ĵ' => 'J', + 'Ķ' => 'K','Ľ' => 'K','Ĺ' => 'K','Ļ' => 'K','Ŀ' => 'K','Ł' => 'L', + 'Ñ' => 'N','Ń' => 'N','Ň' => 'N','Ņ' => 'N','Ŋ' => 'N','Ò' => 'O', + 'Ó' => 'O','Ô' => 'O','Õ' => 'O','Ø' => 'O','Ō' => 'O','Ő' => 'O', + 'Ŏ' => 'O','Ŕ' => 'R','Ř' => 'R','Ŗ' => 'R','Ś' => 'S','Ş' => 'S', + 'Ŝ' => 'S','Ș' => 'S','Š' => 'S','Ť' => 'T','Ţ' => 'T','Ŧ' => 'T', + 'Ț' => 'T','Ù' => 'U','Ú' => 'U','Û' => 'U','Ū' => 'U','Ů' => 'U', + 'Ű' => 'U','Ŭ' => 'U','Ũ' => 'U','Ų' => 'U','Ŵ' => 'W','Ŷ' => 'Y', + 'Ÿ' => 'Y','Ý' => 'Y','Ź' => 'Z','Ż' => 'Z','Ž' => 'Z','à' => 'a', + 'á' => 'a','â' => 'a','ã' => 'a','ā' => 'a','ą' => 'a','ă' => 'a', + 'å' => 'a','ç' => 'c','ć' => 'c','č' => 'c','ĉ' => 'c','ċ' => 'c', + 'ď' => 'd','đ' => 'd','è' => 'e','é' => 'e','ê' => 'e','ë' => 'e', + 'ē' => 'e','ę' => 'e','ě' => 'e','ĕ' => 'e','ė' => 'e','ƒ' => 'f', + 'ĝ' => 'g','ğ' => 'g','ġ' => 'g','ģ' => 'g','ĥ' => 'h','ħ' => 'h', + 'ì' => 'i','í' => 'i','î' => 'i','ï' => 'i','ī' => 'i','ĩ' => 'i', + 'ĭ' => 'i','į' => 'i','ı' => 'i','ĵ' => 'j','ķ' => 'k','ĸ' => 'k', + 'ł' => 'l','ľ' => 'l','ĺ' => 'l','ļ' => 'l','ŀ' => 'l','ñ' => 'n', + 'ń' => 'n','ň' => 'n','ņ' => 'n','ʼn' => 'n','ŋ' => 'n','ò' => 'o', + 'ó' => 'o','ô' => 'o','õ' => 'o','ø' => 'o','ō' => 'o','ő' => 'o', + 'ŏ' => 'o','ŕ' => 'r','ř' => 'r','ŗ' => 'r','ś' => 's','š' => 's', + 'ť' => 't','ù' => 'u','ú' => 'u','û' => 'u','ū' => 'u','ů' => 'u', + 'ű' => 'u','ŭ' => 'u','ũ' => 'u','ų' => 'u','ŵ' => 'w','ÿ' => 'y', + 'ý' => 'y','ŷ' => 'y','ż' => 'z','ź' => 'z','ž' => 'z','Α' => 'A', + 'Ά' => 'A','Ἀ' => 'A','Ἁ' => 'A','Ἂ' => 'A','Ἃ' => 'A','Ἄ' => 'A', + 'Ἅ' => 'A','Ἆ' => 'A','Ἇ' => 'A','ᾈ' => 'A','ᾉ' => 'A','ᾊ' => 'A', + 'ᾋ' => 'A','ᾌ' => 'A','ᾍ' => 'A','ᾎ' => 'A','ᾏ' => 'A','Ᾰ' => 'A', + 'Ᾱ' => 'A','Ὰ' => 'A','ᾼ' => 'A','Β' => 'B','Γ' => 'G','Δ' => 'D', + 'Ε' => 'E','Έ' => 'E','Ἐ' => 'E','Ἑ' => 'E','Ἒ' => 'E','Ἓ' => 'E', + 'Ἔ' => 'E','Ἕ' => 'E','Ὲ' => 'E','Ζ' => 'Z','Η' => 'I','Ή' => 'I', + 'Ἠ' => 'I','Ἡ' => 'I','Ἢ' => 'I','Ἣ' => 'I','Ἤ' => 'I','Ἥ' => 'I', + 'Ἦ' => 'I','Ἧ' => 'I','ᾘ' => 'I','ᾙ' => 'I','ᾚ' => 'I','ᾛ' => 'I', + 'ᾜ' => 'I','ᾝ' => 'I','ᾞ' => 'I','ᾟ' => 'I','Ὴ' => 'I','ῌ' => 'I', + 'Θ' => 'T','Ι' => 'I','Ί' => 'I','Ϊ' => 'I','Ἰ' => 'I','Ἱ' => 'I', + 'Ἲ' => 'I','Ἳ' => 'I','Ἴ' => 'I','Ἵ' => 'I','Ἶ' => 'I','Ἷ' => 'I', + 'Ῐ' => 'I','Ῑ' => 'I','Ὶ' => 'I','Κ' => 'K','Λ' => 'L','Μ' => 'M', + 'Ν' => 'N','Ξ' => 'K','Ο' => 'O','Ό' => 'O','Ὀ' => 'O','Ὁ' => 'O', + 'Ὂ' => 'O','Ὃ' => 'O','Ὄ' => 'O','Ὅ' => 'O','Ὸ' => 'O','Π' => 'P', + 'Ρ' => 'R','Ῥ' => 'R','Σ' => 'S','Τ' => 'T','Υ' => 'Y','Ύ' => 'Y', + 'Ϋ' => 'Y','Ὑ' => 'Y','Ὓ' => 'Y','Ὕ' => 'Y','Ὗ' => 'Y','Ῠ' => 'Y', + 'Ῡ' => 'Y','Ὺ' => 'Y','Φ' => 'F','Χ' => 'X','Ψ' => 'P','Ω' => 'O', + 'Ώ' => 'O','Ὠ' => 'O','Ὡ' => 'O','Ὢ' => 'O','Ὣ' => 'O','Ὤ' => 'O', + 'Ὥ' => 'O','Ὦ' => 'O','Ὧ' => 'O','ᾨ' => 'O','ᾩ' => 'O','ᾪ' => 'O', + 'ᾫ' => 'O','ᾬ' => 'O','ᾭ' => 'O','ᾮ' => 'O','ᾯ' => 'O','Ὼ' => 'O', + 'ῼ' => 'O','α' => 'a','ά' => 'a','ἀ' => 'a','ἁ' => 'a','ἂ' => 'a', + 'ἃ' => 'a','ἄ' => 'a','ἅ' => 'a','ἆ' => 'a','ἇ' => 'a','ᾀ' => 'a', + 'ᾁ' => 'a','ᾂ' => 'a','ᾃ' => 'a','ᾄ' => 'a','ᾅ' => 'a','ᾆ' => 'a', + 'ᾇ' => 'a','ὰ' => 'a','ᾰ' => 'a','ᾱ' => 'a','ᾲ' => 'a','ᾳ' => 'a', + 'ᾴ' => 'a','ᾶ' => 'a','ᾷ' => 'a','β' => 'b','γ' => 'g','δ' => 'd', + 'ε' => 'e','έ' => 'e','ἐ' => 'e','ἑ' => 'e','ἒ' => 'e','ἓ' => 'e', + 'ἔ' => 'e','ἕ' => 'e','ὲ' => 'e','ζ' => 'z','η' => 'i','ή' => 'i', + 'ἠ' => 'i','ἡ' => 'i','ἢ' => 'i','ἣ' => 'i','ἤ' => 'i','ἥ' => 'i', + 'ἦ' => 'i','ἧ' => 'i','ᾐ' => 'i','ᾑ' => 'i','ᾒ' => 'i','ᾓ' => 'i', + 'ᾔ' => 'i','ᾕ' => 'i','ᾖ' => 'i','ᾗ' => 'i','ὴ' => 'i','ῂ' => 'i', + 'ῃ' => 'i','ῄ' => 'i','ῆ' => 'i','ῇ' => 'i','θ' => 't','ι' => 'i', + 'ί' => 'i','ϊ' => 'i','ΐ' => 'i','ἰ' => 'i','ἱ' => 'i','ἲ' => 'i', + 'ἳ' => 'i','ἴ' => 'i','ἵ' => 'i','ἶ' => 'i','ἷ' => 'i','ὶ' => 'i', + 'ῐ' => 'i','ῑ' => 'i','ῒ' => 'i','ῖ' => 'i','ῗ' => 'i','κ' => 'k', + 'λ' => 'l','μ' => 'm','ν' => 'n','ξ' => 'k','ο' => 'o','ό' => 'o', + 'ὀ' => 'o','ὁ' => 'o','ὂ' => 'o','ὃ' => 'o','ὄ' => 'o','ὅ' => 'o', + 'ὸ' => 'o','π' => 'p','ρ' => 'r','ῤ' => 'r','ῥ' => 'r','σ' => 's', + 'ς' => 's','τ' => 't','υ' => 'y','ύ' => 'y','ϋ' => 'y','ΰ' => 'y', + 'ὐ' => 'y','ὑ' => 'y','ὒ' => 'y','ὓ' => 'y','ὔ' => 'y','ὕ' => 'y', + 'ὖ' => 'y','ὗ' => 'y','ὺ' => 'y','ῠ' => 'y','ῡ' => 'y','ῢ' => 'y', + 'ῦ' => 'y','ῧ' => 'y','φ' => 'f','χ' => 'x','ψ' => 'p','ω' => 'o', + 'ώ' => 'o','ὠ' => 'o','ὡ' => 'o','ὢ' => 'o','ὣ' => 'o','ὤ' => 'o', + 'ὥ' => 'o','ὦ' => 'o','ὧ' => 'o','ᾠ' => 'o','ᾡ' => 'o','ᾢ' => 'o', + 'ᾣ' => 'o','ᾤ' => 'o','ᾥ' => 'o','ᾦ' => 'o','ᾧ' => 'o','ὼ' => 'o', + 'ῲ' => 'o','ῳ' => 'o','ῴ' => 'o','ῶ' => 'o','ῷ' => 'o','А' => 'A', + 'Б' => 'B','В' => 'V','Г' => 'G','Д' => 'D','Е' => 'E','Ё' => 'E', + 'Ж' => 'Z','З' => 'Z','И' => 'I','Й' => 'I','К' => 'K','Л' => 'L', + 'М' => 'M','Н' => 'N','О' => 'O','П' => 'P','Р' => 'R','С' => 'S', + 'Т' => 'T','У' => 'U','Ф' => 'F','Х' => 'K','Ц' => 'T','Ч' => 'C', + 'Ш' => 'S','Щ' => 'S','Ы' => 'Y','Э' => 'E','Ю' => 'Y','Я' => 'Y', + 'а' => 'A','б' => 'B','в' => 'V','г' => 'G','д' => 'D','е' => 'E', + 'ё' => 'E','ж' => 'Z','з' => 'Z','и' => 'I','й' => 'I','к' => 'K', + 'л' => 'L','м' => 'M','н' => 'N','о' => 'O','п' => 'P','р' => 'R', + 'с' => 'S','т' => 'T','у' => 'U','ф' => 'F','х' => 'K','ц' => 'T', + 'ч' => 'C','ш' => 'S','щ' => 'S','ы' => 'Y','э' => 'E','ю' => 'Y', + 'я' => 'Y','ð' => 'd','Ð' => 'D','þ' => 't','Þ' => 'T','ა' => 'a', + 'ბ' => 'b','გ' => 'g','დ' => 'd','ე' => 'e','ვ' => 'v','ზ' => 'z', + 'თ' => 't','ი' => 'i','კ' => 'k','ლ' => 'l','მ' => 'm','ნ' => 'n', + 'ო' => 'o','პ' => 'p','ჟ' => 'z','რ' => 'r','ს' => 's','ტ' => 't', + 'უ' => 'u','ფ' => 'p','ქ' => 'k','ღ' => 'g','ყ' => 'q','შ' => 's', + 'ჩ' => 'c','ც' => 't','ძ' => 'd','წ' => 't','ჭ' => 'c','ხ' => 'k', + 'ჯ' => 'j','ჰ' => 'h','ā' => 'a','ţ' => 't','ʼ' => "'", '̧' => '', + 'ḩ' => 'h','ʼ' => "'",'‘' => "'",'’' => "'",'ừ' => 'u','/' => '', + 'ế' => 'e','ả' => 'a','ị' => 'i','ậ' => 'a','ệ' => 'e','ỉ' => 'i', + 'ồ' => 'o','ề' => 'e','ơ' => 'o','ạ' => 'a','ẵ' => 'a','ư' => 'u', + 'ằ' => 'a','ầ' => 'a','ḑ' => 'd','Ḩ' => 'H','Ḑ' => 'D','ḑ' => 'd', + 'Ģ' => 'G','Š' => 'S','ļ' => 'l','ž' => 'z','Ē' => 'E','ņ' => 'n', + 'Č' => 'C','ș' => 's','ț' => 't', 'ộ' => 'o','ắ' => 'a','ş' => 's', + "'" => '', 'ու' => 'u','ա' => 'a','բ' => 'b','գ' => 'g','դ' => 'd', + 'ե' => 'e','զ' => 'z','է' => 'e','ը' => 'y','թ' => 't','ժ' => 'zh', + 'ի' => 'i','լ' => 'l','խ' => 'kh','ծ' => 'ts','կ' => 'k','հ' => 'h', + 'ձ' => 'dz','ղ' => 'gh','ճ' => 'ch','մ' => 'm','յ' => 'y','ն' => 'n', + 'շ' => 'sh','ո' => 'o','չ' => 'ch','պ' => 'p','ջ' => 'j','ռ' => 'r', + 'ս' => 's','վ' => 'v','տ' => 't','ր' => 'r','ց' => 'ts','փ' => 'p', + 'ք' => 'q','և' => 'ev','օ' => 'o','ֆ' => 'f', + ); + + return str_replace(array_keys($transliterationTable), array_values($transliterationTable), $string); + } + + private static function transliterate($string) + { + $transId = 'Any-Latin; Latin-ASCII; NFD; [:Nonspacing Mark:] Remove; NFC; Lower();'; + if (function_exists('transliterator_transliterate') && $transliterator = \Transliterator::create($transId)) { + $transString = $transliterator->transliterate($string); + } else { + $transString = static::toAscii($string); + } + + return preg_replace('/[^A-Za-z0-9_.]/u', '', $transString); + } + + /** + * @example 'jdoe@acme.biz' + */ + public function email() + { + $format = static::randomElement(static::$emailFormats); + + return $this->generator->parse($format); + } + + /** + * @example 'jdoe@example.com' + */ + final public function safeEmail() + { + return preg_replace('/\s/u', '', $this->userName() . '@' . static::safeEmailDomain()); + } + + /** + * @example 'jdoe@gmail.com' + */ + public function freeEmail() + { + return preg_replace('/\s/u', '', $this->userName() . '@' . static::freeEmailDomain()); + } + + /** + * @example 'jdoe@dawson.com' + */ + public function companyEmail() + { + return preg_replace('/\s/u', '', $this->userName() . '@' . $this->domainName()); + } + + /** + * @example 'gmail.com' + */ + public static function freeEmailDomain() + { + return static::randomElement(static::$freeEmailDomain); + } + + /** + * @example 'example.org' + */ + final public static function safeEmailDomain() + { + $domains = array( + 'example.com', + 'example.org', + 'example.net' + ); + + return static::randomElement($domains); + } + /** + * @example 'jdoe' + */ + public function userName() + { + $format = static::randomElement(static::$userNameFormats); + $username = static::bothify($this->generator->parse($format)); + + return static::transliterate($username); + } + /** + * @example 'fY4èHdZv68' + */ + public function password($minLength = 6, $maxLength = 20) + { + $pattern = str_repeat('*', $this->numberBetween($minLength, $maxLength)); + + return $this->asciify($pattern); + } + + /** + * @example 'tiramisu.com' + */ + public function domainName() + { + return $this->domainWord() . '.' . $this->tld(); + } + + /** + * @example 'faber' + */ + public function domainWord() + { + $lastName = $this->generator->format('lastName'); + + return static::transliterate($lastName); + } + + /** + * @example 'com' + */ + public function tld() + { + return static::randomElement(static::$tld); + } + + /** + * @example 'http://www.runolfsdottir.com/' + */ + public function url() + { + $format = static::randomElement(static::$urlFormats); + + return $this->generator->parse($format); + } + + /** + * @example 'aut-repellat-commodi-vel-itaque-nihil-id-saepe-nostrum' + */ + public function slug($nbWords = 6, $variableNbWords = true) + { + if ($nbWords <= 0) { + return ''; + } + if ($variableNbWords) { + $nbWords = (int) ($nbWords * mt_rand(60, 140) / 100) + 1; + } + $words = $this->generator->words($nbWords); + + return join($words, '-'); + } + + /** + * @example '237.149.115.38' + */ + public function ipv4() + { + return long2ip(mt_rand(0, 1) == 0 ? mt_rand(-2147483648, -2) : mt_rand(16777216, 2147483647)); + } + + /** + * @example '35cd:186d:3e23:2986:ef9f:5b41:42a4:e6f1' + */ + public function ipv6() + { + $res = array(); + for ($i=0; $i < 8; $i++) { + $res []= dechex(mt_rand(0, "65535")); + } + + return join(':', $res); + } + + /** + * @example '10.1.1.17' + */ + public static function localIpv4() + { + if (static::numberBetween(0, 1) === 0) { + // 10.x.x.x range + $ip = long2ip(static::numberBetween(167772160, 184549375)); + } else { + // 192.168.x.x range + $ip = long2ip(static::numberBetween(3232235520, 3232301055)); + } + + return $ip; + } + + /** + * @example '32:F1:39:2F:D6:18' + */ + public static function macAddress() + { + for ($i=0; $i<6; $i++) { + $mac[] = sprintf('%02X', static::numberBetween(0, 0xff)); + } + $mac = implode(':', $mac); + + return $mac; + } +} diff --git a/lib/faker/src/Faker/Provider/Lorem.php b/lib/faker/src/Faker/Provider/Lorem.php new file mode 100755 index 0000000..7ba0ced --- /dev/null +++ b/lib/faker/src/Faker/Provider/Lorem.php @@ -0,0 +1,215 @@ + array( + "4539########", + "4539###########", + "4556########", + "4556###########", + "4916########", + "4916###########", + "4532########", + "4532###########", + "4929########", + "4929###########", + "40240071####", + "40240071#######", + "4485########", + "4485###########", + "4716########", + "4716###########", + "4###########", + "4##############" + ), + 'MasterCard' => array( + "51#############", + "52#############", + "53#############", + "54#############", + "55#############" + ), + 'American Express' => array( + "34############", + "37############" + ), + 'Discover Card' => array( + "6011###########" + ), + ); + + /** + * @var array list of IBAN formats, source: @link http://www.swift.com/dsp/resources/documents/IBAN_Registry.txt + */ + protected static $ibanFormats = array( + 'AD' => array(array('n', 4), array('n', 4), array('c', 12)), + 'AE' => array(array('n', 3), array('n', 16)), + 'AL' => array(array('n', 8), array('c', 16)), + 'AT' => array(array('n', 5), array('n', 11)), + 'AZ' => array(array('a', 4), array('c', 20)), + 'BA' => array(array('n', 3), array('n', 3), array('n', 8), array('n', 2)), + 'BE' => array(array('n', 3), array('n', 7), array('n', 2)), + 'BG' => array(array('a', 4), array('n', 4), array('n', 2), array('c', 8)), + 'BH' => array(array('a', 4), array('c', 14)), + 'BR' => array(array('n', 8), array('n', 5), array('n', 10), array('a', 1), array('c', 1)), + 'CH' => array(array('n', 5), array('c', 12)), + 'CR' => array(array('n', 3), array('n', 14)), + 'CY' => array(array('n', 3), array('n', 5), array('c', 16)), + 'CZ' => array(array('n', 4), array('n', 6), array('n', 10)), + 'DE' => array(array('n', 8), array('n', 10)), + 'DK' => array(array('n', 4), array('n', 9), array('n', 1)), + 'DO' => array(array('c', 4), array('n', 20)), + 'EE' => array(array('n', 2), array('n', 2), array('n', 11), array('n', 1)), + 'ES' => array(array('n', 4), array('n', 4), array('n', 1), array('n', 1), array('n', 10)), + 'FR' => array(array('n', 5), array('n', 5), array('c', 11), array('n', 2)), + 'GB' => array(array('a', 4), array('n', 6), array('n', 8)), + 'GE' => array(array('a', 2), array('n', 16)), + 'GI' => array(array('a', 4), array('c', 15)), + 'GR' => array(array('n', 3), array('n', 4), array('c', 16)), + 'GT' => array(array('c', 4), array('c', 20)), + 'HR' => array(array('n', 7), array('n', 10)), + 'HU' => array(array('n', 3), array('n', 4), array('n', 1), array('n', 15), array('n', 1)), + 'IE' => array(array('a', 4), array('n', 6), array('n', 8)), + 'IL' => array(array('n', 3), array('n', 3), array('n', 13)), + 'IS' => array(array('n', 4), array('n', 2), array('n', 6), array('n', 10)), + 'IT' => array(array('a', 1), array('n', 5), array('n', 5), array('c', 12)), + 'KW' => array(array('a', 4), array('n', 22)), + 'KZ' => array(array('n', 3), array('c', 13)), + 'LB' => array(array('n', 4), array('c', 20)), + 'LI' => array(array('n', 5), array('c', 12)), + 'LT' => array(array('n', 5), array('n', 11)), + 'LU' => array(array('n', 3), array('c', 13)), + 'LV' => array(array('a', 4), array('c', 13)), + 'MC' => array(array('n', 5), array('n', 5), array('c', 11), array('n', 2)), + 'MD' => array(array('c', 2), array('c', 18)), + 'ME' => array(array('n', 3), array('n', 13), array('n', 2)), + 'MK' => array(array('n', 3), array('c', 10), array('n', 2)), + 'MR' => array(array('n', 5), array('n', 5), array('n', 11), array('n', 2)), + 'MT' => array(array('a', 4), array('n', 5), array('c', 18)), + 'MU' => array(array('a', 4), array('n', 2), array('n', 2), array('n', 12), array('n', 3), array('a', 3)), + 'NL' => array(array('a', 4), array('n', 10)), + 'NO' => array(array('n', 4), array('n', 6), array('n', 1)), + 'PK' => array(array('a', 4), array('c', 16)), + 'PL' => array(array('n', 8), array('n', 16)), + 'PS' => array(array('a', 4), array('c', 21)), + 'PT' => array(array('n', 4), array('n', 4), array('n', 11), array('n', 2)), + 'RO' => array(array('a', 4), array('c', 16)), + 'RS' => array(array('n', 3), array('n', 13), array('n', 2)), + 'SA' => array(array('n', 2), array('c', 18)), + 'SE' => array(array('n', 3), array('n', 16), array('n', 1)), + 'SI' => array(array('n', 5), array('n', 8), array('n', 2)), + 'SK' => array(array('n', 4), array('n', 6), array('n', 10)), + 'SM' => array(array('a', 1), array('n', 5), array('n', 5), array('c', 12)), + 'TN' => array(array('n', 2), array('n', 3), array('n', 13), array('n', 2)), + 'TR' => array(array('n', 5), array('n', 1), array('c', 16)), + 'VG' => array(array('a', 4), array('n', 16)), + ); + + /** + * @return string Returns a credit card vendor name + * + * @example 'MasterCard' + */ + public static function creditCardType() + { + return static::randomElement(static::$cardVendors); + } + + /** + * Returns the String of a credit card number. + * + * @param string $type Supporting any of 'Visa', 'MasterCard', 'American Express', and 'Discover' + * @param boolean $formatted Set to true if the output string should contain one separator every 4 digits + * @param string $separator Separator string for formatting card number. Defaults to dash (-). + * @return string + * + * @example '4485480221084675' + */ + public static function creditCardNumber($type = null, $formatted = false, $separator = '-') + { + if (is_null($type)) { + $type = static::creditCardType(); + } + $mask = static::randomElement(static::$cardParams[$type]); + + $number = static::numerify($mask); + $number .= Luhn::computeCheckDigit($number); + + if ($formatted) { + $p1 = substr($number, 0, 4); + $p2 = substr($number, 4, 4); + $p3 = substr($number, 8, 4); + $p4 = substr($number, 12); + $number = $p1 . $separator . $p2 . $separator . $p3 . $separator . $p4; + } + + return $number; + } + + /** + * @param boolean $valid True (by default) to get a valid expiration date, false to get a maybe valid date + * @return \DateTime + * @example 04/13 + */ + public function creditCardExpirationDate($valid = true) + { + if ($valid) { + return $this->generator->dateTimeBetween('now', '36 months'); + } + + return $this->generator->dateTimeBetween('-36 months', '36 months'); + } + + /** + * @param boolean $valid True (by default) to get a valid expiration date, false to get a maybe valid date + * @param string $expirationDateFormat + * @return string + * @example '04/13' + */ + public function creditCardExpirationDateString($valid = true, $expirationDateFormat = null) + { + return $this->creditCardExpirationDate($valid)->format(is_null($expirationDateFormat) ? static::$expirationDateFormat : $expirationDateFormat); + } + + /** + * @param boolean $valid True (by default) to get a valid expiration date, false to get a maybe valid date + * @return array + */ + public function creditCardDetails($valid = true) + { + $type = static::creditCardType(); + + return array( + 'type' => $type, + 'number' => static::creditCardNumber($type), + 'name' => $this->generator->name(), + 'expirationDate' => $this->creditCardExpirationDateString($valid) + ); + } + + /** + * International Bank Account Number (IBAN) + * + * @link http://en.wikipedia.org/wiki/International_Bank_Account_Number + * @param string $countryCode ISO 3166-1 alpha-2 country code + * @param string $prefix for generating bank account number of a specific bank + * @param integer $length total length without country code and 2 check digits + * @return string + */ + public static function iban($countryCode, $prefix = '', $length = null) + { + $countryCode = is_null($countryCode) ? self::randomKey(self::$ibanFormats) : strtoupper($countryCode); + + $format = !isset(static::$ibanFormats[$countryCode]) ? null : static::$ibanFormats[$countryCode]; + if ($length === null) { + if ($format === null) { + $length = 24; + } else { + $length = 0; + foreach ($format as $part) { + list($class, $groupCount) = $part; + $length += $groupCount; + } + } + } + if ($format === null) { + $format = array(array('n', $length)); + } + + $expandedFormat = ''; + foreach ($format as $item) { + list($class, $length) = $item; + $expandedFormat .= str_repeat($class, $length); + } + + $result = $prefix; + $expandedFormat = substr($expandedFormat, strlen($result)); + foreach (str_split($expandedFormat) as $class) { + switch ($class) { + default: + case 'c': + $result .= mt_rand(0, 100) <= 50 ? static::randomDigit() : strtoupper(static::randomLetter()); + break; + case 'a': + $result .= strtoupper(static::randomLetter()); + break; + case 'n': + $result .= static::randomDigit(); + break; + } + } + + $result = static::addBankCodeChecksum($result, $countryCode); + + $checksum = Iban::checksum($countryCode . '00' . $result); + + return $countryCode . $checksum . $result; + } + + /** + * Calculates a checksum for the national bank and branch code part in the IBAN. + * + * @param string $iban randomly generated $iban + * @param string $countryCode ISO 3166-1 alpha-2 country code + * @return string IBAN with one character altered to a proper checksum + */ + protected static function addBankCodeChecksum($iban, $countryCode = '') + { + return $iban; + } + + /** + * Return the String of a SWIFT/BIC number + * + * @example 'RZTIAT22263' + * @link http://en.wikipedia.org/wiki/ISO_9362 + * @return string Swift/Bic number + */ + public static function swiftBicNumber() + { + return self::regexify("^([A-Z]){4}([A-Z]){2}([0-9A-Z]){2}([0-9A-Z]{3})?$"); + } +} diff --git a/lib/faker/src/Faker/Provider/Person.php b/lib/faker/src/Faker/Provider/Person.php new file mode 100755 index 0000000..bd7cd45 --- /dev/null +++ b/lib/faker/src/Faker/Provider/Person.php @@ -0,0 +1,126 @@ +generator->parse($format); + } + + /** + * @param string|null $gender 'male', 'female' or null for any + * @return string + * @example 'John' + */ + public function firstName($gender = null) + { + if ($gender === static::GENDER_MALE) { + return static::firstNameMale(); + } elseif ($gender === static::GENDER_FEMALE) { + return static::firstNameFemale(); + } + + return $this->generator->parse(static::randomElement(static::$firstNameFormat)); + } + + public static function firstNameMale() + { + return static::randomElement(static::$firstNameMale); + } + + public static function firstNameFemale() + { + return static::randomElement(static::$firstNameFemale); + } + + /** + * @example 'Doe' + * @return string + */ + public function lastName() + { + return static::randomElement(static::$lastName); + } + + /** + * @example 'Mrs.' + * @param string|null $gender 'male', 'female' or null for any + * @return string + */ + public function title($gender = null) + { + if ($gender === static::GENDER_MALE) { + return static::titleMale(); + } elseif ($gender === static::GENDER_FEMALE) { + return static::titleFemale(); + } + + return $this->generator->parse(static::randomElement(static::$titleFormat)); + } + + /** + * @example 'Mr.' + */ + public static function titleMale() + { + return static::randomElement(static::$titleMale); + } + + /** + * @example 'Mrs.' + */ + public static function titleFemale() + { + return static::randomElement(static::$titleFemale); + } +} diff --git a/lib/faker/src/Faker/Provider/PhoneNumber.php b/lib/faker/src/Faker/Provider/PhoneNumber.php new file mode 100755 index 0000000..a010d43 --- /dev/null +++ b/lib/faker/src/Faker/Provider/PhoneNumber.php @@ -0,0 +1,16 @@ +generator->parse(static::randomElement(static::$formats))); + } +} diff --git a/lib/faker/src/Faker/Provider/Text.php b/lib/faker/src/Faker/Provider/Text.php new file mode 100755 index 0000000..675ad85 --- /dev/null +++ b/lib/faker/src/Faker/Provider/Text.php @@ -0,0 +1,137 @@ + 5) { + throw new \InvalidArgumentException('indexSize must be at most 5'); + } + + + $words = $this->getConsecutiveWords($indexSize); + $result = array(); + $resultLength = 0; + // take a random starting point + $next = static::randomKey($words); + while ($resultLength < $maxNbChars && isset($words[$next])) { + // fetch a random word to append + $word = static::randomElement($words[$next]); + + // calculate next index + $currentWords = static::explode($next); + $currentWords[] = $word; + array_shift($currentWords); + $next = static::implode($currentWords); + + // ensure text starts with an uppercase letter + if ($resultLength == 0 && !static::validStart($word)) { + continue; + } + + // append the element + $result[] = $word; + $resultLength += static::strlen($word) + static::$separatorLen; + } + + // remove the element that caused the text to overflow + array_pop($result); + + // build result + $result = static::implode($result); + + return static::appendEnd($result); + } + + protected function getConsecutiveWords($indexSize) + { + if (!isset($this->consecutiveWords[$indexSize])) { + $parts = $this->getExplodedText(); + $words = array(); + $index = array(); + for ($i = 0; $i < $indexSize; $i++) { + $index[] = array_shift($parts); + } + + for ($i = 0, $count = count($parts); $i < $count; $i++) { + $stringIndex = static::implode($index); + if (!isset($words[$stringIndex])) { + $words[$stringIndex] = array(); + } + $word = $parts[$i]; + $words[$stringIndex][] = $word; + array_shift($index); + $index[] = $word; + } + // cache look up words for performance + $this->consecutiveWords[$indexSize] = $words; + } + + return $this->consecutiveWords[$indexSize]; + } + + protected function getExplodedText() + { + if ($this->explodedText === null) { + $this->explodedText = static::explode(preg_replace('/\s+/u', ' ', static::$baseText)); + } + + return $this->explodedText; + } + + protected static function explode($text) + { + return explode(static::$separator, $text); + } + + protected static function implode($words) + { + return implode(static::$separator, $words); + } + + protected static function strlen($text) + { + return function_exists('mb_strlen') ? mb_strlen($text, 'UTF-8') : strlen($text); + } + + protected static function validStart($word) + { + return preg_match('/^\p{Lu}/u', $word); + } + + protected static function appendEnd($text) + { + return $text.'.'; + } +} diff --git a/lib/faker/src/Faker/Provider/UserAgent.php b/lib/faker/src/Faker/Provider/UserAgent.php new file mode 100755 index 0000000..132b480 --- /dev/null +++ b/lib/faker/src/Faker/Provider/UserAgent.php @@ -0,0 +1,162 @@ +> 8) | (($tLo & 0xff000000) >> 24); + $tMi = (($tMi & 0x00ff) << 8) | (($tMi & 0xff00) >> 8); + $tHi = (($tHi & 0x00ff) << 8) | (($tHi & 0xff00) >> 8); + } + + // apply version number + $tHi &= 0x0fff; + $tHi |= (3 << 12); + + // cast to string + $uuid = sprintf( + '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x', + $tLo, + $tMi, + $tHi, + $csHi, + $csLo, + $byte[10], + $byte[11], + $byte[12], + $byte[13], + $byte[14], + $byte[15] + ); + + return $uuid; + } +} diff --git a/lib/faker/src/Faker/Provider/ar_JO/Address.php b/lib/faker/src/Faker/Provider/ar_JO/Address.php new file mode 100755 index 0000000..6f4f258 --- /dev/null +++ b/lib/faker/src/Faker/Provider/ar_JO/Address.php @@ -0,0 +1,152 @@ +generator->parse($format)); + } + + /** + * @example 'wewebit.jo' + */ + public function domainName() + { + return static::randomElement(static::$lastNameAscii) . '.' . $this->tld(); + } +} diff --git a/lib/faker/src/Faker/Provider/ar_JO/Person.php b/lib/faker/src/Faker/Provider/ar_JO/Person.php new file mode 100755 index 0000000..7fcadb3 --- /dev/null +++ b/lib/faker/src/Faker/Provider/ar_JO/Person.php @@ -0,0 +1,108 @@ +generator->parse($format)); + } + + /** + * @example 'wewebit.jo' + */ + public function domainName() + { + return static::randomElement(static::$lastNameAscii) . '.' . $this->tld(); + } +} diff --git a/lib/faker/src/Faker/Provider/ar_SA/Person.php b/lib/faker/src/Faker/Provider/ar_SA/Person.php new file mode 100755 index 0000000..ed1d0d2 --- /dev/null +++ b/lib/faker/src/Faker/Provider/ar_SA/Person.php @@ -0,0 +1,148 @@ +generator->parse(static::randomElement(static::$lastNameFormat)); + } + + public static function lastNameMale() + { + return static::randomElement(static::$lastNameMale); + } + + public static function lastNameFemale() + { + return static::randomElement(static::$lastNameFemale); + } +} diff --git a/lib/faker/src/Faker/Provider/bg_BG/PhoneNumber.php b/lib/faker/src/Faker/Provider/bg_BG/PhoneNumber.php new file mode 100755 index 0000000..e5ec042 --- /dev/null +++ b/lib/faker/src/Faker/Provider/bg_BG/PhoneNumber.php @@ -0,0 +1,20 @@ +generator->parse($format)); + } + + /** + * Generates valid czech IČO + * + * @see http://phpfashion.com/jak-overit-platne-ic-a-rodne-cislo + * @return string + */ + public function ico() + { + $ico = static::numerify('#######'); + $split = str_split($ico); + $prod = 0; + foreach (array(8, 7, 6, 5, 4, 3, 2) as $i => $p) { + $prod += $p * $split[$i]; + } + $mod = $prod % 11; + if ($mod === 0 || $mod === 10) { + return "{$ico}1"; + } elseif ($mod === 1) { + return "{$ico}0"; + } + + return $ico . (11 - $mod); + } +} diff --git a/lib/faker/src/Faker/Provider/cs_CZ/DateTime.php b/lib/faker/src/Faker/Provider/cs_CZ/DateTime.php new file mode 100755 index 0000000..4bd1508 --- /dev/null +++ b/lib/faker/src/Faker/Provider/cs_CZ/DateTime.php @@ -0,0 +1,61 @@ +format('w')]; + } + + /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * @return string + * @example '2' + */ + public static function dayOfMonth($max = 'now') + { + return static::dateTime($max)->format('j'); + } + + /** + * Full date with inflected month + * @return string + * @example '16. listopadu 2003' + */ + public function formattedDate() + { + $format = static::randomElement(static::$formattedDateFormat); + + return $this->generator->parse($format); + } +} diff --git a/lib/faker/src/Faker/Provider/cs_CZ/Internet.php b/lib/faker/src/Faker/Provider/cs_CZ/Internet.php new file mode 100755 index 0000000..d0d993d --- /dev/null +++ b/lib/faker/src/Faker/Provider/cs_CZ/Internet.php @@ -0,0 +1,9 @@ +generator->boolean() ? static::GENDER_MALE : static::GENDER_FEMALE; + } + + $startTimestamp = strtotime("-${maxAge} year"); + $endTimestamp = strtotime("-${minAge} year"); + $randTimestamp = static::numberBetween($startTimestamp, $endTimestamp); + + $year = intval(date('Y', $randTimestamp)); + $month = intval(date('n', $randTimestamp)); + $day = intval(date('j', $randTimestamp)); + $suffix = static::numberBetween(0, 999); + + // women has +50 to month + if ($gender == static::GENDER_FEMALE) { + $month += 50; + } + // from year 2004 everyone has +20 to month when birth numbers in one day are exhausted + if ($year >= 2004 && $this->generator->boolean(10)) { + $month += 20; + } + + $birthNumber = sprintf('%02d%02d%02d%03d', $year % 100, $month, $day, $suffix); + + // from year 1954 birth number includes CRC + if ($year >= 1954) { + $crc = intval($birthNumber, 10) % 11; + if ($crc == 10) { + $crc = 0; + } + $birthNumber .= sprintf('%d', $crc); + } + + // add slash + if ($this->generator->boolean($slashProbability)) { + $birthNumber = substr($birthNumber, 0, 6) . '/' . substr($birthNumber, 6); + } + + return $birthNumber; + } + + public static function birthNumberMale() + { + return static::birthNumber(static::GENDER_MALE); + } + + public static function birthNumberFemale() + { + return static::birthNumber(static::GENDER_FEMALE); + } + + public function title($gender = null) + { + return static::titleMale(); + } + + /** + * replaced by specific unisex Czech title + */ + public static function titleMale() + { + return static::randomElement(static::$title); + } + + /** + * replaced by specific unisex Czech title + */ + public static function titleFemale() + { + return static::titleMale(); + } + + /** + * @param string|null $gender 'male', 'female' or null for any + * @example 'Albrecht' + */ + public function lastName($gender = null) + { + if ($gender === static::GENDER_MALE) { + return static::lastNameMale(); + } elseif ($gender === static::GENDER_FEMALE) { + return static::lastNameFemale(); + } + + return $this->generator->parse(static::randomElement(static::$lastNameFormat)); + } + + public static function lastNameMale() + { + return static::randomElement(static::$lastNameMale); + } + + public static function lastNameFemale() + { + return static::randomElement(static::$lastNameFemale); + } +} diff --git a/lib/faker/src/Faker/Provider/cs_CZ/PhoneNumber.php b/lib/faker/src/Faker/Provider/cs_CZ/PhoneNumber.php new file mode 100755 index 0000000..90495df --- /dev/null +++ b/lib/faker/src/Faker/Provider/cs_CZ/PhoneNumber.php @@ -0,0 +1,14 @@ + + */ +class Address extends \Faker\Provider\Address +{ + /** + * @var array Danish city suffixes. + */ + protected static $citySuffix = array( + 'sted', 'bjerg', 'borg', 'rød', 'lund', 'by', + ); + + /** + * @var array Danish street suffixes. + */ + protected static $streetSuffix = array( + 'vej', 'gade', 'skov', 'shaven', + ); + + /** + * @var array Danish street word suffixes. + */ + protected static $streetSuffixWord = array( + 'Vej', 'Gade', 'Allé', 'Boulevard', 'Plads', 'Have', + ); + + /** + * @var array Danish building numbers. + */ + protected static $buildingNumber = array( + '%##', '%#', '%#', '%', '%', '%', '%?', '% ?', + ); + + /** + * @var array Danish building level. + */ + protected static $buildingLevel = array( + 'st.', '%.', '%. sal.', + ); + + /** + * @var array Danish building sides. + */ + protected static $buildingSide = array( + 'tv.', 'th.', + ); + + /** + * @var array Danish zip code. + */ + protected static $postcode = array( + '%###' + ); + + /** + * @var array Danish cities. + */ + protected static $cityNames = array( + 'Aabenraa', 'Aabybro', 'Aakirkeby', 'Aalborg', 'Aalestrup', 'Aars', 'Aarup', 'Agedrup', 'Agerbæk', 'Agerskov', + 'Albertslund', 'Allerød', 'Allinge', 'Allingåbro', 'Almind', 'Anholt', 'Ansager', 'Arden', 'Asaa', 'Askeby', + 'Asnæs', 'Asperup', 'Assens', 'Augustenborg', 'Aulum', 'Auning', 'Bagenkop', 'Bagsværd', 'Balle', 'Ballerup', + 'Bandholm', 'Barrit', 'Beder', 'Bedsted', 'Bevtoft', 'Billum', 'Billund', 'Bindslev', 'Birkerød', 'Bjerringbro', + 'Bjert', 'Bjæverskov', 'Blokhus', 'Blommenslyst', 'Blåvand', 'Boeslunde', 'Bogense', 'Bogø', 'Bolderslev', 'Bording', + 'Borre', 'Borup', 'Brøndby', 'Brabrand', 'Bramming', 'Brande', 'Branderup', 'Bredebro', 'Bredsten', 'Brenderup', + 'Broager', 'Broby', 'Brovst', 'Bryrup', 'Brædstrup', 'Strand', 'Brønderslev', 'Brønshøj', 'Brørup', 'Bække', + 'Bækmarksbro', 'Bælum', 'Børkop', 'Bøvlingbjerg', 'Charlottenlund', 'Christiansfeld', 'Dalby', 'Dalmose', + 'Dannemare', 'Daugård', 'Dianalund', 'Dragør', 'Dronninglund', 'Dronningmølle', 'Dybvad', 'Dyssegård', 'Ebberup', + 'Ebeltoft', 'Egernsund', 'Egtved', 'Egå', 'Ejby', 'Ejstrupholm', 'Engesvang', 'Errindlev', 'Erslev', 'Esbjerg', + 'Eskebjerg', 'Eskilstrup', 'Espergærde', 'Faaborg', 'Fanø', 'Farsø', 'Farum', 'Faxe', 'Ladeplads', 'Fejø', + 'Ferritslev', 'Fjenneslev', 'Fjerritslev', 'Flemming', 'Fredensborg', 'Fredericia', 'Frederiksberg', + 'Frederikshavn', 'Frederikssund', 'Frederiksværk', 'Frørup', 'Frøstrup', 'Fuglebjerg', 'Føllenslev', 'Føvling', + 'Fårevejle', 'Fårup', 'Fårvang', 'Gadbjerg', 'Gadstrup', 'Galten', 'Gandrup', 'Gedser', 'Gedsted', 'Gedved', 'Gelsted', + 'Gentofte', 'Gesten', 'Gilleleje', 'Gislev', 'Gislinge', 'Gistrup', 'Give', 'Gjerlev', 'Gjern', 'Glamsbjerg', + 'Glejbjerg', 'Glesborg', 'Glostrup', 'Glumsø', 'Gram', 'Gredstedbro', 'Grenaa', 'Greve', 'Grevinge', 'Grindsted', + 'Græsted', 'Gråsten', 'Gudbjerg', 'Sydfyn', 'Gudhjem', 'Gudme', 'Guldborg', 'Gørding', 'Gørlev', 'Gørløse', + 'Haderslev', 'Haderup', 'Hadsten', 'Hadsund', 'Hals', 'Hammel', 'Hampen', 'Hanstholm', 'Harboøre', 'Harlev', 'Harndrup', + 'Harpelunde', 'Hasle', 'Haslev', 'Hasselager', 'Havdrup', 'Havndal', 'Hedehusene', 'Hedensted', 'Hejls', 'Hejnsvig', + 'Hellebæk', 'Hellerup', 'Helsinge', 'Helsingør', 'Hemmet', 'Henne', 'Herfølge', 'Herlev', 'Herlufmagle', 'Herning', + 'Hesselager', 'Hillerød', 'Hinnerup', 'Hirtshals', 'Hjallerup', 'Hjerm', 'Hjortshøj', 'Hjørring', 'Hobro', 'Holbæk', + 'Holeby', 'Holmegaard', 'Holstebro', 'Holsted', 'Holte', 'Horbelev', 'Hornbæk', 'Hornslet', 'Hornsyld', 'Horsens', + 'Horslunde', 'Hovborg', 'Hovedgård', 'Humble', 'Humlebæk', 'Hundested', 'Hundslund', 'Hurup', 'Hvalsø', 'Hvide', + 'Sande', 'Hvidovre', 'Højbjerg', 'Højby', 'Højer', 'Højslev', 'Høng', 'Hørning', 'Hørsholm', 'Hørve', 'Hårlev', + 'Idestrup', 'Ikast', 'Ishøj', 'Janderup', 'Vestj', 'Jelling', 'Jerslev', 'Sjælland', 'Jerup', 'Jordrup', 'Juelsminde', + 'Jyderup', 'Jyllinge', 'Jystrup', 'Midtsj', 'Jægerspris', 'Kalundborg', 'Kalvehave', 'Karby', 'Karise', 'Karlslunde', + 'Karrebæksminde', 'Karup', 'Kastrup', 'Kerteminde', 'Kettinge', 'Kibæk', 'Kirke', 'Hyllinge', 'Såby', 'Kjellerup', + 'Klampenborg', 'Klarup', 'Klemensker', 'Klippinge', 'Klovborg', 'Knebel', 'Kokkedal', 'Kolding', 'Kolind', 'Kongens', + 'Lyngby', 'Kongerslev', 'Korsør', 'Kruså', 'Kvistgård', 'Kværndrup', 'København', 'Køge', 'Langebæk', 'Langeskov', + 'Langå', 'Lejre', 'Lemming', 'Lemvig', 'Lille', 'Skensved', 'Lintrup', 'Liseleje', 'Lundby', 'Lunderskov', 'Lynge', + 'Lystrup', 'Læsø', 'Løgstrup', 'Løgstør', 'Løgumkloster', 'Løkken', 'Løsning', 'Låsby', 'Malling', 'Mariager', + 'Maribo', 'Marslev', 'Marstal', 'Martofte', 'Melby', 'Mern', 'Mesinge', 'Middelfart', 'Millinge', 'Morud', 'Munke', + 'Bjergby', 'Munkebo', 'Møldrup', 'Mørke', 'Mørkøv', 'Måløv', 'Mårslet', 'Nakskov', 'Nexø', 'Nibe', 'Nimtofte', + 'Nordborg', 'Nyborg', 'Nykøbing', 'Nyrup', 'Nysted', 'Nærum', 'Næstved', 'Nørager', 'Nørre', 'Aaby', 'Alslev', + 'Asmindrup', 'Nebel', 'Snede', 'Nørreballe', 'Nørresundby', 'Odder', 'Odense', 'Oksbøl', 'Otterup', 'Oure', 'Outrup', + 'Padborg', 'Pandrup', 'Præstø', 'Randbøl', 'Randers', 'Ranum', 'Rask', 'Mølle', 'Redsted', 'Regstrup', 'Ribe', 'Ringe', + 'Ringkøbing', 'Ringsted', 'Risskov', 'Roskilde', 'Roslev', 'Rude', 'Rudkøbing', 'Ruds', 'Vedby', 'Rungsted', 'Kyst', + 'Rynkeby', 'Ryomgård', 'Ryslinge', 'Rødby', 'Rødding', 'Rødekro', 'Rødkærsbro', 'Rødovre', 'Rødvig', 'Stevns', + 'Rønde', 'Rønne', 'Rønnede', 'Rørvig', 'Sabro', 'Sakskøbing', 'Saltum', 'Samsø', 'Sandved', 'Sejerø', 'Silkeborg', + 'Sindal', 'Sjællands', 'Odde', 'Sjølund', 'Skagen', 'Skals', 'Skamby', 'Skanderborg', 'Skibby', 'Skive', 'Skjern', + 'Skodsborg', 'Skovlunde', 'Skælskør', 'Skærbæk', 'Skævinge', 'Skødstrup', 'Skørping', 'Skårup', 'Slagelse', + 'Slangerup', 'Smørum', 'Snedsted', 'Snekkersten', 'Snertinge', 'Solbjerg', 'Solrød', 'Sommersted', 'Sorring', 'Sorø', + 'Spentrup', 'Spjald', 'Sporup', 'Spøttrup', 'Stakroge', 'Stege', 'Stenderup', 'Stenlille', 'Stenløse', 'Stenstrup', + 'Stensved', 'Stoholm', 'Jyll', 'Stokkemarke', 'Store', 'Fuglede', 'Heddinge', 'Merløse', 'Storvorde', 'Stouby', + 'Strandby', 'Struer', 'Strøby', 'Stubbekøbing', 'Støvring', 'Suldrup', 'Sulsted', 'Sunds', 'Svaneke', 'Svebølle', + 'Svendborg', 'Svenstrup', 'Svinninge', 'Sydals', 'Sæby', 'Søborg', 'Søby', 'Ærø', 'Søllested', 'Sønder', 'Felding', + 'Sønderborg', 'Søndersø', 'Sørvad', 'Taastrup', 'Tappernøje', 'Tarm', 'Terndrup', 'Them', 'Thisted', 'Thorsø', + 'Thyborøn', 'Thyholm', 'Tikøb', 'Tilst', 'Tinglev', 'Tistrup', 'Tisvildeleje', 'Tjele', 'Tjæreborg', 'Toftlund', + 'Tommerup', 'Toreby', 'Torrig', 'Tranbjerg', 'Tranekær', 'Trige', 'Trustrup', 'Tune', 'Tureby', 'Tylstrup', 'Tølløse', + 'Tønder', 'Tørring', 'Tårs', 'Ugerløse', 'Uldum', 'Ulfborg', 'Ullerslev', 'Ulstrup', 'Vadum', 'Valby', 'Vallensbæk', + 'Vamdrup', 'Vandel', 'Vanløse', 'Varde', 'Vedbæk', 'Veflinge', 'Vejby', 'Vejen', 'Vejers', 'Vejle', 'Vejstrup', + 'Veksø', 'Vemb', 'Vemmelev', 'Vesløs', 'Vestbjerg', 'Vester', 'Skerninge', 'Vesterborg', 'Vestervig', 'Viborg', 'Viby', + 'Videbæk', 'Vildbjerg', 'Vils', 'Vinderup', 'Vipperød', 'Virum', 'Vissenbjerg', 'Viuf', 'Vodskov', 'Vojens', 'Vonge', + 'Vorbasse', 'Vordingborg', 'Væggerløse', 'Værløse', 'Ærøskøbing', 'Ølgod', 'Ølsted', 'Ølstykke', 'Ørbæk', + 'Ørnhøj', 'Ørsted', 'Djurs', 'Østbirk', 'Øster', 'Assels', 'Ulslev', 'Østermarie', 'Østervrå', 'Åbyhøj', + 'Ålbæk', 'Ålsgårde', 'Århus', 'Årre', 'Årslev', 'Haarby', 'Nivå', 'Rømø', 'Omme', 'Vrå', 'Ørum', + ); + + /** + * @var array Danish municipalities, called 'kommuner' in danish. + */ + protected static $kommuneNames = array( + 'København', 'Frederiksberg', 'Ballerup', 'Brøndby', 'Dragør', 'Gentofte', 'Gladsaxe', 'Glostrup', 'Herlev', + 'Albertslund', 'Hvidovre', 'Høje Taastrup', 'Lyngby-Taarbæk', 'Rødovre', 'Ishøj', 'Tårnby', 'Vallensbæk', + 'Allerød', 'Fredensborg', 'Helsingør', 'Hillerød', 'Hørsholm', 'Rudersdal', 'Egedal', 'Frederikssund', 'Greve', + 'Halsnæs', 'Roskilde', 'Solrød', 'Gribskov', 'Odsherred', 'Holbæk', 'Faxe', 'Kalundborg', 'Ringsted', 'Slagelse', + 'Stevns', 'Sorø', 'Lejre', 'Lolland', 'Næstved', 'Guldborgsund', 'Vordingborg', 'Bornholm', 'Middelfart', + 'Christiansø', 'Assens', 'Faaborg-Midtfyn', 'Kerteminde', 'Nyborg', 'Odense', 'Svendborg', 'Nordfyns', 'Langeland', + 'Ærø', 'Haderslev', 'Billund', 'Sønderborg', 'Tønder', 'Esbjerg', 'Fanø', 'Varde', 'Vejen', 'Aabenraa', + 'Fredericia', 'Horsens', 'Kolding', 'Vejle', 'Herning', 'Holstebro', 'Lemvig', 'Struer', 'Syddjurs', 'Furesø', + 'Norddjurs', 'Favrskov', 'Odder', 'Randers', 'Silkeborg', 'Samsø', 'Skanderborg', 'Aarhus', 'Ikast-Brande', + 'Ringkøbing-Skjern', 'Hedensted', 'Morsø', 'Skive', 'Thisted', 'Viborg', 'Brønderslev', 'Frederikshavn', + 'Vesthimmerlands', 'Læsø', 'Rebild', 'Mariagerfjord', 'Jammerbugt', 'Aalborg', 'Hjørring', 'Køge', + ); + + /** + * @var array Danish regions. + */ + protected static $regionNames = array( + 'Region Nordjylland', 'Region Midtjylland', 'Region Syddanmark', 'Region Hovedstaden', 'Region Sjælland', + ); + + /** + * @link https://github.com/umpirsky/country-list/blob/master/country/cldr/da_DK/country.php + * + * @var array Some countries in danish. + */ + protected static $country = array( + 'Andorra', 'Forenede Arabiske Emirater', 'Afghanistan', 'Antigua og Barbuda', 'Anguilla', 'Albanien', 'Armenien', + 'Hollandske Antiller', 'Angola', 'Antarktis', 'Argentina', 'Amerikansk Samoa', 'Østrig', 'Australien', 'Aruba', + 'Åland', 'Aserbajdsjan', 'Bosnien-Hercegovina', 'Barbados', 'Bangladesh', 'Belgien', 'Burkina Faso', 'Bulgarien', + 'Bahrain', 'Burundi', 'Benin', 'Saint Barthélemy', 'Bermuda', 'Brunei Darussalam', 'Bolivia', 'Brasilien', 'Bahamas', + 'Bhutan', 'Bouvetø', 'Botswana', 'Hviderusland', 'Belize', 'Canada', 'Cocosøerne', 'Congo-Kinshasa', + 'Centralafrikanske Republik', 'Congo', 'Schweiz', 'Elfenbenskysten', 'Cook-øerne', 'Chile', 'Cameroun', 'Kina', + 'Colombia', 'Costa Rica', 'Serbien og Montenegro', 'Cuba', 'Kap Verde', 'Juleøen', 'Cypern', 'Tjekkiet', 'Tyskland', + 'Djibouti', 'Danmark', 'Dominica', 'Den Dominikanske Republik', 'Algeriet', 'Ecuador', 'Estland', 'Egypten', + 'Vestsahara', 'Eritrea', 'Spanien', 'Etiopien', 'Finland', 'Fiji-øerne', 'Falklandsøerne', + 'Mikronesiens Forenede Stater', 'Færøerne', 'Frankrig', 'Gabon', 'Storbritannien', 'Grenada', 'Georgien', + 'Fransk Guyana', 'Guernsey', 'Ghana', 'Gibraltar', 'Grønland', 'Gambia', 'Guinea', 'Guadeloupe', 'Ækvatorialguinea', + 'Grækenland', 'South Georgia og De Sydlige Sandwichøer', 'Guatemala', 'Guam', 'Guinea-Bissau', 'Guyana', + 'SAR Hongkong', 'Heard- og McDonald-øerne', 'Honduras', 'Kroatien', 'Haiti', 'Ungarn', 'Indonesien', 'Irland', + 'Israel', 'Isle of Man', 'Indien', 'Det Britiske Territorium i Det Indiske Ocean', 'Irak', 'Iran', 'Island', + 'Italien', 'Jersey', 'Jamaica', 'Jordan', 'Japan', 'Kenya', 'Kirgisistan', 'Cambodja', 'Kiribati', 'Comorerne', + 'Saint Kitts og Nevis', 'Nordkorea', 'Sydkorea', 'Kuwait', 'Caymanøerne', 'Kasakhstan', 'Laos', 'Libanon', + 'Saint Lucia', 'Liechtenstein', 'Sri Lanka', 'Liberia', 'Lesotho', 'Litauen', 'Luxembourg', 'Letland', 'Libyen', + 'Marokko', 'Monaco', 'Republikken Moldova', 'Montenegro', 'Saint Martin', 'Madagaskar', 'Marshalløerne', + 'Republikken Makedonien', 'Mali', 'Myanmar', 'Mongoliet', 'SAR Macao', 'Nordmarianerne', 'Martinique', + 'Mauretanien', 'Montserrat', 'Malta', 'Mauritius', 'Maldiverne', 'Malawi', 'Mexico', 'Malaysia', 'Mozambique', + 'Namibia', 'Ny Caledonien', 'Niger', 'Norfolk Island', 'Nigeria', 'Nicaragua', 'Holland', 'Norge', 'Nepal', 'Nauru', + 'Niue', 'New Zealand', 'Oman', 'Panama', 'Peru', 'Fransk Polynesien', 'Papua Ny Guinea', 'Filippinerne', 'Pakistan', + 'Polen', 'Saint Pierre og Miquelon', 'Pitcairn', 'Puerto Rico', 'De palæstinensiske områder', 'Portugal', 'Palau', + 'Paraguay', 'Qatar', 'Reunion', 'Rumænien', 'Serbien', 'Rusland', 'Rwanda', 'Saudi-Arabien', 'Salomonøerne', + 'Seychellerne', 'Sudan', 'Sverige', 'Singapore', 'St. Helena', 'Slovenien', 'Svalbard og Jan Mayen', 'Slovakiet', + 'Sierra Leone', 'San Marino', 'Senegal', 'Somalia', 'Surinam', 'Sao Tome og Principe', 'El Salvador', 'Syrien', + 'Swaziland', 'Turks- og Caicosøerne', 'Tchad', 'Franske Besiddelser i Det Sydlige Indiske Ocean', 'Togo', + 'Thailand', 'Tadsjikistan', 'Tokelau', 'Timor-Leste', 'Turkmenistan', 'Tunesien', 'Tonga', 'Tyrkiet', + 'Trinidad og Tobago', 'Tuvalu', 'Taiwan', 'Tanzania', 'Ukraine', 'Uganda', 'De Mindre Amerikanske Oversøiske Øer', + 'USA', 'Uruguay', 'Usbekistan', 'Vatikanstaten', 'St. Vincent og Grenadinerne', 'Venezuela', + 'De britiske jomfruøer', 'De amerikanske jomfruøer', 'Vietnam', 'Vanuatu', 'Wallis og Futunaøerne', 'Samoa', + 'Yemen', 'Mayotte', 'Sydafrika', 'Zambia', 'Zimbabwe', + ); + + /** + * @var array Danish city format. + */ + protected static $cityFormats = array( + '{{cityName}}', + ); + + /** + * @var array Danish street's name formats. + */ + protected static $streetNameFormats = array( + '{{lastName}}{{streetSuffix}}', + '{{middleName}}{{streetSuffix}}', + '{{lastName}} {{streetSuffixWord}}', + '{{middleName}} {{streetSuffixWord}}', + ); + + /** + * @var array Danish street's address formats. + */ + protected static $streetAddressFormats = array( + '{{streetName}} {{buildingNumber}}', + '{{streetName}} {{buildingNumber}}, {{buildingLevel}}', + '{{streetName}} {{buildingNumber}}, {{buildingLevel}} {{buildingSide}}', + ); + + /** + * @var array Danish address format. + */ + protected static $addressFormats = array( + "{{streetAddress}}\n{{postcode}} {{city}}", + ); + + /** + * Randomly return a real city name. + * + * @return string + */ + public static function cityName() + { + return static::randomElement(static::$cityNames); + } + + /** + * Randomly return a suffix word. + * + * @return string + */ + public static function streetSuffixWord() + { + return static::randomElement(static::$streetSuffixWord); + } + + /** + * Randomly return a building number. + * + * @return string + */ + public static function buildingNumber() + { + return static::toUpper(static::bothify(static::randomElement(static::$buildingNumber))); + } + + /** + * Randomly return a building level. + * + * @return string + */ + public static function buildingLevel() + { + return static::numerify(static::randomElement(static::$buildingLevel)); + } + + /** + * Randomly return a side of the building. + * + * @return string + */ + public static function buildingSide() + { + return static::randomElement(static::$buildingSide); + } + + /** + * Randomly return a real municipality name, called 'kommune' in danish. + * + * @return string + */ + public static function kommune() + { + return static::randomElement(static::$kommuneNames); + } + + /** + * Randomly return a real region name. + * + * @return string + */ + public static function region() + { + return static::randomElement(static::$regionNames); + } +} diff --git a/lib/faker/src/Faker/Provider/da_DK/Company.php b/lib/faker/src/Faker/Provider/da_DK/Company.php new file mode 100755 index 0000000..b9f289c --- /dev/null +++ b/lib/faker/src/Faker/Provider/da_DK/Company.php @@ -0,0 +1,70 @@ + + */ +class Company extends \Faker\Provider\Company +{ + /** + * @var array Danish company name formats. + */ + protected static $formats = array( + '{{lastName}} {{companySuffix}}', + '{{lastName}} {{companySuffix}}', + '{{lastName}} {{companySuffix}}', + '{{firstname}} {{lastName}} {{companySuffix}}', + '{{middleName}} {{companySuffix}}', + '{{middleName}} {{companySuffix}}', + '{{middleName}} {{companySuffix}}', + '{{firstname}} {{middleName}} {{companySuffix}}', + '{{lastName}} & {{lastName}} {{companySuffix}}', + '{{lastName}} og {{lastName}} {{companySuffix}}', + '{{lastName}} & {{lastName}} {{companySuffix}}', + '{{lastName}} og {{lastName}} {{companySuffix}}', + '{{middleName}} & {{middleName}} {{companySuffix}}', + '{{middleName}} og {{middleName}} {{companySuffix}}', + '{{middleName}} & {{lastName}}', + '{{middleName}} og {{lastName}}', + ); + + /** + * @var array Company suffixes. + */ + protected static $companySuffix = array('ApS', 'A/S', 'I/S', 'K/S'); + + /** + * @link http://cvr.dk/Site/Forms/CMS/DisplayPage.aspx?pageid=60 + * + * @var string CVR number format. + */ + protected static $cvrFormat = '%#######'; + + /** + * @link http://cvr.dk/Site/Forms/CMS/DisplayPage.aspx?pageid=60 + * + * @var string P number (production number) format. + */ + protected static $pFormat = '%#########'; + + /** + * Generates a CVR number (8 digits). + * + * @return string + */ + public static function cvr() + { + return static::numerify(static::$cvrFormat); + } + + /** + * Generates a P entity number (10 digits). + * + * @return string + */ + public static function p() + { + return static::numerify(static::$pFormat); + } +} diff --git a/lib/faker/src/Faker/Provider/da_DK/Internet.php b/lib/faker/src/Faker/Provider/da_DK/Internet.php new file mode 100755 index 0000000..1f778de --- /dev/null +++ b/lib/faker/src/Faker/Provider/da_DK/Internet.php @@ -0,0 +1,30 @@ + + */ +class Internet extends \Faker\Provider\Internet +{ + /** + * @var array Some safe email TLD. + */ + protected static $safeEmailTld = array( + 'org', 'com', 'net', 'dk', 'dk', 'dk', + ); + + /** + * @var array Some email domains in Denmark. + */ + protected static $freeEmailDomain = array( + 'gmail.com', 'yahoo.com', 'yahoo.dk', 'hotmail.com', 'hotmail.dk', 'mail.dk', 'live.dk' + ); + + /** + * @var array Some TLD. + */ + protected static $tld = array( + 'com', 'com', 'com', 'biz', 'info', 'net', 'org', 'dk', 'dk', 'dk', + ); +} diff --git a/lib/faker/src/Faker/Provider/da_DK/Payment.php b/lib/faker/src/Faker/Provider/da_DK/Payment.php new file mode 100755 index 0000000..6a5b6a8 --- /dev/null +++ b/lib/faker/src/Faker/Provider/da_DK/Payment.php @@ -0,0 +1,19 @@ + + */ +class Person extends \Faker\Provider\Person +{ + /** + * @var array Danish person name formats. + */ + protected static $maleNameFormats = array( + '{{firstNameMale}} {{lastName}}', + '{{firstNameMale}} {{lastName}}', + '{{firstNameMale}} {{lastName}}', + '{{firstNameMale}} {{middleName}} {{lastName}}', + '{{firstNameMale}} {{middleName}} {{lastName}}', + '{{firstNameMale}} {{middleName}}-{{middleName}} {{lastName}}', + '{{firstNameMale}} {{middleName}} {{middleName}}-{{lastName}}', + ); + + protected static $femaleNameFormats = array( + '{{firstNameFemale}} {{lastName}}', + '{{firstNameFemale}} {{lastName}}', + '{{firstNameFemale}} {{lastName}}', + '{{firstNameFemale}} {{middleName}} {{lastName}}', + '{{firstNameFemale}} {{middleName}} {{lastName}}', + '{{firstNameFemale}} {{middleName}}-{{middleName}} {{lastName}}', + '{{firstNameFemale}} {{middleName}} {{middleName}}-{{lastName}}', + ); + + /** + * @var array Danish first names. + */ + protected static $firstNameMale = array( + 'Aage', 'Adam', 'Adolf', 'Ahmad', 'Ahmed', 'Aksel', 'Albert', 'Alex', 'Alexander', 'Alf', 'Alfred', 'Ali', 'Allan', + 'Anders', 'Andreas', 'Anker', 'Anton', 'Arne', 'Arnold', 'Arthur', 'Asbjørn', 'Asger', 'August', 'Axel', 'Benjamin', + 'Benny', 'Bent', 'Bernhard', 'Birger', 'Bjarne', 'Bjørn', 'Bo', 'Brian', 'Bruno', 'Børge', 'Carl', 'Carlo', + 'Carsten', 'Casper', 'Charles', 'Chris', 'Christian', 'Christoffer', 'Christopher', 'Claus', 'Dan', 'Daniel', 'David', 'Dennis', + 'Ebbe', 'Edmund', 'Edvard', 'Egon', 'Einar', 'Ejvind', 'Elias', 'Emanuel', 'Emil', 'Erik', 'Erland', 'Erling', + 'Ernst', 'Esben', 'Ferdinand', 'Finn', 'Flemming', 'Frank', 'Freddy', 'Frederik', 'Frits', 'Fritz', 'Frode', 'Georg', + 'Gerhard', 'Gert', 'Gunnar', 'Gustav', 'Hans', 'Harald', 'Harry', 'Hassan', 'Heine', 'Heinrich', 'Helge', 'Helmer', + 'Helmuth', 'Henning', 'Henrik', 'Henry', 'Herman', 'Hermann', 'Holger', 'Hugo', 'Ib', 'Ibrahim', 'Ivan', 'Jack', + 'Jacob', 'Jakob', 'Jan', 'Janne', 'Jens', 'Jeppe', 'Jesper', 'Jimmi', 'Jimmy', 'Joachim', 'Johan', 'Johannes', + 'John', 'Johnny', 'Jon', 'Jonas', 'Jonathan', 'Josef', 'Jul', 'Julius', 'Jørgen', 'Jørn', 'Kai', 'Kaj', + 'Karl', 'Karlo', 'Karsten', 'Kasper', 'Kenneth', 'Kent', 'Kevin', 'Kjeld', 'Klaus', 'Knud', 'Kristian', 'Kristoffer', + 'Kurt', 'Lars', 'Lasse', 'Leif', 'Lennart', 'Leo', 'Leon', 'Louis', 'Lucas', 'Lukas', 'Mads', 'Magnus', + 'Malthe', 'Marc', 'Marcus', 'Marinus', 'Marius', 'Mark', 'Markus', 'Martin', 'Martinus', 'Mathias', 'Max', 'Michael', + 'Mikael', 'Mike', 'Mikkel', 'Mogens', 'Mohamad', 'Mohamed', 'Mohammad', 'Morten', 'Nick', 'Nicklas', 'Nicolai', 'Nicolaj', + 'Niels', 'Niklas', 'Nikolaj', 'Nils', 'Olaf', 'Olav', 'Ole', 'Oliver', 'Oscar', 'Oskar', 'Otto', 'Ove', + 'Palle', 'Patrick', 'Paul', 'Peder', 'Per', 'Peter', 'Philip', 'Poul', 'Preben', 'Rasmus', 'Rene', 'René', + 'Richard', 'Robert', 'Rolf', 'Rudolf', 'Rune', 'Sebastian', 'Sigurd', 'Simon', 'Simone', 'Steen', 'Stefan', 'Steffen', + 'Sten', 'Stig', 'Sune', 'Sven', 'Svend', 'Søren', 'Tage', 'Theodor', 'Thomas', 'Thor', 'Thorvald', 'Tim', + 'Tobias', 'Tom', 'Tommy', 'Tonny', 'Torben', 'Troels', 'Uffe', 'Ulrik', 'Vagn', 'Vagner', 'Valdemar', 'Vang', + 'Verner', 'Victor', 'Viktor', 'Villy', 'Walther', 'Werner', 'Wilhelm', 'William', 'Willy', 'Åge', 'Bendt', 'Bjarke', + 'Chr', 'Eigil', 'Ejgil', 'Ejler', 'Ejnar', 'Ejner', 'Evald', 'Folmer', 'Gunner', 'Gurli', 'Hartvig', 'Herluf', 'Hjalmar', + 'Ingemann', 'Ingolf', 'Ingvard', 'Keld', 'Kresten', 'Laurids', 'Laurits', 'Lauritz', 'Ludvig', 'Lynge', 'Oluf', 'Osvald', + 'Povl', 'Richardt', 'Sigfred', 'Sofus', 'Thorkild', 'Viggo', 'Vilhelm', 'Villiam', + ); + + protected static $firstNameFemale = array( + 'Aase', 'Agathe', 'Agnes', 'Alberte', 'Alexandra', 'Alice', 'Alma', 'Amalie', 'Amanda', 'Andrea', 'Ane', 'Anette', 'Anita', + 'Anja', 'Ann', 'Anna', 'Annalise', 'Anne', 'Anne-Lise', 'Anne-Marie', 'Anne-Mette', 'Annelise', 'Annette', 'Anni', 'Annie', + 'Annika', 'Anny', 'Asta', 'Astrid', 'Augusta', 'Benedikte', 'Bente', 'Berit', 'Bertha', 'Betina', 'Bettina', 'Betty', + 'Birgit', 'Birgitte', 'Birte', 'Birthe', 'Bitten', 'Bodil', 'Britt', 'Britta', 'Camilla', 'Carina', 'Carla', 'Caroline', + 'Cathrine', 'Cecilie', 'Charlotte', 'Christa', 'Christen', 'Christiane', 'Christina', 'Christine', 'Clara', 'Conni', 'Connie', 'Conny', + 'Dagmar', 'Dagny', 'Diana', 'Ditte', 'Dora', 'Doris', 'Dorte', 'Dorthe', 'Ebba', 'Edel', 'Edith', 'Eleonora', + 'Eli', 'Elin', 'Eline', 'Elinor', 'Elisa', 'Elisabeth', 'Elise', 'Ella', 'Ellen', 'Ellinor', 'Elly', 'Elna', + 'Elsa', 'Else', 'Elsebeth', 'Elvira', 'Emilie', 'Emma', 'Emmy', 'Erna', 'Ester', 'Esther', 'Eva', 'Evelyn', + 'Frede', 'Frederikke', 'Freja', 'Frida', 'Gerda', 'Gertrud', 'Gitte', 'Grete', 'Grethe', 'Gudrun', 'Hanna', 'Hanne', + 'Hardy', 'Harriet', 'Hedvig', 'Heidi', 'Helen', 'Helena', 'Helene', 'Helga', 'Helle', 'Henny', 'Henriette', 'Herdis', + 'Hilda', 'Iben', 'Ida', 'Ilse', 'Ina', 'Inga', 'Inge', 'Ingeborg', 'Ingelise', 'Inger', 'Ingrid', 'Irene', + 'Iris', 'Irma', 'Isabella', 'Jane', 'Janni', 'Jannie', 'Jeanette', 'Jeanne', 'Jenny', 'Jes', 'Jette', 'Joan', + 'Johanna', 'Johanne', 'Jonna', 'Josefine', 'Josephine', 'Juliane', 'Julie', 'Jytte', 'Kaja', 'Kamilla', 'Karen', 'Karin', + 'Karina', 'Karla', 'Karoline', 'Kate', 'Kathrine', 'Katja', 'Katrine', 'Ketty', 'Kim', 'Kirsten', 'Kirstine', 'Klara', + 'Krista', 'Kristen', 'Kristina', 'Kristine', 'Laila', 'Laura', 'Laurine', 'Lea', 'Lena', 'Lene', 'Lilian', 'Lilli', + 'Lillian', 'Lilly', 'Linda', 'Line', 'Lis', 'Lisa', 'Lisbet', 'Lisbeth', 'Lise', 'Liselotte', 'Lissi', 'Lissy', + 'Liv', 'Lizzie', 'Lone', 'Lotte', 'Louise', 'Lydia', 'Lykke', 'Lærke', 'Magda', 'Magdalene', 'Mai', 'Maiken', + 'Maj', 'Maja', 'Majbritt', 'Malene', 'Maren', 'Margit', 'Margrethe', 'Maria', 'Mariane', 'Marianne', 'Marie', 'Marlene', + 'Martha', 'Martine', 'Mary', 'Mathilde', 'Matilde', 'Merete', 'Merethe', 'Meta', 'Mette', 'Mia', 'Michelle', 'Mie', + 'Mille', 'Minna', 'Mona', 'Monica', 'Nadia', 'Nancy', 'Nanna', 'Nicoline', 'Nikoline', 'Nina', 'Ninna', 'Oda', + 'Olga', 'Olivia', 'Orla', 'Paula', 'Pauline', 'Pernille', 'Petra', 'Pia', 'Poula', 'Ragnhild', 'Randi', 'Rasmine', + 'Rebecca', 'Rebekka', 'Rigmor', 'Rikke', 'Rita', 'Rosa', 'Rose', 'Ruth', 'Sabrina', 'Sandra', 'Sanne', 'Sara', + 'Sarah', 'Selma', 'Severin', 'Sidsel', 'Signe', 'Sigrid', 'Sine', 'Sofia', 'Sofie', 'Solveig', 'Solvejg', 'Sonja', + 'Sophie', 'Stephanie', 'Stine', 'Susan', 'Susanne', 'Tanja', 'Thea', 'Theodora', 'Therese', 'Thi', 'Thyra', 'Tina', + 'Tine', 'Tove', 'Trine', 'Ulla', 'Vera', 'Vibeke', 'Victoria', 'Viktoria', 'Viola', 'Vita', 'Vivi', 'Vivian', + 'Winnie', 'Yrsa', 'Yvonne', 'Agnete', 'Agnethe', 'Alfrida', 'Alvilda', 'Anine', 'Bolette', 'Dorthea', 'Gunhild', + 'Hansine', 'Inge-Lise', 'Jensine', 'Juel', 'Jørgine', 'Kamma', 'Kristiane', 'Maj-Britt', 'Margrete', 'Metha', 'Nielsine', + 'Oline', 'Petrea', 'Petrine', 'Pouline', 'Ragna', 'Sørine', 'Thora', 'Valborg', 'Vilhelmine', + ); + + /** + * @var array Danish middle names. + */ + protected static $middleName = array( + 'Møller', 'Lund', 'Holm', 'Jensen', 'Juul', 'Nielsen', 'Kjær', 'Hansen', 'Skov', 'Østergaard', 'Vestergaard', + 'Nørgaard', 'Dahl', 'Bach', 'Friis', 'Søndergaard', 'Andersen', 'Bech', 'Pedersen', 'Bruun', 'Nygaard', 'Winther', + 'Bang', 'Krogh', 'Schmidt', 'Christensen', 'Hedegaard', 'Toft', 'Damgaard', 'Holst', 'Sørensen', 'Juhl', 'Munk', + 'Skovgaard', 'Søgaard', 'Aagaard', 'Berg', 'Dam', 'Petersen', 'Lind', 'Overgaard', 'Brandt', 'Larsen', 'Bak', 'Schou', + 'Vinther', 'Bjerregaard', 'Riis', 'Bundgaard', 'Kruse', 'Mølgaard', 'Hjorth', 'Ravn', 'Madsen', 'Rasmussen', + 'Jørgensen', 'Kristensen', 'Bonde', 'Bay', 'Hougaard', 'Dalsgaard', 'Kjærgaard', 'Haugaard', 'Munch', 'Bjerre', 'Due', + 'Sloth', 'Leth', 'Kofoed', 'Thomsen', 'Kragh', 'Højgaard', 'Dalgaard', 'Hjort', 'Kirkegaard', 'Bøgh', 'Beck', 'Nissen', + 'Rask', 'Høj', 'Brix', 'Storm', 'Buch', 'Bisgaard', 'Birch', 'Gade', 'Kjærsgaard', 'Hald', 'Lindberg', 'Høgh', 'Falk', + 'Koch', 'Thorup', 'Borup', 'Knudsen', 'Vedel', 'Poulsen', 'Bøgelund', 'Juel', 'Frost', 'Hvid', 'Bjerg', 'Bæk', 'Elkjær', + 'Hartmann', 'Kirk', 'Sand', 'Sommer', 'Skou', 'Nedergaard', 'Meldgaard', 'Brink', 'Lindegaard', 'Fischer', 'Rye', + 'Hoffmann', 'Daugaard', 'Gram', 'Johansen', 'Meyer', 'Schultz', 'Fogh', 'Bloch', 'Lundgaard', 'Brøndum', 'Jessen', + 'Busk', 'Holmgaard', 'Lindholm', 'Krog', 'Egelund', 'Engelbrecht', 'Buus', 'Korsgaard', 'Ellegaard', 'Tang', 'Steen', + 'Kvist', 'Olsen', 'Nørregaard', 'Fuglsang', 'Wulff', 'Damsgaard', 'Hauge', 'Sonne', 'Skytte', 'Brun', 'Kronborg', + 'Abildgaard', 'Fabricius', 'Bille', 'Skaarup', 'Rahbek', 'Borg', 'Torp', 'Klitgaard', 'Nørskov', 'Greve', 'Hviid', + 'Mørch', 'Buhl', 'Rohde', 'Mørk', 'Vendelbo', 'Bjørn', 'Laursen', 'Egede', 'Rytter', 'Lehmann', 'Guldberg', 'Rosendahl', + 'Krarup', 'Krogsgaard', 'Westergaard', 'Rosendal', 'Fisker', 'Højer', 'Rosenberg', 'Svane', 'Storgaard', 'Pihl', + 'Mohamed', 'Bülow', 'Birk', 'Hammer', 'Bro', 'Kaas', 'Clausen', 'Nymann', 'Egholm', 'Ingemann', 'Haahr', 'Olesen', + 'Nøhr', 'Brinch', 'Bjerring', 'Christiansen', 'Schrøder', 'Guldager', 'Skjødt', 'Højlund', 'Ørum', 'Weber', + 'Bødker', 'Bruhn', 'Stampe', 'Astrup', 'Schack', 'Mikkelsen', 'Høyer', 'Husted', 'Skriver', 'Lindgaard', 'Yde', + 'Sylvest', 'Lykkegaard', 'Ploug', 'Gammelgaard', 'Pilgaard', 'Brogaard', 'Degn', 'Kaae', 'Kofod', 'Grønbæk', + 'Lundsgaard', 'Bagge', 'Lyng', 'Rømer', 'Kjeldgaard', 'Hovgaard', 'Groth', 'Hyldgaard', 'Ladefoged', 'Jacobsen', + 'Linde', 'Lange', 'Stokholm', 'Bredahl', 'Hein', 'Mose', 'Bækgaard', 'Sandberg', 'Klarskov', 'Kamp', 'Green', + 'Iversen', 'Riber', 'Smedegaard', 'Nyholm', 'Vad', 'Balle', 'Kjeldsen', 'Strøm', 'Borch', 'Lerche', 'Grønlund', + 'Vestergård', 'Østergård', 'Nyborg', 'Qvist', 'Damkjær', 'Kold', 'Sønderskov', 'Bank', + ); + + /** + * @var array Danish last names. + */ + protected static $lastName = array( + 'Jensen', 'Nielsen', 'Hansen', 'Pedersen', 'Andersen', 'Christensen', 'Larsen', 'Sørensen', 'Rasmussen', 'Petersen', + 'Jørgensen', 'Madsen', 'Kristensen', 'Olsen', 'Christiansen', 'Thomsen', 'Poulsen', 'Johansen', 'Knudsen', 'Mortensen', + 'Møller', 'Jacobsen', 'Jakobsen', 'Olesen', 'Frederiksen', 'Mikkelsen', 'Henriksen', 'Laursen', 'Lund', 'Schmidt', + 'Eriksen', 'Holm', 'Kristiansen', 'Clausen', 'Simonsen', 'Svendsen', 'Andreasen', 'Iversen', 'Jeppesen', 'Mogensen', + 'Jespersen', 'Nissen', 'Lauridsen', 'Frandsen', 'Østergaard', 'Jepsen', 'Kjær', 'Carlsen', 'Vestergaard', 'Jessen', + 'Nørgaard', 'Dahl', 'Christoffersen', 'Skov', 'Søndergaard', 'Bertelsen', 'Bruun', 'Lassen', 'Bach', 'Gregersen', + 'Friis', 'Johnsen', 'Steffensen', 'Kjeldsen', 'Bech', 'Krogh', 'Lauritsen', 'Danielsen', 'Mathiesen', 'Andresen', + 'Brandt', 'Winther', 'Toft', 'Ravn', 'Mathiasen', 'Dam', 'Holst', 'Nilsson', 'Lind', 'Berg', 'Schou', 'Overgaard', + 'Kristoffersen', 'Schultz', 'Klausen', 'Karlsen', 'Paulsen', 'Hermansen', 'Thorsen', 'Koch', 'Thygesen', 'Bak', 'Kruse', + 'Bang', 'Juhl', 'Davidsen', 'Berthelsen', 'Nygaard', 'Lorentzen', 'Villadsen', 'Lorenzen', 'Damgaard', 'Bjerregaard', + 'Lange', 'Hedegaard', 'Bendtsen', 'Lauritzen', 'Svensson', 'Justesen', 'Juul', 'Hald', 'Beck', 'Kofoed', 'Søgaard', + 'Meyer', 'Kjærgaard', 'Riis', 'Johannsen', 'Carstensen', 'Bonde', 'Ibsen', 'Fischer', 'Andersson', 'Bundgaard', + 'Johannesen', 'Eskildsen', 'Hemmingsen', 'Andreassen', 'Thomassen', 'Schrøder', 'Persson', 'Hjorth', 'Enevoldsen', + 'Nguyen', 'Henningsen', 'Jønsson', 'Olsson', 'Asmussen', 'Michelsen', 'Vinther', 'Markussen', 'Kragh', 'Thøgersen', + 'Johansson', 'Dalsgaard', 'Gade', 'Bjerre', 'Ali', 'Laustsen', 'Buch', 'Ludvigsen', 'Hougaard', 'Kirkegaard', 'Marcussen', + 'Mølgaard', 'Ipsen', 'Sommer', 'Ottosen', 'Müller', 'Krog', 'Hoffmann', 'Clemmensen', 'Nikolajsen', 'Brodersen', + 'Therkildsen', 'Leth', 'Michaelsen', 'Graversen', 'Frost', 'Dalgaard', 'Albertsen', 'Laugesen', 'Due', 'Ebbesen', + 'Munch', 'Svenningsen', 'Ottesen', 'Fisker', 'Albrechtsen', 'Axelsen', 'Erichsen', 'Sloth', 'Bentsen', 'Westergaard', + 'Bisgaard', 'Nicolaisen', 'Magnussen', 'Thuesen', 'Povlsen', 'Thorup', 'Høj', 'Bentzen', 'Johannessen', 'Vilhelmsen', + 'Isaksen', 'Bendixen', 'Ovesen', 'Villumsen', 'Lindberg', 'Thomasen', 'Kjærsgaard', 'Buhl', 'Kofod', 'Ahmed', 'Smith', + 'Storm', 'Christophersen', 'Bruhn', 'Matthiesen', 'Wagner', 'Bjerg', 'Gram', 'Nedergaard', 'Dinesen', 'Mouritsen', + 'Boesen', 'Borup', 'Abrahamsen', 'Wulff', 'Gravesen', 'Rask', 'Pallesen', 'Greve', 'Korsgaard', 'Haugaard', 'Josefsen', + 'Bæk', 'Espersen', 'Thrane', 'Mørch', 'Frank', 'Lynge', 'Rohde', 'Larsson', 'Hammer', 'Torp', 'Sonne', 'Boysen', 'Bay', + 'Pihl', 'Fabricius', 'Høyer', 'Birch', 'Skou', 'Kirk', 'Antonsen', 'Høgh', 'Damsgaard', 'Dall', 'Truelsen', 'Daugaard', + 'Fuglsang', 'Martinsen', 'Therkelsen', 'Jansen', 'Karlsson', 'Caspersen', 'Steen', 'Callesen', 'Balle', 'Bloch', 'Smidt', + 'Rahbek', 'Hjort', 'Bjørn', 'Skaarup', 'Sand', 'Storgaard', 'Willumsen', 'Busk', 'Hartmann', 'Ladefoged', 'Skovgaard', + 'Philipsen', 'Damm', 'Haagensen', 'Hviid', 'Duus', 'Kvist', 'Adamsen', 'Mathiassen', 'Degn', 'Borg', 'Brix', 'Troelsen', + 'Ditlevsen', 'Brøndum', 'Svane', 'Mohamed', 'Birk', 'Brink', 'Hassan', 'Vester', 'Elkjær', 'Lykke', 'Nørregaard', + 'Meldgaard', 'Mørk', 'Hvid', 'Abildgaard', 'Nicolajsen', 'Bengtsson', 'Stokholm', 'Ahmad', 'Wind', 'Rømer', 'Gundersen', + 'Carlsson', 'Grøn', 'Khan', 'Skytte', 'Bagger', 'Hendriksen', 'Rosenberg', 'Jonassen', 'Severinsen', 'Jürgensen', + 'Boisen', 'Groth', 'Bager', 'Fogh', 'Hussain', 'Samuelsen', 'Pilgaard', 'Bødker', 'Dideriksen', 'Brogaard', 'Lundberg', + 'Hansson', 'Schwartz', 'Tran', 'Skriver', 'Klitgaard', 'Hauge', 'Højgaard', 'Qvist', 'Voss', 'Strøm', 'Wolff', 'Krarup', + 'Green', 'Odgaard', 'Tønnesen', 'Blom', 'Gammelgaard', 'Jæger', 'Kramer', 'Astrup', 'Würtz', 'Lehmann', 'Koefoed', + 'Skøtt', 'Lundsgaard', 'Bøgh', 'Vang', 'Martinussen', 'Sandberg', 'Weber', 'Holmgaard', 'Bidstrup', 'Meier', 'Drejer', + 'Schneider', 'Joensen', 'Dupont', 'Lorentsen', 'Bro', 'Bagge', 'Terkelsen', 'Kaspersen', 'Keller', 'Eliasen', 'Lyberth', + 'Husted', 'Mouritzen', 'Krag', 'Kragelund', 'Nørskov', 'Vad', 'Jochumsen', 'Hein', 'Krogsgaard', 'Kaas', 'Tolstrup', + 'Ernst', 'Hermann', 'Børgesen', 'Skjødt', 'Holt', 'Buus', 'Gotfredsen', 'Kjeldgaard', 'Broberg', 'Roed', 'Sivertsen', + 'Bergmann', 'Bjerrum', 'Petersson', 'Smed', 'Jeremiassen', 'Nyborg', 'Borch', 'Foged', 'Terp', 'Mark', 'Busch', + 'Lundgaard', 'Boye', 'Yde', 'Hinrichsen', 'Matzen', 'Esbensen', 'Hertz', 'Westh', 'Holmberg', 'Geertsen', 'Raun', + 'Aagaard', 'Kock', 'Falk', 'Munk', + ); + + /** + * Randomly return a danish name. + * + * @return string + */ + public static function middleName() + { + return static::randomElement(static::$middleName); + } + + /** + * Randomly return a danish CPR number (Personnal identification number) format. + * + * @link http://cpr.dk/cpr/site.aspx?p=16 + * @link http://en.wikipedia.org/wiki/Personal_identification_number_%28Denmark%29 + * + * @return string + */ + public static function cpr() + { + $birthdate = new \DateTime('@' . mt_rand(0, time())); + + return sprintf('%s-%s', $birthdate->format('dmy'), static::numerify('%###')); + } +} diff --git a/lib/faker/src/Faker/Provider/da_DK/PhoneNumber.php b/lib/faker/src/Faker/Provider/da_DK/PhoneNumber.php new file mode 100755 index 0000000..af96d3f --- /dev/null +++ b/lib/faker/src/Faker/Provider/da_DK/PhoneNumber.php @@ -0,0 +1,21 @@ + + */ +class PhoneNumber extends \Faker\Provider\PhoneNumber +{ + /** + * @var array Danish phonenumber formats. + */ + protected static $formats = array( + '+45 ## ## ## ##', + '+45 #### ####', + '+45########', + '## ## ## ##', + '#### ####', + '########', + ); +} diff --git a/lib/faker/src/Faker/Provider/de_AT/Address.php b/lib/faker/src/Faker/Provider/de_AT/Address.php new file mode 100755 index 0000000..22bcf12 --- /dev/null +++ b/lib/faker/src/Faker/Provider/de_AT/Address.php @@ -0,0 +1,99 @@ +generator->parse(static::randomElement(static::$lastNameFormat)); + } + + /** + * @example 'Θεωδωρόπουλος' + */ + public static function lastNameMale() + { + return static::randomElement(static::$lastNameMale); + } + + /** + * @example 'Κοκκίνου' + */ + public static function lastNameFemale() + { + return static::randomElement(static::$lastNameFemale); + } +} diff --git a/lib/faker/src/Faker/Provider/el_GR/PhoneNumber.php b/lib/faker/src/Faker/Provider/el_GR/PhoneNumber.php new file mode 100755 index 0000000..107253d --- /dev/null +++ b/lib/faker/src/Faker/Provider/el_GR/PhoneNumber.php @@ -0,0 +1,19 @@ +generator->parse($format)); + } + + /** + * NPA-format area code + * + * @see https://en.wikipedia.org/wiki/North_American_Numbering_Plan#Numbering_system + * + * @return string + */ + public static function areaCode() + { + $digits[] = self::numberBetween(2, 9); + $digits[] = self::randomDigit(); + $digits[] = self::randomDigitNot($digits[1]); + + return join('', $digits); + } + + /** + * NXX-format central office exchange code + * + * @see https://en.wikipedia.org/wiki/North_American_Numbering_Plan#Numbering_system + * + * @return string + */ + public static function exchangeCode() + { + $digits[] = self::numberBetween(2, 9); + $digits[] = self::randomDigit(); + + if ($digits[1] === 1) { + $digits[] = self::randomDigitNot(1); + } else { + $digits[] = self::randomDigit(); + } + + return join('', $digits); + } +} diff --git a/lib/faker/src/Faker/Provider/en_US/Text.php b/lib/faker/src/Faker/Provider/en_US/Text.php new file mode 100755 index 0000000..b3c5258 --- /dev/null +++ b/lib/faker/src/Faker/Provider/en_US/Text.php @@ -0,0 +1,3720 @@ +numberBetween($min = 10000, $max = 100000000); + } +} diff --git a/lib/faker/src/Faker/Provider/es_VE/PhoneNumber.php b/lib/faker/src/Faker/Provider/es_VE/PhoneNumber.php new file mode 100755 index 0000000..74caecc --- /dev/null +++ b/lib/faker/src/Faker/Provider/es_VE/PhoneNumber.php @@ -0,0 +1,29 @@ +generator->parse($format)); + } + + /** + * @example 'ahmad.ir' + */ + public function domainName() + { + return static::randomElement(static::$lastNameAscii) . '.' . $this->tld(); + } +} diff --git a/lib/faker/src/Faker/Provider/fa_IR/Person.php b/lib/faker/src/Faker/Provider/fa_IR/Person.php new file mode 100755 index 0000000..055b863 --- /dev/null +++ b/lib/faker/src/Faker/Provider/fa_IR/Person.php @@ -0,0 +1,137 @@ + 5) { + throw new \InvalidArgumentException('indexSize must be at most 5'); + } + + $words = $this->getConsecutiveWords($indexSize); + $result = array(); + $resultLength = 0; + // take a random starting point + $next = static::randomKey($words); + while ($resultLength < $maxNbChars && isset($words[$next])) { + // fetch a random word to append + $word = static::randomElement($words[$next]); + + // calculate next index + $currentWords = explode(' ', $next); + + $currentWords[] = $word; + array_shift($currentWords); + $next = implode(' ', $currentWords); + + if ($resultLength == 0 && !preg_match('/^[\x{0600}-\x{06FF}]/u', $word)) { + continue; + } + // append the element + $result[] = $word; + $resultLength += strlen($word) + 1; + } + + // remove the element that caused the text to overflow + array_pop($result); + + // build result + $result = implode(' ', $result); + + return $result.'.'; + } + + /** + * License: Creative Commons Attribution-ShareAlike License + * + * Title: مدیر مدرسه + * Author: جلال آل‌احمد + * Language: Persian + * + * @see http://fa.wikisource.org/wiki/%D9%85%D8%AF%DB%8C%D8%B1_%D9%85%D8%AF%D8%B1%D8%B3%D9%87 + * @var string + */ + protected static $baseText = <<<'EOT' +از در که وارد شدم سیگارم دستم بود. زورم آمد سلام کنم. همین طوری دنگم گرفته بود قد باشم. رئیس فرهنگ که اجازه‌ی نشستن داد، نگاهش لحظه‌ای روی دستم مکث کرد و بعد چیزی را که می‌نوشت، تمام کرد و می‌خواست متوجه من بشود که رونویس حکم را روی میزش گذاشته بودم. حرفی نزدیم. رونویس را با کاغذهای ضمیمه‌اش زیر و رو کرد و بعد غبغب انداخت و آرام و مثلاً خالی از عصبانیت گفت: + +- جا نداریم آقا. این که نمی‌شه! هر روز یه حکم می‌دند دست یکی می‌فرستنش سراغ من... دیروز به آقای مدیر کل... + +حوصله‌ی این اباطیل را نداشتم. حرفش را بریدم که: + +- ممکنه خواهش کنم زیر همین ورقه مرقوم بفرمایید؟ + +و سیگارم را توی زیرسیگاری براق روی میزش تکاندم. روی میز، پاک و مرتب بود. درست مثل اتاق همان مهمان‌خانه‌ی تازه‌عروس‌ها. هر چیز به جای خود و نه یک ذره گرد. فقط خاکستر سیگار من زیادی بود. مثل تفی در صورت تازه تراشیده‌ای.... قلم را برداشت و زیر حکم چیزی نوشت و امضا کرد و من از در آمده بودم بیرون. خلاص. تحمل این یکی را نداشتم. با اداهایش. پیدا بود که تازه رئیس شده. زورکی غبغب می‌انداخت و حرفش را آهسته توی چشم آدم می‌زد. انگار برای شنیدنش گوش لازم نیست. صد و پنجاه تومان در کارگزینی کل مایه گذاشته بودم تا این حکم را به امضا رسانده بودم. توصیه هم برده بودم و تازه دو ماه هم دویده بودم. مو، لای درزش نمی‌رفت. می‌دانستم که چه او بپذیرد، چه نپذیرد، کار تمام است. خودش هم می‌دانست. حتماً هم دستگیرش شد که با این نک و نالی که می‌کرد، خودش را کنف کرده. ولی کاری بود و شده بود. در کارگزینی کل، سفارش کرده بودند که برای خالی نبودن عریضه رونویس را به رؤیت رئیس فرهنگ هم برسانم تازه این طور شد. و گر نه بالی حکم کارگزینی کل چه کسی می‌توانست حرفی بزند؟ یک وزارت خانه بود و یک کارگزینی! شوخی که نبود. ته دلم قرص‌تر از این‌ها بود که محتاج به این استدلال‌ها باشم. اما به نظرم همه‌ی این تقصیرها از این سیگار لعنتی بود که به خیال خودم خواسته بودم خرجش را از محل اضافه حقوق شغل جدیدم در بیاورم. البته از معلمی، هم اُقم نشسته بود. ده سال «الف.ب.» درس دادن و قیافه‌های بهت‌زده‌ی بچه‌های مردم برای مزخرف‌ترین چرندی که می‌گویی... و استغناء با غین و استقراء با قاف و خراسانی و هندی و قدیمی‌ترین شعر دری و صنعت ارسال مثل و ردالعجز... و از این مزخرفات! دیدم دارم خر می‌شوم. گفتم مدیر بشوم. مدیر دبستان! دیگر نه درس خواهم داد و نه مجبور خواهم بود برای فرار از اتلاف وقت، در امتحان تجدیدی به هر احمق بی‌شعوری هفت بدهم تا ایام آخر تابستانم را که لذیذترین تکه‌ی تعطیلات است، نجات داده باشم. این بود که راه افتادم. رفتم و از اهلش پرسیدم. از یک کار چاق کن. دستم را توی دست کارگزینی گذاشت و قول و قرار و طرفین خوش و خرم و یک روز هم نشانی مدرسه را دستم دادند که بروم وارسی، که باب میلم هست یا نه. + +و رفتم. مدرسه دو طبقه بود و نوساز بود و در دامنه‌ی کوه تنها افتاده بود و آفتاب‌رو بود. یک فرهنگ‌دوست خرپول، عمارتش را وسط زمین خودش ساخته بود و بیست و پنج سال هم در اختیار فرهنگ گذاشته بود که مدرسه‌اش کنند و رفت و آمد بشود و جاده‌ها کوبیده بشود و این قدر ازین بشودها بشود، تا دل ننه باباها بسوزد و برای این‌که راه بچه‌هاشان را کوتاه بکنند، بیایند همان اطراف مدرسه را بخرند و خانه بسازند و زمین یارو از متری یک عباسی بشود صد تومان. یارو اسمش را هم روی دیوار مدرسه کاشی‌کاری کرده بود. هنوز در و همسایه پیدا نکرده بودند که حرف‌شان بشود و لنگ و پاچه‌ی سعدی و باباطاهر را بکشند میان و یک ورق دیگر از تاریخ‌الشعرا را بکوبند روی نبش دیوار کوچه‌شان. تابلوی مدرسه هم حسابی و بزرگ و خوانا. از صد متری داد می‌زد که توانا بود هر.... هر چه دلتان بخواهد! با شیر و خورشیدش که آن بالا سر، سه پا ایستاده بود و زورکی تعادل خودش را حفظ می‌کرد و خورشید خانم روی کولش با ابروهای پیوسته و قمچیلی که به دست داشت و تا سه تیر پرتاب، اطراف مدرسه بیابان بود. درندشت و بی آب و آبادانی و آن ته رو به شمال، ردیف کاج‌های درهم فرو رفته‌ای که از سر دیوار گلی یک باغ پیدا بود روی آسمان لکه‌ی دراز و تیره‌ای زده بود. حتماً تا بیست و پنج سال دیگر همه‌ی این اطراف پر می‌شد و بوق ماشین و ونگ ونگ بچه‌ها و فریاد لبویی و زنگ روزنامه‌فروشی و عربده‌ی گل به سر دارم خیار! نان یارو توی روغن بود. + +- راستی شاید متری ده دوازده شاهی بیشتر نخریده باشد؟ شاید هم زمین‌ها را همین جوری به ثبت داده باشد؟ هان؟ + +- احمق به توچه؟!... + +بله این فکرها را همان روزی کردم که ناشناس به مدرسه سر زدم و آخر سر هم به این نتیجه رسیدم که مردم حق دارند جایی بخوابند که آب زیرشان نرود. + +- تو اگر مردی، عرضه داشته باش مدیر همین مدرسه هم بشو. + +و رفته بودم و دنبال کار را گرفته بودم تا رسیده بودم به این‌جا. همان روز وارسی فهمیده بودم که مدیر قبلی مدرسه زندانی است. لابد کله‌اش بوی قرمه‌سبزی می‌داده و باز لابد حالا دارد کفاره‌ی گناهانی را می‌دهد که یا خودش نکرده یا آهنگری در بلخ کرده. جزو پر قیچی‌های رئیس فرهنگ هم کسی نبود که با مدیرشان، اضافه حقوقی نصیبش بشود و ناچار سر و دستی برای این کار بشکند. خارج از مرکز هم نداشت. این معلومات را توی کارگزینی به دست آورده بودم. هنوز «گه خوردم نامه‌نویسی» هم مد نشده بود که بگویم یارو به این زودی‌ها از سولدونی در خواهد آمد. فکر نمی‌کردم که دیگری هم برای این وسط بیابان دلش لک زده باشد با زمستان سختش و با رفت و آمد دشوارش. + +این بود که خیالم راحت بود. از همه‌ی این‌ها گذشته کارگزینی کل موافقت کرده بود! دست است که پیش از بلند شدن بوی اسکناس، آن جا هم دو سه تا عیب شرعی و عرفی گرفته بودند و مثلاً گفته بودن لابد کاسه‌ای زیر نیم کاسه است که فلانی یعنی من، با ده سال سابقه‌ی تدریس، می‌خواهد مدیر دبستان بشود! غرض‌شان این بود که لابد خل شدم که از شغل مهم و محترم دبیری دست می‌شویم. ماهی صد و پنجاه تومان حق مقام در آن روزها پولی نبود که بتوانم نادیده بگیرم. و تازه اگر ندیده می‌گرفتم چه؟ باز باید بر می‌گشتم به این کلاس‌ها و این جور حماقت‌ها. این بود که پیش رئیس فرهنگ، صاف برگشتم به کارگزینی کل، سراغ آن که بفهمی نفهمی، دلال کارم بود. و رونویس حکم را گذاشتم و گفتم که چه طور شد و آمدم بیرون. + +دو روز بعد رفتم سراغش. معلوم شد که حدسم درست بوده است و رئیس فرهنگ گفته بوده: «من از این لیسانسه‌های پر افاده نمی‌خواهم که سیگار به دست توی هر اتاقی سر می‌کنند.» + +و یارو برایش گفته بود که اصلاً وابدا..! فلانی همچین و همچون است و مثقالی هفت صنار با دیگران فرق دارد و این هندوانه‌ها و خیال من راحت باشد و پنج‌شنبه یک هفته‌ی دیگر خودم بروم پهلوی او... و این کار را کردم. این بار رئیس فرهنگ جلوی پایم بلند شد که: «ای آقا... چرا اول نفرمودید؟!...» و از کارمندهایش گله کرد و به قول خودش، مرا «در جریان موقعیت محل» گذاشت و بعد با ماشین خودش مرا به مدرسه رساند و گفت زنگ را زودتر از موعد زدند و در حضور معلم‌ها و ناظم، نطق غرایی در خصائل مدیر جدید – که من باشم – کرد و بعد هم مرا گذاشت و رفت با یک مدرسه‌ی شش کلاسه‌ی «نوبنیاد» و یک ناظم و هفت تا معلم و دویست و سی و پنج تا شاگرد. دیگر حسابی مدیر مدرسه شده بودم! + +ناظم، جوان رشیدی بود که بلند حرف می‌زد و به راحتی امر و نهی می‌کرد و بیا و برویی داشت و با شاگردهای درشت، روی هم ریخته بود که خودشان ترتیب کارها را می‌دادند و پیدا بود که به سر خر احتیاجی ندارد و بی‌مدیر هم می‌تواند گلیم مدرسه را از آب بکشد. معلم کلاس چهار خیلی گنده بود. دو تای یک آدم حسابی. توی دفتر، اولین چیزی که به چشم می‌آمد. از آن‌هایی که اگر توی کوچه ببینی، خیال می‌کنی مدیر کل است. لفظ قلم حرف می‌زد و شاید به همین دلیل بود که وقتی رئیس فرهنگ رفت و تشریفات را با خودش برد، از طرف همکارانش تبریک ورود گفت و اشاره کرد به اینکه «ان‌شاءالله زیر سایه‌ی سرکار، سال دیگر کلاس‌های دبیرستان را هم خواهیم داشت.» پیدا بود که این هیکل کم‌کم دارد از سر دبستان زیادی می‌کند! وقتی حرف می‌زد همه‌اش درین فکر بودم که با نان آقا معلمی چه طور می‌شد چنین هیکلی به هم زد و چنین سر و تیپی داشت؟ و راستش تصمیم گرفتم که از فردا صبح به صبح ریشم را بتراشم و یخه‌ام تمیز باشد و اتوی شلوارم تیز. + +معلم کلاس اول باریکه‌ای بود، سیاه سوخته. با ته ریشی و سر ماشین کرده‌ای و یخه‌ی بسته. بی‌کراوات. شبیه میرزابنویس‌های دم پست‌خانه. حتی نوکر باب می‌نمود. و من آن روز نتوانستم بفهمم وقتی حرف می‌زند کجا را نگاه می‌کند. با هر جیغ کوتاهی که می‌زد هرهر می‌خندید. با این قضیه نمی‌شد کاری کرد. معلم کلاس سه، یک جوان ترکه‌ای بود؛ بلند و با صورت استخوانی و ریش از ته تراشیده و یخه‌ی بلند آهاردار. مثل فرفره می‌جنبید. چشم‌هایش برق عجیبی می‌زد که فقط از هوش نبود، چیزی از ناسلامتی در برق چشم‌هایش بود که مرا واداشت از ناظم بپرسم مبادا مسلول باشد. البته مسلول نبود، تنها بود و در دانشگاه درس می‌خواند. کلاس‌های پنجم و ششم را دو نفر با هم اداره می‌کردند. یکی فارسی و شرعیات و تاریخ، جغرافی و کاردستی و این جور سرگرمی‌ها را می‌گفت، که جوانکی بود بریانتین زده، با شلوار پاچه تنگ و پوشت و کراوات زرد و پهنی که نعش یک لنگر بزرگ آن را روی سینه‌اش نگه داشته بود و دائماً دستش حمایل موهای سرش بود و دم به دم توی شیشه‌ها نگاه می‌کرد. و آن دیگری که حساب و مرابحه و چیزهای دیگر می‌گفت، جوانی بود موقر و سنگین مازندرانی به نظر می‌آمد و به خودش اطمینان داشت. غیر از این‌ها، یک معلم ورزش هم داشتیم که دو هفته بعد دیدمش و اصفهانی بود و از آن قاچاق‌ها. + +رئیس فرهنگ که رفت، گرم و نرم از همه‌شان حال و احوال پرسیدم. بعد به همه سیگار تعارف کردم. سراپا همکاری و همدردی بود. از کار و بار هر کدامشان پرسیدم. فقط همان معلم کلاس سه، دانشگاه می‌رفت. آن که لنگر به سینه انداخته بود، شب‌ها انگلیسی می‌خواند که برود آمریکا. چای و بساطی در کار نبود و ربع ساعت‌های تفریح، فقط توی دفتر جمع می‌شدند و دوباره از نو. و این نمی‌شد. باید همه‌ی سنن را رعایت کرد. دست کردم و یک پنج تومانی روی میز گذاشتم و قرار شد قبل و منقلی تهیه کنند و خودشان چای را راه بیندازند. + +بعد از زنگ قرار شد من سر صف نطقی بکنم. ناظم قضیه را در دو سه کلمه برای بچه‌ها گفت که من رسیدم و همه دست زدند. چیزی نداشتم برایشان بگویم. فقط یادم است اشاره‌ای به این کردم که مدیر خیلی دلش می‌خواست یکی از شما را به جای فرزند داشته باشد و حالا نمی‌داند با این همه فرزند چه بکند؟! که بی‌صدا خندیدند و در میان صف‌های عقب یکی پکی زد به خنده. واهمه برم داشت که «نه بابا. کار ساده‌ای هم نیست!» قبلاً فکر کرده بودم که می‌روم و فارغ از دردسر اداره‌ی کلاس، در اتاق را روی خودم می‌بندم و کار خودم را می‌کنم. اما حالا می‌دیدم به این سادگی‌ها هم نیست. اگر فردا یکی‌شان زد سر اون یکی را شکست، اگر یکی زیر ماشین رفت؛ اگر یکی از ایوان افتاد؛ چه خاکی به سرم خواهم ریخت؟ + +حالا من مانده بودم و ناظم که چیزی از لای در آهسته خزید تو. کسی بود؛ فراش مدرسه با قیافه‌ای دهاتی و ریش نتراشیده و قدی کوتاه و گشاد گشاد راه می‌رفت و دست‌هایش را دور از بدن نگه می‌داشت. آمد و همان کنار در ایستاد. صاف توی چشمم نگاه می‌کرد. حال او را هم پرسیدم. هر چه بود او هم می‌توانست یک گوشه‌ی این بار را بگیرد. در یک دقیقه همه‌ی درد دل‌هایش را کرد و التماس دعاهایش که تمام شد، فرستادمش برایم چای درست کند و بیاورد. بعد از آن من به ناظم پرداختم. سال پیش، از دانشسرای مقدماتی در آمده بود. یک سال گرمسار و کرج کار کرده بود و امسال آمده بود این‌جا. پدرش دو تا زن داشته. از اولی دو تا پسر که هر دو تا چاقوکش از آب در آمده‌اند و از دومی فقط او مانده بود که درس‌خوان شده و سرشناس و نان مادرش را می‌دهد که مریض است و از پدر سال‌هاست که خبری نیست و... یک اتاق گرفته‌اند به پنجاه تومان و صد و پنجاه تومان حقوق به جایی نمی‌رسد و تازه زور که بزند سه سال دیگر می‌تواند از حق فنی نظامت مدرسه استفاده کند + +... بعد بلند شدیم که به کلاس‌ها سرکشی کنیم. بعد با ناظم به تک تک کلاس‌ها سر زدیم در این میان من به یاد دوران دبستان خودم افتادم. در کلاس ششم را باز کردیم «... ت بی پدرو مادر» جوانک بریانتین زده خورد توی صورت‌مان. یکی از بچه‌ها صورتش مثل چغندر قرمز بود. لابد بزک فحش هنوز باقی بود. قرائت فارسی داشتند. معلم دستهایش توی جیبش بود و سینه‌اش را پیش داده بود و زبان به شکایت باز کرد: + +- آقای مدیر! اصلاً دوستی سرشون نمی‌شه. تو سَری می‌خوان. ملاحظه کنید بنده با چه صمیمیتی... + +حرفش را در تشدید «ایت» بریدم که: + +- صحیح می‌فرمایید. این بار به من ببخشید. + +و از در آمدیم بیرون. بعد از آن به اطاقی که در آینده مال من بود سر زدیم. بهتر از این نمی‌شد. بی سر و صدا، آفتاب‌رو، دور افتاده. + +وسط حیاط، یک حوض بزرگ بود و کم‌عمق. تنها قسمت ساختمان بود که رعایت حال بچه‌های قد و نیم قد در آن شده بود. دور حیاط دیوار بلندی بود درست مثل دیوار چین. سد مرتفعی در مقابل فرار احتمالی فرهنگ و ته حیاط مستراح و اتاق فراش بغلش و انبار زغال و بعد هم یک کلاس. به مستراح هم سر کشیدیم. همه بی در و سقف و تیغه‌ای میان آن‌ها. نگاهی به ناظم کردم که پا به پایم می‌آمد. گفت: + +- دردسر عجیبی شده آقا. تا حالا صد تا کاغذ به ادارفردا صبح رفتم مدرسه. بچه‌ها با صف‌هاشان به طرف کلاس‌ها می‌رفتند و ناظم چوب به دست توی ایوان ایستاده بود و توی دفتر دو تا از معلم‌ها بودند. معلوم شد کار هر روزه‌شان است. ناظم را هم فرستادم سر یک کلاس دیگر و خودم آمدم دم در مدرسه به قدم زدن؛ فکر کردم از هر طرف که بیایند مرا این ته، دم در مدرسه خواهند دید و تمام طول راه در این خجالت خواهند ماند و دیگر دیر نخواهند آمد. یک سیاهی از ته جاده‌ی جنوبی پیداشد. جوانک بریانتین زده بود. مسلماً او هم مرا می‌دید، ولی آهسته‌تر از آن می‌آمد که یک معلم تأخیر کرده جلوی مدیرش می‌آمد. جلوتر که آمد حتی شنیدم که سوت می‌زد. اما بی‌انصاف چنان سلانه سلانه می‌آمد که دیدم هیچ جای گذشت نیست. اصلاً محل سگ به من نمی‌گذاشت. داشتم از کوره در می‌رفتم که یک مرتبه احساس کردم تغییری در رفتار خود داد و تند کرد. + +به خیر گذشت و گرنه خدا عالم است چه اتفاقی می‌افتاد. سلام که کرد مثل این که می‌خواست چیزی بگوید که پیش دستی کردم: + +- بفرمایید آقا. بفرمایید، بچه‌ها منتظرند. + +واقعاً به خیر گذشت. شاید اتوبوسش دیر کرده. شاید راه‌بندان بوده؛ جاده قرق بوده و باز یک گردن‌کلفتی از اقصای عالم می‌آمده که ازین سفره‌ی مرتضی علی بی‌نصیب نماند. به هر صورت در دل بخشیدمش. چه خوب شد که بد و بی‌راهی نگفتی! که از دور علم افراشته‌ی هیکل معلم کلاس چهارم نمایان شد. از همان ته مرا دیده بود. تقریباً می‌دوید. تحمل این یکی را نداشتم. «بدکاری می‌کنی. اول بسم‌الله و مته به خشخاش!» رفتم و توی دفتر نشستم و خودم را به کاری مشغول کردم که هن هن کنان رسید. چنان عرق از پیشانی‌اش می‌ریخت که راستی خجالت کشیدم. یک لیوان آب از کوه به دستش دادم و مسخ‌شده‌ی خنده‌اش را با آب به خوردش دادم و بلند که شد برود، گفتم: + +- عوضش دو کیلو لاغر شدید. + +برگشت نگاهی کرد و خنده‌ای و رفت. ناگهان ناظم از در وارد شد و از را ه نرسیده گفت: + +- دیدید آقا! این جوری می‌آند مدرسه. اون قرتی که عین خیالش هم نبود آقا! اما این یکی... + +از او پرسیدم: + +- انگار هنوز دو تا از کلاس‌ها ولند؟ + +- بله آقا. کلاس سه ورزش دارند. گفتم بنشینند دیکته بنویسند آقا. معلم حساب پنج و شش هم که نیومده آقا. + +در همین حین یکی از عکس‌های بزرگ دخمه‌های هخامنشی را که به دیوار کوبیده بود پس زد و: + +- نگاه کنید آقا... + +روی گچ دیوار با مداد قرمز و نه چندان درشت، به عجله و ناشیانه علامت داس کشیده بودند. همچنین دنبال کرد: + +- از آثار دوره‌ی اوناست آقا. کارشون همین چیزها بود. روزنومه بفروشند. تبلیغات کنند و داس چکش بکشند آقا. رئیس‌شون رو که گرفتند چه جونی کندم آقا تا حالی‌شون کنم که دست ور دارند آقا. و از روی میز پرید پایین. + +- گفتم مگه باز هم هستند؟ + +- آره آقا، پس چی! یکی همین آقازاده که هنوز نیومده آقا. هر روز نیم ساعت تأخیر داره آقا. یکی هم مثل کلاس سه. + +- خوب چرا تا حالا پاکش نکردی؟ + +- به! آخه آدم درد دلشو واسه‌ی کی بگه؟ آخه آقا در میان تو روی آدم می‌گند جاسوس، مأمور! باهاش حرفم شده آقا. کتک و کتک‌کاری! + +و بعد یک سخنرانی که چه طور مدرسه را خراب کرده‌اند و اعتماد اهل محله را چه طور از بین برده‌اند که نه انجمنی، نه کمکی به بی‌بضاعت‌ها؛ و از این حرف ها. + +بعد از سخنرانی آقای ناظم دستمالم را دادم که آن عکس‌ها را پاک کند و بعد هم راه افتادم که بروم سراغ اتاق خودم. در اتاقم را که باز کردم، داشتم دماغم با بوی خاک نم کشیده‌اش اخت می‌کرد که آخرین معلم هم آمد. آمدم توی ایوان و با صدای بلند، جوری که در تمام مدرسه بشنوند، ناظم را صدا زدم و گفتم با قلم قرمز برای آقا یک ساعت تأخیر بگذارند.ه‌ی ساختمان نوشتیم آقا. می‌گند نمی‌شه پول دولت رو تو ملک دیگرون خرج کرد. + +- گفتم راست می‌گند. + +دیگه کافی بود. آمدیم بیرون. همان توی حیاط تا نفسی تازه کنیم وضع مالی و بودجه و ازین حرف‌های مدرسه را پرسیدم. هر اتاق ماهی پانزده ریال حق نظافت داشت. لوازم‌التحریر و دفترها را هم اداره‌ی فرهنگ می‌داد. ماهی بیست و پنج تومان هم برای آب خوردن داشتند که هنوز وصول نشده بود. برای نصب هر بخاری سالی سه تومان. ماهی سی تومان هم تنخواه‌گردان مدرسه بود که مثل پول آب سوخت شده بود و حالا هم ماه دوم سال بود. اواخر آبان. حالیش کردم که حوصله‌ی این کارها را ندارم و غرضم را از مدیر شدن برایش خلاصه کردم و گفتم حاضرم همه‌ی اختیارات را به او بدهم. «اصلاً انگار که هنوز مدیر نیامده.» مهر مدرسه هم پهلوی خودش باشد. البته او را هنوز نمی‌شناختم. شنیده بودم که مدیرها قبلاً ناظم خودشان را انتخاب می‌کنند، اما من نه کسی را سراغ داشتم و نه حوصله‌اش را. حکم خودم را هم به زور گرفته بودم. سنگ‌هامان را وا کندیم و به دفتر رفتیم و چایی را که فراش از بساط خانه‌اش درست کرده بود، خوردیم تا زنگ را زدند و باز هم زدند و من نگاهی به پرونده‌های شاگردها کردم که هر کدام عبارت بود از دو برگ کاغذ. از همین دو سه برگ کاغذ دانستم که اولیای بچه‌ها اغلب زارع و باغبان و اویارند و قبل از این‌که زنگ آخر را بزنند و مدرسه تعطیل بشود بیرون آمدم. برای روز اول خیلی زیاد بود. + +فردا صبح رفتم مدرسه. بچه‌ها با صف‌هاشان به طرف کلاس‌ها می‌رفتند و ناظم چوب به دست توی ایوان ایستاده بود و توی دفتر دو تا از معلم‌ها بودند. معلوم شد کار هر روزه‌شان است. ناظم را هم فرستادم سر یک کلاس دیگر و خودم آمدم دم در مدرسه به قدم زدن؛ فکر کردم از هر طرف که بیایند مرا این ته، دم در مدرسه خواهند دید و تمام طول راه در این خجالت خواهند ماند و دیگر دیر نخواهند آمد. یک سیاهی از ته جاده‌ی جنوبی پیداشد. جوانک بریانتین زده بود. مسلماً او هم مرا می‌دید، ولی آهسته‌تر از آن می‌آمد که یک معلم تأخیر کرده جلوی مدیرش می‌آمد. جلوتر که آمد حتی شنیدم که سوت می‌زد. اما بی‌انصاف چنان سلانه سلانه می‌آمد که دیدم هیچ جای گذشت نیست. اصلاً محل سگ به من نمی‌گذاشت. داشتم از کوره در می‌رفتم که یک مرتبه احساس کردم تغییری در رفتار خود داد و تند کرد. + +به خیر گذشت و گرنه خدا عالم است چه اتفاقی می‌افتاد. سلام که کرد مثل این که می‌خواست چیزی بگوید که پیش دستی کردم: + +- بفرمایید آقا. بفرمایید، بچه‌ها منتظرند. + +واقعاً به خیر گذشت. شاید اتوبوسش دیر کرده. شاید راه‌بندان بوده؛ جاده قرق بوده و باز یک گردن‌کلفتی از اقصای عالم می‌آمده که ازین سفره‌ی مرتضی علی بی‌نصیب نماند. به هر صورت در دل بخشیدمش. چه خوب شد که بد و بی‌راهی نگفتی! که از دور علم افراشته‌ی هیکل معلم کلاس چهارم نمایان شد. از همان ته مرا دیده بود. تقریباً می‌دوید. تحمل این یکی را نداشتم. «بدکاری می‌کنی. اول بسم‌الله و مته به خشخاش!» رفتم و توی دفتر نشستم و خودم را به کاری مشغول کردم که هن هن کنان رسید. چنان عرق از پیشانی‌اش می‌ریخت که راستی خجالت کشیدم. یک لیوان آب از کوه به دستش دادم و مسخ‌شده‌ی خنده‌اش را با آب به خوردش دادم و بلند که شد برود، گفتم: + +- عوضش دو کیلو لاغر شدید. + +برگشت نگاهی کرد و خنده‌ای و رفت. ناگهان ناظم از در وارد شد و از را ه نرسیده گفت: + +- دیدید آقا! این جوری می‌آند مدرسه. اون قرتی که عین خیالش هم نبود آقا! اما این یکی... + +از او پرسیدم: + +- انگار هنوز دو تا از کلاس‌ها ولند؟ + +- بله آقا. کلاس سه ورزش دارند. گفتم بنشینند دیکته بنویسند آقا. معلم حساب پنج و شش هم که نیومده آقا. + +در همین حین یکی از عکس‌های بزرگ دخمه‌های هخامنشی را که به دیوار کوبیده بود پس زد و: + +- نگاه کنید آقا... + +روی گچ دیوار با مداد قرمز و نه چندان درشت، به عجله و ناشیانه علامت داس کشیده بودند. همچنین دنبال کرد: + +- از آثار دوره‌ی اوناست آقا. کارشون همین چیزها بود. روزنومه بفروشند. تبلیغات کنند و داس چکش بکشند آقا. رئیس‌شون رو که گرفتند چه جونی کندم آقا تا حالی‌شون کنم که دست ور دارند آقا. و از روی میز پرید پایین. + +- گفتم مگه باز هم هستند؟ + +- آره آقا، پس چی! یکی همین آقازاده که هنوز نیومده آقا. هر روز نیم ساعت تأخیر داره آقا. یکی هم مثل کلاس سه. + +- خوب چرا تا حالا پاکش نکردی؟ + +- به! آخه آدم درد دلشو واسه‌ی کی بگه؟ آخه آقا در میان تو روی آدم می‌گند جاسوس، مأمور! باهاش حرفم شده آقا. کتک و کتک‌کاری! + +و بعد یک سخنرانی که چه طور مدرسه را خراب کرده‌اند و اعتماد اهل محله را چه طور از بین برده‌اند که نه انجمنی، نه کمکی به بی‌بضاعت‌ها؛ و از این حرف ها. + +بعد از سخنرانی آقای ناظم دستمالم را دادم که آن عکس‌ها را پاک کند و بعد هم راه افتادم که بروم سراغ اتاق خودم. در اتاقم را که باز کردم، داشتم دماغم با بوی خاک نم کشیده‌اش اخت می‌کرد که آخرین معلم هم آمد. آمدم توی ایوان و با صدای بلند، جوری که در تمام مدرسه بشنوند، ناظم را صدا زدم و گفتم با قلم قرمز برای آقا یک ساعت تأخیر بگذارند. + +روز سوم باز اول وقت مدرسه بودم. هنوز از پشت دیوار نپیچیده بودم که صدای سوز و بریز بچه‌ها به پیشبازم آمد. تند کردم. پنج تا از بچه‌ها توی ایوان به خودشان می‌پیچیدند و ناظم ترکه‌ای به دست داشت و به نوبت به کف دست‌شان می‌زد. بچه‌ها التماس می‌کردند؛ گریه می‌کردند؛ اما دستشان را هم دراز می‌کردند. نزدیک بود داد بزنم یا با لگد بزنم و ناظم را پرت کنم آن طرف. پشتش به من بود و من را نمی‌دید. ناگهان زمزمه‌ای توی صف‌ها افتاد که یک مرتبه مرا به صرافت انداخت که در مقام مدیریت مدرسه، به سختی می‌شود ناظم را کتک زد. این بود که خشمم را فرو خوردم و آرام از پله‌ها رفتم بالا. ناظم، تازه متوجه من شده بود در همین حین دخالتم را کردم و خواهش کردم این بار همه‌شان را به من ببخشند. + +نمی‌دانم چه کار خطایی از آنها سر زده بود که ناظم را تا این حد عصبانی کرده بود. بچه‌ها سکسکه‌کنان رفتند توی صف‌ها و بعد زنگ را زدند و صف‌ها رفتند به کلاس‌ها و دنبالشان هم معلم‌ها که همه سر وقت حاضر بودند. نگاهی به ناظم انداختم که تازه حالش سر جا آمده بود و گفتم در آن حالی که داشت، ممکن بود گردن یک کدامشان را بشکند. که مرتبه براق شد: + +- اگه یک روز جلوشونو نگیرید سوارتون می‌شند آقا. نمی‌دونید چه قاطرهای چموشی شده‌اند آقا. + +مثل بچه مدرسه‌ای‌ها آقا آقا می‌کرد. موضوع را برگرداندم و احوال مادرش را پرسیدم. خنده، صورتش را از هم باز کرد و صدا زد فراش برایش آب بیاورد. یادم هست آن روز نیم ساعتی برای آقای ناظم صحبت کردم. پیرانه. و او جوان بود و زود می‌شد رامش کرد. بعد ازش خواستم که ترکه‌ها را بشکند و آن وقت من رفتم سراغ اتاق خودم. + +در همان هفته‌ی اول به کارها وارد شدم. فردای زمستان و نه تا بخاری زغال سنگی و روزی چهار بار آب آوردن و آب و جاروی اتاق‌ها با یک فراش جور در نمی‌آید. یک فراش دیگر از اداره ی فرهنگ خواستم که هر روز منتظر ورودش بودیم. بعد از ظهرها را نمی‌رفتم. روزهای اول با دست و دل لرزان، ولی سه چهار روزه جرأت پیدا کردم. احساس می‌کردم که مدرسه زیاد هم محض خاطر من نمی‌گردد. کلاس اول هم یکسره بود و به خاطر بچه‌های جغله دلهره‌ای نداشتم. در بیابان‌های اطراف مدرسه هم ماشینی آمد و رفت نداشت و گرچه پست و بلند بود اما به هر صورت از حیاط مدرسه که بزرگ‌تر بود. معلم ها هم، هر بعد از ظهری دو تاشان به نوبت می‌رفتند یک جوری باهم کنار آمده بودند. و ترسی هم از این نبود که بچه‌ها از علم و فرهنگ ثقل سرد بکنند. یک روز هم بازرس آمد و نیم ساعتی پیزر لای پالان هم گذاشتیم و چای و احترامات متقابل! و در دفتر بازرسی تصدیق کرد که مدرسه «با وجود عدم وسایل» بسیار خوب اداره می‌شود. + +بچه‌ها مدام در مدرسه زمین می‌خوردند، بازی می‌کردند، زمین می‌خوردند. مثل اینکه تاتوله خورده بودند. ساده‌ترین شکل بازی‌هایشان در ربع ساعت‌های تفریح، دعوا بود. فکر می‌کردم علت این همه زمین خوردن شاید این باشد که بیش‌ترشان کفش حسابی ندارند. آن‌ها هم که داشتند، بچه‌ننه بودند و بلد نبودند بدوند و حتی راه بروند. این بود که روزی دو سه بار، دست و پایی خراش بر می‌داشت. پرونده‌ی برق و تلفن مدرسه را از بایگانی بسیار محقر مدرسه بیرون کشیده بودم و خوانده بودم. اگر یک خرده می‌دویدی تا دو سه سال دیگر هم برق مدرسه درست می‌شد و هم تلفنش. دوباره سری به اداره ساختمان زدم و موضوع را تازه کردم و به رفقایی که دورادور در اداره‌ی برق و تلفن داشتم، یکی دو بار رو انداختم که اول خیال می‌کردند کار خودم را می‌خواهم به اسم مدرسه راه بیندازم و ناچار رها کردم. این قدر بود که ادای وظیفه‌ای می‌کرد. مدرسه آب نداشت. نه آب خوراکی و نه آب جاری. با هرزاب بهاره، آب انبار زیر حوض را می‌انباشتند که تلمبه‌ای سرش بود و حوض را با همان پر می‌کردند و خود بچه‌ها. اما برای آب خوردن دو تا منبع صد لیتری داشتیم از آهن سفید که مثل امامزاده‌ای یا سقاخانه‌ای دو قلو، روی چهار پایه کنار حیاط بود و روزی دو بار پر و خالی می‌شد. این آب را از همان باغی می‌آوردیم که ردیف کاج‌هایش روی آسمان، لکه‌ی دراز سیاه انداخته بود. البته فراش می‌آورد. با یک سطل بزرگ و یک آب‌پاش که سوراخ بود و تا به مدرسه می‌رسید، نصف شده بود. هر دو را از جیب خودم دادم تعمیر کردند. + +یک روز هم مالک مدرسه آمد. پیرمردی موقر و سنگین که خیال می‌کرد برای سرکشی به خانه‌ی مستأجرنشینش آمده. از در وارد نشده فریادش بلند شد و فحش را کشید به فراش و به فرهنگ که چرا بچه‌ها دیوار مدرسه را با زغال سیاه کرده‌اند واز همین توپ و تشرش شناختمش. کلی با او صحبت کردیم البته او دو برابر سن من را داشت. برایش چای هم آوردیم و با معلم‌ها آشنا شد و قول‌ها داد و رفت. کنه‌ای بود. درست یک پیرمرد. یک ساعت و نیم درست نشست. ماهی یک بار هم این برنامه را داشتند که بایست پیه‌اش را به تن می‌مالیدم. + +اما معلم‌ها. هر کدام یک ابلاغ بیست و چهار ساعته در دست داشتند، ولی در برنامه به هر کدام‌شان بیست ساعت درس بیشتر نرسیده بود. کم کم قرار شد که یک معلم از فرهنگ بخواهیم و به هر کدام‌شان هجده ساعت درس بدهیم، به شرط آن‌که هیچ بعد از ظهری مدرسه تعطیل نباشد. حتی آن که دانشگاه می‌رفت می‌توانست با هفته‌ای هجده ساعت درس بسازد. و دشوارترین کار همین بود که با کدخدامنشی حل شد و من یک معلم دیگر از فرهنگ خواستم. + +اواخر هفته‌ی دوم، فراش جدید آمد. مرد پنجاه ساله‌ای باریک و زبر و زرنگ که شب‌کلاه می‌گذاشت و لباس آبی می‌پوشید و تسبیح می‌گرداند و از هر کاری سر رشته داشت. آب خوردن را نوبتی می‌آوردند. مدرسه تر و تمیز شد و رونقی گرفت. فراش جدید سرش توی حساب بود. هر دو مستخدم با هم تمام بخاری‌ها را راه انداختند و یک کارگر هم برای کمک به آن‌ها آمد. فراش قدیمی را چهار روز پشت سر هم، سر ظهر می‌فرستادیم اداره‌ی فرهنگ و هر آن منتظر زغال بودیم. هنوز یک هفته از آمدن فراش جدید نگذشته بود که صدای همه‌ی معلم‌ها در آمده بود. نه به هیچ کدامشان سلام می‌کرد و نه به دنبال خرده فرمایش‌هایشان می‌رفت. درست است که به من سلام می‌کرد، اما معلم‌ها هم، لابد هر کدام در حدود من صاحب فضایل و عنوان و معلومات بودند که از یک فراش مدرسه توقع سلام داشته باشند. اما انگار نه انگار. + +بدتر از همه این که سر خر معلم‌ها بود. من که از همان اول، خرجم را سوا کرده بودم و آن‌ها را آزاد گذاشته بودم که در مواقع بیکاری در دفتر را روی خودشان ببندند و هر چه می‌خواهند بگویند و هر کاری می‌خواهند بکنند. اما او در فاصله‌ی ساعات درس، همچه که معلم‌ها می‌آمدند، می‌آمد توی دفتر و همین طوری گوشه‌ی اتاق می‌ایستاد و معلم‌ها کلافه می‌شدند. نه می‌توانستند شلکلک‌های معلمی‌شان را در حضور او کنار بگذارند و نه جرأت می‌کردند به او چیزی بگویند. بدزبان بود و از عهده‌ی همه‌شان بر می‌آمد. یکی دوبار دنبال نخود سیاه فرستاده بودندش. اما زرنگ بود و فوری کار را انجام می‌داد و بر می‌گشت. حسابی موی دماغ شده بود. ده سال تجربه این حداقل را به من آموخته بود که اگر معلم‌ها در ربع ساعت‌های تفریح نتوانند بخندند، سر کلاس، بچه‌های مردم را کتک خواهند زد. این بود که دخالت کردم. یک روز فراش جدید را صدا زدم. اول حال و احوالپرسی و بعد چند سال سابقه دارد و چند تا بچه و چه قدر می‌گیرد... که قضیه حل شد. سی صد و خرده‌ای حقوق می‌گرفت. با بیست و پنج سال سابقه. کار از همین جا خراب بود. پیدا بود که معلم‌ها حق دارند او را غریبه بدانند. نه دیپلمی، نه کاغذپاره‌ای، هر چه باشد یک فراش که بیشتر نبود! و تازه قلدر هم بود و حق هم داشت. اول به اشاره و کنایه و بعد با صراحت بهش فهماندم که گر چه معلم جماعت اجر دنیایی ندارد، اما از او که آدم متدین و فهمیده‌ای است بعید است و از این حرف‌ها... که یک مرتبه پرید توی حرفم که: + +- ای آقا! چه می‌فرمایید؟ شما نه خودتون این کاره‌اید و نه اینارو می‌شناسید. امروز می‌خواند سیگار براشون بخرم، فردا می‌فرستنم سراغ عرق. من این‌ها رو می‌شناسم. + +راست می‌گفت. زودتر از همه، او دندان‌های مرا شمرده بود. فهمیده بود که در مدرسه هیچ‌کاره‌ام. می‌خواستم کوتاه بیایم، ولی مدیر مدرسه بودن و در مقابل یک فراش پررو ساکت ماندن!... که خر خر کامیون زغال به دادم رسید. ترمز که کرد و صدا خوابید گفتم: + +- این حرف‌ها قباحت داره. معلم جماعت کجا پولش به عرق می‌رسه؟ حالا بدو زغال آورده‌اند. + +و همین طور که داشت بیرون می‌رفت، افزودم: + +- دو روز دیگه که محتاجت شدند و ازت قرض خواستند با هم رفیق می‌شید. + +و آمدم توی ایوان. در بزرگ آهنی مدرسه را باز کرده بودند و کامیون آمده بود تو و داشتند بارش را جلوی انبار ته حیاط خالی می‌کردند و راننده، کاغذی به دست ناظم داد که نگاهی به آن انداخت و مرا نشان داد که در ایوان بالا ایستاده بودم و فرستادش بالا. کاغذش را با سلام به دستم داد. بیجک زغال بود. رسید رسمی اداره‌ی فرهنگ بود در سه نسخه و روی آن ورقه‌ی ماشین شده‌ی «باسکول» که می‌گفت کامیون و محتویاتش جمعاً دوازده خروار است. اما رسیدهای رسمی اداری فرهنگ ساکت بودند. جای مقدار زغالی که تحویل مدرسه داده شده بود، در هر سه نسخه خالی بود. پیدا بود که تحویل گیرنده باید پرشان کند. همین کار را کردم. اوراق را بردم توی اتاق و با خودنویسم عدد را روی هر سه ورق نوشتم و امضا کردم و به دست راننده دادم که راه افتاد و از همان بالا به ناظم گفتم: + +- اگر مهر هم بایست زد، خودت بزن بابا. + +و رفتم سراغ کارم که ناگهان در باز شد و ناظم آمد تو؛ بیجک زغال دستش بود و: + +- مگه نفهمیدین آقا؟ مخصوصاً جاش رو خالی گذاشته بودند آقا... + +نفهمیده بودم. اما اگر هم فهمیده بودم، فرقی نمی‌کرد و به هر صورت از چنین کودنی نا به هنگام از جا در رفتم و به شدت گفتم: + +- خوب؟ + +- هیچ چی آقا.... رسم‌شون همینه آقا. اگه باهاشون کنار نیایید کارمونو لنگ می‌گذارند آقا... + +که از جا در رفتم. به چنین صراحتی مرا که مدیر مدرسه بودم در معامله شرکت می‌داد. و فریاد زدم: + +- عجب! حالا سرکار برای من تکلیف هم معین می‌کنید؟... خاک بر سر این فرهنگ با مدیرش که من باشم! برو ورقه رو بده دست‌شون، گورشون رو گم کنند. پدر سوخته‌ها... + +چنان فریاد زده بودم که هیچ کس در مدرسه انتظار نداشت. مدیر سر به زیر و پا به راهی بودم که از همه خواهش می‌کردم و حالا ناظم مدرسه، داشت به من یاد می‌داد که به جای نه خروار زغال مثلا هجده خروار تحویل بگیرم و بعد با اداره‌ی فرهنگ کنار بیایم. هی هی!.... تا ظهر هیچ کاری نتوانستم بکنم، جز این‌که چند بار متن استعفانامه‌ام را بنویسم و پاره کنم... قدم اول را این جور جلوی پای آدم می‌گذارند. + +بارندگی که شروع شد دستور دادم بخاری‌ها را از هفت صبح بسوزانند. بچه‌ها همیشه زود می‌آمدند. حتی روزهای بارانی. مثل این‌که اول آفتاب از خانه بیرون‌شان می‌کنند. یا ناهارنخورده. خیلی سعی کردم یک روز زودتر از بچه‌ها مدرسه باشم. اما عاقبت نشد که مدرسه را خالی از نفسِ به علم‌آلوده‌ی بچه‌ها استنشاق کنم. از راه که می‌رسیدند دور بخاری جمع می‌شدند و گیوه‌هاشان را خشک می‌کردند. و خیلی زود فهمیدم که ظهر در مدرسه ماندن هم مسأله کفش بود. هر که داشت نمی‌ماند.این قاعده در مورد معلم‌ها هم صدق می‌کرد اقلاً یک پول واکس جلو بودند. وقتی که باران می‌بارید تمام کوهپایه و بدتر از آن تمام حیاط مدرسه گل می‌شد. بازی و دویدن متوقف شده بود. مدرسه سوت و کور بود. این جا هم مسأله کفش بود. چشم اغلبشان هم قرمز بود. پیدا بود باز آن روز صبح یک فصل گریه کرده‌اند و در خانه‌شان علم صراطی بوده است. + +مدرسه داشت تخته می‌شد. عده‌ی غایب‌های صبح ده برابر شده بود و ساعت اول هیچ معلمی نمی‌توانست درس بدهد. دست‌های ورم‌کرده و سرمازده کار نمی‌کرد. حتی معلم کلاس اولمان هم می‌دانست که فرهنگ و معلومات مدارس ما صرفاً تابع تمرین است. مشق و تمرین. ده بار بیست بار. دست یخ‌کرده بیل و رنده را هم نمی‌تواند به کار بگیرد که خیلی هم زمخت‌اند و دست پر کن. این بود که به فکر افتادیم. فراش جدید واردتر از همه‌ی ما بود. یک روز در اتاق دفتر، شورامانندی داشتیم که البته او هم بود. خودش را کم‌کم تحمیل کرده بود. گفت حاضر است یکی از دُم‌کلفت‌های همسایه‌ی مدرسه را وادارد که شن برایمان بفرستد به شرط آن که ما هم برویم و از انجمن محلی برای بچه‌ها کفش و لباس بخواهیم. قرار شد خودش قضیه را دنبال کند که هفته‌ی آینده جلسه‌شان کجاست و حتی بخواهد که دعوت‌مانندی از ما بکنند. دو روز بعد سه تا کامیون شن آمد. دوتایش را توی حیاط مدرسه، خالی کردیم و سومی را دم در مدرسه، و خود بچه‌ها نیم ساعته پهنش کردند. با پا و بیل و هر چه که به دست می‌رسید. + +عصر همان روز ما را به انجمن دعوت کردند. خود من و ناظم باید می‌رفتیم. معلم کلاس چهارم را هم با خودمان بردیم. خانه‌ای که محل جلسه‌ی آن شب انجمن بود، درست مثل مدرسه، دور افتاده و تنها بود. قالی‌ها و کناره‌ها را به فرهنگ می‌آلودیم و می‌رفتیم. مثل این‌که سه تا سه تا روی هم انداخته بودند. اولی که کثیف شد دومی. به بالا که رسیدیم یک حاجی آقا در حال نماز خواندن بود. و صاحب‌خانه با لهجه‌ی غلیظ یزدی به استقبال‌مان آمد. همراهانم را معرفی کردم و لابد خودش فهمید مدیر کیست. برای ما چای آوردند. سیگارم را چاق کردم و با صاحب‌خانه از قالی‌هایش حرف زدیم. ناظم به بچه‌هایی می‌ماند که در مجلس بزرگترها خوابشان می‌گیرد و دل‌شان هم نمی‌خواست دست به سر شوند. سر اعضای انجمن باز شده بود. حاجی آقا صندوقدار بود. من و ناظم عین دو طفلان مسلم بودیم و معلم کلاس چهارم عین خولی وسطمان نشسته. اغلب اعضای انجمن به زبان محلی صحبت می‌کردند و رفتار ناشی داشتند. حتی یک کدامشان نمی‌دانستند که دست و پاهای خود را چه جور ضبط و ربط کنند. بلند بلند حرف می‌زدند. درست مثل این‌که وزارتخانه‌ی دواب سه تا حیوان تازه برای باغ وحش محله‌شان وارد کرده. جلسه که رسمی شد، صاحبخانه معرفی‌مان کرد و شروع کردند. مدام از خودشان صحبت می‌کردند از این‌که دزد دیشب فلان جا را گرفته و باید درخواست پاسبان شبانه کنیم و... + +همین طور یک ساعت حرف زدند و به مهام امور رسیدگی کردند و من و معلم کلاس چهارم سیگار کشیدیم. انگار نه انگار که ما هم بودیم. نوکرشان که آمد استکان‌ها را جمع کند، چیزی روی جلد اشنو نوشتم و برای صاحبخانه فرستادم که یک مرتبه به صرافت ما افتاد و اجازه خواست و: + +- آقایان عرضی دارند. بهتر است کارهای خودمان را بگذاریم برای بعد. + +مثلاً می‌خواست بفهماند که نباید همه‌ی حرف‌ها را در حضور ما زده باشند. و اجازه دادند معلم کلاس چهار شروع کرد به نطق و او هم شروع کرد که هر چه باشد ما زیر سایه‌ی آقایانیم و خوش‌آیند نیست که بچه‌هایی باشند که نه لباس داشته باشند و نه کفش درست و حسابی و از این حرف‌ها و مدام حرف می‌زد. ناظم هم از چُرت در آمد چیزهایی را که از حفظ کرده بود گفت و التماس دعا و کار را خراب کرد.تشری به ناظم زدم که گدابازی را بگذارد کنار و حالی‌شان کردم که صحبت از تقاضا نیست و گدایی. بلکه مدرسه دور افتاده است و مستراح بی در و پیکر و از این اباطیل... چه خوب شد که عصبانی نشدم. و قرار شد که پنج نفرشان فردا عصر بیایند که مدرسه را وارسی کنند و تشکر و اظهار خوشحالی و در آمدیم. + +در تاریکی بیابان هفت تا سواری پشت در خانه ردیف بودند و راننده‌ها توی یکی از آن‌ها جمع شده بودند و اسرار ارباب‌هاشان را به هم می‌گفتند. در این حین من مدام به خودم می‌گفتم من چرا رفتم؟ به من چه؟ مگر من در بی کفش و کلاهی‌شان مقصر بودم؟ می‌بینی احمق؟ مدیر مدرسه هم که باشی باید شخصیت و غرورت را لای زرورق بپیچی و طاق کلاهت بگذاری که اقلاً نپوسد. حتی اگر بخواهی یک معلم کوفتی باشی، نه چرا دور می‌زنی؟ حتی اگر یک فراش ماهی نود تومانی باشی، باید تا خرخره توی لجن فرو بروی.در همین حین که من در فکر بودم ناظم گفت: + +- دیدید آقا چه طور باهامون رفتار کردند؟ با یکی از قالی‌هاشون آقا تمام مدرسه رو می‌خرید. + +گفتم: + +- تا سر و کارت با الف.ب است به‌پا قیاس نکنی. خودخوری می‌آره. + +و معلم کلاس چهار گفت: + +- اگه فحشمون هم می‌دادند من باز هم راضی بودم، باید واقع‌بین بود. خدا کنه پشیمون نشند. + +بعد هم مدتی درد دل کردیم و تا اتوبوس برسد و سوار بشیم، معلوم شد که معلم کلاس چهار با زنش متارکه کرده و مادر ناظم را سرطانی تشخیص دادند. و بعد هم شب بخیر... + +دو روز تمام مدرسه نرفتم. خجالت می‌کشیدم توی صورت یک کدام‌شان نگاه کنم. و در همین دو روز حاجی آقا با دو نفر آمده بودند، مدرسه را وارسی و صورت‌برداری و ناظم می‌گفت که حتی بچه‌هایی هم که کفش و کلاهی داشتند پاره و پوره آمده بودند. و برای بچه‌ها کفش و لباس خریدند. روزهای بعد احساس کردم زن‌هایی که سر راهم لب جوی آب ظرف می‌شستند، سلام می‌کنند و یک بار هم دعای خیر یکی‌شان را از عقب سر شنیدم.اما چنان از خودم بدم آمده بود که رغبتم نمی‌شد به کفش و لباس‌هاشان نگاه کنم. قربان همان گیوه‌های پاره! بله، نان گدایی فرهنگ را نو نوار کرده بود. + +تازه از دردسرهای اول کار مدرسه فارغ شده بودم که شنیدم که یک روز صبح، یکی از اولیای اطفال آمد. بعد از سلام و احوالپرسی دست کرد توی جیبش و شش تا عکس در آورد، گذاشت روی میزم. شش تا عکس زن لخت. لخت لخت و هر کدام به یک حالت. یعنی چه؟ نگاه تندی به او کردم. آدم مرتبی بود. اداری مانند. کسر شأن خودم می‌دانستم که این گوشه‌ی از زندگی را طبق دستور عکاس‌باشی فلان جنده‌خانه‌ی بندری ببینم. اما حالا یک مرد اتو کشیده‌ی مرتب آمده بود و شش تا از همین عکس‌ها را روی میزم پهن کرده بود و به انتظار آن که وقاحت عکس‌ها چشم‌هایم را پر کند داشت سیگار چاق می‌کرد. + +حسابی غافلگیر شده بودم... حتماً تا هر شش تای عکس‌ها را ببینم، بیش از یک دقیقه طول کشید. همه از یک نفر بود. به این فکر گریختم که الان هزار ها یا میلیون ها نسخه‌ی آن، توی جیب چه جور آدم‌هایی است و در کجاها و چه قدر خوب بود که همه‌ی این آدم‌ها را می‌شناختم یا می‌دیدم. بیش ازین نمی‌شد گریخت. یارو به تمام وزنه وقاحتش، جلوی رویم نشسته بود. سیگاری آتش زدم و چشم به او دوختم. کلافه بود و پیدا بود برای کتک‌کاری هم آماده باشد. سرخ شده بود و داشت در دود سیگارش تکیه‌گاهی برای جسارتی که می‌خواست به خرج بدهد می‌جست. عکس‌ها را با یک ورقه از اباطیلی که همان روز سیاه کرده بودم، پوشاندم و بعد با لحنی که دعوا را با آن شروع می‌کنند؛ پرسیدم: + +- خوب، غرض؟ + +و صدایم توی اتاق پیچید. حرکتی از روی بیچارگی به خودش داد و همه‌ی جسارت‌ها را با دستش توی جیبش کرد و آرام‌تر از آن چیزی که با خودش تو آورده بود، گفت: + +- چه عرض کنم؟... از معلم کلاس پنج تون بپرسید. + +که راحت شدم و او شروع کرد به این که «این چه فرهنگی است؟ خراب بشود. پس بچه‌های مردم با چه اطمینانی به مدرسه بیایند؟ + +و از این حرف‌ها... + +خلاصه این آقا معلم کاردستی کلاس پنجم، این عکس‌ها را داده به پسر آقا تا آن‌ها را روی تخته سه لایی بچسباند و دورش را سمباده بکشد و بیاورد. به هر صورت معلم کلاس پنج بی‌گدار به آب زده. و حالا من چه بکنم؟ به او چه جوابی بدهم؟ بگویم معلم را اخراج می‌کنم؟ که نه می‌توانم و نه لزومی دارد. او چه بکند؟ حتماً در این شهر کسی را ندارد که به این عکس‌ها دلخوش کرده. ولی آخر چرا این جور؟ یعنی این قدر احمق است که حتی شاگردهایش را نمی‌شناسد؟... پاشدم ناظم را صدا بزنم که خودش آمده بود بالا، توی ایوان منتظر ایستاده بود. من آخرین کسی بودم که از هر اتفاقی در مدرسه خبردار می‌شدم. حضور این ولی طفل گیجم کرده بود که چنین عکس‌هایی را از توی جیب پسرش، و لابد به همین وقاحتی که آن‌ها را روی میز من ریخت، در آورده بوده. وقتی فهمید هر دو در مانده‌ایم سوار بر اسب شد که اله می‌کنم و بله می‌کنم، در مدرسه را می‌بندم، و از این جفنگیات.... + +حتماً نمی‌دانست که اگر در هر مدرسه بسته بشود، در یک اداره بسته شده است. اما من تا او بود نمی‌توانستم فکرم را جمع کنم. می‌خواست پسرش را بخواهیم تا شهادت بدهد و چه جانی کندیم تا حالیش کنیم که پسرش هر چه خفت کشیده، بس است و وعده‌ها دادیم که معلمش را دم خورشید کباب کنیم و از نان خوردن بیندازیم. یعنی اول ناظم شروع کرد که از دست او دل پری داشت و من هم دنبالش را گرفتم. برای دک کردن او چاره‌ای جز این نبود. و بعد رفت، ما دو نفری ماندیم با شش تا عکس زن لخت. حواسم که جمع شد به ناظم سپردم صدایش را در نیاورد و یک هفته‌ی تمام مطلب را با عکس‌ها، توی کشوی میزم قفل کردم و بعد پسرک را صدا زدم. نه عزیزدُردانه می‌نمود و نه هیچ جور دیگر. داد می‌زد که از خانواده‌ی عیال‌واری است. کم‌خونی و فقر. دیدم معلمش زیاد هم بد تشخیص نداده. یعنی زیاد بی‌گدار به آب نزده. گفتم: + +- خواهر برادر هم داری؟ + +- آ... آ...آقا داریم آقا. + +- چند تا؟ + +- آ... آقا چهار تا آقا. + +- عکس‌ها رو خودت به بابات نشون دادی؟ + +- نه به خدا آقا... به خدا قسم... + +- پس چه طور شد؟ + +و دیدم از ترس دارد قالب تهی می‌کند. گرچه چوب‌های ناظم شکسته بود، اما ترس او از من که مدیر باشم و از ناظم و از مدرسه و از تنبیه سالم مانده بود. + +- نترس بابا. کاریت نداریم. تقصیر آقا معلمه که عکس‌ها رو داده... تو کار بدی نکردی بابا جان. فهمیدی؟ اما می‌خواهم ببینم چه طور شد که عکس‌ها دست بابات افتاد. + +- آ.. آ... آخه آقا... آخه... + +می‌دانستم که باید کمکش کنم تا به حرف بیاید. + +گفتم: + +- می‌دونی بابا؟ عکس‌هام چیز بدی نبود. تو خودت فهمیدی چی بود؟ + +- آخه آقا...نه آقا.... خواهرم آقا... خواهرم می‌گفت... + +- خواهرت؟ از تو کوچک‌تره؟ + +- نه آقا. بزرگ‌تره. می‌گفتش که آقا... می‌گفتش که آقا... هیچ چی سر عکس‌ها دعوامون شد. + +دیگر تمام بود. عکس‌ها را به خواهرش نشان داده بود که لای دفترچه پر بوده از عکس آرتیست‌ها. به او پز داده بوده. اما حاضر نبوده، حتی یکی از آن‌ها را به خواهرش بدهد. آدم مورد اعتماد معلم باشد و چنین خبطی بکند؟ و تازه جواب معلم را چه بدهد؟ ناچار خواهر او را لو داده بوده. بعد از او معلم را احضار کردم. علت احضار را می‌دانست. و داد می‌زد که چیزی ندارد بگوید. پس از یک هفته مهلت، هنوز از وقاحتی که من پیدا کرده بودم، تا از آدم خلع سلاح‌شده‌ای مثل او، دست بر ندارم، در تعجب بود. به او سیگار تعارف کردم و این قصه را برایش تعریف کردم که در اوایل تأسیس وزارت معارف، یک روز به وزیر خبر می‌دهند که فلان معلم با فلان بچه روابطی دارد. وزیر فوراً او را می‌خواهد و حال و احوال او را می‌پرسد و این‌که چرا تا به حال زن نگرفته و ناچار تقصیر گردن بی‌پولی می‌افتد و دستور که فلان قدر به او کمک کنند تا عروسی راه بیندازد و خود او هم دعوت بشود و قضیه به همین سادگی تمام می‌شود. و بعد گفتم که خیلی جوان‌ها هستند که نمی‌توانند زن بگیرند و وزرای فرهنگ هم این روزها گرفتار مصاحبه‌های روزنامه‌ای و رادیویی هستند. اما در نجیب‌خانه‌ها که باز است و ازین مزخرفات... و هم‌دردی و نگذاشتم یک کلمه حرف بزند. بعد هم عکس را که توی پاکت گذاشته بودم، به دستش دادم و وقاحت را با این جمله به حد اعلا رساندم که: + +- اگر به تخته نچسبونید، ضررشون کم‌تره. + +تا حقوقم به لیست اداره‌ی فرهنگ برسه، سه ماه طول کشید. فرهنگی‌های گداگشنه و خزانه‌ی خالی و دست‌های از پا درازتر! اما خوبیش این بود که در مدرسه‌ی ما فراش جدیدمان پولدار بود و به همه‌شان قرض داد. کم کم بانک مدرسه شده بود. از سیصد و خرده‌ای تومان که می‌گرفت، پنجاه تومان را هم خرج نمی‌کرد. نه سیگار می‌کشید و نه اهل سینما بود و نه برج دیگری داشت. از این گذشته، باغبان یکی از دم‌کلفت‌های همان اطراف بود و باغی و دستگاهی و سور و ساتی و لابد آشپزخانه‌ی مرتبی. خیلی زود معلم‌ها فهمیدند که یک فراش پولدار خیلی بیش‌تر به درد می‌خورد تا یک مدیر بی‌بو و خاصیت. + +این از معلم‌ها. حقوق مرا هم هنوز از مرکز می‌دادند. با حقوق ماه بعد هم اسم مرا هم به لیست اداره منتقل کردند. درین مدت خودم برای خودم ورقه انجام کار می‌نوشتم و امضا می‌کردم و می‌رفتم از مدرسه‌ای که قبلاً در آن درس می‌دادم، حقوقم را می‌گرفتم. سر و صدای حقوق که بلند می‌شد معلم‌ها مرتب می‌شدند و کلاس ماهی سه چهار روز کاملاً دایر بود. تا ورقه‌ی انجام کار به دستشان بدهم. غیر از همان یک بار - در اوایل کار- که برای معلم حساب پنج و شش قرمز توی دفتر گذاشتیم، دیگر با مداد قرمز کاری نداشتیم و خیال همه‌شان راحت بود. وقتی برای گرفتن حقوقم به اداره رفتم، چنان شلوغی بود که به خودم گفتم کاش اصلاً حقوقم را منتقل نکرده بودم. نه می‌توانستم سر صف بایستم و نه می‌توانستم از حقوقم بگذرم. تازه مگر مواجب‌بگیر دولت چیزی جز یک انبان گشاده‌ی پای صندوق است؟..... و اگر هم می‌ماندی با آن شلوغی باید تا دو بعداز ظهر سر پا بایستی. همه‌ی جیره‌خوارهای اداره بو برده بودند که مدیرم. و لابد آن‌قدر ساده لوح بودند که فکر کنند روزی گذارشان به مدرسه‌ی ما بیفتد. دنبال سفته‌ها می‌گشتند، به حسابدار قبلی فحش می‌دادند، التماس می‌کردند که این ماه را ندیده بگیرید و همه‌ی حق و حساب‌دان شده بودند و یکی که زودتر از نوبت پولش را می‌گرفت صدای همه در می‌آمد. در لیست مدرسه، بزرگ‌ترین رقم مال من بود. درست مثل بزرگ‌ترین گناه در نامه‌ی عمل. دو برابر فراش جدیدمان حقوق می‌گرفتم. از دیدن رقم‌های مردنی حقوق دیگران چنان خجالت کشیدم که انگار مال آن‌ها را دزدیده‌ام. و تازه خلوت که شد و ده پانزده تا امضا که کردم، صندوق‌دار چشمش به من افتاد و با یک معذرت، شش صد تومان پول دزدی را گذاشت کف دستم... مرده شور! + +هنوز برف اول نباریده بود که یک روز عصر، معلم کلاس چهار رفت زیر ماشین. زیر یک سواری. مثل همه‌ی عصرها من مدرسه نبودم. دم غروب بود که فراش قدیمی مدرسه دم در خونه‌مون، خبرش را آورد. که دویدم به طرف لباسم و تا حاضر بشوم، می‌شنیدم که دارد قضیه را برای زنم تعریف می‌کند. ماشین برای یکی از آمریکایی‌ها بوده. باقیش را از خانه که در آمدیم برایم تعریف کرد. گویا یارو خودش پشت فرمون بوده و بعد هم هول شده و در رفته. بچه‌ها خبر را به مدرسه برگردانده‌اند و تا فراش و زنش برسند، جمعیت و پاسبان‌ها سوارش کرده بودند و فرستاده بوده‌اند مریض‌خانه. به اتوبوس که رسیدم، دیدم لاک پشت است. فراش را مرخص کردم و پریدم توی تاکسی. اول رفتم سراغ پاسگاه جدید کلانتری. تعاریف تکه و پاره‌ای از پرونده مطلع بود. اما پرونده تصریحی نداشت که راننده که بوده. اما هیچ کس نمی‌دانست عاقبت چه بلایی بر سر معلم کلاس چهار ما آمده است. کشیک پاسگاه همین قدر مطلع بود که درین جور موارد «طبق جریان اداری» اول می‌روند سرکلانتری، بعد دایره‌ی تصادفات و بعد بیمارستان. اگر آشنا در نمی‌آمدیم، کشیک پاسگاه مسلماً نمی‌گذاشت به پرونده نگاه چپ بکنم. احساس کردم میان اهل محل کم‌کم دارم سرشناس می‌شوم. و از این احساس خنده‌ام گرفت. + +ساعت ۸ دم در بیمارستان بودم، اگر سالم هم بود حتماً یه چیزیش شده بود. همان طور که من یه چیزیم می‌شد. روی در بیمارستان نوشته شده بود: «از ساعت ۷ به بعد ورود ممنوع». در زدم. از پشت در کسی همین آیه را صادر کرد. دیدم فایده ندارد و باید از یک چیزی کمک بگیرم. از قدرتی، از مقامی، از هیکلی، از یک چیزی. صدایم را کلفت کردم و گفتم:« من...» می‌خواستم بگویم من مدیر مدرسه‌ام. ولی فوراً پشیمان شدم. یارو لابد می‌گفت مدیر مدرسه کدام سگی است؟ این بود با کمی مکث و طمطراق فراوان جمله‌ام را این طور تمام کردم: + +- ...بازرس وزارت فرهنگم. + +که کلون صدایی کرد و لای در باز شد. یارو با چشم‌هایش سلام کرد. رفتم تو و با همان صدا پرسیدم: + +- این معلمه مدرسه که تصادف کرده... + +تا آخرش را خواند. یکی را صدا زد و دنبالم فرستاد که طبقه‌ی فلان، اتاق فلان. از حیاط به راهرو و باز به حیاط دیگر که نصفش را برف پوشانده بود و من چنان می‌دویدم که یارو از عقب سرم هن هن می‌کرد. طبقه‌ی اول و دوم و چهارم. چهار تا پله یکی. راهرو تاریک بود و پر از بوهای مخصوص بود. هن هن کنان دری را نشان داد که هل دادم و رفتم تو. بو تندتر بود و تاریکی بیشتر. تالاری بود پر از تخت و جیرجیر کفش و خرخر یک نفر. دور یک تخت چهار نفر ایستاده بودند. حتماً خودش بود. پای تخت که رسیدم، احساس کردم همه‌ی آنچه از خشونت و تظاهر و ابهت به کمک خواسته بودم آب شد و بر سر و صورتم راه افتاد. و این معلم کلاس چهارم مدرسه‌ام بود. سنگین و با شکم بر آمده دراز کشیده بود. خیلی کوتاه‌تر از زمانی که سر پا بود به نظرم آمد. صورت و سینه‌اش از روپوش چرک‌مُرد بیرون بود. صورتش را که شسته بودند کبود کبود بود، درست به رنگ جای سیلی روی صورت بچه‌ها. مرا که دید، لبخند و چه لبخندی! شاید می‌خواست بگوید مدرسه‌ای که مدیرش عصرها سر کار نباشد، باید همین جورها هم باشد. خنده توی صورت او همین طور لرزید و لرزید تا یخ زد. + +«آخر چرا تصادف کردی؟...» + +مثل این که سوال را ازو کردم. اما وقتی که دیدم نمی‌تواند حرف بزند و به جای هر جوابی همان خنده‌ی یخ‌بسته را روی صورت دارد، خودم را به عنوان او دم چک گرفتم. «آخه چرا؟ چرا این هیکل مدیر کلی را با خودت این قد این ور و آن ور می‌بری تا بزنندت؟ تا زیرت کنند؟ مگر نمی‌دانستی که معلم حق ندارد این قدر خوش‌هیکل باشد؟ آخر چرا تصادف کردی؟» به چنان عتاب و خطابی این‌ها را می‌گفتم که هیچ مطمئن نیستم بلند بلند به خودش نگفته باشم. و یک مرتبه به کله‌ام زد که «مبادا خودت چشمش زده باشی؟» و بعد: «احمق خاک بر سر! بعد از سی و چند سال عمر، تازه خرافاتی شدی!» و چنان از خودم بیزاریم گرفت که می‌خواستم به یکی فحش بدهم، کسی را بزنم. که چشمم به دکتر کشیک افتاد. + +- مرده شور این مملکتو ببره. ساعت چهار تا حالا از تن این مرد خون می‌ره. حیفتون نیومد؟... + +دستی روی شانه‌ام نشست و فریادم را خواباند. برگشتم پدرش بود. او هم می‌خندید. دو نفر دیگر هم با او بودند. همه دهاتی‌وار؛ همه خوش قد و قواره. حظ کردم! آن دو تا پسرهایش بودند یا برادرزاده‌هایش یا کسان دیگرش. تازه داشت گل از گلم می‌شکفت که شنیدم: + +- آقا کی باشند؟ + +این راهم دکتر کشیک گفت که من باز سوار شدم: + +- مرا می‌گید آقا؟ من هیشکی. یک آقا مدیر کوفتی. این هم معلمم. + +که یک مرتبه عقل هی زد و «پسر خفه شو» و خفه شدم. بغض توی گلویم بود. دلم می‌خواست یک کلمه دیگر بگوید. یک کنایه بزند... نسبت به مهارت هیچ دکتری تا کنون نتوانسته‌ام قسم بخورم. دستش را دراز کرد که به اکراه فشار دادم و بعد شیشه‌ی بزرگی را نشانم داد که وارونه بالای تخت آویزان بود و خرفهمم کرد که این جوری غذا به او می‌رسانند و عکس هم گرفته‌اند و تا فردا صبح اگر زخم‌ها چرک نکند، جا خواهند انداخت و گچ خواهند کرد. که یکی دیگر از راه رسید. گوشی به دست و سفید پوش و معطر. با حرکاتی مثل آرتیست سینما. سلامم کرد. صدایش در ته ذهنم چیزی را مختصر تکانی داد. اما احتیاجی به کنجکاوی نبود. یکی از شاگردهای نمی‌دانم چند سال پیشم بود. خودش خودش را معرفی کرد. آقای دکتر...! عجب روزگاری! هر تکه از وجودت را با مزخرفی از انبان مزخرفاتت، مثل ذره‌ای روزی در خاکی ریخته‌ای که حالا سبز کرده. چشم داری احمق. این تویی که روی تخت دراز کشیده‌ای. ده سال آزگار از پلکان ساعات و دقایق عمرت هر لحظه یکی بالا رفته و تو فقط خستگی این بار را هنوز در تن داری. این جوجه‌فکلی و جوجه‌های دیگر که نمی‌شناسی‌شان، همه از تخمی سر در آورده‌اند که روزی حصار جوانی تو بوده و حالا شکسته و خالی مانده. دستش را گرفتم و کشیدمش کناری و در گوشش هر چه بد و بی‌راه می‌دانستم، به او و همکارش و شغلش دادم. مثلاً می‌خواستم سفارش معلم کلاس چهار مدرسه‌ام را کرده باشم. بعد هم سری برای پدر تکان دادم و گریختم. از در که بیرون آمدم، حیاط بود و هوای بارانی. از در بزرگ که بیرون آمدم به این فکر می‌کردم که «اصلا به تو چه؟ اصلاً چرا آمدی؟ می‌خواستی کنجکاوی‌ات را سیرکنی؟» و دست آخر به این نتیجه رسیدم که «طعمه‌ای برای میزنشین‌های شهربانی و دادگستری به دست آمده و تو نه می‌توانی این طعمه را از دستشان بیرون بیاوری و نه هیچ کار دیگری می‌توانی بکنی...» + +و داشتم سوار تاکسی می‌شدم تا برگردم خانه که یک دفعه به صرافت افتادم که اقلاً چرا نپرسیدی چه بلایی به سرش آمده؟» خواستم عقب‌گرد کنم، اما هیکل کبود معلم کلاس چهارم روی تخت بود و دیدم نمی‌توانم. خجالت می‌کشیدم و یا می‌ترسیدم. آن شب تا ساعت دو بیدار بودم و فردا یک گزارش مفصل به امضای مدیر مدرسه و شهادت همه‌ی معلم‌ها برای اداره‌ی فرهنگ و کلانتری محل و بعد هم دوندگی در اداره‌ی بیمه و قرار بر این که روزی نه تومان بودجه برای خرج بیمارستان او بدهند و عصر پس از مدتی رفتم مدرسه و کلاس‌ها را تعطیل کردم و معلم‌ها و بچه‌های ششم را فرستادم عیادتش و دسته گل و ازین بازی‌ها... و یک ساعتی در مدرسه تنها ماندم و فارغ از همه چیز برای خودم خیال بافتم.... و فردا صبح پدرش آمد سلام و احوالپرسی و گفت یک دست و یک پایش شکسته و کمی خونریزی داخل مغز و از طرف یارو آمریکاییه آمده‌اند عیادتش و وعده و وعید که وقتی خوب شد، در اصل چهار استخدامش کنند و با زبان بی‌زبانی حالیم کرد که گزارش را بیخود داده‌ام و حالا هم داده‌ام، دنبالش نکنم و رضایت طرفین و کاسه‌ی از آش داغ‌تر و از این حرف‌ها... خاک بر سر مملکت. + +اوایل امر توجهی به بچه‌ها نداشتم. خیال می‌کردم اختلاف سِنی میان‌مان آن قدر هست که کاری به کار همدیگر نداشته باشیم. همیشه سرم به کار خودم بود. در دفتر را می‌بستم و در گرمای بخاری دولت قلم صد تا یک غاز می‌زدم. اما این کار مرتب سه چهار هفته بیش‌تر دوام نکرد. خسته شدم. ناچار به مدرسه بیشتر می‌رسیدم. یاد روزهای قدیمی با دوستان قدیمی به خیر چه آدم‌های پاک و بی‌آلایشی بودند، چه شخصیت‌های بی‌نام و نشانی و هر کدام با چه زبانی و با چه ادا و اطوارهای مخصوص به خودشان و این جوان‌های چلفته‌ای. چه مقلدهای بی‌دردسری برای فرهنگی‌مابی! نه خبری از دیروزشان داشتند و نه از املاک تازه‌ای که با هفتاد واسطه به دست‌شان داده بودند، چیزی سرشان می‌شد. بدتر از همه بی‌دست و پایی‌شان بود. آرام و مرتب درست مثل واگن شاه عبدالعظیم می‌آمدند و می‌رفتند. فقط بلد بودند روزی ده دقیقه دیرتر بیایند و همین. و از این هم بدتر تنگ‌نظری‌شان بود. + +سه بار شاهد دعواهایی بودم که سر یک گلدان میخک یا شمعدانی بود. بچه‌باغبان‌ها زیاد بودند و هر کدام‌شان حداقل ماهی یک گلدان میخک یا شمعدانی می‌آوردند که در آن برف و سرما نعمتی بود. اول تصمیم گرفتم، مدرسه را با آن‌ها زینت دهم. ولی چه فایده؟ نه کسی آب‌شان می‌داد و نه مواظبتی. و باز بدتر از همه‌ی این‌ها، بی‌شخصیتی معلم‌ها بود که درمانده‌ام کرده بود. دو کلمه نمی‌توانستند حرف بزنند. عجب هیچ‌کاره‌هایی بودند! احساس کردم که روز به روز در کلاس‌ها معلم‌ها به جای دانش‌آموزان جاافتاده‌تر می‌شوند. در نتیجه گفتم بیش‌تر متوجه بچه‌ها باشم. + +آن‌ها که تنها با ناظم سر و کار داشتند و مثل این بود که به من فقط یک سلام نیمه‌جویده بدهکارند. با این همه نومیدکننده نبودند. توی کوچه مواظب‌شان بودم. می‌خواستم حرف و سخن‌ها و درد دل‌ها و افکارشان را از یک فحش نیمه‌کاره یا از یک ادای نیمه‌تمام حدس بزنم، که سلام‌نکرده در می‌رفتند. خیلی کم تنها به مدرسه می‌آمدند. پیدا بود که سر راه همدیگر می‌ایستند یا در خانه‌ی یکدیگر می‌روند. سه چهار نفرشان هم با اسکورت می‌آمدند. از بیست سی نفری که ناهار می‌ماندند، فقط دو نفرشان چلو خورش می‌آوردند؛ فراش اولی مدرسه برایم خبر می‌آورد. بقیه گوشت‌کوبیده، پنیر گردوئی، دم پختکی و از این جور چیزها. دو نفرشان هم بودند که نان سنگک خالی می‌آوردند. برادر بودند. پنجم و سوم. صبح که می‌آمدند، جیب‌هاشان باد کرده بود. سنگک را نصف می‌کردند و توی جیب‌هاشان می‌تپاندند و ظهر می‌شد، مثل آن‌هایی که ناهارشان را در خانه می‌خورند، می‌رفتند بیرون. من فقط بیرون رفتن‌شان را می‌دیدم. اما حتی همین‌ها هر کدام روزی، یکی دو قران از فراش مدرسه خرت و خورت می‌خریدند. از همان فراش قدیمی مدرسه که ماهی پنج تومان سرایداریش را وصول کرده بودم. هر روز که وارد اتاقم می‌شدم پشت سر من می‌آمد بارانی‌ام را بر می‌داشت و شروع می‌کرد به گزارش دادن، که دیروز باز دو نفر از معلم‌ها سر یک گلدان دعوا کرده‌اند یا مأمور فرماندار نظامی آمده یا دفتردار عوض شده و از این اباطیل... پیدا بود که فراش جدید هم در مطالبی که او می‌گفت، سهمی دارد. + +یک روز در حین گزارش دادن، اشاره‌ای کرد به این مطلب که دیروز عصر یکی از بچه‌های کلاس چهار دو تا کله قند به او فروخته است. درست مثل اینکه سر کلاف را به دستم داده باشد پرسیدم: + +- چند؟ + +- دو تومنش دادم آقا. + +- زحمت کشیدی. نگفتی از کجا آورده؟ + +- من که ضامن بهشت و جهنمش نبودم آقا. + +بعد پرسیدم: + +- چرا به آقای ناظم خبر ندادی؟ + +می‌دانستم که هم او و هم فراش جدید، ناظم را هووی خودشان می‌دانند و خیلی چیزهاشان از او مخفی بود. این بود که میان من و ناظم خاصه‌خرجی می‌کردند. در جوابم همین طور مردد مانده بود که در باز شد و فراش جدید آمد تو. که: + +- اگه خبرش می‌کرد آقا بایست سهمش رو می‌داد... + +اخمم را درهم کشیدم و گفتم: + +- تو باز رفتی تو کوک مردم! اونم این جوری سر نزده که نمی‌آیند تو اتاق کسی، پیرمرد! + +و بعد اسم پسرک را ازشان پرسیدم و حالی‌شان کردم که چندان مهم نیست و فرستادمشان برایم چای بیاورند. بعد کارم را زودتر تمام کردم و رفتم به اتاق دفتر احوالی از مادر ناظم پرسیدم و به هوای ورق زدن پرونده‌ها فهمیدم که پسرک شاگرد دوساله است و پدرش تاجر بازار. بعد برگشتم به اتاقم. یادداشتی برای پدر نوشتم که پس فردا صبح، بیاید مدرسه و دادم دست فراش جدید که خودش برساند و رسیدش را بیاورد. + +و پس فردا صبح یارو آمد. باید مدیر مدرسه بود تا دانست که اولیای اطفال چه راحت تن به کوچک‌ترین خرده‌فرمایش‌های مدرسه می‌دهند. حتم دارم که اگر از اجرای ثبت هم دنبال‌شان بفرستی به این زودی‌ها آفتابی نشوند. چهل و پنج ساله مردی بود با یخه‌ی بسته بی‌کراوات و پالتویی که بیش‌تر به قبا می‌ماند. و خجالتی می‌نمود. هنوز ننشسته، پرسیدم: + +- شما دو تا زن دارید آقا؟ + +درباره‌ی پسرش برای خودم پیش‌گویی‌هایی کرده بودم و گفتم این طوری به او رودست می‌زنم. پیدا بود که از سؤالم زیاد یکه نخورده است. گفتم برایش چای آوردند و سیگاری تعارفش کردم که ناشیانه دود کرد از ترس این که مبادا جلویم در بیاید که - به شما چه مربوط است و از این اعتراض‌ها - امانش ندادم و سؤالم را این جور دنبال کردم: + +- البته می‌بخشید. چون لابد به همین علت بچه شما دو سال در یک کلاس مانده. + +شروع کرده بودم برایش یک میتینگ بدهم که پرید وسط حرفم: + +- به سر شما قسم، روزی چهار زار پول تو جیبی داره آقا. پدرسوخته‌ی نمک به حروم...! + +حالیش کردم که علت، پول تو جیبی نیست و خواستم که عصبانی نشود و قول گرفتم که اصلاً به روی پسرش هم نیاورد و آن وقت میتینگم را برایش دادم که لابد پسر در خانه مهر و محبتی نمی‌بیند و غیب‌گویی‌های دیگر... تا عاقبت یارو خجالتش ریخت و سرِ درد دلش باز شد که عفریته زن اولش همچه بوده و همچون بوده و پسرش هم به خودش برده و کی طلاقش داده و از زن دومش چند تا بچه دارد و این نره‌خر حالا باید برای خودش نان‌آور شده باشد و زنش حق دارد که با دو تا بچه‌ی خرده‌پا به او نرسد... من هم کلی برایش صحبت کردم. چایی دومش را هم سر کشید و قول‌هایش را که داد و رفت، من به این فکر افتادم که «نکند علمای تعلیم و تربیت هم، همین جورها تخم دوزرده می‌کنند!» + +یک روز صبح که رسیدم، ناظم هنوز نیامده بود. از این اتفاق‌ها کم می‌افتاد. ده دقیقه‌ای از زنگ می‌گذشت و معلم‌ها در دفتر سرگرم اختلاط بودند. خودم هم وقتی معلم بودم به این مرض دچار بودم. اما وقتی مدیر شدم تازه فهمیدم که معلم‌ها چه لذتی می‌برند. حق هم داشتند. آدم وقتی مجبور باشد شکلکی را به صورت بگذارد که نه دیگران از آن می‌خندند و نه خود آدم لذتی می‌برد، پیداست که رفع تکلیف می‌کند. زنگ را گفتم زدند و بچه‌ها سر کلاس رفتند. دو تا از کلاس‌ها بی‌معلم بود. یکی از ششمی‌ها را فرستادم سر کلاس سوم که برای‌شان دیکته بگوید و خودم رفتم سر کلاس چهار. مدیر هم که باشی، باز باید تمرین کنی که مبادا فوت و فن معلمی از یادت برود. در حال صحبت با بچه‌ها بودم که فراش خبر آورد که خانمی توی دفتر منتظرم است. خیال کردم لابد همان زنکه‌ی بیکاره‌ای است که هفته‌ای یک بار به هوای سرکشی، به وضع درس و مشق بچه‌اش سری می‌زند. زن سفیدرویی بود با چشم‌های درشت محزون و موی بور. بیست و پنج ساله هم نمی‌نمود. اما بچه‌اش کلاس سوم بود. روز اول که دیدمش لباس نارنجی به تن داشت و تن بزک کرده بود. از زیارت من خیلی خوشحال شد و از مراتب فضل و ادبم خبر داشت. + +خیلی ساده آمده بود تا با دو تا مرد حرفی زده باشد. آن طور که ناظم خبر می‌داد، یک سالی طلاق گرفته بود و روی هم رفته آمد و رفتنش به مدرسه باعث دردسر بود. وسط بیابان و مدرسه‌ای پر از معلم‌های عزب و بی‌دست و پا و یک زن زیبا... ناچار جور در نمی‌آمد. این بود که دفعات بعد دست به سرش می‌کردم، اما از رو نمی‌رفت. سراغ ناظم و اتاق دفتر را می‌گرفت و صبر می‌کرد تا زنگ را بزنند و معلم‌ها جمع بشوند و لابد حرف و سخنی و خنده‌ای و بعد از معلم کلاس سوم سراغ کار و بار و بچه‌اش را می‌گرفت و زنگ بعد را که می‌زدند، خداحافظی می‌کرد و می‌رفت. آزاری نداشت. با چشم‌هایش نفس معلم‌ها را می‌برید. و حالا باز هم همان زن بود و آمده بود و من تا از پلکان پایین بروم در ذهنم جملات زننده‌ای ردیف می‌کردم، تا پایش را از مدرسه ببرد که در را باز کردم و سلام... + +عجب! او نبود. دخترک یکی دو ساله‌ای بود با دهان گشاد و موهای زبرش را به زحمت عقب سرش گلوله کرده بود و بفهمی نفهمی دستی توی صورتش برده بود. روی هم رفته زشت نبود. اما داد می‌زد که معلم است. گفتم که مدیر مدرسه‌ام و حکمش را داد دستم که دانشسرا دیده بود و تازه استخدام شده بود. برایمان معلم فرستاده بودند. خواستم بگویم «مگر رئیس فرهنگ نمی‌داند که این جا بیش از حد مرد است» ولی دیدم لزومی ندارد و فکر کردم این هم خودش تنوعی است. + +به هر صورت زنی بود و می‌توانست محیط خشن مدرسه را که به طرز ناشیانه‌ای پسرانه بود، لطافتی بدهد و خوش‌آمد گفتم و چای آوردند که نخورد و بردمش کلاس‌های سوم و چهارم را نشانش دادم که هر کدام را مایل است، قبول کند و صحبت از هجده ساعت درس که در انتظار او بود و برگشتیم به دفتر .پرسید غیر از او هم، معلم زن داریم. گفتم: + +- متأسفانه راه مدرسه‌ی ما را برای پاشنه‌ی کفش خانم‌ها نساخته‌اند. + +که خندید و احساس کردم زورکی می‌خندد. بعد کمی این دست و آن دست کرد و عاقبت: + +- آخه من شنیده بودم شما با معلماتون خیلی خوب تا می‌کنید. + +صدای جذابی داشت. فکر کردم حیف که این صدا را پای تخته سیاه خراب خواهد کرد. و گفتم: + +- اما نه این قدر که مدرسه تعطیل بشود خانم! و لابد به عرض‌تون رسیده که همکارهای شما، خودشون نشسته‌اند و تصمیم گرفته‌اند که هجده ساعت درس بدهند. بنده هیچ‌کاره‌ام. + +- اختیار دارید. + +و نفهمیدم با این «اختیار دارید» چه می‌خواست بگوید. اما پیدا بود که بحث سر ساعات درس نیست. آناً تصمیم گرفتم، امتحانی بکنم: + +- این را هم اطلاع داشته باشید که فقط دو تا از معلم‌های ما متأهل‌اند. + +که قرمز شد و برای این که کار دیگری نکرده باشد، برخاست و حکمش را از روی میز برداشت. پا به پا می‌شد که دیدم باید به دادش برسم. ساعت را از او پرسیدم. وقت زنگ بود. فراش را صدا کردم که زنگ را بزند و بعد به او گفتم، بهتر است مشورت دیگری هم با رئیس فرهنگ بکند و ما به هر صورت خوشحال خواهیم شد که افتخار همکاری با خانمی مثل ایشان را داشته باشیم و خداحافظ شما. از در دفتر که بیرون رفت، صدای زنگ برخاست و معلم‌ها انگار موشان را آتش زده‌اند، به عجله رسیدند و هر کدام از پشت سر، آن قدر او را پاییدند تا از در بزرگ آهنی مدرسه بیرون رفت. + +فردا صبح معلوم شد که ناظم، دنبال کار مادرش بوده است که قرار بود بستری شود، تا جای سرطان گرفته را یک دوره برق بگذارند. کل کار بیمارستان را من به کمک دوستانم انجام دادم و موقع آن رسیده بود که مادرش برود بیمارستان اما وحشتش گرفته بود و حاضر نبود به بیمارستان برود. و ناظم می‌خواست رسماً دخالت کنم و با هم برویم خانه‌شان و با زبان چرب و نرمی که به قول ناظم داشتم مادرش را راضی کنم. چاره‌ای نبود. مدرسه را به معلم‌ها سپردیم و راه افتادیم. بالاخره به خانه‌ی آن‌ها رسیدیم. خانه‌ای بسیار کوچک و اجاره‌ای. مادر با چشم‌های گود نشسته و انگار زغال به صورت مالیده! سیاه نبود اما رنگش چنان تیره بود که وحشتم گرفت. اصلاً صورت نبود. زخم سیاه شده‌ای بود که انگار از جای چشم‌ها و دهان سر باز کرده است. کلی با مادرش صحبت کردم. از پسرش و کلی دروغ و دونگ، و چادرش را روی چارقدش انداختیم و علی... و خلاصه در بیمارستان بستری شدند. + +فردا که به مدرسه آمدم، ناظم سرحال بود و پیدا بود که از شر چیزی خلاص شده است و خبر داد که معلم کلاس سه را گرفته‌اند. یک ماه و خرده‌ای می‌شد که مخفی بود و ما ورقه‌ی انجام کارش را به جانشین غیر رسمی‌اش داده بودیم و حقوقش لنگ نشده بود و تا خبر رسمی بشنود و در روزنامه‌ای بیابد و قضیه به اداره‌ی فرهنگ و لیست حقوق بکشد، باز هم می‌دادیم. اما خبر که رسمی شد، جانشین واجد شرایط هم نمی‌توانست بفرستد و باید طبق مقررات رفتار می‌کردیم و بدیش همین بود. کم کم احساس کردم که مدرسه خلوت شده است و کلاس‌ها اغلب اوقات بی‌کارند. جانشین معلم کلاس چهار هنوز سر و صورتی به کارش نداده بود و حالا یک کلاس دیگر هم بی‌معلم شد. این بود که باز هم به سراغ رئیس فرهنگ رفتم. معلوم شد آن دخترک ترسیده و «نرسیده متلک پیچش کرده‌اید» رئیس فرهنگ این طور می‌گفت. و ترجیح داده بود همان زیر نظر خودش دفترداری کند. و بعد قول و قرار و فردا و پس فردا و عاقبت چهار روز دوندگی تا دو تا معلم گرفتم. یکی جوانکی رشتی که گذاشتیمش کلاس چهار و دیگری باز یکی ازین آقاپسرهای بریانتین‌زده که هر روز کراوات عوض می‌کرد، با نقش‌ها و طرح‌های عجیب. عجب فرهنگ را با قرتی‌ها در آمیخته بودند! باداباد. او را هم گذاشتیم سر کلاس سه. اواخر بهمن، یک روز ناظم آمد اتاقم که بودجه‌ی مدرسه را زنده کرده است. گفتم: + +- مبارکه، چه قدر گرفتی؟ + +- هنوز هیچ چی آقا. قراره فردا سر ظهر بیاند این جا آقا و همین جا قالش رو بکنند. + +و فردا اصلاً مدرسه نرفتم. حتماً می‌خواست من هم باشم و در بده بستان ماهی پانزده قران، حق نظافت هر اتاق نظارت کنم و از مدیریتم مایه بگذارم تا تنخواه‌گردان مدرسه و حق آب و دیگر پول‌های عقب‌افتاده وصول بشود... فردا سه نفری آمده بودند مدرسه. ناهار هم به خرج ناظم خورده بودند. و قرار دیگری برای یک سور حسابی گذاشته بودند و رفته بودند و ناظم با زبان بی‌زبانی حالیم کرد که این بار حتماً باید باشم و آن طور که می‌گفت، جای شکرش باقی بود که مراعات کرده بودند و حق بوقی نخواسته بودند. اولین باری بود که چنین اهمیتی پیدا می‌کردم. این هم یک مزیت دیگر مدیری مدرسه بود! سی صد تومان از بودجه‌ی دولت بسته به این بود که به فلان مجلس بروی یا نروی. تا سه روز دیگر موعد سور بود، اصلاً یادم نیست چه کردم. اما همه‌اش در این فکر بودم که بروم یا نروم؟ یک بار دیگر استعفانامه‌ام را توی جیبم گذاشتم و بی این که صدایش را در بیاورم، روز سور هم نرفتم. + +بعد دیدم این طور که نمی‌شود. گفتم بروم قضایا را برای رئیس فرهنگ بگویم. و رفتم. سلام و احوالپرسی نشستم. اما چه بگویم؟ بگویم چون نمی‌خواستم در خوردن سور شرکت کنم، استعفا می‌دهم؟... دیدم چیزی ندارم که بگویم. و از این گذشته خفت‌آور نبود که به خاطر سیصد تومان جا بزنم و استعفا بدهم؟ و «خداحافظ؛ فقط آمده بودم سلام عرض کنم.» و از این دروغ‌ها و استعفانامه‌ام را توی جوی آب انداختم. اما ناظم؛ یک هفته‌ای مثل سگ بود. عصبانی، پر سر و صدا و شارت و شورت! حتی نرفتم احوال مادرش را بپرسم. یک هفته‌ی تمام می‌رفتم و در اتاقم را می‌بستم و سوراخ‌های گوشم را می‌گرفتم و تا اِز و چِزّ بچه‌ها بخوابد، از این سر تا آن سر اتاق را می‌کوبیدم. ده روز تمام، قلب من و بچه‌ها با هم و به یک اندازه از ترس و وحشت تپید. تا عاقبت پول‌ها وصول شد. منتها به جای سیصد و خرده‌ای، فقط صد و پنجاه تومان. علت هم این بود که در تنظیم صورت حساب‌ها اشتباهاتی رخ داده بود که ناچار اصلاحش کرده بودند! + +غیر از آن زنی که هفته‌ای یک بار به مدرسه سری می‌زد، از اولیای اطفال دو سه نفر دیگر هم بودند که مرتب بودند. یکی همان پاسبانی که با کمربند، پاهای پسرش را بست و فلک کرد. یکی هم کارمند پست و تلگرافی بود که ده روزی یک بار می‌آمد و پدر همان بچه‌ی شیطان. و یک استاد نجار که پسرش کلاس اول بود و خودش سواد داشت و به آن می‌بالید و کارآمد می‌نمود. یک مقنی هم بود درشت استخوان و بلندقد که بچه‌اش کلاس سوم بود و هفته‌ای یک بار می‌آمد و همان توی حیاط، ده پانزده دقیقه‌ای با فراش‌ها اختلاط می‌کرد و بی سر و صدا می‌رفت. نه کاری داشت، نه چیزی از آدم می‌خواست و همان طور که آمده بود چند دقیقه‌ای را با فراش صحبت می‌کرد و بعد می رفت. فقط یک روز نمی‌دانم چرا رفته بود بالای دیوار مدرسه. البته اول فکر کردم مأمور اداره برق است ولی بعد متوجه شدم که همان مرد مقنی است. بچه‌ها جیغ و فریاد می‌کردند و من همه‌اش درین فکر بودم که چه طور به سر دیوار رفته است؟ ماحصل داد و فریادش این بود که چرا اسم پسر او را برای گرفتن کفش و لباس به انجمن ندادیم. وقتی به او رسیدم نگاهی به او انداختم و بعد تشری به ناظم و معلم ها زدم که ولش کردند و بچه‌ها رفتند سر کلاس و بعد بی این که نگاهی به او بکنم، گفتم: + +- خسته نباشی اوستا. + +و همان طور که به طرف دفتر می‌رفتم رو به ناظم و معلم‌ها افزودم: + +- لابد جواب درست و حسابی نشنیده که رفته سر دیوار. + +که پشت سرم گرپ صدایی آمد و از در دفتر که رفتم تو، او و ناظم با هم وارد شدند. گفتم نشست. و به جای این‌که حرفی بزند به گریه افتاد. هرگز گمان نمی‌کردم از چنان قد و قامتی صدای گریه در بیاید. این بود که از اتاق بیرون آمدم و فراش را صدا زدم که آب برایش بیاورد و حالش که جا آمد، بیاوردش پهلوی من. اما دیگر از او خبری نشد که نشد. نه آن روز و نه هیچ روز دیگر. آن روز چند دقیقه‌ای بعد از شیشه‌ی اتاق خودم دیدمش که دمش را لای پایش گذاشته بود از در مدرسه بیرون می‌رفت و فراش جدید آمد که بله می‌گفتند از پسرش پنج تومان خواسته بودند تا اسمش را برای کفش و لباس به انجمن بدهند. پیدا بود باز توی کوک ناظم رفته است. مرخصش کردم و ناظم را خواستم. معلوم شد می‌خواسته ناظم را بزند. همین جوری و بی‌مقدمه. + +اواخر بهمن بود که یکی از روزهای برفی با یکی دیگر از اولیای اطفال آشنا شدم. یارو مرد بسیار کوتاهی بود؛ فرنگ مآب و بزک کرده و اتو کشیده که ننشسته از تحصیلاتش و از سفرهای فرنگش حرف زد. می‌خواست پسرش را آن وقت سال از مدرسه‌ی دیگر به آن جا بیاورد. پسرش از آن بچه‌هایی بود که شیر و مربای صبحانه‌اش را با قربان صدقه توی حلقشان می‌تپانند. کلاس دوم بود و ثلث اول دو تا تجدید آورده بود. می‌گفت در باغ ییلاقی‌اش که نزدیک مدرسه است، باغبانی دارند که پسرش شاگرد ماست و درس‌خوان است و پیدا است که بچه‌ها زیر سایه شما خوب پیشرفت می‌کنند. و از این پیزرها. و حال به خاطر همین بچه، توی این برف و سرما، آمده‌اند ساکن باغ ییلاقی شده‌اند. بلند شدم ناظم را صدا کردم و دست او و بچه‌اش را توی دست ناظم گذاشتم و خداحافظ شما... و نیم ساعت بعد ناظم برگشت که یارو خانه‌ی شهرش را به یک دبیرستان اجاره داده، به ماهی سه هزار و دویست تومان، و التماس دعا داشته، یعنی معلم سرخانه می‌خواسته و حتی بدش نمی‌آمده است که خود مدیر زحمت بکشند و ازین گنده‌گوزی‌ها... احساس کردم که ناظم دهانش آب افتاده است. و من به ناظم حالی کردم خودش برود بهتر است و فقط کاری بکند که نه صدای معلم‌ها در بیاید و نه آخر سال، برای یک معدل ده احتیاجی به من بمیرم و تو بمیری پیدا کند. همان روز عصر ناظم رفته بود و قرار و مدار برای هر روز عصر یک ساعت به ماهی صد و پنجاه تومان. + +دیگر دنیا به کام ناظم بود. حال مادرش هم بهتر بود و از بیمارستان مرخصش کرده بودند و به فکر زن گرفتن افتاده بود. و هر روز هم برای یک نفر نقشه می‌کشید حتی برای من هم. یک روز در آمد که چرا ما خودمان «انجمن خانه و مدرسه» نداشته باشیم؟ نشسته بود و حسابش را کرده بود دیده بود که پنجاه شصت نفری از اولیای مدرسه دستشان به دهان‌شان می‌رسد و از آن هم که به پسرش درس خصوصی می‌داد قول مساعد گرفته بود. حالیش کردم که مواظب حرف و سخن اداره‌ای باشد و هر کار دلش می‌خواهد بکند. کاغذ دعوت را هم برایش نوشتم با آب و تاب و خودش برای اداره‌ی فرهنگ، داد ماشین کردند و به وسیله‌ی خود بچه‌ها فرستاد. و جلسه با حضور بیست و چند نفری از اولیای بچه‌ها رسمی شد. خوبیش این بود که پاسبان کشیک پاسگاه هم آمده بود و دم در برای همه، پاشنه‌هایش را به هم می‌کوبید و معلم‌ها گوش تا گوش نشسته بودند و مجلس ابهتی داشت و ناظم، چای و شیرینی تهیه کرده بود و چراغ زنبوری کرایه کرده بود و باران هم گذاشت پشتش و سالون برای اولین بار در عمرش به نوایی رسید. + +یک سرهنگ بود که رئیسش کردیم و آن زن را که هفته‌ای یک بار می‌آمد نایب رئیس. آن که ناظم به پسرش درس خصوصی می‌داد نیامده بود. اما پاکت سربسته‌ای به اسم مدیر فرستاده بود که فی‌المجلس بازش کردیم. عذرخواهی از این‌که نتوانسته بود بیاید و وجه ناقابلی جوف پاکت. صد و پنجاه تومان. و پول را روی میز صندوق‌دار گذاشتیم که ضبط و ربط کند. نائب رئیس بزک کرده و معطر شیرینی تعارف می‌کرد و معلم‌ها با هر بار که شیرینی بر می‌داشتند، یک بار تا بناگوش سرخ می‌شدند و فراش‌ها دست به دست چای می‌آوردند. + +در فکر بودم که یک مرتبه احساس کردم، سیصد چهارصد تومان پول نقد، روی میز است و هشت صد تومان هم تعهد کرده بودند. پیرزن صندوقدار که کیف پولش را همراهش نیاورده بود ناچار حضار تصویب کردند که پول‌ها فعلاً پیش ناظم باشد. و صورت مجلس مرتب شد و امضاها ردیف پای آن و فردا فهمیدم که ناظم همان شب روی خشت نشسته بوده و به معلم‌ها سور داده بوده است. اولین کاری که کردم رونوشت مجلس آن شب را برای اداره‌ی فرهنگ فرستادم. و بعد همان استاد نجار را صدا کردم و دستور دادم برای مستراح‌ها دو روزه در بسازد که ناظم خیلی به سختی پولش را داد. و بعد در کوچه‌ی مدرسه درخت کاشتیم. تور والیبال را تعویض و تعدادی توپ در اختیار بچه‌ها گذاشتیم برای تمرین در بعد از ظهرها و آمادگی برای مسابقه با دیگر مدارس و در همین حین سر و کله‌ی بازرس تربیت بدنی هم پیدا شد و هر روز سرکشی و بیا و برو. تا یک روز که به مدرسه رسیدم شنیدم که از سالون سر و صدا می‌آید. صدای هالتر بود. ناظم سر خود رفته بود و سرخود دویست سیصد تومان داده بود و هالتر خریده بود و بچه‌های لاغر زیر بار آن گردن خود را خرد می‌کردند. من در این میان حرفی نزدم. می‌توانستم حرفی بزنم؟ من چیکاره بودم؟ اصلاً به من چه ربطی داشت؟ هر کار که دلشان می‌خواهد بکنند. مهم این بود که سالون مدرسه رونقی گرفته بود. ناظم هم راضی بود و معلم‌ها هم. چون نه خبر از حسادتی بود و نه حرف و سخنی پیش آمد. فقط می‌بایست به ناظم سفارش می کردم که فکر فراش‌ها هم باشد. + +کم کم خودمان را برای امتحان‌های ثلث دوم آماده می‌کردیم. این بود که اوایل اسفند، یک روز معلم‌ها را صدا زدم و در شورا مانندی که کردیم بی‌مقدمه برایشان داستان یکی از همکاران سابقم را گفتم که هر وقت بیست می‌داد تا دو روز تب داشت. البته معلم‌ها خندیدند. ناچار تشویق شدم و داستان آخوندی را گفتم که در بچگی معلم شرعیاتمان بود و زیر عبایش نمره می‌داد و دستش چنان می‌لرزید که عبا تکان می‌خورد و درست ده دقیقه طول می‌کشید. و تازه چند؟ بهترین شاگردها دوازده. و البته باز هم خندیدند. که این بار کلافه‌ام کرد. و بعد حالیشان کردم که بد نیست در طرح سؤال‌ها مشورت کنیم و از این حرف‌ها... + +و از شنبه‌ی بعد، امتحانات شروع شد. درست از نیمه‌ی دوم اسفند. سؤال‌ها را سه نفری می‌دیدیم. خودم با معلم هر کلاس و ناظم. در سالون میزها را چیده بودیم البته از وقتی هالتردار شده بود خیلی زیباتر شده بود. در سالون کاردستی‌های بچه‌ها در همه جا به چشم می‌خورد. هر کسی هر چیزی را به عنوان کاردستی درست کرده بودند و آورده بودند. که برای این کاردستی‌ها چه پول‌ها که خرج نشده بود و چه دست‌ها که نبریده بود و چه دعواها که نشده بود و چه عرق‌ها که ریخته نشده بود. پیش از هر امتحان که می‌شد، خودم یک میتینگ برای بچه‌ها می‌دادم که ترس از معلم و امتحان بی‌جا است و باید اعتماد به نفس داشت و ازین مزخرفات....ولی مگر حرف به گوش کسی می‌رفت؟ از در که وارد می‌شدند، چنان هجومی می‌بردند که نگو! به جاهای دور از نظر. یک بار چنان بود که احساس کردم مثل این‌که از ترس، لذت می‌برند. اگر معلم نبودی یا مدیر، به راحتی می‌توانستی حدس بزنی که کی‌ها با هم قرار و مداری دارند و کدام یک پهلو دست کدام یک خواهد نشست. یکی دو بار کوشیدم بالای دست یکی‌شان بایستم و ببینم چه می‌نویسد. ولی چنان مضطرب می‌شدند و دستشان به لرزه می‌افتاد که از نوشتن باز می‌ماندند. می‌دیدم که این مردان آینده، درین کلاس‌ها و امتحان‌ها آن قدر خواهند ترسید که وقتی دیپلمه بشوند یا لیسانسه، اصلاً آدم نوع جدیدی خواهند شد. آدمی انباشته از وحشت، انبانی از ترس و دلهره. به این ترتیب یک روز بیشتر دوام نیاوردم. چون دیدم نمی‌توانم قلب بچگانه‌ای داشته باشم تا با آن ترس و وحشت بچه‌ها را درک کنم و هم‌دردی نشان بدهم.این جور بود که می‌دیدم که معلم مدرسه هم نمی‌توانم باشم. + +دو روز قبل از عید کارنامه‌ها آماده بود و منتظر امضای مدیر. دویست و سی و شش تا امضا اقلاً تا ظهر طول می‌کشید. پیش از آن هم تا می‌توانستم از امضای دفترهای حضور و غیاب می‌گریختم. خیلی از جیره‌خورهای دولت در ادارات دیگر یا در میان همکارانم دیده بودم که در مواقع بیکاری تمرین امضا می‌کنند. پیش از آن نمی‌توانستم بفهمم چه طور از مدیری یک مدرسه یا کارمندی ساده یک اداره می‌شود به وزارت رسید. یا اصلاً آرزویش را داشت. نیم‌قراضه امضای آماده و هر کدام معرف یک شخصیت، بعد نیم‌ذرع زبان چرب و نرم که با آن، مار را از سوراخ بیرون بکشی، یا همه جا را بلیسی و یک دست هم قیافه. نه یک جور. دوازده جور. + +در این فکرها بودم که ناگهان در میان کارنامه‌ها چشمم به یک اسم آشنا افتاد. به اسم پسران جناب سرهنگ که رئیس انجمن بود. رفتم توی نخ نمراتش. همه متوسط بود و جای ایرادی نبود. و یک مرتبه به صرافت افتادم که از اول سال تا به حال بچه‌های مدرسه را فقط به اعتبار وضع مالی پدرشان قضاوت کرده‌ام. درست مثل این پسر سرهنگ که به اعتبار کیابیای پدرش درس نمی‌خواند. دیدم هر کدام که پدرشان فقیرتر است به نظر من باهوش‌تر می‌آمده‌اند. البته ناظم با این حرف‌ها کاری نداشت. مر قانونی را عمل می‌کرد. از یکی چشم می‌پوشید به دیگری سخت می‌گرفت. + +اما من مثل این که قضاوتم را درباره‌ی بچه‌ها از پیش کرده باشم و چه خوب بود که نمره‌ها در اختیار من نبود و آن یکی هم «انظباط» مال آخر سال بود. مسخره‌ترین کارها آن است که کسی به اصلاح وضعی دست بزند، اما در قلمروی که تا سر دماغش بیشتر نیست. و تازه مدرسه‌ی من، این قلمروی فعالیت من، تا سر دماغم هم نبود. به همان توی ذهنم ختم می‌شد. وضعی را که دیگران ترتیب داده بودند. به این ترتیب بعد از پنج شش ماه، می‌فهمیدم که حسابم یک حساب عقلایی نبوده است. احساساتی بوده است. ضعف‌های احساساتی مرا خشونت‌های عملی ناظم جبران می‌کرد و این بود که جمعاً نمی‌توانستم ازو بگذرم. مرد عمل بود. کار را می‌برید و پیش می‌رفت. در زندگی و در هر کاری، هر قدمی بر می‌داشت، برایش هدف بود. و چشم از وجوه دیگر قضیه می‌پوشید. این بود که برش داشت. و من نمی‌توانستم. چرا که اصلاً مدیر نبودم. خلاص... + +و کارنامه‌ی پسر سرهنگ را که زیر دستم عرق کرده بود، به دقت و احتیاج خشک کردم و امضایی زیر آن گذاشتم به قدری بد خط و مسخره بود که به یاد امضای فراش جدیدمان افتادم. حتماً جناب سرهنگ کلافه می‌شد که چرا چنین آدم بی‌سوادی را با این خط و ربط امضا مدیر مدرسه کرده‌اند. آخر یک جناب سرهنگ هم می‌داند که امضای آدم معرف شخصیت آدم است. + +اواخر تعطیلات نوروز رفتم به ملاقات معلم ترکه‌ای کلاس سوم. ناظم که با او میانه‌ی خوشی نداشت. ناچار با معلم حساب کلاس پنج و شش قرار و مداری گذاشته بودم که مختصری علاقه‌ای هم به آن حرف و سخن‌ها داشت. هم به وسیله‌ی او بود که می‌دانستم نشانی‌اش کجا است و توی کدام زندان است. در راه قبل از هر چیز خبر داد که رئیس فرهنگ عوض شده و این طور که شایع است یکی از هم دوره‌ای‌های من، جایش آمده. گفتم: + +- عجب! چرا؟ مگه رئیس قبلی چپش کم بود؟ + +- چه عرض کنم. می‌گند پا تو کفش یکی از نماینده‌ها کرده. شما خبر ندارید؟ + +- چه طور؟ از کجا خبر داشته باشم؟ + +- هیچ چی... می گند دو تا از کارچاق‌کن‌های انتخاباتی یارو از صندوق فرهنگ حقوق می‌گرفته‌اند؛ شب عیدی رئیس فرهنگ حقوق‌شون رو زده. + +- عجب! پس اونم می‌خواسته اصلاحات کنه! بیچاره. + +و بعد از این حرف زدیم که الحمدالله مدرسه مرتب است و آرام و معلم‌ها همکاری می‌کنند و ناظم بیش از اندازه همه‌کاره شده است. و من فهمیدم که باز لابد مشتری خصوصی تازه‌ای پیدا شده است که سر و صدای همه همکارها بلند شده. دم در زندان شلوغ بود. کلاه مخملی‌ها، عم‌قزی گل‌بته‌ها، خاله خانباجی‌ها و... اسم نوشتیم و نوبت گرفتیم و به جای پاها، دست‌هامان زیر بار کوچکی که داشتیم، خسته شد و خواب رفت تا نوبتمان شد. از این اتاق به آن اتاق و عاقبت نرده‌های آهنی و پشت آن معلم کلاس سه و... عجب چاق شده بود!درست مثل یک آدم حسابی شده بود. خوشحال شدیم و احوالپرسی و تشکر؛ و دیگر چه بگویم؟ بگویم چرا خودت را به دردسر انداختی؟ پیدا بود از مدرسه و کلاس به او خوش‌تر می‌گذرد. ایمانی بود و او آن را داشت و خوشبخت بود و دردسری نمی‌دید و زندان حداقل برایش کلاس درس بود. عاقبت پرسیدم: + +- پرونده‌ای هم برات درست کردند یا هنوز بلاتکلیفی؟ + +- امتحانمو دادم آقا مدیر، بد از آب در نیومد. + +- یعنی چه؟ + +- یعنی بی‌تکلیف نیستم. چون اسمم تو لیست جیره‌ی زندون رفته. خیالم راحته. چون سختی‌هاش گذشته. + +دیگر چه بگویم. دیدم چیزی ندارم خداحافظی کردم و او را با معلم حساب تنها گذاشتم و آمدم بیرون و تا مدت ملاقات تمام بشود، دم در زندان قدم زدم و به زندانی فکر کردم که برای خودم ساخته بودم. یعنی آن خرپول فرهنگ‌دوست ساخته بود. و من به میل و رغبت خودم را در آن زندانی کرده بودم. این یکی را به ضرب دگنک این جا آورده بودند. ناچار حق داشت که خیالش راحت باشد. اما من به میل و رغبت رفته بودم و چه بکنم؟ ناظم چه طور؟ راستی اگر رئیس فرهنگ از هم دوره‌ای‌های خودم باشد؛ چه طور است بروم و ازو بخواهم که ناظم را جای من بگذارد، یا همین معلم حساب را؟... که معلم حساب در آمد و راه افتادیم. با او هم دیگر حرفی نداشتم. سر پیچ خداحافظ شما و تاکسی گرفتم و یک سر به اداره‌ی فرهنگ زدم. گرچه دهم عید بود، اما هنوز رفت و آمد سال نو تمام نشده بود. برو و بیا و شیرینی و چای دو جانبه. رفتم تو. سلام و تبریک و همین تعارفات را پراندم. + +بله خودش بود. یکی از پخمه‌های کلاس. که آخر سال سوم کشتیارش شدم دو بیت شعر را حفظ کند، نتوانست که نتوانست. و حالا او رئیس بود و من آقا مدیر. راستی حیف از من، که حتی وزیر چنین رئیس فرهنگ‌هایی باشم! میز همان طور پاک بود و رفته. اما زیرسیگاری انباشته از خاکستر و ته سیگار. بلند شد و چلپ و چولوپ روبوسی کردیم و پهلوی خودش جا باز کرد و گوش تا گوش جیره‌خورهای فرهنگ تبریکات صمیمانه و بدگویی از ماسبق و هندوانه و پیزرها! و دو نفر که قد و قواره‌شان به درد گود زورخانه می‌خورد یا پای صندوق انتخابات شیرینی به مردم می‌دادند. نزدیک بود شیرینی را توی ظرفش بیندازم که دیدم بسیار احمقانه است. سیگارم که تمام شد قضیه‌ی رئیس فرهنگ قبلی و آن دو نفر را در گوشی ازش پرسیدم، حرفی نزد. فقط نگاهی می‌کرد که شبیه التماس بود و من فرصت جستم تا وضع معلم کلاس سوم را برایش روشن کنم و از او بخواهم تا آن جا که می‌تواند جلوی حقوقش را نگیرد. و از در که آمدم بیرون، تازه یادم آمد که برای کار دیگری پیش رئیس فرهنگ بودم. + +باز دیروز افتضاحی به پا شد. معقول یک ماهه‌ی فروردین راحت بودیم. اول اردیبهشت ماه جلالی و کوس رسوایی سر دیوار مدرسه. نزدیک آخر وقت یک جفت پدر و مادر، بچه‌شان در میان، وارد اتاق شدند. یکی بر افروخته و دیگری رنگ و رو باخته و بچه‌شان عیناً مثل این عروسک‌های کوکی. سلام و علیک و نشستند. خدایا دیگر چه اتفاقی افتاده است؟ + +- چه خبر شده که با خانوم سرافرازمون کردید؟ + +مرد اشاره‌ای به زنش کرد که بلند شد و دست بچه را گرفت و رفت بیرون و من ماندم و پدر. اما حرف نمی‌زد. به خودش فرصت می‌داد تا عصبانیتش بپزد. سیگارم را در آوردم و تعارفش کردم. مثل این که مگس مزاحمی را از روی دماغش بپراند، سیگار را رد کرد و من که سیگارم را آتش می‌زدم، فکر کردم لابد دردی دارد که چنین دست و پا بسته و چنین متکی به خانواده به مدرسه آمده. باز پرسیدم: + +- خوب، حالا چه فرمایش داشتید؟ + +که یک مرتبه ترکید: + +- اگه من مدیر مدرسه بودم و هم‌چه اتفاقی می‌افتاد، شیکم خودمو پاره می‌کردم. خجالت بکش مرد! برو استعفا بده. تا اهل محل نریختن تیکه تیکه‌ات کنند، دو تا گوشتو وردار و دررو. بچه‌های مردم می‌آن این جا درس بخونن و حسن اخلاق. نمی‌آن که... + +- این مزخرفات کدومه آقا! حرف حساب سرکار چیه؟ + +و حرکتی کردم که او را از در بیندازم بیرون. اما آخر باید می‌فهمیدم چه مرگش است. «ولی آخر با من چه کار دارد؟» + +- آبروی من رفته. آبروی صد ساله‌ی خونواده‌ام رفته. اگه در مدرسه‌ی تو رو تخته نکنم، تخم بابام نیستم. آخه من دیگه با این بچه چی کار کنم؟ تو این مدرسه ناموس مردم در خطره. کلانتری فهمیده؛ پزشک قانونی فهمیده؛ یک پرونده درست شده پنجاه ورق؛ تازه می‌گی حرف حسابم چیه؟ حرف حسابم اینه که صندلی و این مقام از سر تو زیاده. حرف حسابم اینه که می‌دم محاکمه‌ات کنند و از نون خوردن بندازنت... + +او می‌گفت و من گوش می‌کردم و مثل دو تا سگ هار به جان هم افتاده بودیم که در باز شد و ناظم آمد تو. به دادم رسید. در همان حال که من و پدر بچه در حال دعوا بودیم زن و بچه همان آقا رفته بودند و قضایا را برای ناظم تعریف کرده بودند و او فرستاده بوده فاعل را از کلاس کشیده بودند بیرون... و گفت چه طور است زنگ بزنیم و جلوی بچه‌ها ادبش کنیم و کردیم. یعنی این بار خود من رفتم میدان. پسرک نره‌خری بود از پنجمی‌ها با لباس مرتب و صورت سرخ و سفید و سالکی به گونه. جلوی روی بچه‌ها کشیدمش زیر مشت و لگد و بعد سه تا از ترکه‌ها را که فراش جدید فوری از باغ همسایه آورده بود، به سر و صورتش خرد کردم. چنان وحشی شده بودم که اگر ترکه‌ها نمی‌رسید، پسرک را کشته بودم. این هم بود که ناظم به دادش رسید و وساطت کرد و لاشه‌اش را توی دفتر بردند و بچه‌ها را مرخص کردند و من به اتاقم برگشتم و با حالی زار روی صندلی افتادم، نه از پدر خبری بود و نه از مادر و نه از عروسک‌های کوکی‌شان که ناموسش دست کاری شده بود. و تازه احساس کردم که این کتک‌کاری را باید به او می‌زدم. خیس عرق بودم و دهانم تلخ بود. تمام فحش‌هایی که می‌بایست به آن مردکه‌ی دبنگ می‌دادم و نداده بودم، در دهانم رسوب کرده بود و مثل دم مار تلخ شده بود. اصلاً چرا زدمش؟ چرا نگذاشتم مثل همیشه ناظم میدان‌داری کند که هم کارکشته‌تر بود و هم خونسردتر. لابد پسرک با دخترعمه‌اش هم نمی‌تواند بازی کند. لابد توی خانواده‌شان، دخترها سر ده دوازده سالگی باید از پسرهای هم سن رو بگیرند. نکند عیبی کرده باشد؟ و یک مرتبه به صرافت افتادم که بروم ببینم چه بلایی به سرش آورده‌ام. بلند شدم و یکی از فراش‌ها را صدا کردم که فهمیدم روانه‌اش کرده‌اند. آبی آورد که روی دستم می‌ریخت و صورتم را می‌شستم و می‌کوشیدم که لرزش دست‌هایم را نبیند. و در گوشم آهسته گفت که پسر مدیر شرکت اتوبوسرانی است و بدجوری کتک خورده و آن‌ها خیلی سعی کرده‌اند که تر و تمیزش کنند... + +احمق مثلا داشت توی دل مرا خالی می‌کرد. نمی‌دانست که من اول تصمیم را گرفتم، بعد مثل سگ هار شدم. و تازه می‌فهمیدم کسی را زده‌ام که لیاقتش را داشته. حتماً از این اتفاق‌ها جای دیگر هم می‌افتد. آدم بردارد پایین تنه بچه‌ی خودش را، یا به قول خودش ناموسش را بگذارد سر گذر که کلانتر محل و پزشک معاینه کنند! تا پرونده درست کنند؟ با این پدرو مادرها بچه‌ها حق دارند که قرتی و دزد و دروغگو از آب در بیایند. این مدرسه‌ها را اول برای پدر و مادرها باز کنند... + +با این افکار به خانه رسیدم. زنم در را که باز کرد؛ چشم‌هایش گرد شد. همیشه وقتی می‌ترسد این طور می‌شود. برای اینکه خیال نکند آدم کشته‌ام، زود قضایا را برایش گفتم. و دیدم که در ماند. یعنی ساکت ماند. آب سرد، عرق بیدمشک، سیگار پشت سیگار فایده نداشت، لقمه از گلویم پایین نمی‌رفت و دست‌ها هنوز می‌لرزید. هر کدام به اندازه‌ی یک ماه فعالیت کرده بودند. با سیگار چهارم شروع کردم: + +- می‌دانی زن؟ بابای یارو پول‌داره. مسلماً کار به دادگستری و این جور خنس‌ها می‌کشه. مدیریت که الفاتحه. اما خیلی دلم می‌خواد قضیه به دادگاه برسه. یک سال آزگار رو دل کشیده‌ام و دیگه خسته شده‌ام. دلم می‌خواد یکی بپرسه چرا بچه‌ی مردم رو این طوری زدی، چرا تنبیه بدنی کردی! آخه یک مدیر مدرسه هم حرف‌هایی داره که باید یک جایی بزنه... + +که بلند شد و رفت سراغ تلفن. دو سه تا از دوستانم را که در دادگستری کاره‌ای بودند، گرفت و خودم قضیه را برایشان گفتم که مواظب باشند. فردا پسرک فاعل به مدرسه نیامده بود. و ناظم برایم گفت که قضیه ازین قرار بوده است که دوتایی به هوای دیدن مجموعه تمبرهای فاعل با هم به خانه‌ای می‌روند و قضایا همان جا اتفاق می‌افتد و داد و هوار و دخالت پدر و مادرهای طرفین و خط و نشان و شبانه کلانتری؛ و تمام اهل محل خبر دارند. او هم نظرش این بود که کار به دادگستری خواهد کشید. + +و من یک هفته‌ی تمام به انتظار اخطاریه‌ی دادگستری صبح و عصر به مدرسه رفتم و مثل بخت‌النصر پشت پنجره ایستادم. اما در تمام این مدت نه از فاعل خبری شد، نه از مفعول و نه از پدر و مادر ناموس‌پرست و نه از مدیر شرکت اتوبوسرانی. انگار نه انگار که اتفاقی افتاده. بچه‌ها می‌آمدند و می‌رفتند؛ برای آب خوردن عجله می‌کردند؛ به جای بازی کتک‌کاری می‌کردند و همه چیز مثل قبل بود. فقط من ماندم و یک دنیا حرف و انتظار. تا عاقبت رسید.... احضاریه‌ای با تعیین وقت قبلی برای دو روز بعد، در فلان شعبه و پیش فلان بازپرس دادگستری. آخر کسی پیدا شده بود که به حرفم گوش کند. + +تا دو روز بعد که موعد احضار بود، اصلاً از خانه در نیامدم. نشستم و ماحصل حرف‌هایم را روی کاغذ آوردم. حرف‌هایی که با همه‌ی چرندی هر وزیر فرهنگی می‌توانست با آن یک برنامه‌ی هفت ساله برای کارش بریزد. و سر ساعت معین رفتم دادگستری. اتاق معین و بازپرس معین. در را باز کردم و سلام، و تا آمدم خودم را معرفی کنم و احضاریه را در بیاورم، یارو پیش‌دستی کرد و صندلی آورد و چای سفارش داد و «احتیاجی به این حرف‌ها نیست و قضیه‌ی کوچک بود و حل شد و راضی به زحمت شما نبودیم...» + +که عرق سرد بر بدن من نشست. چایی‌ام را که خوردم، روی همان کاغذ نشان‌دار دادگستری استعفانامه‌ام را نوشتم و به نام هم‌کلاسی پخمه‌ام که تازه رئیس شده بود، دم در پست کردم. +EOT; +} diff --git a/lib/faker/src/Faker/Provider/fi_FI/Address.php b/lib/faker/src/Faker/Provider/fi_FI/Address.php new file mode 100755 index 0000000..8e0829e --- /dev/null +++ b/lib/faker/src/Faker/Provider/fi_FI/Address.php @@ -0,0 +1,85 @@ + 'Ain'), array('02' => 'Aisne'), array('03' => 'Allier'), array('04' => 'Alpes-de-Haute-Provence'), array('05' => 'Hautes-Alpes'), + array('06' => 'Alpes-Maritimes'), array('07' => 'Ardèche'), array('08' => 'Ardennes'), array('09' => 'Ariège'), array('10' => 'Aube'), + array('11' => 'Aude'), array('12' => 'Aveyron'), array('13' => 'Bouches-du-Rhône'), array('14' => 'Calvados'), array('15' => 'Cantal'), + array('16' => 'Charente'), array('17' => 'Charente-Maritime'), array('18' => 'Cher'), array('19' => 'Corrèze'), array('2A' => 'Corse-du-Sud'), + array('2B' => 'Haute-Corse'), array('21' => "Côte-d'Or"), array('22' => "Côtes-d'Armor"), array('23' => 'Creuse'), array('24' => 'Dordogne'), + array('25' => 'Doubs'), array('26' => 'Drôme'), array('27' => 'Eure'), array('28' => 'Eure-et-Loir'), array('29' => 'Finistère'), array('30' => 'Gard'), + array('31' => 'Haute-Garonne'), array('32' => 'Gers'), array('33' => 'Gironde'), array('34' => 'Hérault'), array('35' => 'Ille-et-Vilaine'), + array('36' => 'Indre'), array('37' => 'Indre-et-Loire'), array('38' => 'Isère'), array('39' => 'Jura'), array('40' => 'Landes'), array('41' => 'Loir-et-Cher'), + array('42' => 'Loire'), array('43' => 'Haute-Loire'), array('44' => 'Loire-Atlantique'), array('45' => 'Loiret'), array('46' => 'Lot'), + array('47' => 'Lot-et-Garonne'), array('48' => 'Lozère'), array('49' => 'Maine-et-Loire'), array('50' => 'Manche'), array('51' => 'Marne'), + array('52' => 'Haute-Marne'), array('53' => 'Mayenne'), array('54' => 'Meurthe-et-Moselle'), array('55' => 'Meuse'), array('56' => 'Morbihan'), + array('57' => 'Moselle'), array('58' => 'Nièvre'), array('59' => 'Nord'), array('60' => 'Oise'), array('61' => 'Orne'), array('62' => 'Pas-de-Calais'), + array('63' => 'Puy-de-Dôme'), array('64' => 'Pyrénées-Atlantiques'), array('65' => 'Hautes-Pyrénées'), array('66' => 'Pyrénées-Orientales'), + array('67' => 'Bas-Rhin'), array('68' => 'Haut-Rhin'), array('69' => 'Rhône'), array('70' => 'Haute-Saône'), array('71' => 'Saône-et-Loire'), + array('72' => 'Sarthe'), array('73' => 'Savoie'), array('74' => 'Haute-Savoie'), array('75' => 'Paris'), array('76' => 'Seine-Maritime'), + array('77' => 'Seine-et-Marne'), array('78' => 'Yvelines'), array('79' => 'Deux-Sèvres'), array('80' => 'Somme'), array('81' => 'Tarn'), + array('82' => 'Tarn-et-Garonne'), array('83' => 'Var'), array('84' => 'Vaucluse'), array('85' => 'Vendée'), array('86' => 'Vienne'), + array('87' => 'Haute-Vienne'), array('88' => 'Vosges'), array('89' => 'Yonne'), array('90' => 'Territoire de Belfort'), array('91' => 'Essonne'), + array('92' => 'Hauts-de-Seine'), array('93' => 'Seine-Saint-Denis'), array('94' => 'Val-de-Marne'), array('95' => "Val-d'Oise"), + array('971' => 'Guadeloupe'), array('972' => 'Martinique'), array('973' => 'Guyane'), array('974' => 'La Réunion'), array('976' => 'Mayotte') + ); + + /** + * @example 'rue' + */ + public static function streetPrefix() + { + return static::randomElement(static::$streetPrefix); + } + + /** + * Randomly returns a french region. + * + * @example 'Guadeloupe' + * + * @return string + */ + public static function region() + { + return static::randomElement(static::$regions); + } + + /** + * Randomly returns a french department ('departmentNumber' => 'departmentName'). + * + * @example array('2B' => 'Haute-Corse') + * + * @return array + */ + public static function department() + { + return static::randomElement(static::$departments); + } + + /** + * Randomly returns a french department name. + * + * @example 'Ardèche' + * + * @return string + */ + public static function departmentName() + { + $randomDepartmentName = array_values(static::department()); + + return $randomDepartmentName[0]; + } + + /** + * Randomly returns a french department number. + * + * @example '59' + * + * @return string + */ + public static function departmentNumber() + { + $randomDepartmentNumber = array_keys(static::department()); + + return $randomDepartmentNumber[0]; + } +} diff --git a/lib/faker/src/Faker/Provider/fr_FR/Company.php b/lib/faker/src/Faker/Provider/fr_FR/Company.php new file mode 100755 index 0000000..5f44066 --- /dev/null +++ b/lib/faker/src/Faker/Provider/fr_FR/Company.php @@ -0,0 +1,169 @@ +generator->parse($format)); + + if ($this->isCatchPhraseValid($catchPhrase)) { + break; + } + } while (true); + + return $catchPhrase; + } + + /** + * Generates a siret number (14 digits) that passes the Luhn check. + * + * @see http://fr.wikipedia.org/wiki/Syst%C3%A8me_d'identification_du_r%C3%A9pertoire_des_%C3%A9tablissements + * @return string + */ + public function siret($formatted = true) + { + $siret = $this->siren(false); + $nicFormat = static::randomElement(static::$siretNicFormats); + $siret .= $this->numerify($nicFormat); + $siret .= Luhn::computeCheckDigit($siret); + if ($formatted) { + $siret = substr($siret, 0, 3) . ' ' . substr($siret, 3, 3) . ' ' . substr($siret, 6, 3) . ' ' . substr($siret, 9, 5); + } + + return $siret; + } + + /** + * Generates a siren number (9 digits) that passes the Luhn check. + * + * @see http://fr.wikipedia.org/wiki/Syst%C3%A8me_d%27identification_du_r%C3%A9pertoire_des_entreprises + * @return string + */ + public function siren($formatted = true) + { + $siren = $this->numerify('%#######'); + $siren .= Luhn::computeCheckDigit($siren); + if ($formatted) { + $siren = substr($siren, 0, 3) . ' ' . substr($siren, 3, 3) . ' ' . substr($siren, 6, 3); + } + + return $siren; + } + + /** + * @var array An array containing string which should not appear twice in a catch phrase. + */ + protected static $wordsWhichShouldNotAppearTwice = array('sécurité', 'simpl'); + + /** + * Validates a french catch phrase. + * + * @param string $catchPhrase The catch phrase to validate. + * + * @return boolean (true if valid, false otherwise) + */ + protected static function isCatchPhraseValid($catchPhrase) + { + foreach (static::$wordsWhichShouldNotAppearTwice as $word) { + // Fastest way to check if a piece of word does not appear twice. + $beginPos = strpos($catchPhrase, $word); + $endPos = strrpos($catchPhrase, $word); + + if ($beginPos !== false && $beginPos != $endPos) { + return false; + } + } + + return true; + } +} diff --git a/lib/faker/src/Faker/Provider/fr_FR/Internet.php b/lib/faker/src/Faker/Provider/fr_FR/Internet.php new file mode 100755 index 0000000..8e3024b --- /dev/null +++ b/lib/faker/src/Faker/Provider/fr_FR/Internet.php @@ -0,0 +1,9 @@ +generator->parse($format); + } + + public static function country() + { + return static::randomElement(static::$country); + } + + public static function postcode() + { + return static::toUpper(static::bothify(static::randomElement(static::$postcode))); + } + + public static function regionSuffix() + { + return static::randomElement(static::$regionSuffix); + } + + public static function region() + { + return static::randomElement(static::$region); + } + + public static function cityPrefix() + { + return static::randomElement(static::$cityPrefix); + } + + public function city() + { + return static::randomElement(static::$city); + } + + public function streetPrefix() + { + return static::randomElement(static::$streetPrefix); + } + + public static function street() + { + return static::randomElement(static::$street); + } +} diff --git a/lib/faker/src/Faker/Provider/hy_AM/Company.php b/lib/faker/src/Faker/Provider/hy_AM/Company.php new file mode 100755 index 0000000..8ef3cce --- /dev/null +++ b/lib/faker/src/Faker/Provider/hy_AM/Company.php @@ -0,0 +1,54 @@ +generator->parse($format); + } + + public static function street() + { + return static::randomElement(static::$street); + } + + public static function buildingNumber() + { + return static::numberBetween(1, 999); + } +} diff --git a/lib/faker/src/Faker/Provider/id_ID/Company.php b/lib/faker/src/Faker/Provider/id_ID/Company.php new file mode 100755 index 0000000..7839f1e --- /dev/null +++ b/lib/faker/src/Faker/Provider/id_ID/Company.php @@ -0,0 +1,43 @@ +generator->parse($lastNameRandomElement); + } + + /** + * Return last name for male + * + * @access public + * @return string last name + */ + public static function lastNameMale() + { + return static::randomElement(static::$lastNameMale); + } + + /** + * Return last name for female + * + * @access public + * @return string last name + */ + public static function lastNameFemale() + { + return static::randomElement(static::$lastNameFemale); + } + + /** + * For academic title + * + * @access public + * @return string suffix + */ + public static function suffix() + { + return static::randomElement(static::$suffix); + } +} diff --git a/lib/faker/src/Faker/Provider/id_ID/PhoneNumber.php b/lib/faker/src/Faker/Provider/id_ID/PhoneNumber.php new file mode 100755 index 0000000..de5c969 --- /dev/null +++ b/lib/faker/src/Faker/Provider/id_ID/PhoneNumber.php @@ -0,0 +1,55 @@ + + */ +class Address extends \Faker\Provider\Address +{ + /** + * @var array Countries in icelandic + */ + protected static $country = array( + 'Afganistan', 'Albanía', 'Alsír', 'Andorra', 'Angóla', 'Angvilla', 'Antígva og Barbúda', 'Argentína', + 'Armenía', 'Arúba', 'Aserbaídsjan', 'Austur-Kongó', 'Austurríki', 'Austur-Tímor', 'Álandseyjar', + 'Ástralía', 'Bahamaeyjar', 'Bandaríkin', 'Bandaríska Samóa', 'Bangladess', 'Barbados', 'Barein', + 'Belgía', 'Belís', 'Benín', 'Bermúdaeyjar', 'Bosnía og Hersegóvína', 'Botsvana', 'Bouvet-eyja', 'Bólivía', + 'Brasilía', 'Bresku Indlandshafseyjar', 'Bretland', 'Brúnei', 'Búlgaría', 'Búrkína Fasó', 'Búrúndí', 'Bútan', + 'Cayman-eyjar', 'Chile', 'Cooks-eyjar', 'Danmörk', 'Djíbútí', 'Dóminíka', 'Dóminíska lýðveldið', 'Egyptaland', + 'Eistland', 'Ekvador', 'El Salvador', 'England', 'Erítrea', 'Eþíópía', 'Falklandseyjar', 'Filippseyjar', + 'Finnland', 'Fídjieyjar', 'Fílabeinsströndin', 'Frakkland', 'Franska Gvæjana', 'Franska Pólýnesía', + 'Frönsku suðlægu landsvæðin', 'Færeyjar', 'Gabon', 'Gambía', 'Gana', 'Georgía', 'Gíbraltar', 'Gínea', + 'Gínea-Bissá', 'Grenada', 'Grikkland', 'Grænhöfðaeyjar', 'Grænland', 'Gvadelúpeyjar', 'Gvam', 'Gvatemala', + 'Gvæjana', 'Haítí', 'Heard og McDonalds-eyjar', 'Holland', 'Hollensku Antillur', 'Hondúras', 'Hong Kong', + 'Hvíta-Rússland', 'Indland', 'Indónesía', 'Írak', 'Íran', 'Írland', 'Ísland', 'Ísrael', 'Ítalía', 'Jamaíka', + 'Japan', 'Jemen', 'Jólaey', 'Jómfrúaeyjar', 'Jórdanía', 'Kambódía', 'Kamerún', 'Kanada', 'Kasakstan', 'Katar', + 'Kenía', 'Kirgisistan', 'Kína', 'Kíribatí', 'Kongó', 'Austur-Kongó', 'Vestur-Kongó', 'Kostaríka', 'Kókoseyjar', + 'Kólumbía', 'Kómoreyjar', 'Kórea', 'Norður-Kórea;', 'Suður-Kórea', 'Króatía', 'Kúba', 'Kúveit', 'Kýpur', + 'Laos', 'Lesótó', 'Lettland', 'Liechtenstein', 'Litháen', 'Líbanon', 'Líbería', 'Líbía', 'Lúxemborg', + 'Madagaskar', 'Makaó', 'Makedónía', 'Malasía', 'Malaví', 'Maldíveyjar', 'Malí', 'Malta', 'Marokkó', + 'Marshall-eyjar', 'Martiník', 'Mayotte', 'Máritanía', 'Máritíus', 'Mexíkó', 'Mið-Afríkulýðveldið', + 'Miðbaugs-Gínea', 'Míkrónesía', 'Mjanmar', 'Moldóva', 'Mongólía', 'Montserrat', 'Mónakó', 'Mósambík', + 'Namibía', 'Nárú', 'Nepal', 'Niue', 'Níger', 'Nígería', 'Níkaragva', 'Norður-Írland', 'Norður-Kórea', + 'Norður-Maríanaeyjar', 'Noregur', 'Norfolkeyja', 'Nýja-Kaledónía', 'Nýja-Sjáland', 'Óman', 'Pakistan', + 'Palá', 'Palestína', 'Panama', 'Papúa Nýja-Gínea', 'Paragvæ', 'Páfagarður', 'Perú', 'Pitcairn', 'Portúgal', + 'Pólland', 'Púertó Ríkó', 'Réunion', 'Rúanda', 'Rúmenía', 'Rússland', 'Salómonseyjar', 'Sambía', + 'Sameinuðu arabísku furstadæmin', 'Samóa', 'San Marínó', 'Sankti Helena', 'Sankti Kristófer og Nevis', + 'Sankti Lúsía', 'Sankti Pierre og Miquelon', 'Sankti Vinsent og Grenadíneyjar', 'Saó Tóme og Prinsípe', + 'Sádi-Arabía', 'Senegal', 'Serbía', 'Seychelles-eyjar', 'Simbabve', 'Singapúr', 'Síerra Leóne', 'Skotland', + 'Slóvakía', 'Slóvenía', 'Smáeyjar Bandaríkjanna', 'Sómalía', 'Spánn', 'Srí Lanka', 'Suður-Afríka', + 'Suður-Georgía og Suður-Sandvíkureyjar', 'Suður-Kórea', 'Suðurskautslandið', 'Súdan', 'Súrínam', 'Jan Mayen', + 'Svartfjallaland', 'Svasíland', 'Sviss', 'Svíþjóð', 'Sýrland', 'Tadsjikistan', 'Taíland', 'Taívan', 'Tansanía', + 'Tékkland', 'Tonga', 'Tógó', 'Tókelá', 'Trínidad og Tóbagó', 'Tsjad', 'Tsjetsjenía', 'Turks- og Caicos-eyjar', + 'Túnis', 'Túrkmenistan', 'Túvalú', 'Tyrkland', 'Ungverjaland', 'Úganda', 'Úkraína', 'Úrúgvæ', 'Úsbekistan', + 'Vanúatú', 'Venesúela', 'Vestur-Kongó', 'Vestur-Sahara', 'Víetnam', 'Wales', 'Wallis- og Fútúnaeyjar', 'Þýskaland' + ); + + /** + * @var array Icelandic cities. + */ + protected static $cityNames = array( + 'Reykjavík', 'Seltjarnarnes', 'Vogar', 'Kópavogur', 'Garðabær', 'Hafnarfjörður', 'Reykjanesbær', 'Grindavík', + 'Sandgerði', 'Garður', 'Reykjanesbær', 'Mosfellsbær', 'Akranes', 'Borgarnes', 'Reykholt', 'Stykkishólmur', + 'Flatey', 'Grundarfjörður', 'Ólafsvík', 'Snæfellsbær', 'Hellissandur', 'Búðardalur', 'Reykhólahreppur', + 'Ísafjörður', 'Hnífsdalur', 'Bolungarvík', 'Súðavík', 'Flateyri', 'Suðureyri', 'Patreksfjörður', + 'Tálknafjörður', 'Bíldudalur', 'Þingeyri', 'Staður', 'Hólmavík', 'Drangsnes', 'Árneshreppur', 'Hvammstangi', + 'Blönduós', 'Skagaströnd', 'Sauðárkrókur', 'Varmahlíð', 'Hofsós', 'Fljót', 'Siglufjörður', 'Akureyri', + 'Grenivík', 'Grímsey', 'Dalvík', 'Ólafsfjörður', 'Hrísey', 'Húsavík', 'Fosshóll', 'Laugar', 'Mývatn', + 'Kópasker', 'Raufarhöfn', 'Þórshöfn', 'Bakkafjörður', 'Vopnafjörður', 'Egilsstaðir', 'Seyðisfjörður', + 'Mjóifjörður', 'Borgarfjörður', 'Reyðarfjörður', 'Eskifjörður', 'Neskaupstaður', 'Fáskrúðsfjörður', + 'Stöðvarfjörður', 'Breiðdalsvík', 'Djúpivogur', 'Höfn', 'Selfoss', 'Hveragerði', 'Þorlákshöfn', 'Ölfus', + 'Eyrarbakki', 'Stokkseyri', 'Laugarvatn', 'Flúðir', 'Hella', 'Hvolsvöllur', 'Vík', 'Kirkjubæjarklaustur', + 'Vestmannaeyjar' + ); + + /** + * @var array Street name suffix. + */ + protected static $streetSuffix = array( + 'ás', 'bakki', 'braut', 'bær', 'brún', 'berg', 'fold', 'gata', 'gróf', + 'garðar', 'höfði', 'heimar', 'hamar', 'hólar', 'háls', 'kvísl', 'lækur', + 'leiti', 'land', 'múli', 'nes', 'rimi', 'stígur', 'stræti', 'stekkur', + 'slóð', 'skógar', 'sel', 'teigur', 'tún', 'vangur', 'vegur', 'vogur', + 'vað' + ); + + /** + * @var array Street name prefix. + */ + protected static $streetPrefix = array( + 'Aðal', 'Austur', 'Bakka', 'Braga', 'Báru', 'Brunn', 'Fiski', 'Leifs', + 'Týs', 'Birki', 'Suður', 'Norður', 'Vestur', 'Austur', 'Sanda', 'Skógar', + 'Stór', 'Sunnu', 'Tungu', 'Tangar', 'Úlfarfells', 'Vagn', 'Vind', 'Ysti', + 'Þing', 'Hamra', 'Hóla', 'Kríu', 'Iðu', 'Spóa', 'Starra', 'Uglu', 'Vals' + ); + + /** + * @var Icelandic zip code. + **/ + protected static $postcode = array( + '%##' + ); + + /** + * @var array Icelandic regions. + */ + protected static $regionNames = array( + 'Höfuðborgarsvæðið', 'Norðurland', 'Suðurland', 'Vesturland', 'Vestfirðir', 'Austurland', 'Suðurnes' + ); + + /** + * @var array Icelandic building numbers. + */ + protected static $buildingNumber = array( + '%##', '%#', '%#', '%', '%', '%', '%?', '% ?', + ); + + /** + * @var array Icelandic city format. + */ + protected static $cityFormats = array( + '{{cityName}}', + ); + + /** + * @var array Icelandic street's name formats. + */ + protected static $streetNameFormats = array( + '{{streetPrefix}}{{streetSuffix}}', + '{{streetPrefix}}{{streetSuffix}}', + '{{firstNameMale}}{{streetSuffix}}', + '{{firstNameFemale}}{{streetSuffix}}' + ); + + /** + * @var array Icelandic street's address formats. + */ + protected static $streetAddressFormats = array( + '{{streetName}} {{buildingNumber}}' + ); + + /** + * @var array Icelandic address format. + */ + protected static $addressFormats = array( + "{{streetAddress}}\n{{postcode}} {{city}}", + ); + + /** + * Randomly return a real city name. + * + * @return string + */ + public static function cityName() + { + return static::randomElement(static::$cityNames); + } + + /** + * Randomly return a street prefix. + * + * @return string + */ + public static function streetPrefix() + { + return static::randomElement(static::$streetPrefix); + } + + /** + * Randomly return a building number. + * + * @return string + */ + public static function buildingNumber() + { + return static::toUpper(static::bothify(static::randomElement(static::$buildingNumber))); + } + + /** + * Randomly return a real region name. + * + * @return string + */ + public static function region() + { + return static::randomElement(static::$regionNames); + } +} diff --git a/lib/faker/src/Faker/Provider/is_IS/Company.php b/lib/faker/src/Faker/Provider/is_IS/Company.php new file mode 100755 index 0000000..6b93451 --- /dev/null +++ b/lib/faker/src/Faker/Provider/is_IS/Company.php @@ -0,0 +1,53 @@ + + */ +class Company extends \Faker\Provider\Company +{ + /** + * @var array Danish company name formats. + */ + protected static $formats = array( + '{{lastName}} {{companySuffix}}', + '{{lastName}} {{companySuffix}}', + '{{lastName}} {{companySuffix}}', + '{{firstname}} {{lastName}} {{companySuffix}}', + '{{middleName}} {{companySuffix}}', + '{{middleName}} {{companySuffix}}', + '{{middleName}} {{companySuffix}}', + '{{firstname}} {{middleName}} {{companySuffix}}', + '{{lastName}} & {{lastName}} {{companySuffix}}', + '{{lastName}} og {{lastName}} {{companySuffix}}', + '{{lastName}} & {{lastName}} {{companySuffix}}', + '{{lastName}} og {{lastName}} {{companySuffix}}', + '{{middleName}} & {{middleName}} {{companySuffix}}', + '{{middleName}} og {{middleName}} {{companySuffix}}', + '{{middleName}} & {{lastName}}', + '{{middleName}} og {{lastName}}', + ); + + /** + * @var array Company suffixes. + */ + protected static $companySuffix = array('ehf.', 'hf.', 'sf.'); + + /** + * @link http://www.rsk.is/atvinnurekstur/virdisaukaskattur/ + * + * @var string VSK number format. + */ + protected static $vskFormat = '%####'; + + /** + * Generates a VSK number (5 digits). + * + * @return string + */ + public static function vsk() + { + return static::numerify(static::$vskFormat); + } +} diff --git a/lib/faker/src/Faker/Provider/is_IS/Internet.php b/lib/faker/src/Faker/Provider/is_IS/Internet.php new file mode 100755 index 0000000..a265da6 --- /dev/null +++ b/lib/faker/src/Faker/Provider/is_IS/Internet.php @@ -0,0 +1,23 @@ + + */ +class Internet extends \Faker\Provider\Internet +{ + /** + * @var array Some email domains in Denmark. + */ + protected static $freeEmailDomain = array( + 'gmail.com', 'yahoo.com', 'hotmail.com', 'visir.is', 'simnet.is', 'internet.is' + ); + + /** + * @var array Some TLD. + */ + protected static $tld = array( + 'com', 'com', 'com', 'net', 'is', 'is', 'is', + ); +} diff --git a/lib/faker/src/Faker/Provider/is_IS/Payment.php b/lib/faker/src/Faker/Provider/is_IS/Payment.php new file mode 100755 index 0000000..c119c38 --- /dev/null +++ b/lib/faker/src/Faker/Provider/is_IS/Payment.php @@ -0,0 +1,19 @@ + + */ +class Person extends \Faker\Provider\Person +{ + /** + * @var array Icelandic person name formats. + */ + protected static $maleNameFormats = array( + '{{firstNameMale}} {{lastNameMale}}', + '{{firstNameMale}} {{lastNameMale}}', + '{{firstNameMale}} {{middleName}} {{lastNameMale}}', + '{{firstNameMale}} {{middleName}} {{lastNameMale}}', + ); + + protected static $femaleNameFormats = array( + '{{firstNameFemale}} {{lastNameFemale}}', + '{{firstNameFemale}} {{lastNameFemale}}', + '{{firstNameFemale}} {{middleName}} {{lastNameFemale}}', + '{{firstNameFemale}} {{middleName}} {{lastNameFemale}}', + ); + + /** + * @var string Icelandic women names. + */ + protected static $firstNameFemale = array('Aagot', 'Abela', 'Abigael', 'Ada', 'Adda', 'Addý', 'Adela', 'Adelía', 'Adríana', 'Aðalbjörg', 'Aðalbjört', 'Aðalborg', 'Aðaldís', 'Aðalfríður', 'Aðalheiður', 'Aðalrós', 'Aðalsteina', 'Aðalsteinunn', 'Aðalveig', 'Agata', 'Agatha', 'Agða', 'Agla', 'Agnea', 'Agnes', 'Agneta', 'Alanta', 'Alba', 'Alberta', 'Albína', 'Alda', 'Aldís', 'Aldný', 'Aleta', 'Aletta', 'Alexa', 'Alexandra', 'Alexandría', 'Alexis', 'Alexía', 'Alfa', 'Alfífa', 'Alice', 'Alida', 'Alída', 'Alína', 'Alís', 'Alísa', 'Alla', 'Allý', 'Alma', 'Alrún', 'Alva', 'Alvilda', 'Amadea', 'Amal', 'Amalía', 'Amanda', 'Amelía', 'Amilía', 'Amíra', 'Amy', 'Amý', 'Analía', 'Anastasía', 'Andra', 'Andrá', 'Andrea', 'Anetta', 'Angela', 'Angelíka', 'Anika', 'Anita', 'Aníka', 'Anína', 'Aníta', 'Anja', 'Ann', 'Anna', 'Annabella', 'Annalísa', 'Anne', 'Annelí', 'Annetta', 'Anney', 'Annika', 'Annía', 'Anný', 'Antonía', 'Apríl', 'Ardís', 'Arey', 'Arinbjörg', 'Aris', 'Arisa', 'Aría', 'Aríanna', 'Aríella', 'Arín', 'Arína', 'Arís', 'Armenía', 'Arna', 'Arnbjörg', 'Arnborg', 'Arndís', 'Arney', 'Arnfinna', 'Arnfríður', 'Arngerður', 'Arngunnur', 'Arnheiður', 'Arnhildur', 'Arnika', 'Arnkatla', 'Arnlaug', 'Arnleif', 'Arnlín', 'Arnljót', 'Arnóra', 'Arnrós', 'Arnrún', 'Arnþóra', 'Arnþrúður', 'Asírí', 'Askja', 'Assa', 'Astrid', 'Atalía', 'Atena', 'Athena', 'Atla', 'Atlanta', 'Auðbjörg', 'Auðbjört', 'Auðdís', 'Auðlín', 'Auðna', 'Auðný', 'Auðrún', 'Auður', 'Aurora', 'Axelía', 'Axelma', 'Aþena', 'Ágústa', 'Ágústína', 'Álfdís', 'Álfey', 'Álfgerður', 'Álfheiður', 'Álfhildur', 'Álfrós', 'Álfrún', 'Álfsól', 'Árbjörg', 'Árbjört', 'Árdís', 'Árelía', 'Árlaug', 'Ármey', 'Árna', 'Árndís', 'Árney', 'Árnheiður', 'Árnína', 'Árný', 'Áróra', 'Ársól', 'Ársæl', 'Árún', 'Árveig', 'Árvök', 'Árþóra', 'Ása', 'Ásbjörg', 'Ásborg', 'Ásdís', 'Ásfríður', 'Ásgerður', 'Áshildur', 'Áskatla', 'Ásla', 'Áslaug', 'Ásleif', 'Ásný', 'Ásrós', 'Ásrún', 'Ást', 'Ásta', 'Ástbjörg', 'Ástbjört', 'Ástdís', 'Ástfríður', 'Ástgerður', 'Ástheiður', 'Ásthildur', 'Ástríður', 'Ástrós', 'Ástrún', 'Ástveig', 'Ástþóra', 'Ástþrúður', 'Ásvör', 'Baldey', 'Baldrún', 'Baldvina', 'Barbara', 'Barbára', 'Bassí', 'Bára', 'Bebba', 'Begga', 'Belinda', 'Bella', 'Benedikta', 'Bengta', 'Benidikta', 'Benía', 'Beníta', 'Benna', 'Benney', 'Benný', 'Benta', 'Bentey', 'Bentína', 'Bera', 'Bergdís', 'Bergey', 'Bergfríður', 'Bergheiður', 'Berghildur', 'Berglaug', 'Berglind', 'Berglín', 'Bergljót', 'Bergmannía', 'Bergný', 'Bergrán', 'Bergrín', 'Bergrós', 'Bergrún', 'Bergþóra', 'Berit', 'Bernódía', 'Berta', 'Bertha', 'Bessí', 'Bestla', 'Beta', 'Betanía', 'Betsý', 'Bettý', 'Bil', 'Birgit', 'Birgitta', 'Birna', 'Birta', 'Birtna', 'Bíbí', 'Bína', 'Bjargdís', 'Bjargey', 'Bjargheiður', 'Bjarghildur', 'Bjarglind', 'Bjarkey', 'Bjarklind', 'Bjarma', 'Bjarndís', 'Bjarney', 'Bjarnfríður', 'Bjarngerður', 'Bjarnheiður', 'Bjarnhildur', 'Bjarnlaug', 'Bjarnrún', 'Bjarnveig', 'Bjarný', 'Bjarnþóra', 'Bjarnþrúður', 'Bjartey', 'Bjartmey', 'Björg', 'Björgey', 'Björgheiður', 'Björghildur', 'Björk', 'Björney', 'Björnfríður', 'Björt', 'Bláey', 'Blíða', 'Blín', 'Blómey', 'Blædís', 'Blær', 'Bobba', 'Boga', 'Bogdís', 'Bogey', 'Bogga', 'Boghildur', 'Borg', 'Borgdís', 'Borghildur', 'Borgný', 'Borgrún', 'Borgþóra', 'Botnía', 'Bóel', 'Bót', 'Bóthildur', 'Braga', 'Braghildur', 'Branddís', 'Brá', 'Brák', 'Brigitta', 'Brimdís', 'Brimhildur', 'Brimrún', 'Brit', 'Britt', 'Britta', 'Bríana', 'Bríanna', 'Bríet', 'Bryndís', 'Brynfríður', 'Bryngerður', 'Brynheiður', 'Brynhildur', 'Brynja', 'Brynný', 'Burkney', 'Bylgja', 'Camilla', 'Carla', 'Carmen', 'Cecilia', 'Cecilía', 'Charlotta', 'Charlotte', 'Christina', 'Christine', 'Clara', 'Daðey', 'Daðína', 'Dagbjörg', 'Dagbjört', 'Dagfríður', 'Daggrós', 'Dagheiður', 'Dagmar', 'Dagmey', 'Dagný', 'Dagrún', 'Daldís', 'Daley', 'Dalía', 'Dalla', 'Dallilja', 'Dalrós', 'Dana', 'Daney', 'Danfríður', 'Danheiður', 'Danhildur', 'Danía', 'Daníela', 'Daníella', 'Dara', 'Debora', 'Debóra', 'Dendý', 'Didda', 'Dilja', 'Diljá', 'Dimmblá', 'Dimmey', 'Día', 'Díana', 'Díanna', 'Díma', 'Dís', 'Dísa', 'Dísella', 'Donna', 'Doris', 'Dorothea', 'Dóa', 'Dómhildur', 'Dóra', 'Dórey', 'Dóris', 'Dórothea', 'Dórótea', 'Dóróthea', 'Drauma', 'Draumey', 'Drífa', 'Droplaug', 'Drótt', 'Dröfn', 'Dúa', 'Dúfa', 'Dúna', 'Dýrborg', 'Dýrfinna', 'Dýrleif', 'Dýrley', 'Dýrunn', 'Dæja', 'Dögg', 'Dögun', 'Ebba', 'Ebonney', 'Edda', 'Edel', 'Edil', 'Edit', 'Edith', 'Eðna', 'Efemía', 'Egedía', 'Eggrún', 'Egla', 'Eiðný', 'Eiðunn', 'Eik', 'Einbjörg', 'Eindís', 'Einey', 'Einfríður', 'Einhildur', 'Einína', 'Einrún', 'Eir', 'Eirdís', 'Eirfinna', 'Eiríka', 'Eirný', 'Eirún', 'Elba', 'Eldbjörg', 'Eldey', 'Eldlilja', 'Eldrún', 'Eleina', 'Elektra', 'Elena', 'Elenborg', 'Elfa', 'Elfur', 'Elina', 'Elinborg', 'Elisabeth', 'Elía', 'Elíana', 'Elín', 'Elína', 'Elíná', 'Elínbet', 'Elínbjörg', 'Elínbjört', 'Elínborg', 'Elíndís', 'Elíngunnur', 'Elínheiður', 'Elínrós', 'Elírós', 'Elísa', 'Elísabet', 'Elísabeth', 'Elka', 'Ella', 'Ellen', 'Elley', 'Ellisif', 'Ellín', 'Elly', 'Ellý', 'Elma', 'Elna', 'Elsa', 'Elsabet', 'Elsie', 'Elsí', 'Elsý', 'Elva', 'Elvi', 'Elvíra', 'Elvý', 'Embla', 'Emelía', 'Emelíana', 'Emelína', 'Emeralda', 'Emilía', 'Emilíana', 'Emilíanna', 'Emilý', 'Emma', 'Emmý', 'Emý', 'Enea', 'Eneka', 'Engilbjört', 'Engilráð', 'Engilrós', 'Engla', 'Enika', 'Enja', 'Enóla', 'Eres', 'Erika', 'Erin', 'Erla', 'Erlen', 'Erlín', 'Erna', 'Esja', 'Esmeralda', 'Ester', 'Esther', 'Estiva', 'Ethel', 'Etna', 'Eufemía', 'Eva', 'Evelyn', 'Evey', 'Evfemía', 'Evgenía', 'Evíta', 'Evlalía', 'Ey', 'Eybjörg', 'Eybjört', 'Eydís', 'Eyfríður', 'Eygerður', 'Eygló', 'Eyhildur', 'Eyja', 'Eyjalín', 'Eyleif', 'Eylín', 'Eyrós', 'Eyrún', 'Eyveig', 'Eyvör', 'Eyþóra', 'Eyþrúður', 'Fanndís', 'Fanney', 'Fannlaug', 'Fanny', 'Fanný', 'Febrún', 'Fema', 'Filipía', 'Filippa', 'Filippía', 'Finna', 'Finnbjörg', 'Finnbjörk', 'Finnboga', 'Finnborg', 'Finndís', 'Finney', 'Finnfríður', 'Finnlaug', 'Finnrós', 'Fía', 'Fídes', 'Fífa', 'Fjalldís', 'Fjóla', 'Flóra', 'Folda', 'Fransiska', 'Franziska', 'Frán', 'Fregn', 'Freydís', 'Freygerður', 'Freyja', 'Freylaug', 'Freyleif', 'Friðbjörg', 'Friðbjört', 'Friðborg', 'Friðdís', 'Friðdóra', 'Friðey', 'Friðfinna', 'Friðgerður', 'Friðjóna', 'Friðlaug', 'Friðleif', 'Friðlín', 'Friðmey', 'Friðný', 'Friðrika', 'Friðrikka', 'Friðrós', 'Friðrún', 'Friðsemd', 'Friðveig', 'Friðþóra', 'Frigg', 'Fríða', 'Fríður', 'Frostrós', 'Fróðný', 'Fura', 'Fönn', 'Gabríela', 'Gabríella', 'Gauja', 'Gauthildur', 'Gefjun', 'Gefn', 'Geira', 'Geirbjörg', 'Geirdís', 'Geirfinna', 'Geirfríður', 'Geirhildur', 'Geirlaug', 'Geirlöð', 'Geirný', 'Geirríður', 'Geirrún', 'Geirþrúður', 'Georgía', 'Gerða', 'Gerður', 'Gestheiður', 'Gestný', 'Gestrún', 'Gillý', 'Gilslaug', 'Gissunn', 'Gía', 'Gígja', 'Gísela', 'Gísla', 'Gísley', 'Gíslína', 'Gíslný', 'Gíslrún', 'Gíslunn', 'Gíta', 'Gjaflaug', 'Gloría', 'Gló', 'Glóa', 'Glóbjört', 'Glódís', 'Glóð', 'Glóey', 'Gná', 'Góa', 'Gógó', 'Grein', 'Gret', 'Greta', 'Grélöð', 'Grét', 'Gréta', 'Gríma', 'Grímey', 'Grímheiður', 'Grímhildur', 'Gróa', 'Guðbjörg', 'Guðbjört', 'Guðborg', 'Guðdís', 'Guðfinna', 'Guðfríður', 'Guðjóna', 'Guðlaug', 'Guðleif', 'Guðlín', 'Guðmey', 'Guðmunda', 'Guðmundína', 'Guðný', 'Guðríður', 'Guðrún', 'Guðsteina', 'Guðveig', 'Gullbrá', 'Gullveig', 'Gullý', 'Gumma', 'Gunnbjörg', 'Gunnbjört', 'Gunnborg', 'Gunndís', 'Gunndóra', 'Gunnella', 'Gunnfinna', 'Gunnfríður', 'Gunnharða', 'Gunnheiður', 'Gunnhildur', 'Gunnjóna', 'Gunnlaug', 'Gunnleif', 'Gunnlöð', 'Gunnrún', 'Gunnur', 'Gunnveig', 'Gunnvör', 'Gunný', 'Gunnþóra', 'Gunnþórunn', 'Gurrý', 'Gúa', 'Gyða', 'Gyðja', 'Gyðríður', 'Gytta', 'Gæfa', 'Gæflaug', 'Hadda', 'Haddý', 'Hafbjörg', 'Hafborg', 'Hafdís', 'Hafey', 'Hafliða', 'Haflína', 'Hafný', 'Hafrós', 'Hafrún', 'Hafsteina', 'Hafþóra', 'Halla', 'Hallbera', 'Hallbjörg', 'Hallborg', 'Halldís', 'Halldóra', 'Halley', 'Hallfríður', 'Hallgerður', 'Hallgunnur', 'Hallkatla', 'Hallný', 'Hallrún', 'Hallveig', 'Hallvör', 'Hanna', 'Hanney', 'Hansa', 'Hansína', 'Harpa', 'Hauður', 'Hákonía', 'Heba', 'Hedda', 'Hedí', 'Heiða', 'Heiðbjörg', 'Heiðbjörk', 'Heiðbjört', 'Heiðbrá', 'Heiðdís', 'Heiðlaug', 'Heiðlóa', 'Heiðný', 'Heiðrós', 'Heiðrún', 'Heiður', 'Heiðveig', 'Hekla', 'Helen', 'Helena', 'Helga', 'Hella', 'Helma', 'Hendrikka', 'Henný', 'Henrietta', 'Henrika', 'Henríetta', 'Hera', 'Herbjörg', 'Herbjört', 'Herborg', 'Herdís', 'Herfríður', 'Hergerður', 'Herlaug', 'Hermína', 'Hersilía', 'Herta', 'Hertha', 'Hervör', 'Herþrúður', 'Hilda', 'Hildegard', 'Hildibjörg', 'Hildigerður', 'Hildigunnur', 'Hildiríður', 'Hildisif', 'Hildur', 'Hilma', 'Himinbjörg', 'Hind', 'Hinrika', 'Hinrikka', 'Hjalta', 'Hjaltey', 'Hjálmdís', 'Hjálmey', 'Hjálmfríður', 'Hjálmgerður', 'Hjálmrós', 'Hjálmrún', 'Hjálmveig', 'Hjördís', 'Hjörfríður', 'Hjörleif', 'Hjörný', 'Hjörtfríður', 'Hlaðgerður', 'Hlédís', 'Hlíf', 'Hlín', 'Hlökk', 'Hólmbjörg', 'Hólmdís', 'Hólmfríður', 'Hrafna', 'Hrafnborg', 'Hrafndís', 'Hrafney', 'Hrafngerður', 'Hrafnheiður', 'Hrafnhildur', 'Hrafnkatla', 'Hrafnlaug', 'Hrafntinna', 'Hraundís', 'Hrefna', 'Hreindís', 'Hróðný', 'Hrólfdís', 'Hrund', 'Hrönn', 'Hugbjörg', 'Hugbjört', 'Hugborg', 'Hugdís', 'Hugljúf', 'Hugrún', 'Huld', 'Hulda', 'Huldís', 'Huldrún', 'Húnbjörg', 'Húndís', 'Húngerður', 'Hvönn', 'Hödd', 'Högna', 'Hörn', 'Ida', 'Idda', 'Iða', 'Iðunn', 'Ilmur', 'Immý', 'Ina', 'Inda', 'India', 'Indiana', 'Indía', 'Indíana', 'Indíra', 'Indra', 'Inga', 'Ingdís', 'Ingeborg', 'Inger', 'Ingey', 'Ingheiður', 'Inghildur', 'Ingibjörg', 'Ingibjört', 'Ingiborg', 'Ingifinna', 'Ingifríður', 'Ingigerður', 'Ingilaug', 'Ingileif', 'Ingilín', 'Ingimaría', 'Ingimunda', 'Ingiríður', 'Ingirós', 'Ingisól', 'Ingiveig', 'Ingrid', 'Ingrún', 'Ingunn', 'Ingveldur', 'Inna', 'Irena', 'Irene', 'Irja', 'Irma', 'Irmý', 'Irpa', 'Isabel', 'Isabella', 'Ída', 'Íma', 'Ína', 'Ír', 'Íren', 'Írena', 'Íris', 'Írunn', 'Ísabel', 'Ísabella', 'Ísadóra', 'Ísafold', 'Ísalind', 'Ísbjörg', 'Ísdís', 'Ísey', 'Ísfold', 'Ísgerður', 'Íshildur', 'Ísis', 'Íslaug', 'Ísleif', 'Ísmey', 'Ísold', 'Ísól', 'Ísrún', 'Íssól', 'Ísveig', 'Íunn', 'Íva', 'Jakobína', 'Jana', 'Jane', 'Janetta', 'Jannika', 'Jara', 'Jarún', 'Jarþrúður', 'Jasmín', 'Járnbrá', 'Járngerður', 'Jenetta', 'Jenna', 'Jenný', 'Jensína', 'Jessý', 'Jovina', 'Jóa', 'Jóanna', 'Jódís', 'Jófríður', 'Jóhanna', 'Jólín', 'Jóna', 'Jónanna', 'Jónasína', 'Jónbjörg', 'Jónbjört', 'Jóndís', 'Jóndóra', 'Jóney', 'Jónfríður', 'Jóngerð', 'Jónheiður', 'Jónhildur', 'Jóninna', 'Jónída', 'Jónína', 'Jónný', 'Jóný', 'Jóra', 'Jóríður', 'Jórlaug', 'Jórunn', 'Jósebína', 'Jósefín', 'Jósefína', 'Judith', 'Júdea', 'Júdit', 'Júlía', 'Júlíana', 'Júlíanna', 'Júlíetta', 'Júlírós', 'Júnía', 'Júníana', 'Jökla', 'Jökulrós', 'Jörgína', 'Kaðlín', 'Kaja', 'Kalla', 'Kamilla', 'Kamí', 'Kamma', 'Kapitola', 'Kapítóla', 'Kara', 'Karen', 'Karin', 'Karitas', 'Karí', 'Karín', 'Karína', 'Karítas', 'Karla', 'Karlinna', 'Karlína', 'Karlotta', 'Karolína', 'Karó', 'Karólín', 'Karólína', 'Kassandra', 'Kata', 'Katarína', 'Katerína', 'Katharina', 'Kathinka', 'Katinka', 'Katla', 'Katrín', 'Katrína', 'Katý', 'Kára', 'Kellý', 'Kendra', 'Ketilbjörg', 'Ketilfríður', 'Ketilríður', 'Kiddý', 'Kira', 'Kirsten', 'Kirstín', 'Kittý', 'Kjalvör', 'Klara', 'Kládía', 'Klementína', 'Kleópatra', 'Kolbjörg', 'Kolbrá', 'Kolbrún', 'Koldís', 'Kolfinna', 'Kolfreyja', 'Kolgríma', 'Kolka', 'Konkordía', 'Konný', 'Korka', 'Kormlöð', 'Kornelía', 'Kókó', 'Krista', 'Kristbjörg', 'Kristborg', 'Kristel', 'Kristensa', 'Kristey', 'Kristfríður', 'Kristgerður', 'Kristin', 'Kristine', 'Kristíana', 'Kristíanna', 'Kristín', 'Kristína', 'Kristjana', 'Kristjóna', 'Kristlaug', 'Kristlind', 'Kristlín', 'Kristný', 'Kristólína', 'Kristrós', 'Kristrún', 'Kristveig', 'Kristvina', 'Kristþóra', 'Kría', 'Kæja', 'Laila', 'Laíla', 'Lana', 'Lara', 'Laufey', 'Laufheiður', 'Laufhildur', 'Lauga', 'Laugey', 'Laugheiður', 'Lára', 'Lárensína', 'Láretta', 'Lárey', 'Lea', 'Leikný', 'Leila', 'Lena', 'Leonóra', 'Leóna', 'Leónóra', 'Lilja', 'Liljá', 'Liljurós', 'Lill', 'Lilla', 'Lillian', 'Lillý', 'Lily', 'Lilý', 'Lind', 'Linda', 'Linddís', 'Lingný', 'Lisbeth', 'Listalín', 'Liv', 'Líba', 'Líf', 'Lífdís', 'Lín', 'Lína', 'Línbjörg', 'Líndís', 'Líneik', 'Líney', 'Línhildur', 'Lísa', 'Lísabet', 'Lísandra', 'Lísbet', 'Lísebet', 'Lív', 'Ljósbjörg', 'Ljósbrá', 'Ljótunn', 'Lofn', 'Loftveig', 'Logey', 'Lokbrá', 'Lotta', 'Louisa', 'Lousie', 'Lovísa', 'Lóa', 'Lóreley', 'Lukka', 'Lúcía', 'Lúðvíka', 'Lúísa', 'Lúna', 'Lúsinda', 'Lúsía', 'Lúvísa', 'Lydia', 'Lydía', 'Lyngheiður', 'Lýdía', 'Læla', 'Maddý', 'Magda', 'Magdalena', 'Magðalena', 'Magga', 'Maggey', 'Maggý', 'Magna', 'Magndís', 'Magnea', 'Magnes', 'Magney', 'Magnfríður', 'Magnheiður', 'Magnhildur', 'Magnúsína', 'Magný', 'Magnþóra', 'Maía', 'Maídís', 'Maísól', 'Maj', 'Maja', 'Malen', 'Malena', 'Malía', 'Malín', 'Malla', 'Manda', 'Manúela', 'Mara', 'Mardís', 'Marela', 'Marella', 'Maren', 'Marey', 'Marfríður', 'Margit', 'Margot', 'Margret', 'Margrét', 'Margrjet', 'Margunnur', 'Marheiður', 'Maria', 'Marie', 'Marikó', 'Marinella', 'Marit', 'Marí', 'María', 'Maríam', 'Marían', 'Maríana', 'Maríanna', 'Marín', 'Marína', 'Marínella', 'Maríon', 'Marísa', 'Marísól', 'Marít', 'Maríuerla', 'Marja', 'Markrún', 'Marlaug', 'Marlena', 'Marlín', 'Marlís', 'Marólína', 'Marsa', 'Marselía', 'Marselína', 'Marsibil', 'Marsilía', 'Marsý', 'Marta', 'Martha', 'Martína', 'Mary', 'Marý', 'Matta', 'Mattea', 'Matthea', 'Matthilda', 'Matthildur', 'Matthía', 'Mattíana', 'Mattína', 'Mattý', 'Maxima', 'Mábil', 'Málfríður', 'Málhildur', 'Málmfríður', 'Mánadís', 'Máney', 'Mára', 'Meda', 'Mekkin', 'Mekkín', 'Melinda', 'Melissa', 'Melkorka', 'Melrós', 'Messíana', 'Metta', 'Mey', 'Mikaela', 'Mikaelína', 'Mikkalína', 'Milda', 'Mildríður', 'Milla', 'Millý', 'Minerva', 'Minna', 'Minney', 'Minný', 'Miriam', 'Mirja', 'Mirjam', 'Mirra', 'Mist', 'Mía', 'Mínerva', 'Míra', 'Míranda', 'Mítra', 'Mjaðveig', 'Mjalldís', 'Mjallhvít', 'Mjöll', 'Mona', 'Monika', 'Módís', 'Móeiður', 'Móey', 'Móheiður', 'Móna', 'Mónika', 'Móníka', 'Munda', 'Mundheiður', 'Mundhildur', 'Mundína', 'Myrra', 'Mýr', 'Mýra', 'Mýrún', 'Mörk', 'Nadia', 'Nadía', 'Nadja', 'Nana', 'Nanna', 'Nanný', 'Nansý', 'Naomí', 'Naómí', 'Natalie', 'Natalía', 'Náttsól', 'Nella', 'Nellý', 'Nenna', 'Nicole', 'Niðbjörg', 'Nikíta', 'Nikoletta', 'Nikólína', 'Ninja', 'Ninna', 'Nína', 'Níní', 'Njála', 'Njóla', 'Norma', 'Nóa', 'Nóra', 'Nótt', 'Nýbjörg', 'Odda', 'Oddbjörg', 'Oddfreyja', 'Oddfríður', 'Oddgerður', 'Oddhildur', 'Oddlaug', 'Oddleif', 'Oddný', 'Oddrún', 'Oddveig', 'Oddvör', 'Oktavía', 'Októvía', 'Olga', 'Ollý', 'Ora', 'Orka', 'Ormheiður', 'Ormhildur', 'Otkatla', 'Otta', 'Óda', 'Ófelía', 'Óla', 'Ólafía', 'Ólafína', 'Ólavía', 'Ólivía', 'Ólína', 'Ólöf', 'Ósa', 'Ósk', 'Ótta', 'Pamela', 'París', 'Patricia', 'Patrisía', 'Pála', 'Páldís', 'Páley', 'Pálfríður', 'Pálhanna', 'Pálheiður', 'Pálhildur', 'Pálín', 'Pálína', 'Pálmey', 'Pálmfríður', 'Pálrún', 'Perla', 'Peta', 'Petra', 'Petrea', 'Petrína', 'Petronella', 'Petrónella', 'Petrós', 'Petrún', 'Petrúnella', 'Pétrína', 'Pétrún', 'Pía', 'Polly', 'Pollý', 'Pría', 'Rafney', 'Rafnhildur', 'Ragna', 'Ragnbjörg', 'Ragney', 'Ragnfríður', 'Ragnheiður', 'Ragnhildur', 'Rakel', 'Ramóna', 'Randalín', 'Randíður', 'Randý', 'Ranka', 'Rannva', 'Rannveig', 'Ráðhildur', 'Rán', 'Rebekka', 'Reginbjörg', 'Regína', 'Rein', 'Renata', 'Reyn', 'Reyndís', 'Reynheiður', 'Reynhildur', 'Rikka', 'Ripley', 'Rita', 'Ríkey', 'Rín', 'Ríta', 'Ronja', 'Rorí', 'Roxanna', 'Róberta', 'Róbjörg', 'Rós', 'Rósa', 'Rósalind', 'Rósanna', 'Rósbjörg', 'Rósborg', 'Róselía', 'Rósey', 'Rósfríður', 'Róshildur', 'Rósinkara', 'Rósinkransa', 'Róska', 'Róslaug', 'Róslind', 'Róslinda', 'Róslín', 'Rósmary', 'Rósmarý', 'Rósmunda', 'Rósný', 'Runný', 'Rut', 'Ruth', 'Rúbý', 'Rún', 'Rúna', 'Rúndís', 'Rúnhildur', 'Rúrí', 'Röfn', 'Rögn', 'Röskva', 'Sabína', 'Sabrína', 'Saga', 'Salbjörg', 'Saldís', 'Salgerður', 'Salín', 'Salína', 'Salka', 'Salma', 'Salný', 'Salome', 'Salóme', 'Salvör', 'Sandra', 'Sanna', 'Santía', 'Sara', 'Sarína', 'Sefanía', 'Selja', 'Selka', 'Selma', 'Senía', 'Septíma', 'Sera', 'Serena', 'Seselía', 'Sesilía', 'Sesselía', 'Sesselja', 'Sessilía', 'Sif', 'Sigdís', 'Sigdóra', 'Sigfríð', 'Sigfríður', 'Sigga', 'Siggerður', 'Sigmunda', 'Signa', 'Signhildur', 'Signý', 'Sigríður', 'Sigrún', 'Sigurást', 'Sigurásta', 'Sigurbára', 'Sigurbirna', 'Sigurbjörg', 'Sigurbjört', 'Sigurborg', 'Sigurdís', 'Sigurdóra', 'Sigurdríf', 'Sigurdrífa', 'Sigurða', 'Sigurey', 'Sigurfinna', 'Sigurfljóð', 'Sigurgeira', 'Sigurhanna', 'Sigurhelga', 'Sigurhildur', 'Sigurjóna', 'Sigurlaug', 'Sigurleif', 'Sigurlilja', 'Sigurlinn', 'Sigurlín', 'Sigurlína', 'Sigurmunda', 'Sigurnanna', 'Sigurósk', 'Sigurrós', 'Sigursteina', 'Sigurunn', 'Sigurveig', 'Sigurvina', 'Sigurþóra', 'Sigyn', 'Sigþóra', 'Sigþrúður', 'Silfa', 'Silfá', 'Silfrún', 'Silja', 'Silka', 'Silla', 'Silva', 'Silvana', 'Silvía', 'Sirra', 'Sirrý', 'Siv', 'Sía', 'Símonía', 'Sísí', 'Síta', 'Sjöfn', 'Skarpheiður', 'Skugga', 'Skuld', 'Skúla', 'Skúlína', 'Snjáfríður', 'Snjáka', 'Snjófríður', 'Snjólaug', 'Snorra', 'Snót', 'Snæbjörg', 'Snæbjört', 'Snæborg', 'Snæbrá', 'Snædís', 'Snæfríður', 'Snælaug', 'Snærós', 'Snærún', 'Soffía', 'Sofie', 'Sofía', 'Solveig', 'Sonja', 'Sonný', 'Sophia', 'Sophie', 'Sól', 'Sóla', 'Sólbjörg', 'Sólbjört', 'Sólborg', 'Sólbrá', 'Sólbrún', 'Sóldís', 'Sóldögg', 'Sóley', 'Sólfríður', 'Sólgerður', 'Sólhildur', 'Sólín', 'Sólkatla', 'Sóllilja', 'Sólný', 'Sólrós', 'Sólrún', 'Sólveig', 'Sólvör', 'Sónata', 'Stefana', 'Stefanía', 'Stefánný', 'Steina', 'Steinbjörg', 'Steinborg', 'Steindís', 'Steindóra', 'Steiney', 'Steinfríður', 'Steingerður', 'Steinhildur', 'Steinlaug', 'Steinrós', 'Steinrún', 'Steinunn', 'Steinvör', 'Steinþóra', 'Stella', 'Stígheiður', 'Stígrún', 'Stína', 'Stjarna', 'Styrgerður', 'Sumarlína', 'Sumarrós', 'Sunna', 'Sunnefa', 'Sunneva', 'Sunniva', 'Sunníva', 'Susan', 'Súla', 'Súsan', 'Súsanna', 'Svafa', 'Svala', 'Svalrún', 'Svana', 'Svanbjörg', 'Svanbjört', 'Svanborg', 'Svandís', 'Svaney', 'Svanfríður', 'Svanheiður', 'Svanhildur', 'Svanhvít', 'Svanlaug', 'Svanrós', 'Svanþrúður', 'Svava', 'Svea', 'Sveina', 'Sveinbjörg', 'Sveinborg', 'Sveindís', 'Sveiney', 'Sveinfríður', 'Sveingerður', 'Sveinhildur', 'Sveinlaug', 'Sveinrós', 'Sveinrún', 'Sveinsína', 'Sveinveig', 'Sylgja', 'Sylva', 'Sylvía', 'Sæbjörg', 'Sæbjört', 'Sæborg', 'Sædís', 'Sæfinna', 'Sæfríður', 'Sæhildur', 'Sælaug', 'Sæmunda', 'Sæný', 'Særós', 'Særún', 'Sæsól', 'Sæunn', 'Sævör', 'Sölva', 'Sölvey', 'Sölvína', 'Tala', 'Talía', 'Tamar', 'Tamara', 'Tanía', 'Tanja', 'Tanya', 'Tanya', 'Tara', 'Tea', 'Teitný', 'Tekla', 'Telma', 'Tera', 'Teresa', 'Teresía', 'Thea', 'Thelma', 'Theodóra', 'Theódóra', 'Theresa', 'Tindra', 'Tinna', 'Tirsa', 'Tía', 'Tíbrá', 'Tína', 'Todda', 'Torbjörg', 'Torfey', 'Torfheiður', 'Torfhildur', 'Tóbý', 'Tóka', 'Tóta', 'Tristana', 'Trú', 'Tryggva', 'Tryggvína', 'Týra', 'Ugla', 'Una', 'Undína', 'Unna', 'Unnbjörg', 'Unndís', 'Unnur', 'Urður', 'Úa', 'Úlfa', 'Úlfdís', 'Úlfey', 'Úlfheiður', 'Úlfhildur', 'Úlfrún', 'Úlla', 'Úna', 'Úndína', 'Úranía', 'Úrsúla', 'Vagna', 'Vagnbjörg', 'Vagnfríður', 'Vaka', 'Vala', 'Valbjörg', 'Valbjörk', 'Valbjört', 'Valborg', 'Valdheiður', 'Valdís', 'Valentína', 'Valería', 'Valey', 'Valfríður', 'Valgerða', 'Valgerður', 'Valhildur', 'Valka', 'Vallý', 'Valný', 'Valrós', 'Valrún', 'Valva', 'Valý', 'Valþrúður', 'Vanda', 'Vár', 'Veig', 'Veiga', 'Venus', 'Vera', 'Veronika', 'Verónika', 'Veróníka', 'Vetrarrós', 'Vébjörg', 'Védís', 'Végerður', 'Vélaug', 'Véný', 'Vibeka', 'Victoría', 'Viðja', 'Vigdís', 'Vigný', 'Viktoria', 'Viktoría', 'Vilborg', 'Vildís', 'Vilfríður', 'Vilgerður', 'Vilhelmína', 'Villa', 'Villimey', 'Vilma', 'Vilný', 'Vinbjörg', 'Vinný', 'Vinsý', 'Virginía', 'Víbekka', 'Víf', 'Vígdögg', 'Víggunnur', 'Víóla', 'Víóletta', 'Vísa', 'Von', 'Von', 'Voney', 'Vordís', 'Ylfa', 'Ylfur', 'Ylja', 'Ylva', 'Ynja', 'Yrja', 'Yrsa', 'Ýja', 'Ýma', 'Ýr', 'Ýrr', 'Þalía', 'Þeba', 'Þeódís', 'Þeódóra', 'Þjóðbjörg', 'Þjóðhildur', 'Þoka', 'Þorbjörg', 'Þorfinna', 'Þorgerður', 'Þorgríma', 'Þorkatla', 'Þorlaug', 'Þorleif', 'Þorsteina', 'Þorstína', 'Þóra', 'Þóranna', 'Þórarna', 'Þórbjörg', 'Þórdís', 'Þórða', 'Þórelfa', 'Þórelfur', 'Þórey', 'Þórfríður', 'Þórgunna', 'Þórgunnur', 'Þórhalla', 'Þórhanna', 'Þórheiður', 'Þórhildur', 'Þórkatla', 'Þórlaug', 'Þórleif', 'Þórný', 'Þórodda', 'Þórsteina', 'Þórsteinunn', 'Þórstína', 'Þórunn', 'Þórveig', 'Þórvör', 'Þrá', 'Þrúða', 'Þrúður', 'Þula', 'Þura', 'Þurí', 'Þuríður', 'Þurý', 'Þúfa', 'Þyri', 'Þyrí', 'Þöll', 'Ægileif', 'Æsa', 'Æsgerður', 'Ögmunda', 'Ögn', 'Ölrún', 'Ölveig', 'Örbrún', 'Örk', 'Ösp'); + + /** + * @var string Icelandic men names. + */ + protected static $firstNameMale = array('Aage', 'Abel', 'Abraham', 'Adam', 'Addi', 'Adel', 'Adíel', 'Adólf', 'Adrían', 'Adríel', 'Aðalberg', 'Aðalbergur', 'Aðalbert', 'Aðalbjörn', 'Aðalborgar', 'Aðalgeir', 'Aðalmundur', 'Aðalráður', 'Aðalsteinn', 'Aðólf', 'Agnar', 'Agni', 'Albert', 'Aldar', 'Alex', 'Alexander', 'Alexíus', 'Alfons', 'Alfred', 'Alfreð', 'Ali', 'Allan', 'Alli', 'Almar', 'Alrekur', 'Alvar', 'Alvin', 'Amír', 'Amos', 'Anders', 'Andreas', 'André', 'Andrés', 'Andri', 'Anes', 'Anfinn', 'Angantýr', 'Angi', 'Annar', 'Annarr', 'Annas', 'Annel', 'Annes', 'Anthony', 'Anton', 'Antoníus', 'Aran', 'Arent', 'Ares', 'Ari', 'Arilíus', 'Arinbjörn', 'Aríel', 'Aríus', 'Arnald', 'Arnaldur', 'Arnar', 'Arnberg', 'Arnbergur', 'Arnbjörn', 'Arndór', 'Arnes', 'Arnfinnur', 'Arnfreyr', 'Arngeir', 'Arngils', 'Arngrímur', 'Arnkell', 'Arnlaugur', 'Arnleifur', 'Arnljótur', 'Arnmóður', 'Arnmundur', 'Arnoddur', 'Arnold', 'Arnór', 'Arnsteinn', 'Arnúlfur', 'Arnviður', 'Arnþór', 'Aron', 'Arthur', 'Arthúr', 'Artúr', 'Asael', 'Askur', 'Aspar', 'Atlas', 'Atli', 'Auðbergur', 'Auðbert', 'Auðbjörn', 'Auðgeir', 'Auðkell', 'Auðmundur', 'Auðólfur', 'Auðun', 'Auðunn', 'Austar', 'Austmann', 'Austmar', 'Austri', 'Axel', 'Ágúst', 'Áki', 'Álfar', 'Álfgeir', 'Álfgrímur', 'Álfur', 'Álfþór', 'Ámundi', 'Árbjartur', 'Árbjörn', 'Árelíus', 'Árgeir', 'Árgils', 'Ármann', 'Árni', 'Ársæll', 'Ás', 'Ásberg', 'Ásbergur', 'Ásbjörn', 'Ásgautur', 'Ásgeir', 'Ásgils', 'Ásgrímur', 'Ási', 'Áskell', 'Áslaugur', 'Áslákur', 'Ásmar', 'Ásmundur', 'Ásólfur', 'Ásröður', 'Ástbjörn', 'Ástgeir', 'Ástmar', 'Ástmundur', 'Ástráður', 'Ástríkur', 'Ástvald', 'Ástvaldur', 'Ástvar', 'Ástvin', 'Ástþór', 'Ásvaldur', 'Ásvarður', 'Ásþór', 'Baldur', 'Baldvin', 'Baldwin', 'Baltasar', 'Bambi', 'Barði', 'Barri', 'Bassi', 'Bastían', 'Baugur', 'Bárður', 'Beinir', 'Beinteinn', 'Beitir', 'Bekan', 'Benedikt', 'Benidikt', 'Benjamín', 'Benoný', 'Benóní', 'Benóný', 'Bent', 'Berent', 'Berg', 'Bergfinnur', 'Berghreinn', 'Bergjón', 'Bergmann', 'Bergmar', 'Bergmundur', 'Bergsteinn', 'Bergsveinn', 'Bergur', 'Bergvin', 'Bergþór', 'Bernhard', 'Bernharð', 'Bernharður', 'Berni', 'Bernódus', 'Bersi', 'Bertel', 'Bertram', 'Bessi', 'Betúel', 'Bill', 'Birgir', 'Birkir', 'Birnir', 'Birtingur', 'Birtir', 'Bjargar', 'Bjargmundur', 'Bjargþór', 'Bjarkan', 'Bjarkar', 'Bjarki', 'Bjarmar', 'Bjarmi', 'Bjarnar', 'Bjarnfinnur', 'Bjarnfreður', 'Bjarnharður', 'Bjarnhéðinn', 'Bjarni', 'Bjarnlaugur', 'Bjarnleifur', 'Bjarnólfur', 'Bjarnsteinn', 'Bjarnþór', 'Bjartmann', 'Bjartmar', 'Bjartur', 'Bjartþór', 'Bjólan', 'Bjólfur', 'Björgmundur', 'Björgólfur', 'Björgúlfur', 'Björgvin', 'Björn', 'Björnólfur', 'Blængur', 'Blær', 'Blævar', 'Boði', 'Bogi', 'Bolli', 'Borgar', 'Borgúlfur', 'Borgþór', 'Bóas', 'Bói', 'Bótólfur', 'Bragi', 'Brandur', 'Breki', 'Bresi', 'Brestir', 'Brimar', 'Brimi', 'Brimir', 'Brími', 'Brjánn', 'Broddi', 'Bruno', 'Bryngeir', 'Brynjar', 'Brynjólfur', 'Brynjúlfur', 'Brynleifur', 'Brynsteinn', 'Bryntýr', 'Brynþór', 'Burkni', 'Búi', 'Búri', 'Bæring', 'Bæringur', 'Bæron', 'Böðvar', 'Börkur', 'Carl', 'Cecil', 'Christian', 'Christopher', 'Cýrus', 'Daði', 'Dagbjartur', 'Dagfari', 'Dagfinnur', 'Daggeir', 'Dagmann', 'Dagnýr', 'Dagur', 'Dagþór', 'Dalbert', 'Dalli', 'Dalmann', 'Dalmar', 'Dalvin', 'Damjan', 'Dan', 'Danelíus', 'Daniel', 'Danival', 'Daníel', 'Daníval', 'Dante', 'Daríus', 'Darri', 'Davíð', 'Demus', 'Deníel', 'Dennis', 'Diðrik', 'Díómedes', 'Dofri', 'Dolli', 'Dominik', 'Dómald', 'Dómaldi', 'Dómaldur', 'Dónald', 'Dónaldur', 'Dór', 'Dóri', 'Dósóþeus', 'Draupnir', 'Dreki', 'Drengur', 'Dufgus', 'Dufþakur', 'Dugfús', 'Dúi', 'Dúnn', 'Dvalinn', 'Dýri', 'Dýrmundur', 'Ebbi', 'Ebeneser', 'Ebenezer', 'Eberg', 'Edgar', 'Edilon', 'Edílon', 'Edvard', 'Edvin', 'Edward', 'Eðvald', 'Eðvar', 'Eðvarð', 'Efraím', 'Eggert', 'Eggþór', 'Egill', 'Eiðar', 'Eiður', 'Eikar', 'Eilífur', 'Einar', 'Einir', 'Einvarður', 'Einþór', 'Eiríkur', 'Eivin', 'Elberg', 'Elbert', 'Eldar', 'Eldgrímur', 'Eldjárn', 'Eldmar', 'Eldon', 'Eldór', 'Eldur', 'Elentínus', 'Elfar', 'Elfráður', 'Elimar', 'Elinór', 'Elis', 'Elí', 'Elías', 'Elíeser', 'Elímar', 'Elínbergur', 'Elínmundur', 'Elínór', 'Elís', 'Ellert', 'Elli', 'Elliði', 'Ellís', 'Elmar', 'Elvar', 'Elvin', 'Elvis', 'Emanúel', 'Embrek', 'Emerald', 'Emil', 'Emmanúel', 'Engilbert', 'Engilbjartur', 'Engiljón', 'Engill', 'Enok', 'Eric', 'Erik', 'Erlar', 'Erlendur', 'Erling', 'Erlingur', 'Ernestó', 'Ernir', 'Ernst', 'Eron', 'Erpur', 'Esekíel', 'Esjar', 'Esra', 'Estefan', 'Evald', 'Evan', 'Evert', 'Eyberg', 'Eyjólfur', 'Eylaugur', 'Eyleifur', 'Eymar', 'Eymundur', 'Eyríkur', 'Eysteinn', 'Eyvar', 'Eyvindur', 'Eyþór', 'Fabrisíus', 'Falgeir', 'Falur', 'Fannar', 'Fannberg', 'Fanngeir', 'Fáfnir', 'Fálki', 'Felix', 'Fengur', 'Fenrir', 'Ferdinand', 'Ferdínand', 'Fertram', 'Feykir', 'Filip', 'Filippus', 'Finn', 'Finnbjörn', 'Finnbogi', 'Finngeir', 'Finnjón', 'Finnlaugur', 'Finnur', 'Finnvarður', 'Fífill', 'Fjalar', 'Fjarki', 'Fjólar', 'Fjólmundur', 'Fjölnir', 'Fjölvar', 'Fjörnir', 'Flemming', 'Flosi', 'Flóki', 'Flórent', 'Flóvent', 'Forni', 'Fossmar', 'Fólki', 'Francis', 'Frank', 'Franklín', 'Frans', 'Franz', 'Fránn', 'Frár', 'Freybjörn', 'Freygarður', 'Freymar', 'Freymóður', 'Freymundur', 'Freyr', 'Freysteinn', 'Freyviður', 'Freyþór', 'Friðberg', 'Friðbergur', 'Friðbert', 'Friðbjörn', 'Friðfinnur', 'Friðgeir', 'Friðjón', 'Friðlaugur', 'Friðleifur', 'Friðmann', 'Friðmar', 'Friðmundur', 'Friðrik', 'Friðsteinn', 'Friður', 'Friðvin', 'Friðþjófur', 'Friðþór', 'Friedrich', 'Fritz', 'Frímann', 'Frosti', 'Fróði', 'Fróðmar', 'Funi', 'Fúsi', 'Fylkir', 'Gabriel', 'Gabríel', 'Gael', 'Galdur', 'Gamalíel', 'Garðar', 'Garibaldi', 'Garpur', 'Garri', 'Gaui', 'Gaukur', 'Gauti', 'Gautrekur', 'Gautur', 'Gautviður', 'Geir', 'Geirarður', 'Geirfinnur', 'Geirharður', 'Geirhjörtur', 'Geirhvatur', 'Geiri', 'Geirlaugur', 'Geirleifur', 'Geirmundur', 'Geirólfur', 'Geirröður', 'Geirtryggur', 'Geirvaldur', 'Geirþjófur', 'Geisli', 'Gellir', 'Georg', 'Gerald', 'Gerðar', 'Geri', 'Gestur', 'Gilbert', 'Gilmar', 'Gils', 'Gissur', 'Gizur', 'Gídeon', 'Gígjar', 'Gísli', 'Gjúki', 'Glói', 'Glúmur', 'Gneisti', 'Gnúpur', 'Gnýr', 'Goði', 'Goðmundur', 'Gottskálk', 'Gottsveinn', 'Gói', 'Grani', 'Grankell', 'Gregor', 'Greipur', 'Greppur', 'Gretar', 'Grettir', 'Grétar', 'Grímar', 'Grímkell', 'Grímlaugur', 'Grímnir', 'Grímólfur', 'Grímur', 'Grímúlfur', 'Guðberg', 'Guðbergur', 'Guðbjarni', 'Guðbjartur', 'Guðbjörn', 'Guðbrandur', 'Guðfinnur', 'Guðfreður', 'Guðgeir', 'Guðjón', 'Guðlaugur', 'Guðleifur', 'Guðleikur', 'Guðmann', 'Guðmar', 'Guðmon', 'Guðmundur', 'Guðni', 'Guðráður', 'Guðröður', 'Guðsteinn', 'Guðvarður', 'Guðveigur', 'Guðvin', 'Guðþór', 'Gumi', 'Gunnar', 'Gunnberg', 'Gunnbjörn', 'Gunndór', 'Gunngeir', 'Gunnhallur', 'Gunnlaugur', 'Gunnleifur', 'Gunnólfur', 'Gunnóli', 'Gunnröður', 'Gunnsteinn', 'Gunnvaldur', 'Gunnþór', 'Gustav', 'Gutti', 'Guttormur', 'Gústaf', 'Gústav', 'Gylfi', 'Gyrðir', 'Gýgjar', 'Gýmir', 'Haddi', 'Haddur', 'Hafberg', 'Hafgrímur', 'Hafliði', 'Hafnar', 'Hafni', 'Hafsteinn', 'Hafþór', 'Hagalín', 'Hagbarður', 'Hagbert', 'Haki', 'Hallberg', 'Hallbjörn', 'Halldór', 'Hallfreður', 'Hallgarður', 'Hallgeir', 'Hallgils', 'Hallgrímur', 'Hallkell', 'Hallmann', 'Hallmar', 'Hallmundur', 'Hallsteinn', 'Hallur', 'Hallvarður', 'Hallþór', 'Hamar', 'Hannes', 'Hannibal', 'Hans', 'Harald', 'Haraldur', 'Harri', 'Harry', 'Harrý', 'Hartmann', 'Hartvig', 'Hauksteinn', 'Haukur', 'Haukvaldur', 'Hákon', 'Háleygur', 'Hálfdan', 'Hálfdán', 'Hámundur', 'Hárekur', 'Hárlaugur', 'Hásteinn', 'Hávar', 'Hávarður', 'Hávarr', 'Hávarr', 'Heiðar', 'Heiðarr', 'Heiðberg', 'Heiðbert', 'Heiðlindur', 'Heiðmann', 'Heiðmar', 'Heiðmundur', 'Heiðrekur', 'Heikir', 'Heilmóður', 'Heimir', 'Heinrekur', 'Heisi', 'Hektor', 'Helgi', 'Helmút', 'Hemmert', 'Hendrik', 'Henning', 'Henrik', 'Henry', 'Henrý', 'Herbert', 'Herbjörn', 'Herfinnur', 'Hergeir', 'Hergill', 'Hergils', 'Herjólfur', 'Herlaugur', 'Herleifur', 'Herluf', 'Hermann', 'Hermóður', 'Hermundur', 'Hersir', 'Hersteinn', 'Hersveinn', 'Hervar', 'Hervarður', 'Hervin', 'Héðinn', 'Hilaríus', 'Hilbert', 'Hildar', 'Hildibergur', 'Hildibrandur', 'Hildigeir', 'Hildiglúmur', 'Hildimar', 'Hildimundur', 'Hildingur', 'Hildir', 'Hildiþór', 'Hilmar', 'Hilmir', 'Himri', 'Hinrik', 'Híram', 'Hjallkár', 'Hjalti', 'Hjarnar', 'Hjálmar', 'Hjálmgeir', 'Hjálmtýr', 'Hjálmur', 'Hjálmþór', 'Hjörleifur', 'Hjörtur', 'Hjörtþór', 'Hjörvar', 'Hleiðar', 'Hlégestur', 'Hlér', 'Hlini', 'Hlíðar', 'Hlíðberg', 'Hlífar', 'Hljómur', 'Hlynur', 'Hlöðmundur', 'Hlöður', 'Hlöðvarður', 'Hlöðver', 'Hnefill', 'Hnikar', 'Hnikarr', 'Holgeir', 'Holger', 'Holti', 'Hólm', 'Hólmar', 'Hólmbert', 'Hólmfastur', 'Hólmgeir', 'Hólmgrímur', 'Hólmkell', 'Hólmsteinn', 'Hólmþór', 'Hóseas', 'Hrafn', 'Hrafnar', 'Hrafnbergur', 'Hrafnkell', 'Hrafntýr', 'Hrannar', 'Hrappur', 'Hraunar', 'Hreggviður', 'Hreiðar', 'Hreiðmar', 'Hreimur', 'Hreinn', 'Hringur', 'Hrímnir', 'Hrollaugur', 'Hrolleifur', 'Hróaldur', 'Hróar', 'Hróbjartur', 'Hróðgeir', 'Hróðmar', 'Hróðólfur', 'Hróðvar', 'Hrói', 'Hrólfur', 'Hrómundur', 'Hrútur', 'Hrærekur', 'Hugberg', 'Hugi', 'Huginn', 'Hugleikur', 'Hugo', 'Hugó', 'Huldar', 'Huxley', 'Húbert', 'Húgó', 'Húmi', 'Húnbogi', 'Húni', 'Húnn', 'Húnröður', 'Hvannar', 'Hyltir', 'Hylur', 'Hængur', 'Hænir', 'Höður', 'Högni', 'Hörður', 'Höskuldur', 'Illugi', 'Immanúel', 'Indriði', 'Ingberg', 'Ingi', 'Ingiberg', 'Ingibergur', 'Ingibert', 'Ingibjartur', 'Ingibjörn', 'Ingileifur', 'Ingimagn', 'Ingimar', 'Ingimundur', 'Ingivaldur', 'Ingiþór', 'Ingjaldur', 'Ingmar', 'Ingólfur', 'Ingvaldur', 'Ingvar', 'Ingvi', 'Ingþór', 'Ismael', 'Issi', 'Ían', 'Ígor', 'Ími', 'Ísak', 'Ísar', 'Ísarr', 'Ísbjörn', 'Íseldur', 'Ísgeir', 'Ísidór', 'Ísleifur', 'Ísmael', 'Ísmar', 'Ísólfur', 'Ísrael', 'Ívan', 'Ívar', 'Jack', 'Jafet', 'Jaki', 'Jakob', 'Jakop', 'Jamil', 'Jan', 'Janus', 'Jarl', 'Jason', 'Járngrímur', 'Játgeir', 'Játmundur', 'Játvarður', 'Jenni', 'Jens', 'Jeremías', 'Jes', 'Jesper', 'Jochum', 'Johan', 'John', 'Joshua', 'Jóakim', 'Jóann', 'Jóel', 'Jóhann', 'Jóhannes', 'Jói', 'Jómar', 'Jómundur', 'Jón', 'Jónar', 'Jónas', 'Jónatan', 'Jónbjörn', 'Jóndór', 'Jóngeir', 'Jónmundur', 'Jónsteinn', 'Jónþór', 'Jósafat', 'Jósavin', 'Jósef', 'Jósep', 'Jósteinn', 'Jósúa', 'Jóvin', 'Julian', 'Júlí', 'Júlían', 'Júlíus', 'Júní', 'Júníus', 'Júrek', 'Jökull', 'Jörfi', 'Jörgen', 'Jörmundur', 'Jörri', 'Jörundur', 'Jörvar', 'Jörvi', 'Kaj', 'Kakali', 'Kaktus', 'Kaldi', 'Kaleb', 'Kali', 'Kalman', 'Kalmann', 'Kalmar', 'Kaprasíus', 'Karel', 'Karim', 'Karkur', 'Karl', 'Karles', 'Karli', 'Karvel', 'Kaspar', 'Kasper', 'Kastíel', 'Katarínus', 'Kató', 'Kár', 'Kári', 'Keran', 'Ketilbjörn', 'Ketill', 'Kilían', 'Kiljan', 'Kjalar', 'Kjallakur', 'Kjaran', 'Kjartan', 'Kjarval', 'Kjárr', 'Kjói', 'Klemens', 'Klemenz', 'Klængur', 'Knútur', 'Knörr', 'Koðrán', 'Koggi', 'Kolbeinn', 'Kolbjörn', 'Kolfinnur', 'Kolgrímur', 'Kolmar', 'Kolskeggur', 'Kolur', 'Kolviður', 'Konráð', 'Konstantínus', 'Kormákur', 'Kornelíus', 'Kort', 'Kópur', 'Kraki', 'Kris', 'Kristall', 'Kristberg', 'Kristbergur', 'Kristbjörn', 'Kristdór', 'Kristens', 'Krister', 'Kristfinnur', 'Kristgeir', 'Kristian', 'Kristinn', 'Kristján', 'Kristjón', 'Kristlaugur', 'Kristleifur', 'Kristmann', 'Kristmar', 'Kristmundur', 'Kristofer', 'Kristófer', 'Kristvaldur', 'Kristvarður', 'Kristvin', 'Kristþór', 'Krummi', 'Kveldúlfur', 'Lambert', 'Lars', 'Laufar', 'Laugi', 'Lauritz', 'Lár', 'Lárent', 'Lárentíus', 'Lárus', 'Leiðólfur', 'Leif', 'Leifur', 'Leiknir', 'Leo', 'Leon', 'Leonard', 'Leonhard', 'Leó', 'Leópold', 'Leví', 'Lér', 'Liljar', 'Lindar', 'Lindberg', 'Línberg', 'Líni', 'Ljósálfur', 'Ljótur', 'Ljúfur', 'Loðmundur', 'Loftur', 'Logi', 'Loki', 'Lórens', 'Lórenz', 'Ludvig', 'Lundi', 'Lúðvíg', 'Lúðvík', 'Lúkas', 'Lúter', 'Lúther', 'Lyngar', 'Lýður', 'Lýtingur', 'Maggi', 'Magngeir', 'Magni', 'Magnús', 'Magnþór', 'Makan', 'Manfred', 'Manfreð', 'Manúel', 'Mar', 'Marbjörn', 'Marel', 'Margeir', 'Margrímur', 'Mari', 'Marijón', 'Marinó', 'Marías', 'Marínó', 'Marís', 'Maríus', 'Marjón', 'Markó', 'Markús', 'Markþór', 'Maron', 'Marri', 'Mars', 'Marsellíus', 'Marteinn', 'Marten', 'Marthen', 'Martin', 'Marvin', 'Mathías', 'Matthías', 'Matti', 'Mattías', 'Max', 'Maximus', 'Máni', 'Már', 'Márus', 'Mekkinó', 'Melkíor', 'Melkólmur', 'Melrakki', 'Mensalder', 'Merkúr', 'Methúsalem', 'Metúsalem', 'Meyvant', 'Michael', 'Mikael', 'Mikjáll', 'Mikkael', 'Mikkel', 'Mildinberg', 'Mías', 'Mímir', 'Míó', 'Mír', 'Mjöllnir', 'Mjölnir', 'Moli', 'Morgan', 'Moritz', 'Mosi', 'Móði', 'Móri', 'Mórits', 'Móses', 'Muggur', 'Muni', 'Muninn', 'Múli', 'Myrkvi', 'Mýrkjartan', 'Mörður', 'Narfi', 'Natan', 'Natanael', 'Nataníel', 'Náttmörður', 'Náttúlfur', 'Neisti', 'Nenni', 'Neptúnus', 'Nicolas', 'Nikanor', 'Nikolai', 'Nikolas', 'Nikulás', 'Nils', 'Níels', 'Níls', 'Njáll', 'Njörður', 'Nonni', 'Norbert', 'Norðmann', 'Normann', 'Nóam', 'Nóel', 'Nói', 'Nóni', 'Nóri', 'Nóvember', 'Númi', 'Nývarð', 'Nökkvi', 'Oddbergur', 'Oddbjörn', 'Oddfreyr', 'Oddgeir', 'Oddi', 'Oddkell', 'Oddleifur', 'Oddmar', 'Oddsteinn', 'Oddur', 'Oddvar', 'Oddþór', 'Oktavíus', 'Októ', 'Októvíus', 'Olaf', 'Olav', 'Olgeir', 'Oliver', 'Olivert', 'Orfeus', 'Ormar', 'Ormur', 'Orri', 'Orvar', 'Otkell', 'Otri', 'Otti', 'Ottó', 'Otur', 'Óðinn', 'Ófeigur', 'Ólafur', 'Óli', 'Óliver', 'Ólíver', 'Ómar', 'Ómi', 'Óskar', 'Ósvald', 'Ósvaldur', 'Ósvífur', 'Óttar', 'Óttarr', 'Parmes', 'Patrek', 'Patrekur', 'Patrick', 'Patrik', 'Páll', 'Pálmar', 'Pálmi', 'Pedró', 'Per', 'Peter', 'Pétur', 'Pjetur', 'Príor', 'Rafael', 'Rafn', 'Rafnar', 'Rafnkell', 'Ragnar', 'Ragúel', 'Randver', 'Rannver', 'Rasmus', 'Ráðgeir', 'Ráðvarður', 'Refur', 'Reginbaldur', 'Reginn', 'Reidar', 'Reifnir', 'Reimar', 'Reinar', 'Reinhart', 'Reinhold', 'Reynald', 'Reynar', 'Reynir', 'Reyr', 'Richard', 'Rikharð', 'Rikharður', 'Ríkarður', 'Ríkharð', 'Ríkharður', 'Ríó', 'Robert', 'Rolf', 'Ronald', 'Róbert', 'Rólant', 'Róman', 'Rómeó', 'Rósant', 'Rósar', 'Rósberg', 'Rósenberg', 'Rósi', 'Rósinberg', 'Rósinkar', 'Rósinkrans', 'Rósmann', 'Rósmundur', 'Rudolf', 'Runi', 'Runólfur', 'Rúbar', 'Rúben', 'Rúdólf', 'Rúnar', 'Rúrik', 'Rútur', 'Röðull', 'Rögnvald', 'Rögnvaldur', 'Rögnvar', 'Rökkvi', 'Safír', 'Sakarías', 'Salmann', 'Salmar', 'Salómon', 'Salvar', 'Samson', 'Samúel', 'Sandel', 'Sandri', 'Sandur', 'Saxi', 'Sebastian', 'Sebastían', 'Seifur', 'Seimur', 'Sesar', 'Sesil', 'Sigbergur', 'Sigbert', 'Sigbjartur', 'Sigbjörn', 'Sigdór', 'Sigfastur', 'Sigfinnur', 'Sigfreður', 'Sigfús', 'Siggeir', 'Sighvatur', 'Sigjón', 'Siglaugur', 'Sigmann', 'Sigmar', 'Sigmundur', 'Signar', 'Sigri', 'Sigríkur', 'Sigsteinn', 'Sigtryggur', 'Sigtýr', 'Sigur', 'Sigurbaldur', 'Sigurberg', 'Sigurbergur', 'Sigurbjarni', 'Sigurbjartur', 'Sigurbjörn', 'Sigurbrandur', 'Sigurdór', 'Sigurður', 'Sigurfinnur', 'Sigurgeir', 'Sigurgestur', 'Sigurgísli', 'Sigurgrímur', 'Sigurhans', 'Sigurhjörtur', 'Sigurjón', 'Sigurkarl', 'Sigurlaugur', 'Sigurlás', 'Sigurleifur', 'Sigurliði', 'Sigurlinni', 'Sigurmann', 'Sigurmar', 'Sigurmon', 'Sigurmundur', 'Sigurnýas', 'Sigurnýjas', 'Siguroddur', 'Siguróli', 'Sigurpáll', 'Sigursteinn', 'Sigursveinn', 'Sigurvaldi', 'Sigurvin', 'Sigurþór', 'Sigvaldi', 'Sigvarður', 'Sigþór', 'Silli', 'Sindri', 'Símon', 'Sírnir', 'Sírus', 'Sívar', 'Sjafnar', 'Skafti', 'Skapti', 'Skarphéðinn', 'Skefill', 'Skeggi', 'Skíði', 'Skírnir', 'Skjöldur', 'Skorri', 'Skuggi', 'Skúli', 'Skúta', 'Skær', 'Skæringur', 'Smári', 'Smiður', 'Smyrill', 'Snjóki', 'Snjólaugur', 'Snjólfur', 'Snorri', 'Snæbjartur', 'Snæbjörn', 'Snæhólm', 'Snælaugur', 'Snær', 'Snæringur', 'Snævar', 'Snævarr', 'Snæþór', 'Soffanías', 'Sophanías', 'Sophus', 'Sófónías', 'Sófus', 'Sókrates', 'Sólberg', 'Sólbergur', 'Sólbjartur', 'Sólbjörn', 'Sólimann', 'Sólmar', 'Sólmundur', 'Sólon', 'Sólver', 'Sólvin', 'Spartakus', 'Sporði', 'Spói', 'Stanley', 'Stapi', 'Starkaður', 'Starri', 'Stefan', 'Stefán', 'Stefnir', 'Steinar', 'Steinarr', 'Steinberg', 'Steinbergur', 'Steinbjörn', 'Steindór', 'Steinfinnur', 'Steingrímur', 'Steini', 'Steinkell', 'Steinmann', 'Steinmar', 'Steinmóður', 'Steinn', 'Steinólfur', 'Steinröður', 'Steinvarður', 'Steinþór', 'Stirnir', 'Stígur', 'Stormur', 'Stórólfur', 'Sturla', 'Sturlaugur', 'Sturri', 'Styr', 'Styrbjörn', 'Styrkár', 'Styrmir', 'Styrr', 'Sumarliði', 'Svafar', 'Svali', 'Svan', 'Svanberg', 'Svanbergur', 'Svanbjörn', 'Svangeir', 'Svanhólm', 'Svani', 'Svanlaugur', 'Svanmundur', 'Svanur', 'Svanþór', 'Svavar', 'Sváfnir', 'Sveinar', 'Sveinberg', 'Sveinbjartur', 'Sveinbjörn', 'Sveinjón', 'Sveinlaugur', 'Sveinmar', 'Sveinn', 'Sveinungi', 'Sveinþór', 'Svend', 'Sverre', 'Sverrir', 'Svölnir', 'Svörfuður', 'Sýrus', 'Sæberg', 'Sæbergur', 'Sæbjörn', 'Sæi', 'Sælaugur', 'Sæmann', 'Sæmundur', 'Sær', 'Sævald', 'Sævaldur', 'Sævar', 'Sævarr', 'Sævin', 'Sæþór', 'Sölmundur', 'Sölvar', 'Sölvi', 'Sören', 'Sörli', 'Tandri', 'Tarfur', 'Teitur', 'Theodór', 'Theódór', 'Thomas', 'Thor', 'Thorberg', 'Thór', 'Tindar', 'Tindri', 'Tindur', 'Tinni', 'Tími', 'Tímon', 'Tímoteus', 'Tímóteus', 'Tístran', 'Tjaldur', 'Tjörfi', 'Tjörvi', 'Tobías', 'Tolli', 'Tonni', 'Torfi', 'Tóbías', 'Tói', 'Tóki', 'Tómas', 'Tór', 'Trausti', 'Tristan', 'Trostan', 'Trúmann', 'Tryggvi', 'Tumas', 'Tumi', 'Tyrfingur', 'Týr', 'Ubbi', 'Uggi', 'Ulrich', 'Uni', 'Unnar', 'Unnbjörn', 'Unndór', 'Unnsteinn', 'Unnþór', 'Urðar', 'Uxi', 'Úddi', 'Úlfar', 'Úlfgeir', 'Úlfhéðinn', 'Úlfkell', 'Úlfljótur', 'Úlftýr', 'Úlfur', 'Úlrik', 'Úranus', 'Vagn', 'Vakur', 'Valberg', 'Valbergur', 'Valbjörn', 'Valbrandur', 'Valdemar', 'Valdi', 'Valdimar', 'Valdór', 'Valentín', 'Valentínus', 'Valgarð', 'Valgarður', 'Valgeir', 'Valíant', 'Vallaður', 'Valmar', 'Valmundur', 'Valsteinn', 'Valter', 'Valtýr', 'Valur', 'Valves', 'Valþór', 'Varmar', 'Vatnar', 'Váli', 'Vápni', 'Veigar', 'Veigur', 'Ver', 'Vermundur', 'Vernharð', 'Vernharður', 'Vestar', 'Vestmar', 'Veturliði', 'Vébjörn', 'Végeir', 'Vékell', 'Vélaugur', 'Vémundur', 'Vésteinn', 'Victor', 'Viðar', 'Vigfús', 'Viggó', 'Vignir', 'Vigri', 'Vigtýr', 'Vigur', 'Vikar', 'Viktor', 'Vilberg', 'Vilbergur', 'Vilbert', 'Vilbjörn', 'Vilbogi', 'Vilbrandur', 'Vilgeir', 'Vilhelm', 'Vilhjálmur', 'Vili', 'Viljar', 'Vilji', 'Villi', 'Vilmar', 'Vilmundur', 'Vincent', 'Vinjar', 'Virgill', 'Víðar', 'Víðir', 'Vífill', 'Víglundur', 'Vígmar', 'Vígmundur', 'Vígsteinn', 'Vígþór', 'Víkingur', 'Vopni', 'Vorm', 'Vöggur', 'Völundur', 'Vörður', 'Vöttur', 'Walter', 'Werner', 'Wilhelm', 'Willard', 'William', 'Willum', 'Ylur', 'Ymir', 'Yngvar', 'Yngvi', 'Yrkill', 'Ýmir', 'Ýrar', 'Zakaría', 'Zakarías', 'Zophanías', 'Zophonías', 'Zóphanías', 'Zóphonías', 'Þangbrandur', 'Þengill', 'Þeyr', 'Þiðrandi', 'Þiðrik', 'Þinur', 'Þjálfi', 'Þjóðann', 'Þjóðbjörn', 'Þjóðgeir', 'Þjóðleifur', 'Þjóðmar', 'Þjóðólfur', 'Þjóðrekur', 'Þjóðvarður', 'Þjóstar', 'Þjóstólfur', 'Þorberg', 'Þorbergur', 'Þorbjörn', 'Þorbrandur', 'Þorfinnur', 'Þorgarður', 'Þorgautur', 'Þorgeir', 'Þorgestur', 'Þorgils', 'Þorgísl', 'Þorgnýr', 'Þorgrímur', 'Þorkell', 'Þorlaugur', 'Þorlákur', 'Þorleifur', 'Þorleikur', 'Þormar', 'Þormóður', 'Þormundur', 'Þorri', 'Þorsteinn', 'Þorvaldur', 'Þorvar', 'Þorvarður', 'Þór', 'Þórar', 'Þórarinn', 'Þórbergur', 'Þórbjörn', 'Þórður', 'Þórgnýr', 'Þórgrímur', 'Þórhaddur', 'Þórhalli', 'Þórhallur', 'Þórir', 'Þórlaugur', 'Þórleifur', 'Þórlindur', 'Þórmar', 'Þórmundur', 'Þóroddur', 'Þórormur', 'Þórólfur', 'Þórsteinn', 'Þórörn', 'Þrastar', 'Þráinn', 'Þrándur', 'Þróttur', 'Þrúðmar', 'Þrymur', 'Þröstur', 'Þyrnir', 'Ægir', 'Æsir', 'Ævar', 'Ævarr', 'Ögmundur', 'Ögri', 'Ölnir', 'Ölver', 'Ölvir', 'Öndólfur', 'Önundur', 'Örlaugur', 'Örlygur', 'Örn', 'Örnólfur', 'Örvar', 'Össur', 'Öxar'); + + /** + * @var string Icelandic middle names. + */ + protected static $middleName = array( + 'Aðaldal', 'Aldan', 'Arnberg', 'Arnfjörð', 'Austan', 'Austdal', 'Austfjörð', 'Áss', 'Bakkdal', 'Bakkmann', 'Bald', 'Ben', 'Bergholt', 'Bergland', 'Bíldsfells', 'Bjarg', 'Bjarndal', 'Bjarnfjörð', 'Bláfeld', 'Blómkvist', 'Borgdal', 'Brekkmann', 'Brim', 'Brúnsteð', 'Dalhoff', 'Dan', 'Diljan', 'Ektavon', 'Eldberg', 'Elísberg', 'Elvan', 'Espólín', 'Eyhlíð', 'Eyvík', 'Falk', 'Finndal', 'Fossberg', 'Freydal', 'Friðhólm', 'Giljan', 'Gilsfjörð', 'Gnarr', 'Gnurr', 'Grendal', 'Grindvík', 'Gull', 'Haffjörð', 'Hafnes', 'Hafnfjörð', 'Har', 'Heimdal', 'Heimsberg', 'Helgfell', 'Herberg', 'Hildiberg', 'Hjaltdal', 'Hlíðkvist', 'Hnappdal', 'Hnífsdal', 'Hofland', 'Hofteig', 'Hornfjörð', 'Hólmberg', 'Hrafnan', 'Hrafndal', 'Hraunberg', 'Hreinberg', 'Hreindal', 'Hrútfjörð', 'Hvammdal', 'Hvítfeld', 'Höfðdal', 'Hörðdal', 'Íshólm', 'Júl', 'Kjarrval', 'Knaran', 'Knarran', 'Krossdal', 'Laufkvist', 'Laufland', 'Laugdal', 'Laxfoss', 'Liljan', 'Linddal', 'Línberg', 'Ljós', 'Loðmfjörð', 'Lyngberg', 'Magdal', 'Magg', 'Matt', 'Miðdal', 'Miðvík', 'Mjófjörð', 'Móberg', 'Mýrmann', 'Nesmann', 'Norðland', 'Núpdal', 'Ólfjörð', 'Ósland', 'Ósmann', 'Reginbald', 'Reykfell', 'Reykfjörð', 'Reynholt', 'Salberg', 'Sandhólm', 'Seljan', 'Sigurhólm', 'Skagalín', 'Skíðdal', 'Snæberg', 'Snædahl', 'Sólan', 'Stardal', 'Stein', 'Steinbekk', 'Steinberg', 'Storm', 'Straumberg', 'Svanhild', 'Svarfdal', 'Sædal', 'Val', 'Valagils', 'Vald', 'Varmdal', 'Vatnsfjörð', 'Vattar', 'Vattnes', 'Viðfjörð', 'Vídalín', 'Víking', 'Vopnfjörð', 'Yngling', 'Þor', 'Önfjörð', 'Örbekk', 'Öxdal', 'Öxndal' + ); + + /** + * Randomly return a icelandic middle name. + * + * @return string + */ + public static function middleName() + { + return static::randomElement(static::$middleName); + } + + /** + * Generate prepared last name for further processing + * + * @return string + */ + public function lastName() + { + $name = static::firstNameMale(); + + if (substr($name, -2) === 'ur') { + $name = substr($name, 0, strlen($name) - 2); + } + + if (substr($name, -1) !== 's') { + $name .= 's'; + } + + return $name; + } + + /** + * Randomly return a icelandic last name for woman. + * + * @return string + */ + public function lastNameMale() + { + return $this->lastName().'dóttir'; + } + + /** + * Randomly return a icelandic last name for man. + * + * @return string + */ + public function lastNameFemale() + { + return $this->lastName().'son'; + } + + /** + * Randomly return a icelandic Kennitala (Social Security number) format. + * + * @link http://en.wikipedia.org/wiki/Kennitala + * + * @return string + */ + public static function ssn() + { + // random birth date + $birthdate = new \DateTime('@' . mt_rand(0, time())); + + // last four buffer + $lastFour = null; + + // security variable reference + $ref = '32765432'; + + // valid flag + $valid = false; + + while (! $valid) { + // make two random numbers + $rand = static::randomDigit().static::randomDigit(); + + // 8 char string with birth date and two random numbers + $tmp = $birthdate->format('dmy').$rand; + + // loop through temp string + for ($i = 7, $sum = 0; $i >= 0; $i--) { + // calculate security variable + $sum += ($tmp[$i] * $ref[$i]); + } + + // subtract 11 if not 11 + $chk = ($sum % 11 === 0) ? 0 : (11 - ($sum % 11)); + + if ($chk < 10) { + $lastFour = $rand.$chk.substr($birthdate->format('Y'), 1, 1); + + $valid = true; + } + } + + return sprintf('%s-%s', $birthdate->format('dmy'), $lastFour); + } +} diff --git a/lib/faker/src/Faker/Provider/is_IS/PhoneNumber.php b/lib/faker/src/Faker/Provider/is_IS/PhoneNumber.php new file mode 100755 index 0000000..de91f74 --- /dev/null +++ b/lib/faker/src/Faker/Provider/is_IS/PhoneNumber.php @@ -0,0 +1,20 @@ + + */ +class PhoneNumber extends \Faker\Provider\PhoneNumber +{ + /** + * @var array Icelandic phone number formats. + */ + protected static $formats = array( + '+354 ### ####', + '+354 #######', + '+354#######', + '### ####', + '#######', + ); +} diff --git a/lib/faker/src/Faker/Provider/it_IT/Address.php b/lib/faker/src/Faker/Provider/it_IT/Address.php new file mode 100755 index 0000000..ebfcac0 --- /dev/null +++ b/lib/faker/src/Faker/Provider/it_IT/Address.php @@ -0,0 +1,97 @@ +generator->parse($format); + } +} diff --git a/lib/faker/src/Faker/Provider/ja_JP/Company.php b/lib/faker/src/Faker/Provider/ja_JP/Company.php new file mode 100755 index 0000000..937f375 --- /dev/null +++ b/lib/faker/src/Faker/Provider/ja_JP/Company.php @@ -0,0 +1,17 @@ +generator->parse($format)); + } + + /** + * @example 'yamada.jp' + */ + public function domainName() + { + return static::randomElement(static::$lastNameAscii) . '.' . $this->tld(); + } +} diff --git a/lib/faker/src/Faker/Provider/ja_JP/Person.php b/lib/faker/src/Faker/Provider/ja_JP/Person.php new file mode 100755 index 0000000..20fb6cd --- /dev/null +++ b/lib/faker/src/Faker/Provider/ja_JP/Person.php @@ -0,0 +1,100 @@ +generator->parse($format); + } + + /** + * @example 'アオタ' + */ + public static function firstKanaName() + { + return static::randomElement(static::$firstKanaName); + } + + /** + * @example 'アキラ' + */ + public static function lastKanaName() + { + return static::randomElement(static::$lastKanaName); + } +} diff --git a/lib/faker/src/Faker/Provider/ja_JP/PhoneNumber.php b/lib/faker/src/Faker/Provider/ja_JP/PhoneNumber.php new file mode 100755 index 0000000..f4230d1 --- /dev/null +++ b/lib/faker/src/Faker/Provider/ja_JP/PhoneNumber.php @@ -0,0 +1,12 @@ +generator->parse($format); + } + + public static function country() + { + return static::randomElement(static::$country); + } + + public static function postcode() + { + return static::toUpper(static::bothify(static::randomElement(static::$postcode))); + } + + public static function regionSuffix() + { + return static::randomElement(static::$regionSuffix); + } + + public static function region() + { + return static::randomElement(static::$region); + } + + public static function citySuffix() + { + return static::randomElement(static::$citySuffix); + } + + public function city() + { + return static::randomElement(static::$city); + } + + public static function streetSuffix() + { + return static::randomElement(static::$streetSuffix); + } + + public static function street() + { + return static::randomElement(static::$street); + } +} diff --git a/lib/faker/src/Faker/Provider/kk_KZ/Color.php b/lib/faker/src/Faker/Provider/kk_KZ/Color.php new file mode 100755 index 0000000..082a9d6 --- /dev/null +++ b/lib/faker/src/Faker/Provider/kk_KZ/Color.php @@ -0,0 +1,12 @@ +generator->parse($format); + } + + public static function companyPrefix() + { + return static::randomElement(static::$companyPrefixes); + } + + public static function companyNameElement() + { + return static::randomElement(static::$companyElements); + } + + public static function companyNameSuffix() + { + return static::randomElement(static::$companyNameSuffixes); + } + + /** + * National Business Identification Numbers + * + * @link http://egov.kz/wps/portal/!utWCM/p/b1/04_Sj9Q1MjAwsDQ1s9CP0I_KSyzLTE8syczPS8wB8aPM4oO8PE2cnAwdDSxMw4wMHE08nZ2CA0KDXcwMgQoikRUYWIY4gxS4hwU4mRkbGBgTp98AB3A0IKQ_XD8KVQkWF4AV4LHCzyM_N1U_uKhUPzcqx83SU9cRANth_Rk!/dl4/d5/L0lHSkovd0RNQU5rQUVnQSEhLzRKVUUvZW4!/ + * @param \DateTime $registrationDate + * @return string 12 digits, like 150140000019 + */ + public static function businessIdentificationNumber(\DateTime $registrationDate = null) + { + if (!$registrationDate) { + $registrationDate = \Faker\Provider\DateTime::dateTimeThisYear(); + } + + $dateAsString = $registrationDate->format('ym'); + $legalEntityType = (string) static::numberBetween(4, 6); + $legalEntityAdditionalType = (string) static::numberBetween(0, 3); + $randomDigits = (string) static::numerify('######'); + + return $dateAsString . $legalEntityType . $legalEntityAdditionalType . $randomDigits; + } +} diff --git a/lib/faker/src/Faker/Provider/kk_KZ/Internet.php b/lib/faker/src/Faker/Provider/kk_KZ/Internet.php new file mode 100755 index 0000000..75999c2 --- /dev/null +++ b/lib/faker/src/Faker/Provider/kk_KZ/Internet.php @@ -0,0 +1,9 @@ +format('ymd'); + $genderAndCenturyId = (string) static::numberBetween(1, 6); + $randomDigits = (string) static::numerify('#####'); + + return $dateAsString . $genderAndCenturyId . $randomDigits; + } +} diff --git a/lib/faker/src/Faker/Provider/kk_KZ/PhoneNumber.php b/lib/faker/src/Faker/Provider/kk_KZ/PhoneNumber.php new file mode 100755 index 0000000..edb38dd --- /dev/null +++ b/lib/faker/src/Faker/Provider/kk_KZ/PhoneNumber.php @@ -0,0 +1,16 @@ +generator->parse($format)); + } + + /** + * @example 'kim.kr' + */ + public function domainName() + { + return static::randomElement(static::$lastNameAscii) . '.' . $this->tld(); + } +} diff --git a/lib/faker/src/Faker/Provider/ko_KR/Person.php b/lib/faker/src/Faker/Provider/ko_KR/Person.php new file mode 100755 index 0000000..21bc22c --- /dev/null +++ b/lib/faker/src/Faker/Provider/ko_KR/Person.php @@ -0,0 +1,52 @@ +generator->parse($format); + } + + public static function country() + { + return static::randomElement(static::$country); + } + + public static function postcode() + { + return static::toUpper(static::bothify(static::randomElement(static::$postcode))); + } + + public static function regionSuffix() + { + return static::randomElement(static::$regionSuffix); + } + + public static function region() + { + return static::randomElement(static::$region); + } + + public static function cityPrefix() + { + return static::randomElement(static::$cityPrefix); + } + + public function city() + { + return static::randomElement(static::$city); + } + + public static function streetPrefix() + { + return static::randomElement(static::$streetPrefix); + } + + public static function street() + { + return static::randomElement(static::$street); + } +} diff --git a/lib/faker/src/Faker/Provider/lv_LV/Color.php b/lib/faker/src/Faker/Provider/lv_LV/Color.php new file mode 100755 index 0000000..99e681b --- /dev/null +++ b/lib/faker/src/Faker/Provider/lv_LV/Color.php @@ -0,0 +1,19 @@ +format('dmy'); + $randomDigits = (string) static::numerify('####'); + + $checksum = Luhn::computeCheckDigit($datePart . $randomDigits); + + return $datePart . '-' . $randomDigits . $checksum; + } +} diff --git a/lib/faker/src/Faker/Provider/lv_LV/PhoneNumber.php b/lib/faker/src/Faker/Provider/lv_LV/PhoneNumber.php new file mode 100755 index 0000000..f6b6148 --- /dev/null +++ b/lib/faker/src/Faker/Provider/lv_LV/PhoneNumber.php @@ -0,0 +1,13 @@ +format('dmy'); + + /** + * @todo These number should be random based on birth year + * @link http://no.wikipedia.org/wiki/F%C3%B8dselsnummer + */ + $randomDigits = (string)static::numerify('##'); + + switch($gender) { + case static::GENDER_MALE: + $genderDigit = static::randomElement(array(1,3,5,7,9)); + break; + case static::GENDER_FEMALE: + $genderDigit = static::randomElement(array(0,2,4,6,8)); + break; + default: + $genderDigit = (string)static::numerify('#'); + } + + + $digits = $datePart.$randomDigits.$genderDigit; + + /** + * @todo Calculate modulo 11 of $digits + * @link http://no.wikipedia.org/wiki/F%C3%B8dselsnummer + */ + $checksum = (string)static::numerify('##'); + + + return $digits.$checksum; + } +} diff --git a/lib/faker/src/Faker/Provider/no_NO/PhoneNumber.php b/lib/faker/src/Faker/Provider/no_NO/PhoneNumber.php new file mode 100755 index 0000000..7c80fcf --- /dev/null +++ b/lib/faker/src/Faker/Provider/no_NO/PhoneNumber.php @@ -0,0 +1,22 @@ + 'Aareal Bank Aktiengesellschaft (Spółka Akcyjna) - Oddział w Polsce', + '249' => 'Alior Bank SA', + '247' => 'Banco Espirito Santo de Investimento, S.A. Spółka Akcyjna Oddział w Polsce', + '238' => 'Banco Mais S.A. (SA) Oddział w Polsce', + '106' => 'Bank BPH SA', + '219' => 'Bank DnB NORD Polska SA', + '203' => 'Bank Gospodarki Żywnościowej SA', + '113' => 'Bank Gospodarstwa Krajowego', + '122' => 'Bank Handlowo - Kredytowy SA (w likwidacji 31.03.92)', + '103' => 'Bank Handlowy w Warszawie SA', + '116' => 'Bank Millennium SA', + '154' => 'Bank Ochrony Środowiska SA', + '260' => 'Bank of China (Luxembourg)S.A. Spółka Akcyjna Oddział w Polsce', + '221' => 'Bank of Tokyo-Mitsubishi UFJ (Polska) SA', + '132' => 'Bank Pocztowy SA', + '124' => 'Bank Polska Kasa Opieki SA', + '193' => 'BANK POLSKIEJ SPÓŁDZIELCZOŚCI SA', + '109' => 'Bank Zachodni WBK SA', + '224' => 'Banque PSA Finance SA Oddział w Polsce', + '160' => 'BNP PARIBAS BANK POLSKA SA', + '235' => 'BNP PARIBAS SA Oddział w Polsce', + '243' => 'BNP Paribas Securities Services SKAOddział w Polsce', + '229' => 'BPI Bank Polskich Inwestycji SA', + '215' => 'BRE Bank Hipoteczny SA', + '114' => 'BRE Bank SA', + '239' => 'CAIXABANK, S.A. (SPÓŁKA AKCYJNA)ODDZIAŁ W POLSCE', + '254' => 'Citibank Europe plc (Publiczna Spółka Akcyjna) Oddział w Polsce', + '194' => 'Credit Agricole Bank Polska SA', + '252' => 'CREDIT SUISSE (LUXEMBOURG) S.A. Spółka Akcyjna, Oddział w Polsce', + '236' => 'Danske Bank A/S SA Oddział w Polsce', + '191' => 'Deutsche Bank PBC SA', + '188' => 'Deutsche Bank Polska SA', + '174' => 'DZ BANK Polska SA', + '241' => 'Elavon Financial Services Limited (Spółka z ograniczoną odpowiedzialnością) Oddział w Polsce', + '147' => 'Euro Bank SA', + '265' => 'EUROCLEAR Bank SA/NV (Spółka Akcyjna) - Oddział w Polsce', + '207' => 'FCE Bank Polska SA', + '214' => 'Fiat Bank Polska SA', + '253' => 'FM Bank SA', + '248' => 'Getin Noble Bank SA', + '128' => 'HSBC Bank Polska SA', + '195' => 'Idea Bank SA', + '255' => 'Ikano Bank GmbH (Sp. z o.o.) Oddział w Polsce', + '262' => 'Industrial and Commercial Bank of China (Europe) S.A. (Spółka Akcyjna) Oddział w Polsce', + '105' => 'ING Bank Śląski SA', + '266' => 'Intesa Sanpaolo S.p.A. Spółka Akcyjna Oddział w Polsce', + '168' => 'INVEST - BANK SA', + '258' => 'J.P. Morgan Europe Limited Sp. z o.o. Oddział w Polsce', + '158' => 'Mercedes-Benz Bank Polska SA', + '130' => 'Meritum Bank ICB SA', + '101' => 'Narodowy Bank Polski', + '256' => 'Nordea Bank AB SA Oddział w Polsce', + '144' => 'NORDEA BANK POLSKA SA', + '232' => 'Nykredit Realkredit A/S SA - Oddział w Polsce', + '189' => 'Pekao Bank Hipoteczny SA', + '187' => 'Polski Bank Przedsiębiorczości SA', + '102' => 'Powszechna Kasa Oszczędności Bank Polski SA', + '200' => 'Rabobank Polska SA', + '175' => 'Raiffeisen Bank Polska SA', + '167' => 'RBS Bank (Polska) SA', + '264' => 'RCI Banque Spółka Akcyjna Oddział w Polsce', + '212' => 'Santander Consumer Bank SA', + '263' => 'Saxo Bank A/S Spółka Akcyjna Oddział w Polsce', + '161' => 'SGB-Bank SA', + '237' => 'Skandinaviska Enskilda Banken AB (SA) - Oddział w Polsce', + '184' => 'Societe Generale SA Oddział w Polsce', + '225' => 'Svenska Handelsbanken AB SA Oddział w Polsce', + '227' => 'Sygma Banque Societe Anonyme (SA) Oddział w Polsce', + '216' => 'Toyota Bank Polska SA', + '257' => 'UBS Limited (spółka z ograniczoną odpowiedzialnością) Oddział w Polsce', + '261' => 'Vanquis Bank Limited (spółka z ograniczoną odpowiedzialnością) Oddział w Polsce', + '213' => 'VOLKSWAGEN BANK POLSKA SA', + ); + + /** + * @example 'Euro Bank SA' + */ + public static function bank() + { + return static::randomElement(static::$banks); + } + + /** + * International Bank Account Number (IBAN) + * @link http://en.wikipedia.org/wiki/International_Bank_Account_Number + * @param string $prefix for generating bank account number of a specific bank + * @param string $countryCode ISO 3166-1 alpha-2 country code + * @param integer $length total length without country code and 2 check digits + * @return string + */ + public static function bankAccountNumber($prefix = '', $countryCode = 'PL', $length = null) + { + return static::iban($countryCode, $prefix, $length); + } + + protected static function addBankCodeChecksum($iban, $countryCode = 'PL') + { + if ($countryCode != "PL" || strlen($iban) <= 8) { + return $iban; + } + $checksum = 0; + $weights = array(7, 1, 3, 9, 7, 1, 3); + for ($i = 0; $i < 7; $i++) { + $checksum += $weights[$i] * (int) $iban[$i]; + } + $checksum = $checksum % 10; + + return substr($iban, 0, 7) . $checksum . substr($iban, 8); + } +} diff --git a/lib/faker/src/Faker/Provider/pl_PL/Person.php b/lib/faker/src/Faker/Provider/pl_PL/Person.php new file mode 100755 index 0000000..c6b2402 --- /dev/null +++ b/lib/faker/src/Faker/Provider/pl_PL/Person.php @@ -0,0 +1,226 @@ +generator->parse(static::randomElement(static::$lastNameFormat)); + } + + public static function lastNameMale() + { + return static::randomElement(static::$lastNameMale); + } + + public static function lastNameFemale() + { + return static::randomElement(static::$lastNameFemale); + } + + public function title($gender = null) + { + return static::randomElement(static::$title); + } + + /** + * replaced by specific unisex Polish title + */ + public static function titleMale() + { + return static::title(); + } + + /** + * replaced by specific unisex Polish title + */ + public static function titleFemale() + { + return static::title(); + } + + /** + * PESEL - Universal Electronic System for Registration of the Population + * @link http://en.wikipedia.org/wiki/PESEL + * @param DateTime $birthdate + * @param string $sex M for male or F for female + * @return string 11 digit number, like 44051401358 + */ + public static function pesel($birthdate = null, $sex = null) + { + if ($birthdate === null) { + $birthdate = \Faker\Provider\DateTime::dateTimeThisCentury(); + } + + $weights = array(1, 3, 7, 9, 1, 3, 7, 9, 1, 3); + $length = count($weights); + + $fullYear = (int) $birthdate->format('Y'); + $year = (int) $birthdate->format('y'); + $month = $birthdate->format('m') + (((int) ($fullYear/100) - 14) % 5) * 20; + $day = $birthdate->format('d'); + + $result = array((int) ($year / 10), $year % 10, (int) ($month / 10), $month % 10, (int) ($day / 10), $day % 10); + + for ($i = 6; $i < $length; $i++) { + $result[$i] = static::randomDigit(); + } + if ($sex == "M") { + $result[$length - 1] |= 1; + } elseif ($sex == "F") { + $result[$length - 1] ^= 1; + } + $checksum = 0; + for ($i = 0; $i < $length; $i++) { + $checksum += $weights[$i] * $result[$i]; + } + $checksum = (10 - ($checksum % 10)) % 10; + $result[] = $checksum; + + return implode('', $result); + } + + /** + * National Identity Card number + * @link http://en.wikipedia.org/wiki/Polish_National_Identity_Card + * @return string 3 letters and 6 digits, like ABA300000 + */ + public static function personalIdentityNumber() + { + $range = str_split("ABCDEFGHIJKLMNPRSTUVWXYZ"); + $low = array("A", static::randomElement($range), static::randomElement($range)); + $high = array(static::randomDigit(), static::randomDigit(), static::randomDigit(), static::randomDigit(), static::randomDigit()); + $weights = array(7, 3, 1, 7, 3, 1, 7, 3); + $checksum = 0; + for ($i = 0, $size = count($low); $i < $size; $i++) { + $checksum += $weights[$i] * (ord($low[$i]) - 55); + } + for ($i = 0, $size = count($high); $i < $size; $i++) { + $checksum += $weights[$i+3] * $high[$i]; + } + $checksum %= 10; + + return implode('', $low).$checksum.implode('', $high); + } + + /** + * Taxpayer Identification Number (NIP in Polish) + * @link http://en.wikipedia.org/wiki/PESEL#Other_identifiers + * @link http://pl.wikipedia.org/wiki/NIP + * @return string 10 digit number + */ + public static function taxpayerIdentificationNumber() + { + $weights = array(6, 5, 7, 2, 3, 4, 5, 6, 7); + $result = array(); + do { + $result = array( + static::randomDigitNotNull(), static::randomDigitNotNull(), static::randomDigitNotNull(), + static::randomDigit(), static::randomDigit(), static::randomDigit(), + static::randomDigit(), static::randomDigit(), static::randomDigit(), + ); + $checksum = 0; + for ($i = 0, $size = count($result); $i < $size; $i++) { + $checksum += $weights[$i] * $result[$i]; + } + $checksum %= 11; + } while ($checksum == 10); + $result[] = $checksum; + + return implode('', $result); + } +} diff --git a/lib/faker/src/Faker/Provider/pl_PL/PhoneNumber.php b/lib/faker/src/Faker/Provider/pl_PL/PhoneNumber.php new file mode 100755 index 0000000..65bc5c0 --- /dev/null +++ b/lib/faker/src/Faker/Provider/pl_PL/PhoneNumber.php @@ -0,0 +1,18 @@ + + + Prof. Hart will answer or forward your message. + + We would prefer to send you information by email. + + + **The Legal Small Print** + + + (Three Pages) + + ***START**THE SMALL PRINT!**FOR PUBLIC DOMAIN EBOOKS**START*** + Why is this "Small Print!" statement here? You know: lawyers. + They tell us you might sue us if there is something wrong with + your copy of this eBook, even if you got it for free from + someone other than us, and even if what's wrong is not our + fault. So, among other things, this "Small Print!" statement + disclaims most of our liability to you. It also tells you how + you may distribute copies of this eBook if you want to. + + *BEFORE!* YOU USE OR READ THIS EBOOK + By using or reading any part of this PROJECT GUTENBERG-tm + eBook, you indicate that you understand, agree to and accept + this "Small Print!" statement. If you do not, you can receive + a refund of the money (if any) you paid for this eBook by + sending a request within 30 days of receiving it to the person + you got it from. If you received this eBook on a physical + medium (such as a disk), you must return it with your request. + + ABOUT PROJECT GUTENBERG-TM EBOOKS + This PROJECT GUTENBERG-tm eBook, like most PROJECT GUTENBERG-tm eBooks, + is a "public domain" work distributed by Professor Michael S. Hart + through the Project Gutenberg Association (the "Project"). + Among other things, this means that no one owns a United States copyright + on or for this work, so the Project (and you!) can copy and + distribute it in the United States without permission and + without paying copyright royalties. Special rules, set forth + below, apply if you wish to copy and distribute this eBook + under the "PROJECT GUTENBERG" trademark. + + Please do not use the "PROJECT GUTENBERG" trademark to market + any commercial products without permission. + + To create these eBooks, the Project expends considerable + efforts to identify, transcribe and proofread public domain + works. Despite these efforts, the Project's eBooks and any + medium they may be on may contain "Defects". Among other + things, Defects may take the form of incomplete, inaccurate or + corrupt data, transcription errors, a copyright or other + intellectual property infringement, a defective or damaged + disk or other eBook medium, a computer virus, or computer + codes that damage or cannot be read by your equipment. + + LIMITED WARRANTY; DISCLAIMER OF DAMAGES + But for the "Right of Replacement or Refund" described below, + [1] Michael Hart and the Foundation (and any other party you may + receive this eBook from as a PROJECT GUTENBERG-tm eBook) disclaims + all liability to you for damages, costs and expenses, including + legal fees, and [2] YOU HAVE NO REMEDIES FOR NEGLIGENCE OR + UNDER STRICT LIABILITY, OR FOR BREACH OF WARRANTY OR CONTRACT, + INCLUDING BUT NOT LIMITED TO INDIRECT, CONSEQUENTIAL, PUNITIVE + OR INCIDENTAL DAMAGES, EVEN IF YOU GIVE NOTICE OF THE + POSSIBILITY OF SUCH DAMAGES. + + If you discover a Defect in this eBook within 90 days of + receiving it, you can receive a refund of the money (if any) + you paid for it by sending an explanatory note within that + time to the person you received it from. If you received it + on a physical medium, you must return it with your note, and + such person may choose to alternatively give you a replacement + copy. If you received it electronically, such person may + choose to alternatively give you a second opportunity to + receive it electronically. + + THIS EBOOK IS OTHERWISE PROVIDED TO YOU "AS-IS". NO OTHER + WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, ARE MADE TO YOU AS + TO THE EBOOK OR ANY MEDIUM IT MAY BE ON, INCLUDING BUT NOT + LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A + PARTICULAR PURPOSE. + + Some states do not allow disclaimers of implied warranties or + the exclusion or limitation of consequential damages, so the + above disclaimers and exclusions may not apply to you, and you + may have other legal rights. + + INDEMNITY + You will indemnify and hold Michael Hart, the Foundation, + and its trustees and agents, and any volunteers associated + with the production and distribution of Project Gutenberg-tm + texts harmless, from all liability, cost and expense, including + legal fees, that arise directly or indirectly from any of the + following that you do or cause: [1] distribution of this eBook, + [2] alteration, modification, or addition to the eBook, + or [3] any Defect. + + DISTRIBUTION UNDER "PROJECT GUTENBERG-tm" + You may distribute copies of this eBook electronically, or by + disk, book or any other medium if you either delete this + "Small Print!" and all other references to Project Gutenberg, + or: + + [1] Only give exact copies of it. Among other things, this + requires that you do not remove, alter or modify the + eBook or this "small print!" statement. You may however, + if you wish, distribute this eBook in machine readable + binary, compressed, mark-up, or proprietary form, + including any form resulting from conversion by word + processing or hypertext software, but only so long as + *EITHER*: + + [*] The eBook, when displayed, is clearly readable, and + does *not* contain characters other than those + intended by the author of the work, although tilde + (~), asterisk (*) and underline (_) characters may + be used to convey punctuation intended by the + author, and additional characters may be used to + indicate hypertext links; OR + + [*] The eBook may be readily converted by the reader at + no expense into plain ASCII, EBCDIC or equivalent + form by the program that displays the eBook (as is + the case, for instance, with most word processors); + OR + + [*] You provide, or agree to also provide on request at + no additional cost, fee or expense, a copy of the + eBook in its original plain ASCII form (or in EBCDIC + or other equivalent proprietary form). + + [2] Honor the eBook refund and replacement provisions of this + "Small Print!" statement. + + [3] Pay a trademark license fee to the Foundation of 20% of the + gross profits you derive calculated using the method you + already use to calculate your applicable taxes. If you + don't derive profits, no royalty is due. Royalties are + payable to "Project Gutenberg Literary Archive Foundation" + the 60 days following each date you prepare (or were + legally required to prepare) your annual (or equivalent + periodic) tax return. Please contact us beforehand to + let us know your plans and to work out the details. + + WHAT IF YOU *WANT* TO SEND MONEY EVEN IF YOU DON'T HAVE TO? + Project Gutenberg is dedicated to increasing the number of + public domain and licensed works that can be freely distributed + in machine readable form. + + The Project gratefully accepts contributions of money, time, + public domain materials, or royalty free copyright licenses. + Money should be paid to the: + "Project Gutenberg Literary Archive Foundation." + + If you are interested in contributing scanning equipment or + software or other items, please contact Michael Hart at: + hart@pobox.com + + [Portions of this eBook's header and trailer may be reprinted only + when distributed free of all fees. Copyright (C) 2001, 2002 by + Michael S. Hart. Project Gutenberg is a TradeMark and may not be + used in any sales of Project Gutenberg eBooks or other materials be + they hardware or software or any other related product without + express permission.] + + *END THE SMALL PRINT! FOR PUBLIC DOMAIN EBOOKS*Ver.02/11/02*END* + + */ +} diff --git a/lib/faker/src/Faker/Provider/pt_BR/Address.php b/lib/faker/src/Faker/Provider/pt_BR/Address.php new file mode 100755 index 0000000..2f3593f --- /dev/null +++ b/lib/faker/src/Faker/Provider/pt_BR/Address.php @@ -0,0 +1,132 @@ +generator->numerify('########0001'); + $n .= check_digit($n); + $n .= check_digit($n); + + return $formatted? vsprintf('%d%d.%d%d%d.%d%d%d/%d%d%d%d-%d%d', str_split($n)) : $n; + } +} diff --git a/lib/faker/src/Faker/Provider/pt_BR/Internet.php b/lib/faker/src/Faker/Provider/pt_BR/Internet.php new file mode 100755 index 0000000..7481a6f --- /dev/null +++ b/lib/faker/src/Faker/Provider/pt_BR/Internet.php @@ -0,0 +1,9 @@ + array( + "4##############" + ), + 'MasterCard' => array( + "5##############" + ), + 'American Express' => array( + "34############", + "37############" + ), + 'Discover Card' => array( + "6011###########", + "622############", + "64#############", + "65#############" + ), + 'Diners' => array( + "301############", + "301##########", + "305############", + "305##########", + "36#############", + "36###########", + "38#############", + "38###########", + ), + 'Elo' => array( + "636368#########", + "438935#########", + "504175#########", + "451416#########", + "636297#########", + "5067###########", + "4576###########", + "4011###########", + ), + 'Hipercard' => array( + "38#############", + "60#############", + ), + "Aura" => array( + "50#############" + ) + ); + + /** + * International Bank Account Number (IBAN) + * @link http://en.wikipedia.org/wiki/International_Bank_Account_Number + * @param string $prefix for generating bank account number of a specific bank + * @param string $countryCode ISO 3166-1 alpha-2 country code + * @param integer $length total length without country code and 2 check digits + * @return string + */ + public static function bankAccountNumber($prefix = '', $countryCode = 'BR', $length = null) + { + return static::iban($countryCode, $prefix, $length); + } +} diff --git a/lib/faker/src/Faker/Provider/pt_BR/Person.php b/lib/faker/src/Faker/Provider/pt_BR/Person.php new file mode 100755 index 0000000..be39a2e --- /dev/null +++ b/lib/faker/src/Faker/Provider/pt_BR/Person.php @@ -0,0 +1,133 @@ +generator->numerify('#########'); + $n .= check_digit($n); + $n .= check_digit($n); + + return $formatted? vsprintf('%d%d%d.%d%d%d.%d%d%d-%d%d', str_split($n)) : $n; + } + + /** + * A random RG number, following Sao Paulo state's rules. + * @link http://pt.wikipedia.org/wiki/C%C3%A9dula_de_identidade + * @param bool $formatted If the number should have dots/dashes or not. + * @return string + */ + public function rg($formatted = true) + { + $n = $this->generator->numerify('########'); + $n .= check_digit($n); + + return $formatted? vsprintf('%d%d.%d%d%d.%d%d%d-%s', str_split($n)) : $n; + } +} diff --git a/lib/faker/src/Faker/Provider/pt_BR/PhoneNumber.php b/lib/faker/src/Faker/Provider/pt_BR/PhoneNumber.php new file mode 100755 index 0000000..ab90c53 --- /dev/null +++ b/lib/faker/src/Faker/Provider/pt_BR/PhoneNumber.php @@ -0,0 +1,142 @@ + '')); + } + + return $number; + } + + /** + * Generates an 8-digit landline number without formatting characters. + * @param bool $formatted [def: true] If it should return a formatted number or not. + * @return string + */ + public static function landline($formatted = true) + { + $number = static::numerify(static::randomElement(static::$landlineFormats)); + + if (!$formatted) { + $number = strtr($number, array('-' => '')); + } + + return $number; + } + + /** + * Randomizes between cellphone and landline numbers. + * @param bool $formatted [def: true] If it should return a formatted number or not. + * @return mixed + */ + public static function phone($formatted = true) + { + $options = static::randomElement(array( + array('cellphone', false), + array('cellphone', true), + array('landline', null), + )); + + return call_user_func("static::{$options[0]}", $formatted, $options[1]); + } + + /** + * Generates a complete phone number. + * @param string $type [def: landline] One of "landline" or "cellphone". Defaults to "landline" on invalid values. + * @param bool $formatted [def: true] If the number should be formatted or not. + * @return string + */ + protected static function anyPhoneNumber($type, $formatted = true) + { + $area = static::areaCode(); + $number = ($type == 'cellphone')? + static::cellphone($formatted, in_array($area, static::$ninthDigitAreaCodes)) : + static::landline($formatted); + + return $formatted? "($area) $number" : $area.$number; + } + + /** + * Concatenates {@link areaCode} and {@link cellphone} into a national cellphone number. The ninth digit is + * derived from the area code. + * @param bool $formatted [def: true] If it should return a formatted number or not. + * @return string + */ + public static function cellphoneNumber($formatted = true) + { + return static::anyPhoneNumber('cellphone', $formatted); + } + + /** + * Concatenates {@link areaCode} and {@link landline} into a national landline number. + * @param bool $formatted [def: true] If it should return a formatted number or not. + * @return string + */ + public static function landlineNumber($formatted = true) + { + return static::anyPhoneNumber('landline', $formatted); + } + + /** + * Randomizes between complete cellphone and landline numbers. + * @return mixed + */ + public function phoneNumber() + { + $method = static::randomElement(array('cellphoneNumber', 'landlineNumber')); + return call_user_func("static::$method", true); + } + + /** + * Randomizes between complete cellphone and landline numbers, cleared from formatting symbols. + * @return mixed + */ + public static function phoneNumberCleared() + { + $method = static::randomElement(array('cellphoneNumber', 'landlineNumber')); + return call_user_func("static::$method", false); + } +} diff --git a/lib/faker/src/Faker/Provider/pt_BR/check_digit.php b/lib/faker/src/Faker/Provider/pt_BR/check_digit.php new file mode 100755 index 0000000..ab67db9 --- /dev/null +++ b/lib/faker/src/Faker/Provider/pt_BR/check_digit.php @@ -0,0 +1,35 @@ += 12; + $verifier = 0; + + for ($i = 1; $i <= $length; $i++) { + if (!$second_algorithm) { + $multiplier = $i+1; + } else { + $multiplier = ($i >= 9)? $i-7 : $i+1; + } + $verifier += $numbers[$length-$i] * $multiplier; + } + + $verifier = 11 - ($verifier % 11); + if ($verifier >= 10) { + $verifier = 0; + } + + return $verifier; +} diff --git a/lib/faker/src/Faker/Provider/pt_PT/Address.php b/lib/faker/src/Faker/Provider/pt_PT/Address.php new file mode 100755 index 0000000..4de0e93 --- /dev/null +++ b/lib/faker/src/Faker/Provider/pt_PT/Address.php @@ -0,0 +1,124 @@ + 0; $i--) { + $numbers[$i] = substr($number, $i - 1, 1); + $partial[$i] = $numbers[$i] * $factor; + $sum += $partial[$i]; + if ($factor == $base) { + $factor = 1; + } + $factor++; + } + $res = $sum % 11; + + if ($res == 0 || $res == 1) { + $digit = 0; + } else { + $digit = 11 - $res; + } + + return $digit; + } + + /** + * + * @link http://nomesportugueses.blogspot.pt/2012/01/lista-dos-cem-nomes-mais-usados-em.html + */ + + protected static $firstNameMale = array( + 'Rodrigo', 'João', 'Martim', 'Afonso', 'Tomás', 'Gonçalo', 'Francisco', 'Tiago', + 'Diogo', 'Guilherme', 'Pedro', 'Miguel', 'Rafael', 'Gabriel', 'Santiago', 'Dinis', + 'David', 'Duarte', 'José', 'Simão', 'Daniel', 'Lucas', 'Gustavo', 'André', 'Denis', + 'Salvador', 'António', 'Vasco', 'Henrique', 'Lourenço', 'Manuel', 'Eduardo', 'Bernardo', + 'Leandro', 'Luís', 'Diego', 'Leonardo', 'Alexandre', 'Rúben', 'Mateus', 'Ricardo', + 'Vicente', 'Filipe', 'Bruno', 'Nuno', 'Carlos', 'Rui', 'Hugo', 'Samuel', 'Álvaro', + 'Matias', 'Fábio', 'Ivo', 'Paulo', 'Jorge', 'Xavier', 'Marco', 'Isaac', 'Raúl','Benjamim', + 'Renato', 'Artur', 'Mário', 'Frederico', 'Cristiano', 'Ivan', 'Sérgio', 'Micael', + 'Vítor', 'Edgar', 'Kevin', 'Joaquim', 'Igor', 'Ângelo', 'Enzo', 'Valentim', 'Flávio', + 'Joel', 'Fernando', 'Sebastião', 'Tomé', 'César', 'Cláudio', 'Nelson', 'Lisandro', 'Jaime', + 'Gil', 'Mauro', 'Sandro', 'Hélder', 'Matheus', 'William', 'Gaspar', 'Márcio', + 'Martinho', 'Emanuel', 'Marcos', 'Telmo', 'Davi', 'Wilson' + ); + + protected static $firstNameFemale = array( + 'Maria', 'Leonor', 'Matilde', 'Mariana', 'Ana', 'Beatriz', 'Inês', 'Lara', 'Carolina', 'Margarida', + 'Joana', 'Sofia', 'Diana', 'Francisca', 'Laura', 'Sara', 'Madalena', 'Rita', 'Mafalda', 'Catarina', + 'Luana', 'Marta', 'Íris', 'Alice', 'Bianca', 'Constança', 'Gabriela', 'Eva', 'Clara', 'Bruna', 'Daniela', + 'Iara', 'Filipa', 'Vitória', 'Ariana', 'Letícia', 'Bárbara', 'Camila', 'Rafaela', 'Carlota', 'Yara', + 'Núria', 'Raquel', 'Ema', 'Helena', 'Benedita', 'Érica', 'Isabel', 'Nicole', 'Lia', 'Alícia', 'Mara', + 'Jéssica', 'Soraia', 'Júlia', 'Luna', 'Victória', 'Luísa', 'Teresa', 'Miriam', 'Adriana', 'Melissa', + 'Andreia', 'Juliana', 'Alexandra', 'Yasmin', 'Tatiana', 'Leticia', 'Luciana', 'Eduarda', 'Cláudia', + 'Débora', 'Fabiana', 'Renata', 'Kyara', 'Kelly', 'Irina', 'Mélanie', 'Nádia', 'Cristiana', 'Liliana', + 'Patrícia', 'Vera', 'Doriana', 'Ângela', 'Mia', 'Erica', 'Mónica', 'Isabela', 'Salomé', 'Cátia', + 'Verónica', 'Violeta', 'Lorena', 'Érika', 'Vanessa', 'Iris', 'Anna', 'Viviane', 'Rebeca', 'Neuza', + ); + + protected static $lastName = array( + 'Abreu', 'Almeida', 'Alves', 'Amaral', 'Amorim', 'Andrade', 'Anjos', 'Antunes', 'Araújo', 'Assunção', + 'Azevedo', 'Baptista', 'Barbosa', 'Barros', 'Batista', 'Borges', 'Branco', 'Brito', 'Campos', 'Cardoso', + 'Carneiro', 'Carvalho', 'Castro', 'Coelho', 'Correia', 'Costa', 'Cruz', 'Cunha', 'Domingues', 'Esteves', + 'Faria', 'Fernandes', 'Ferreira', 'Figueiredo', 'Fonseca', 'Freitas', 'Garcia', 'Gaspar', 'Gomes', + 'Gonçalves', 'Guerreiro', 'Henriques', 'Jesus', 'Leal', 'Leite', 'Lima', 'Lopes', 'Loureiro', 'Lourenço', + 'Macedo', 'Machado', 'Magalhães', 'Maia', 'Marques', 'Martins', 'Matias', 'Matos', 'Melo', 'Mendes', + 'Miranda', 'Monteiro', 'Morais', 'Moreira', 'Mota', 'Moura', 'Nascimento', 'Neto', 'Neves', 'Nogueira', + 'Nunes', 'Oliveira', 'Pacheco', 'Paiva', 'Pereira', 'Pinheiro', 'Pinho', 'Pinto', 'Pires', 'Ramos', + 'Reis', 'Ribeiro', 'Rocha', 'Rodrigues', 'Santos', 'Silva', 'Simões', 'Soares', 'Sousa', + 'Sá', 'Tavares', 'Teixeira', 'Torres', 'Valente', 'Vaz', 'Vicente', 'Vieira', + ); +} diff --git a/lib/faker/src/Faker/Provider/pt_PT/PhoneNumber.php b/lib/faker/src/Faker/Provider/pt_PT/PhoneNumber.php new file mode 100755 index 0000000..618a01c --- /dev/null +++ b/lib/faker/src/Faker/Provider/pt_PT/PhoneNumber.php @@ -0,0 +1,50 @@ +generator->parse($format); + } + + public function address() + { + $format = static::randomElement(static::$addressFormats); + + return $this->generator->parse($format); + } + + public function streetAddress() + { + $format = static::randomElement(static::$streetAddressFormats); + + return $this->generator->parse($format); + } +} diff --git a/lib/faker/src/Faker/Provider/ro_MD/Payment.php b/lib/faker/src/Faker/Provider/ro_MD/Payment.php new file mode 100755 index 0000000..5fb9543 --- /dev/null +++ b/lib/faker/src/Faker/Provider/ro_MD/Payment.php @@ -0,0 +1,19 @@ +generator->parse($format); + } + + /** + * @example 'Cluj' + */ + public function county() + { + return static::randomElement(static::$counties); + } + + public function address() + { + $format = static::randomElement(static::$addressFormats); + + return $this->generator->parse($format); + } + + public function streetAddress() + { + $format = static::randomElement(static::$streetAddressFormats); + + return $this->generator->parse($format); + } +} diff --git a/lib/faker/src/Faker/Provider/ro_RO/Payment.php b/lib/faker/src/Faker/Provider/ro_RO/Payment.php new file mode 100755 index 0000000..980e8bb --- /dev/null +++ b/lib/faker/src/Faker/Provider/ro_RO/Payment.php @@ -0,0 +1,19 @@ + '01', 'AR' => '02', 'AG' => '03', 'B' => '40', 'BC' => '04', 'BH' => '05', + 'BN' => '06', 'BT' => '07', 'BV' => '08', 'BR' => '09', 'BZ' => '10', 'CS' => '11', + 'CL' => '51', 'CJ' => '12', 'CT' => '13', 'CV' => '14', 'DB' => '15', 'DJ' => '16', + 'GL' => '17', 'GR' => '52', 'GJ' => '18', 'HR' => '19', 'HD' => '20', 'IL' => '21', + 'IS' => '22', 'IF' => '23', 'MM' => '24', 'MH' => '25', 'MS' => '26', 'NT' => '27', + 'OT' => '28', 'PH' => '29', 'SM' => '30', 'SJ' => '31', 'SB' => '32', 'SV' => '33', + 'TR' => '34', 'TM' => '35', 'TL' => '36', 'VS' => '37', 'VL' => '38', 'VN' => '39', + + 'B1' => '41', 'B2' => '42', 'B3' => '43', 'B4' => '44', 'B5' => '45', 'B6' => '46' + ); + + /** + * Personal Numerical Code (CNP) + * + * @link http://ro.wikipedia.org/wiki/Cod_numeric_personal + * @example 1111111111118 + * + * @param string $gender Valid values: m, f, 1, 2 + * @param integer $century Valid values: 1800, 1900, 2000, 1, 2, 3, 4, 5, 6 + * @param string $county Valid values: 2 letter ISO 3166-2:RO county codes and B1-B6 for Bucharest's 6 sectors + * @return string + * + */ + public function cnp($gender = null, $century = null, $county = null) + { + if (is_null($county) || !array_key_exists($county, static::$cnpCountyCodes)) { + $countyCode = static::randomElement(array_values(static::$cnpCountyCodes)); + } else { + $countyCode = static::$cnpCountyCodes[$county]; + } + + $cnp = (string) static::cnpFirstDigit($gender, $century) + . static::numerify('##') + . sprintf('%02d', $this->generator->month()) + . sprintf('%02d', $this->generator->dayOfMonth()) + . $countyCode + . static::numerify('##%') + ; + + $cnp = static::cnpAddChecksum($cnp); + + return $cnp; + } + + /** + * Calculates the first digit for the Personal Numerical Code (CNP) based on + * the gender and century + * + * @param string $gender Valid values: m, f, 1, 2 + * @param integer $century Valid values: 1800, 1900, 2000, 1, 2, 3, 4, 5, 6 + * @return integer + */ + protected static function cnpFirstDigit($gender = null, $century = null) + { + switch ($century) { + case 1800: + case 3: + case 4: + $centuryCode = 2; + break; + case 1900: + case 1: + case 2: + $centuryCode = 0; + break; + case 2000: + case 5: + case 6: + $centuryCode = 4; + break; + default: + $centuryCode = static::randomElement(array(0, 2, 4, 6, 9)); + } + + switch (strtolower($gender)) { + case 'm': + case 1: + $genderCode = 1; + break; + case 'f': + case 2: + $genderCode = 2; + break; + default: + $genderCode = static::randomElement(array(1, 2)); + } + + $firstDigit = $centuryCode + $genderCode; + + return ($firstDigit > 9) ? 9 : $firstDigit; + } + + /** + * Calculates a checksum for the Personal Numerical Code (CNP). + * + * @param string $cnp Randomly generated CNP + * @return string CNP with the last digit altered to a proper checksum + */ + protected static function cnpAddChecksum($cnp) + { + $checkNumber = 279146358279; + + $checksum = 0; + foreach (range(0, 11) as $digit) { + $checksum += substr($cnp, $digit, 1) * substr($checkNumber, $digit, 1); + } + $checksum = $checksum % 11; + + return substr($cnp, 0, 12) . ($checksum == 10 ? 1 : $checksum); + } +} diff --git a/lib/faker/src/Faker/Provider/ro_RO/PhoneNumber.php b/lib/faker/src/Faker/Provider/ro_RO/PhoneNumber.php new file mode 100755 index 0000000..e8af810 --- /dev/null +++ b/lib/faker/src/Faker/Provider/ro_RO/PhoneNumber.php @@ -0,0 +1,67 @@ + array( + '021#######', // Bucharest + '023#######', + '024#######', + '025#######', + '026#######', + '027#######', // non-geographic + '031#######', // Bucharest + '033#######', + '034#######', + '035#######', + '036#######', + '037#######', // non-geographic + ), + 'mobile' => array( + '07########', + ) + ); + + protected static $specialFormats = array( + 'toll-free' => array( + '0800######', + '0801######', // shared-cost numbers + '0802######', // personal numbering + '0806######', // virtual cards + '0807######', // pre-paid cards + '0870######', // internet dial-up + ), + 'premium-rate' => array( + '0900######', + '0903######', // financial information + '0906######', // adult entertainment + ) + ); + + /** + * @link http://en.wikipedia.org/wiki/Telephone_numbers_in_Romania#Last_years + */ + public function phoneNumber() + { + $type = static::randomElement(array_keys(static::$normalFormats)); + $number = static::numerify(static::randomElement(static::$normalFormats[$type])); + + return $number; + } + + public static function tollFreePhoneNumber() + { + $number = static::numerify(static::randomElement(static::$specialFormats['toll-free'])); + + return $number; + } + + public static function premiumRatePhoneNumber() + { + $number = static::numerify(static::randomElement(static::$specialFormats['premium-rate'])); + + return $number; + } +} diff --git a/lib/faker/src/Faker/Provider/ru_RU/Address.php b/lib/faker/src/Faker/Provider/ru_RU/Address.php new file mode 100755 index 0000000..6174ced --- /dev/null +++ b/lib/faker/src/Faker/Provider/ru_RU/Address.php @@ -0,0 +1,156 @@ +generator->parse($format); + } + + public static function country() + { + return static::randomElement(static::$country); + } + + public static function postcode() + { + return static::toUpper(static::bothify(static::randomElement(static::$postcode))); + } + + public static function regionSuffix() + { + return static::randomElement(static::$regionSuffix); + } + + public static function region() + { + return static::randomElement(static::$region); + } + + public static function cityPrefix() + { + return static::randomElement(static::$cityPrefix); + } + + public function city() + { + return static::randomElement(static::$city); + } + + public static function streetPrefix() + { + return static::randomElement(static::$streetPrefix); + } + + public static function street() + { + return static::randomElement(static::$street); + } +} diff --git a/lib/faker/src/Faker/Provider/ru_RU/Color.php b/lib/faker/src/Faker/Provider/ru_RU/Color.php new file mode 100755 index 0000000..e1af033 --- /dev/null +++ b/lib/faker/src/Faker/Provider/ru_RU/Color.php @@ -0,0 +1,23 @@ +generator->parse($format); + } + + public static function companyPrefix() + { + return static::randomElement(static::$companyPrefixes); + } + + public static function companyNameElement() + { + return static::randomElement(static::$companyElements); + } + + public static function companyNameSuffix() + { + return static::randomElement(static::$companyNameSuffixes); + } +} diff --git a/lib/faker/src/Faker/Provider/ru_RU/Internet.php b/lib/faker/src/Faker/Provider/ru_RU/Internet.php new file mode 100755 index 0000000..53870ee --- /dev/null +++ b/lib/faker/src/Faker/Provider/ru_RU/Internet.php @@ -0,0 +1,9 @@ +.*<' | \ + * sed -r 's/—//' | sed -r 's/[\<\>]//g' | sed -r "s/(^|$)/'/g" | sed -r 's/$/,/' | sed -r 's/\&(laquo|raquo);/"/g' | \ + * sed -r 's/\s+/ /g'" + */ + protected static $banks = array( + 'Новый Промышленный Банк', + 'Новый Символ', + 'Нокссбанк', + 'Ноосфера', + 'Нордеа Банк', + 'Нота-Банк', + 'НС Банк', + 'НСТ-Банк', + 'Нэклис-Банк', + 'Образование', + 'Объединенный Банк Промышленных Инвестиций', + 'Объединенный Банк Республики', + 'Объединенный Капитал', + 'Объединенный Кредитный Банк', + 'Объединенный Кредитный Банк Московский филиал', + 'Объединенный Национальный Банк', + 'Объединенный Резервный Банк', + 'Океан Банк', + 'ОЛМА-Банк', + 'Онего', + 'Оней Банк', + 'ОПМ-Банк', + 'Оргбанк', + 'Оренбург', + 'ОТП Банк', + 'ОФК Банк', + 'Охабанк', + 'Первобанк', + 'Первомайский', + 'Первоуральскбанк', + 'Первый Дортрансбанк', + 'Первый Инвестиционный банк', + 'Первый Клиентский Банк', + 'Первый Чешско-Российский Банк', + 'Пересвет', + 'Пермь', + 'Петербургский Социальный Коммерческий Банк', + 'Петрокоммерц', + 'ПИР Банк', + 'Платина', + 'Плато-Банк', + 'Плюс Банк', + 'Пойдем!', + 'Почтобанк', + 'Прайм Финанс', + 'Преодоление', + 'Приморье', + 'Примсоцбанк', + 'Примтеркомбанк', + 'Прио-Внешторгбанк', + 'Приобье', + 'Приполярный', + 'Приско Капитал Банк', + 'Пробизнесбанк', + 'Проинвестбанк', + 'Прокоммерцбанк', + 'Проминвестбанк', + 'Промрегионбанк', + 'Промсвязьбанк', + 'Промсвязьинвестбанк', + 'Промсельхозбанк', + 'Промтрансбанк', + 'Промышленно-Финансовое Сотрудничество', + 'Промэнергобанк', + 'Профессионал Банк', + 'Профит Банк', + 'Прохладный', + 'Пульс Столицы', + 'Радиотехбанк', + 'Развитие', + 'Развитие-Столица', + 'Райффайзенбанк', + 'Расчетно-Кредитный Банк', + 'Расчетный Дом', + 'РБА', + 'Региональный Банк Развития', + 'Региональный Банк Сбережений', + 'Региональный Коммерческий Банк', + 'Региональный Кредит', + 'Регионфинансбанк', + 'Регнум', + 'Резерв', + 'Ренессанс', + 'Ренессанс Кредит', + 'Рента-Банк', + 'РЕСО Кредит', + 'Республиканский Кредитный Альянс', + 'Ресурс-Траст', + 'Риабанк', + 'Риал-Кредит', + 'Ринвестбанк', + 'Ринвестбанк Московский офис', + 'РИТ-Банк', + 'РН Банк', + 'Росавтобанк', + 'Росбанк', + 'Росбизнесбанк', + 'Росгосстрах Банк', + 'Росдорбанк', + 'РосЕвроБанк', + 'РосинтерБанк', + 'Роспромбанк', + 'Россельхозбанк', + 'Российская Финансовая Корпорация', + 'Российский Капитал', + 'Российский Кредит', + 'Российский Национальный Коммерческий Банк', + 'Россита-Банк', + 'Россия', + 'Рост Банк', + 'Ростфинанс', + 'Росэксимбанк', + 'Росэнергобанк', + 'Роял Кредит Банк', + 'РСКБ', + 'РТС-Банк', + 'РУБанк', + 'Рублев', + 'Руна-Банк', + 'Рунэтбанк', + 'Рускобанк', + 'Руснарбанк', + 'Русский Банк Сбережений', + 'Русский Ипотечный Банк', + 'Русский Международный Банк', + 'Русский Национальный Банк', + 'Русский Стандарт', + 'Русский Торговый Банк', + 'Русский Трастовый Банк', + 'Русский Финансовый Альянс', + 'Русский Элитарный Банк', + 'Русславбанк', + 'Руссобанк', + 'Русстройбанк', + 'Русфинанс Банк', + 'Русь', + 'РусьРегионБанк', + 'Русьуниверсалбанк', + 'РусЮгбанк', + 'РФИ Банк', + 'Саммит Банк', + 'Санкт-Петербургский Банк Инвестиций', + 'Саратов', + 'Саровбизнесбанк', + 'Сбербанк России', + 'Связной Банк', + 'Связь-Банк', + 'СДМ-Банк', + 'Севастопольский Морской банк', + 'Северный Кредит', + 'Северный Народный Банк', + 'Северо-Восточный Альянс', + 'Северо-Западный 1 Альянс Банк', + 'Северстройбанк', + 'Севзапинвестпромбанк', + 'Сельмашбанк', + 'Сервис-Резерв', + 'Сетелем Банк', + 'СИАБ', + 'Сибирский Банк Реконструкции и Развития', + 'Сибнефтебанк', + 'Сибсоцбанк', + 'Сибэс', + 'Сибэс Московский офис', + 'Синергия', + 'Синко-Банк', + 'Система', + 'Сити Инвест Банк', + 'Ситибанк', + 'СКА-Банк', + 'СКБ-Банк', + 'Славия', + 'Славянбанк', + 'Славянский Кредит', + 'Смартбанк', + 'СМБ-Банк', + 'Смолевич', + 'СМП Банк', + 'Снежинский', + 'Собинбанк', + 'Соверен Банк', + 'Советский', + 'Совкомбанк', + 'Современные Стандарты Бизнеса', + 'Содружество', + 'Соколовский', + 'Солид Банк', + 'Солидарность (Москва)', + 'Солидарность (Самара)', + 'Социнвестбанк', + 'Социнвестбанк Московский филиал', + 'Социум-Банк', + 'Союз', + 'Союзный', + 'Спецстройбанк', + 'Спиритбанк', + 'Спурт Банк', + 'Спутник', + 'Ставропольпромстройбанк', + 'Сталь Банк', + 'Стандарт-Кредит', + 'Стар Альянс', + 'СтарБанк', + 'Старооскольский Агропромбанк', + 'Старый Кремль', + 'Стелла-Банк', + 'Столичный Кредит', + 'Стратегия', + 'Строительно-Коммерческий Банк', + 'Стройлесбанк', + 'Сумитомо Мицуи', + 'Сургутнефтегазбанк', + 'СЭБ Банк', + 'Таатта', + 'Таврический', + 'Таганрогбанк', + 'Тагилбанк', + 'Тайдон', + 'Тайм Банк', + 'Тальменка-Банк', + 'Тальменка-Банк Московский филиал', + 'Тамбовкредитпромбанк', + 'Татагропромбанк', + 'Татсоцбанк', + 'Татфондбанк', + 'Таурус Банк', + 'ТверьУниверсалБанк', + 'Тексбанк', + 'Темпбанк', + 'Тендер-Банк', + 'Терра', + 'Тетраполис', + 'Тимер Банк', + 'Тинькофф Банк', + 'Тихоокеанский Внешторгбанк', + 'Тойота Банк', + 'Тольяттихимбанк', + 'Томскпромстройбанк', + 'Торгово-Промышленный Банк Китая', + 'Торговый Городской Банк', + 'Торжокуниверсалбанк', + 'Транскапиталбанк', + 'Транснациональный Банк', + 'Транспортный', + 'Трансстройбанк', + 'Траст Капитал Банк', + 'Тройка-Д Банк', + 'Тульский Промышленник', + 'Тульский Промышленник Московский офис', + 'Тульский Расчетный Центр', + 'Турбобанк', + 'Тусар', + 'ТЭМБР-Банк', + 'ТЭСТ', + 'Углеметбанк', + 'Уздан', + 'Унифин', + 'Унифондбанк', + 'Уралкапиталбанк', + 'Уралприватбанк', + 'Уралпромбанк', + 'Уралсиб', + 'Уралтрансбанк', + 'Уралфинанс', + 'Уральский Банк Реконструкции и Развития', + 'Уральский Межрегиональный Банк', + 'Уральский Финансовый Дом', + 'Ури Банк', + 'Уссури', + 'ФДБ', + 'ФИА-Банк', + 'Финам Банк', + 'Финанс Бизнес Банк', + 'Финансово-Промышленный Капитал', + 'Финансовый Капитал', + 'Финансовый Стандарт', + 'Финарс Банк', + 'Финпромбанк (ФПБ Банк)', + 'Финтрастбанк', + 'ФК Открытие (бывш. НОМОС-Банк)', + 'Флора-Москва', + 'Фольксваген Банк Рус', + 'Фондсервисбанк', + 'Фора-Банк', + 'Форбанк', + 'Форус Банк', + 'Форштадт', + 'Фьючер', + 'Хакасский Муниципальный Банк', + 'Ханты-Мансийский банк Открытие', + 'Химик', + 'Хлынов', + 'Хованский', + 'Холдинвестбанк', + 'Холмск', + 'Хоум Кредит Банк', + 'Центр-инвест', + 'Центрально-Азиатский', + 'Центрально-Европейский Банк', + 'Центркомбанк', + 'ЦентроКредит', + 'Церих', + 'Чайна Констракшн', + 'Чайнасельхозбанк', + 'Челиндбанк', + 'Челябинвестбанк', + 'Черноморский банк развития и реконструкции', + 'Чувашкредитпромбанк', + 'Эйч-Эс-Би-Си Банк (HSBC)', + 'Эко-Инвест', + 'Экономбанк', + 'Экономикс-Банк', + 'Экси-Банк', + 'Эксперт Банк', + 'Экспобанк', + 'Экспресс-Волга', + 'Экспресс-Кредит', + 'Эл Банк', + 'Элита', + 'Эльбин', + 'Энергобанк', + 'Энергомашбанк', + 'Энерготрансбанк', + 'Эно', + 'Энтузиастбанк', + 'Эргобанк', + 'Ю Би Эс Банк', + 'ЮГ-Инвестбанк', + 'Югра', + 'Южный Региональный Банк', + 'ЮМК', + 'Юниаструм Банк', + 'ЮниКредит Банк', + 'Юнистрим', + 'Япы Креди Банк Москва', + 'ЯР-Банк', + 'Яринтербанк', + 'Ярославич', + 'K2 Банк', + 'АББ', + 'Абсолют Банк', + 'Авангард', + 'Аверс', + 'Автоградбанк', + 'АвтоКредитБанк', + 'Автоторгбанк', + 'Агроинкомбанк', + 'Агропромкредит', + 'Агророс', + 'Агросоюз', + 'Адамон Банк', + 'Адамон Банк Московский филиал', + 'Аделантбанк', + 'Адмиралтейский', + 'Азиатско-Тихоокеанский Банк', + 'Азимут', + 'Азия Банк', + 'Азия-Инвест Банк', + 'Ай-Си-Ай-Си-Ай Банк (ICICI)', + 'Айви Банк', + 'АйМаниБанк', + 'Ак Барс', + 'Акибанк', + 'Аккобанк', + 'Акрополь', + 'Аксонбанк', + 'Актив Банк', + 'АктивКапитал Банк', + 'АктивКапитал Банк Московский филиал', + 'АктивКапитал Банк Санкт-Петербургский филиал', + 'Акцент', + 'Акцепт', + 'Акция', + 'Алданзолотобанк', + 'Александровский', + 'Алеф-Банк', + 'Алжан', + 'Алмазэргиэнбанк', + 'АлтайБизнес-Банк', + 'Алтайкапиталбанк', + 'Алтынбанк', + 'Альба Альянс', + 'Альта-Банк', + 'Альтернатива', + 'Альфа-Банк', + 'АМБ Банк', + 'Америкэн Экспресс Банк', + 'Анелик РУ', + 'Анкор Банк', + 'Анталбанк', + 'Апабанк', + 'Аресбанк', + 'Арзамас', + 'Арксбанк', + 'Арсенал', + 'Аспект', + 'Ассоциация', + 'БайкалБанк', + 'БайкалИнвестБанк', + 'Байкалкредобанк', + 'Балаково-Банк', + 'Балтийский Банк', + 'Балтика', + 'Балтинвестбанк', + 'Банк "Акцент" Московский филиал', + 'Банк "МБА-Москва"', + 'Банк "Санкт-Петербург"', + 'Банк АВБ', + 'Банк БКФ', + 'Банк БФА', + 'Банк БЦК-Москва', + 'Банк Город', + 'Банк Жилищного Финансирования', + 'Банк Инноваций и Развития', + 'Банк Интеза', + 'Банк ИТБ', + 'Банк Казани', + 'Банк Китая (Элос)', + 'Банк Кредит Свисс', + 'Банк МБФИ', + 'Банк Москвы', + 'Банк на Красных Воротах', + 'Банк Оранжевый (бывш. Промсервисбанк)', + 'Банк оф Токио-Мицубиси', + 'Банк Премьер Кредит', + 'Банк ПСА Финанс Рус', + 'Банк Развития Технологий', + 'Банк Расчетов и Сбережений', + 'Банк Раунд', + 'Банк РСИ', + 'Банк Сберегательно-кредитного сервиса', + 'Банк СГБ', + 'Банк Торгового Финансирования', + 'Банк Финсервис', + 'Банк Экономический Союз', + 'Банкирский Дом', + 'Банкхаус Эрбе', + 'Башкомснаббанк', + 'Башпромбанк', + 'ББР Банк', + 'Белгородсоцбанк', + 'Бенифит-Банк', + 'Берейт', + 'Бест Эффортс Банк', + 'Бизнес для Бизнеса', + 'Бинбанк', + 'БИНБАНК кредитные карты', + 'Бинбанк Мурманск', + 'БКС Инвестиционный Банк', + 'БМВ Банк', + 'БНП Париба Банк', + 'Богородский', + 'Богородский Муниципальный Банк', + 'Братский АНКБ', + 'БСТ-Банк', + 'Булгар Банк', + 'Бум-Банк', + 'Бумеранг', + 'БФГ-Кредит', + 'БыстроБанк', + 'Вакобанк', + 'Вега-Банк', + 'Век', + 'Великие Луки Банк', + 'Венец', + 'Верхневолжский', + 'Верхневолжский Крымский филиал', + 'Верхневолжский Московский филиал', + 'Верхневолжский Невский филиал', + 'Верхневолжский Таврический филиал', + 'Верхневолжский Ярославский филиал', + 'Веста', + 'Вестинтербанк', + 'Взаимодействие', + 'Викинг', + 'Витабанк', + 'Витязь', + 'Вкабанк', + 'Владбизнесбанк', + 'Владпромбанк', + 'Внешпромбанк', + 'Внешфинбанк', + 'Внешэкономбанк', + 'Военно-Промышленный Банк', + 'Возрождение', + 'Вокбанк', + 'Вологдабанк', + 'Вологжанин', + 'Воронеж', + 'Восточно-Европейский Трастовый Банк', + 'Восточный Экспресс Банк', + 'ВостСибтранскомбанк', + 'ВРБ Москва', + 'Всероссийский Банк Развития Регионов', + 'ВТБ', + 'ВТБ 24', + 'ВУЗ-Банк', + 'Выборг-Банк', + 'Выборг-Банк Московский филиал', + 'Вэлтон Банк', + 'Вятич', + 'Вятка-Банк', + 'Гагаринский', + 'Газбанк', + 'Газнефтьбанк', + 'Газпромбанк', + 'Газстройбанк', + 'Газтрансбанк', + 'Газэнергобанк', + 'Ганзакомбанк', + 'Гарант-Инвест', + 'Гаранти Банк Москва', + 'Геленджик-Банк', + 'Генбанк', + 'Геобанк', + 'Гефест', + 'Глобус', + 'Глобэкс', + 'Голдман Сакс Банк', + 'Горбанк', + 'ГПБ-Ипотека', + 'Гранд Инвест Банк', + 'Гринкомбанк', + 'Гринфилдбанк', + 'Грис-Банк', + 'Гута-Банк', + 'Далена', + 'Далетбанк', + 'Далта-Банк', + 'Дальневосточный Банк', + 'Данске Банк', + 'Девон-Кредит', + 'ДельтаКредит', + 'Денизбанк Москва', + 'Держава', + 'Дж. П. Морган Банк', + 'Джаст Банк', + 'Джей энд Ти Банк', + 'Дил-Банк', + 'Динамичные Системы', + 'Дойче Банк', + 'Долинск', + 'Дом-Банк', + 'Дон-Тексбанк', + 'Донкомбанк', + 'Донхлеббанк', + 'Дорис Банк', + 'Дружба', + 'ЕАТП Банк', + 'Евразийский Банк', + 'Евроазиатский Инвестиционный Банк', + 'ЕвроАксис Банк', + 'Евроальянс', + 'Еврокапитал-Альянс', + 'Еврокоммерц', + 'Еврокредит', + 'Евромет', + 'Европейский Стандарт', + 'Европлан Банк', + 'ЕвроситиБанк', + 'Еврофинанс Моснарбанк', + 'Единственный', + 'Единый Строительный Банк', + 'Екатеринбург', + 'Екатерининский', + 'Енисей', + 'Енисейский Объединенный Банк', + 'Ермак', + 'Живаго-Банк', + 'Жилкредит', + 'Жилстройбанк', + 'Запсибкомбанк', + 'Заречье', + 'Заубер Банк', + 'Земкомбанк', + 'Земский Банк', + 'Зенит', + 'Зенит Сочи', + 'Зернобанк', + 'Зираат Банк', + 'Златкомбанк', + 'И.Д.Е.А. Банк', + 'Иваново', + 'Идеалбанк', + 'Ижкомбанк', + 'ИК Банк', + 'Икано Банк', + 'Инбанк', + 'Инвест-Экобанк', + 'Инвестиционный Банк Кубани', + 'Инвестиционный Республиканский Банк', + 'Инвестиционный Союз', + 'Инвесткапиталбанк', + 'Инвестсоцбанк', + 'Инвестторгбанк', + 'ИНГ Банк', + 'Индустриальный Сберегательный Банк', + 'Инкаробанк', + 'Интерактивный Банк', + 'Интеркоммерц Банк', + 'Интеркоопбанк', + 'Интеркредит', + 'Интернациональный Торговый Банк', + 'Интерпрогрессбанк', + 'Интерпромбанк', + 'Интехбанк', + 'Информпрогресс', + 'Ипозембанк', + 'ИпоТек Банк', + 'Иронбанк', + 'ИРС', + 'Итуруп', + 'Ишбанк', + 'Йошкар-Ола', + 'Калуга', + 'Камский Горизонт', + 'Камский Коммерческий Банк', + 'Камчаткомагропромбанк', + 'Канский', + 'Капитал', + 'Капиталбанк', + 'Кедр', + 'Кемсоцинбанк', + 'Кетовский Коммерческий Банк', + 'Киви Банк', + 'Классик Эконом Банк', + 'Клиентский', + 'Кольцо Урала', + 'Коммерцбанк (Евразия)', + 'Коммерческий Банк Развития', + 'Коммерческий Индо Банк', + 'Консервативный Коммерческий Банк', + 'Констанс-Банк', + 'Континенталь', + 'Конфидэнс Банк', + 'Кор', + 'Кореа Эксчендж Банк Рус', + 'Королевский Банк Шотландии', + 'Космос', + 'Костромаселькомбанк', + 'Кошелев-Банк', + 'Крайинвестбанк', + 'Кранбанк', + 'Креди Агриколь КИБ', + 'Кредит Европа Банк', + 'Кредит Урал Банк', + 'Кредит Экспресс', + 'Кредит-Москва', + 'Кредитинвест', + 'Кредо Финанс', + 'Кредпромбанк', + 'Кремлевский', + 'Крокус-Банк', + 'Крона-Банк', + 'Кросна-Банк', + 'Кроссинвестбанк', + 'Крыловский', + 'КС Банк', + 'Кубанский Универсальный Банк', + 'Кубань Кредит', + 'Кубаньторгбанк', + 'Кузбассхимбанк', + 'Кузнецкбизнесбанк', + 'Кузнецкий', + 'Кузнецкий Мост', + 'Курган', + 'Курскпромбанк', + 'Лада-Кредит', + 'Лайтбанк', + 'Ланта-Банк', + 'Левобережный', + 'Легион', + 'Леноблбанк', + 'Лесбанк', + 'Лето Банк', + 'Липецккомбанк', + 'Логос', + 'Локо-Банк', + 'Лэнд-Банк', + 'М2М Прайвет Банк', + 'Майкопбанк', + 'Майский', + 'МАК-Банк', + 'Максима', + 'Максимум', + 'МАСТ-Банк', + 'Мастер-Капитал', + 'МВС Банк', + 'МДМ Банк', + 'Мегаполис', + 'Международный Акционерный Банк', + 'Международный Банк Развития', + 'Международный Банк Санкт-Петербурга (МБСП)', + 'Международный Коммерческий Банк', + 'Международный Расчетный Банк', + 'Международный Строительный Банк', + 'Международный Финансовый Клуб', + 'Межотраслевая Банковская Корпорация', + 'Межрегиональный Банк Реконструкции', + 'Межрегиональный Клиринговый Банк', + 'Межрегиональный Почтовый Банк', + 'Межрегиональный промышленно-строительный банк', + 'Межрегионбанк', + 'Межтопэнергобанк', + 'Межтрастбанк', + 'Мерседес-Бенц Банк Рус', + 'Металлинвестбанк', + 'Металлург', + 'Меткомбанк (Каменск-Уральский)', + 'Меткомбанк (Череповец)', + 'Метробанк', + 'Метрополь', + 'Мидзухо Банк', + 'Мико-Банк', + 'Милбанк', + 'Миллениум Банк', + 'Мир Бизнес Банк', + 'Мираф-Банк', + 'Мираф-Банк Московский филиал', + 'Миръ', + 'Михайловский ПЖСБ', + 'Морган Стэнли Банк', + 'Морской Банк', + 'Мосводоканалбанк', + 'Москва', + 'Москва-Сити', + 'Московский Вексельный Банк', + 'Московский Индустриальный Банк', + 'Московский Коммерческий Банк', + 'Московский Кредитный Банк', + 'Московский Национальный Инвестиционный Банк', + 'Московский Нефтехимический Банк', + 'Московский Областной Банк', + 'Московско-Парижский Банк', + 'Московское Ипотечное Агентство', + 'Москоммерцбанк', + 'Мосстройэкономбанк (М Банк)', + 'Мострансбанк', + 'Мосуралбанк', + 'МС Банк Рус', + 'МСП Банк', + 'МТИ-Банк', + 'МТС Банк', + 'Муниципальный Камчатпрофитбанк', + 'Мурманский Социальный Коммерческий Банк', + 'МФБанк', + 'Н-Банк', + 'Нальчик', + 'Наратбанк', + 'Народный Банк', + 'Народный Банк Республики Тыва', + 'Народный Доверительный Банк', + 'Народный Земельно-Промышленный Банк', + 'Народный Инвестиционный Банк', + 'Натиксис Банк', + 'Нацинвестпромбанк', + 'Национальная Факторинговая Компания', + 'Национальный Банк "Траст"', + 'Национальный Банк Взаимного Кредита', + 'Национальный Банк Сбережений', + 'Национальный Залоговый Банк', + 'Национальный Клиринговый Банк', + 'Национальный Клиринговый Центр', + 'Национальный Корпоративный Банк', + 'Национальный Резервный Банк', + 'Национальный Стандарт', + 'Наш Дом', + 'НБД-Банк', + 'НБК-Банк', + 'Невастройинвест', + 'Невский Банк', + 'Нейва', + 'Нерюнгрибанк', + 'Нефтепромбанк', + 'Нефтяной Альянс', + 'Нижневолжский Коммерческий Банк', + 'Нико-Банк', + 'НК Банк', + 'НоваховКапиталБанк', + 'Новация', + 'Новикомбанк', + 'Новобанк', + 'Новое Время', + 'Новокиб', + 'Новопокровский', + 'Новый Век', + 'Новый Кредитный Союз', + 'Новый Московский Банк', + ); + + /** + * @example 'Новый Московский Банк' + */ + public static function bank() + { + return static::randomElement(static::$banks); + } +} diff --git a/lib/faker/src/Faker/Provider/ru_RU/Person.php b/lib/faker/src/Faker/Provider/ru_RU/Person.php new file mode 100755 index 0000000..09a59f6 --- /dev/null +++ b/lib/faker/src/Faker/Provider/ru_RU/Person.php @@ -0,0 +1,135 @@ +generator->parse(static::randomElement(static::$lastNameFormat)); + } + + public static function lastNameMale() + { + return static::randomElement(static::$lastNameMale); + } + + public static function lastNameFemale() + { + return static::randomElement(static::$lastNameFemale); + } + + /** + * @example 'PhD' + */ + public static function suffix() + { + return static::randomElement(static::$suffix); + } +} diff --git a/lib/faker/src/Faker/Provider/sk_SK/PhoneNumber.php b/lib/faker/src/Faker/Provider/sk_SK/PhoneNumber.php new file mode 100755 index 0000000..1baf7cc --- /dev/null +++ b/lib/faker/src/Faker/Provider/sk_SK/PhoneNumber.php @@ -0,0 +1,15 @@ +format('ymd'); + + if ($gender && $gender == static::GENDER_MALE) { + $randomDigits = (string)static::numerify('##') . static::randomElement(array(1,3,5,7,9)); + } elseif ($gender && $gender == static::GENDER_FEMALE) { + $randomDigits = (string)static::numerify('##') . static::randomElement(array(0,2,4,6,8)); + } else { + $randomDigits = (string)static::numerify('###'); + } + + + $checksum = Luhn::computeCheckDigit($datePart . $randomDigits); + + return $datePart . '-' . $randomDigits . $checksum; + } +} diff --git a/lib/faker/src/Faker/Provider/sv_SE/PhoneNumber.php b/lib/faker/src/Faker/Provider/sv_SE/PhoneNumber.php new file mode 100755 index 0000000..d15e5dd --- /dev/null +++ b/lib/faker/src/Faker/Provider/sv_SE/PhoneNumber.php @@ -0,0 +1,37 @@ +format('a') === 'am' ? 'öö' : 'ös'; + } + + public static function dayOfWeek($max = 'now') + { + $map = array( + 'Sunday' => 'Pazar', + 'Monday' => 'Pazartesi', + 'Tuesday' => 'Salı', + 'Wednesday' => 'Çarşamba', + 'Thursday' => 'Perşembe', + 'Friday' => 'Cuma', + 'Saturday' => 'Cumartesi', + ); + $week = static::dateTime($max)->format('l'); + return isset($map[$week]) ? $map[$week] : $week; + } + + public static function monthName($max = 'now') + { + $map = array( + 'January' => 'Ocak', + 'February' => 'Şubat', + 'March' => 'Mart', + 'April' => 'Nisan', + 'May' => 'Mayıs', + 'June' => 'Haziran', + 'July' => 'Temmuz', + 'August' => 'Ağustos', + 'September' => 'Eylül', + 'October' => 'Ekim', + 'November' => 'Kasım', + 'December' => 'Aralık', + ); + $month = static::dateTime($max)->format('F'); + return isset($map[$month]) ? $map[$month] : $month; + } +} diff --git a/lib/faker/src/Faker/Provider/tr_TR/Internet.php b/lib/faker/src/Faker/Provider/tr_TR/Internet.php new file mode 100755 index 0000000..ef907d4 --- /dev/null +++ b/lib/faker/src/Faker/Provider/tr_TR/Internet.php @@ -0,0 +1,9 @@ +generator->parse($format); + } + + public static function streetPrefix() + { + return static::randomElement(static::$streetPrefix); + } +} diff --git a/lib/faker/src/Faker/Provider/uk_UA/Color.php b/lib/faker/src/Faker/Provider/uk_UA/Color.php new file mode 100755 index 0000000..197cc3b --- /dev/null +++ b/lib/faker/src/Faker/Provider/uk_UA/Color.php @@ -0,0 +1,23 @@ +generator->parse($format); + } + + public static function companyPrefix() + { + return static::randomElement(static::$companyPrefix); + } + + public static function companyName() + { + return static::randomElement(static::$companyName); + } +} diff --git a/lib/faker/src/Faker/Provider/uk_UA/Internet.php b/lib/faker/src/Faker/Provider/uk_UA/Internet.php new file mode 100755 index 0000000..33214d6 --- /dev/null +++ b/lib/faker/src/Faker/Provider/uk_UA/Internet.php @@ -0,0 +1,9 @@ +generator->parse($format)); + } + + public function hamletPrefix() + { + return static::randomElement(static::$hamletPrefix); + } + + public function wardName() + { + $format = static::randomElement(static::$wardNameFormats); + + return static::bothify($this->generator->parse($format)); + } + + public function wardPrefix() + { + return static::randomElement(static::$wardPrefix); + } + + public function districtName() + { + $format = static::randomElement(static::$districtNameFormats); + + return static::bothify($this->generator->parse($format)); + } + + public function districtPrefix() + { + return static::randomElement(static::$districtPrefix); + } + + /** + * @example 'Hà Nội' + */ + public function city() + { + return static::randomElement(static::$city); + } + + /** + * @example 'Bắc Giang' + */ + public static function province() + { + return static::randomElement(static::$province); + } +} diff --git a/lib/faker/src/Faker/Provider/vi_VN/Color.php b/lib/faker/src/Faker/Provider/vi_VN/Color.php new file mode 100755 index 0000000..4deaa2f --- /dev/null +++ b/lib/faker/src/Faker/Provider/vi_VN/Color.php @@ -0,0 +1,36 @@ +generator->parse(static::randomElement(static::$middleNameFormat)); + } + + public static function middleNameMale() + { + return static::randomElement(static::$middleNameMale); + } + + public static function middleNameFemale() + { + return static::randomElement(static::$middleNameFemale); + } +} diff --git a/lib/faker/src/Faker/Provider/vi_VN/PhoneNumber.php b/lib/faker/src/Faker/Provider/vi_VN/PhoneNumber.php new file mode 100755 index 0000000..5f9f60a --- /dev/null +++ b/lib/faker/src/Faker/Provider/vi_VN/PhoneNumber.php @@ -0,0 +1,61 @@ + array( + '0[a] ### ####', + '(0[a]) ### ####', + '0[a]-###-####', + '(0[a])###-####', + '84-[a]-###-####', + '(84)([a])###-####', + '+84-[a]-###-####', + ), + '8' => array( + '0[a] #### ####', + '(0[a]) #### ####', + '0[a]-####-####', + '(0[a])####-####', + '84-[a]-####-####', + '(84)([a])####-####', + '+84-[a]-####-####', + ), + ); + + public function phoneNumber() + { + $areaCode = static::randomElement(static::$areaCodes); + $areaCodeLength = strlen($areaCode); + $digits = 7; + + if ($areaCodeLength < 2) { + $digits = 8; + } + + return static::numerify(str_replace('[a]', $areaCode, static::randomElement(static::$formats[$digits]))); + } +} diff --git a/lib/faker/src/Faker/Provider/zh_CN/Address.php b/lib/faker/src/Faker/Provider/zh_CN/Address.php new file mode 100755 index 0000000..f36a49a --- /dev/null +++ b/lib/faker/src/Faker/Provider/zh_CN/Address.php @@ -0,0 +1,43 @@ +city() . static::area(); + } + + public static function postcode() + { + $prefix = str_pad(mt_rand(1, 85), 2, 0, STR_PAD_LEFT); + $suffix = '00'; + + return $prefix . mt_rand(10, 88) . $suffix; + } +} diff --git a/lib/faker/src/Faker/Provider/zh_CN/Company.php b/lib/faker/src/Faker/Provider/zh_CN/Company.php new file mode 100755 index 0000000..4a5a738 --- /dev/null +++ b/lib/faker/src/Faker/Provider/zh_CN/Company.php @@ -0,0 +1,26 @@ + array( + '板橋區', '三重區', '中和區', '永和區', + '新莊區', '新店區', '樹林區', '鶯歌區', + '三峽區', '淡水區', '汐止區', '瑞芳區', + '土城區', '蘆洲區', '五股區', '泰山區', + '林口區', '深坑區', '石碇區', '坪林區', + '三芝區', '石門區', '八里區', '平溪區', + '雙溪區', '貢寮區', '金山區', '萬里區', + '烏來區', + ), + '宜蘭縣' => array( + '宜蘭市', '羅東鎮', '蘇澳鎮', '頭城鎮', '礁溪鄉', + '壯圍鄉', '員山鄉', '冬山鄉', '五結鄉', '三星鄉', + '大同鄉', '南澳鄉', + ), + '桃園縣' => array( + '桃園市', '中壢市', '大溪鎮', '楊梅鎮', '蘆竹鄉', + '大園鄉', '龜山鄉', '八德市', '龍潭鄉', '平鎮市', + '新屋鄉', '觀音鄉', '復興鄉', + ), + '新竹縣' => array( + '竹北市', '竹東鎮', '新埔鎮', '關西鎮', '湖口鄉', + '新豐鄉', '芎林鄉', '橫山鄉', '北埔鄉', '寶山鄉', + '峨眉鄉', '尖石鄉', '五峰鄉', + ), + '苗栗縣' => array( + '苗栗市', '苑裡鎮', '通霄鎮', '竹南鎮', '頭份鎮', + '後龍鎮', '卓蘭鎮', '大湖鄉', '公館鄉', '銅鑼鄉', + '南庄鄉', '頭屋鄉', '三義鄉', '西湖鄉', '造橋鄉', + '三灣鄉', '獅潭鄉', '泰安鄉', + ), + '臺中市' => array( + '豐原區', '東勢區', '大甲區', '清水區', '沙鹿區', + '梧棲區', '后里區', '神岡區', '潭子區', '大雅區', + '新社區', '石岡區', '外埔區', '大安區', '烏日區', + '大肚區', '龍井區', '霧峰區', '太平區', '大里區', + '和平區', '中區', '東區', '南區', '西區', '北區', + '西屯區', '南屯區', '北屯區', + ), + '彰化縣' => array( + '彰化市', '鹿港鎮', '和美鎮', '線西鄉', '伸港鄉', + '福興鄉', '秀水鄉', '花壇鄉', '芬園鄉', '員林鎮', + '溪湖鎮', '田中鎮', '大村鄉', '埔鹽鄉', '埔心鄉', + '永靖鄉', '社頭鄉', '二水鄉', '北斗鎮', '二林鎮', + '田尾鄉', '埤頭鄉', '芳苑鄉', '大城鄉', '竹塘鄉', + '溪州鄉', + ), + '南投縣' => array( + '南投市', '埔里鎮', '草屯鎮', '竹山鎮', '集集鎮', + '名間鄉', '鹿谷鄉', '中寮鄉', '魚池鄉', '國姓鄉', + '水里鄉', '信義鄉', '仁愛鄉', + ), + '雲林縣' => array( + '斗六市', '斗南鎮', '虎尾鎮', '西螺鎮', '土庫鎮', + '北港鎮', '古坑鄉', '大埤鄉', '莿桐鄉', '林內鄉', + '二崙鄉', '崙背鄉', '麥寮鄉', '東勢鄉', '褒忠鄉', + '臺西鄉', '元長鄉', '四湖鄉', '口湖鄉', '水林鄉', + ), + '嘉義縣' => array( + '太保市', '朴子市', '布袋鎮', '大林鎮', '民雄鄉', + '溪口鄉', '新港鄉', '六腳鄉', '東石鄉', '義竹鄉', + '鹿草鄉', '水上鄉', '中埔鄉', '竹崎鄉', '梅山鄉', + '番路鄉', '大埔鄉', '阿里山鄉', + ), + '臺南市' => array( + '新營區', '鹽水區', '白河區', '柳營區', '後壁區', + '東山區', '麻豆區', '下營區', '六甲區', '官田區', + '大內區', '佳里區', '學甲區', '西港區', '七股區', + '將軍區', '北門區', '新化區', '善化區', '新市區', + '安定區', '山上區', '玉井區', '楠西區', '南化區', + '左鎮區', '仁德區', '歸仁區', '關廟區', '龍崎區', + '永康區', '東區', '南區', '西區', '北區', '中區', + '安南區', '安平區', + ), + '高雄市' => array( + '鳳山區', '林園區', '大寮區', '大樹區', '大社區', + '仁武區', '鳥松區', '岡山區', '橋頭區', '燕巢區', + '田寮區', '阿蓮區', '路竹區', '湖內區', '茄萣區', + '永安區', '彌陀區', '梓官區', '旗山區', '美濃區', + '六龜區', '甲仙區', '杉林區', '內門區', '茂林區', + '桃源區', '三民區', '鹽埕區', '鼓山區', '左營區', + '楠梓區', '三民區', '新興區', '前金區', '苓雅區', + '前鎮區', '旗津區', '小港區', + ), + '屏東縣' => array( + '屏東市', '潮州鎮', '東港鎮', '恆春鎮', '萬丹鄉', + '長治鄉', '麟洛鄉', '九如鄉', '里港鄉', '鹽埔鄉', + '高樹鄉', '萬巒鄉', '內埔鄉', '竹田鄉', '新埤鄉', + '枋寮鄉', '新園鄉', '崁頂鄉', '林邊鄉', '南州鄉', + '佳冬鄉', '琉球鄉', '車城鄉', '滿州鄉', '枋山鄉', + '三地門鄉', '霧臺鄉', '瑪家鄉', '泰武鄉', '來義鄉', + '春日鄉', '獅子鄉', '牡丹鄉', + ), + '臺東縣' => array( + '臺東市', '成功鎮', '關山鎮', '卑南鄉', '鹿野鄉', + '池上鄉', '東河鄉', '長濱鄉', '太麻里鄉', '大武鄉', + '綠島鄉', '海端鄉', '延平鄉', '金峰鄉', '達仁鄉', + '蘭嶼鄉', + ), + '花蓮縣' => array( + '花蓮市', '鳳林鎮', '玉里鎮', '新城鄉', '吉安鄉', + '壽豐鄉', '光復鄉', '豐濱鄉', '瑞穗鄉', '富里鄉', + '秀林鄉', '萬榮鄉', '卓溪鄉', + ), + '澎湖縣' => array( + '馬公市', '湖西鄉', '白沙鄉', '西嶼鄉', '望安鄉', + '七美鄉', + ), + '基隆市' => array( + '中正區', '七堵區', '暖暖區', '仁愛區', '中山區', + '安樂區', '信義區', + ), + '新竹市' => array( + '東區', '北區', '香山區', + ), + '嘉義市' => array( + '東區', '西區', + ), + '臺北市' => array( + '松山區', '信義區', '大安區', '中山區', '中正區', + '大同區', '萬華區', '文山區', '南港區', '內湖區', + '士林區', '北投區', + ), + '連江縣' => array( + '南竿鄉', '北竿鄉', '莒光鄉', '東引鄉', + ), + '金門縣' => array( + '金城鎮', '金沙鎮', '金湖鎮', '金寧鄉', '烈嶼鄉', '烏坵鄉', + ), + ); + + /** + * @link http://terms.naer.edu.tw/download/287/ + */ + protected static $country = array( + '不丹', '中非', '丹麥', '伊朗', '冰島', '剛果', + '加彭', '北韓', '南非', '卡達', '印尼', '印度', + '古巴', '哥德', '埃及', '多哥', '寮國', '尼日', + '巴曼', '巴林', '巴紐', '巴西', '希臘', '帛琉', + '德國', '挪威', '捷克', '教廷', '斐濟', '日本', + '智利', '東加', '查德', '汶萊', '法國', '波蘭', + '波赫', '泰國', '海地', '瑞典', '瑞士', '祕魯', + '秘魯', '約旦', '紐埃', '緬甸', '美國', '聖尼', + '聖普', '肯亞', '芬蘭', '英國', '荷蘭', '葉門', + '蘇丹', '諾魯', '貝南', '越南', '迦彭', + '迦納', '阿曼', '阿聯', '韓國', '馬利', + '以色列', '以色利', '伊拉克', '俄羅斯', + '利比亞', '加拿大', '匈牙利', '南極洲', + '南蘇丹', '厄瓜多', '吉布地', '吐瓦魯', + '哈撒克', '哈薩克', '喀麥隆', '喬治亞', + '土庫曼', '土耳其', '塔吉克', '塞席爾', + '墨西哥', '大西洋', '奧地利', '孟加拉', + '安哥拉', '安地卡', '安道爾', '尚比亞', + '尼伯爾', '尼泊爾', '巴哈馬', '巴拉圭', + '巴拿馬', '巴貝多', '幾內亞', '愛爾蘭', + '所在國', '摩洛哥', '摩納哥', '敍利亞', + '敘利亞', '新加坡', '東帝汶', '柬埔寨', + '比利時', '波扎那', '波札那', '烏克蘭', + '烏干達', '烏拉圭', '牙買加', '獅子山', + '甘比亞', '盧安達', '盧森堡', '科威特', + '科索夫', '科索沃', '立陶宛', '紐西蘭', + '維德角', '義大利', '聖文森', '艾塞亞', + '菲律賓', '萬那杜', '葡萄牙', '蒲隆地', + '蓋亞納', '薩摩亞', '蘇利南', '西班牙', + '貝里斯', '賴索托', '辛巴威', '阿富汗', + '阿根廷', '馬其頓', '馬拉威', '馬爾他', + '黎巴嫩', '亞塞拜然', '亞美尼亞', '保加利亞', + '南斯拉夫', '厄利垂亞', '史瓦濟蘭', '吉爾吉斯', + '吉里巴斯', '哥倫比亞', '坦尚尼亞', '塞內加爾', + '塞内加爾', '塞爾維亞', '多明尼加', '多米尼克', + '奈及利亞', '委內瑞拉', '宏都拉斯', '尼加拉瓜', + '巴基斯坦', '庫克群島', '愛沙尼亞', '拉脫維亞', + '摩爾多瓦', '摩里西斯', '斯洛伐克', '斯里蘭卡', + '格瑞那達', '模里西斯', '波多黎各', '澳大利亞', + '烏茲別克', '玻利維亞', '瓜地馬拉', '白俄羅斯', + '突尼西亞', '納米比亞', '索馬利亞', '索馬尼亞', + '羅馬尼亞', '聖露西亞', '聖馬利諾', '莫三比克', + '莫三鼻克', '葛摩聯盟', '薩爾瓦多', '衣索比亞', + '西薩摩亞', '象牙海岸', '賴比瑞亞', '賽普勒斯', + '馬來西亞', '馬爾地夫', '克羅埃西亞', + '列支敦斯登', '哥斯大黎加', '布吉納法索', + '布吉那法索', '幾內亞比索', '幾內亞比紹', + '斯洛維尼亞', '索羅門群島', '茅利塔尼亞', + '蒙特內哥羅', '赤道幾內亞', '阿爾及利亞', + '阿爾及尼亞', '阿爾巴尼亞', '馬紹爾群島', + '馬達加斯加', '密克羅尼西亞', '沙烏地阿拉伯', + '千里達及托巴哥', + ); + + protected static $postcode = array('###-##', '###'); + + public function street() + { + return static::randomElement(static::$street); + } + + public static function randomChineseNumber() + { + $digits = array( + '', '一', '二', '三', '四', '五', '六', '七', '八', '九', + ); + return $digits[static::randomDigitNotNull()]; + } + + public static function randomNumber2() + { + return static::randomNumber(2) + 1; + } + + public static function randomNumber3() + { + return static::randomNumber(3) + 1; + } + + public static function localLatitude() + { + return number_format(mt_rand(22000000, 25000000)/1000000, 6); + } + + public static function localLongitude() + { + return number_format(mt_rand(120000000, 122000000)/1000000, 6); + } + + public function city() + { + $county = static::randomElement(array_keys(static::$city)); + $city = static::randomElement(static::$city[$county]); + return $county.$city; + } + + public function state() + { + return '臺灣省'; + } + + public static function stateAbbr() + { + return '臺'; + } + + public static function cityPrefix() + { + return ''; + } + + public static function citySuffix() + { + return ''; + } + + public static function secondaryAddress() + { + return (static::randomNumber(2)+1).static::randomElement(static::$secondaryAddressSuffix); + } +} diff --git a/lib/faker/src/Faker/Provider/zh_TW/Color.php b/lib/faker/src/Faker/Provider/zh_TW/Color.php new file mode 100755 index 0000000..7be5953 --- /dev/null +++ b/lib/faker/src/Faker/Provider/zh_TW/Color.php @@ -0,0 +1,66 @@ +generator->parse($format); + } + + public static function companyModifier() + { + return static::randomElement(static::$companyModifier); + } + + public static function companyPrefix() + { + return static::randomElement(static::$companyPrefix); + } + + public function catchPhrase() + { + return static::randomElement(static::$catchPhrase); + } + + public function bs() + { + $result = ''; + foreach (static::$bsWords as &$word) { + $result .= static::randomElement($word); + } + return $result; + } +} diff --git a/lib/faker/src/Faker/Provider/zh_TW/DateTime.php b/lib/faker/src/Faker/Provider/zh_TW/DateTime.php new file mode 100755 index 0000000..6df5e92 --- /dev/null +++ b/lib/faker/src/Faker/Provider/zh_TW/DateTime.php @@ -0,0 +1,46 @@ +format('a') === 'am' ? '上午' : '下午'; + } + + public static function dayOfWeek($max = 'now') + { + $map = array( + 'Sunday' => '星期日', + 'Monday' => '星期一', + 'Tuesday' => '星期二', + 'Wednesday' => '星期三', + 'Thursday' => '星期四', + 'Friday' => '星期五', + 'Saturday' => '星期六', + ); + $week = static::dateTime($max)->format('l'); + return isset($map[$week]) ? $map[$week] : $week; + } + + public static function monthName($max = 'now') + { + $map = array( + 'January' => '一月', + 'February' => '二月', + 'March' => '三月', + 'April' => '四月', + 'May' => '五月', + 'June' => '六月', + 'July' => '七月', + 'August' => '八月', + 'September' => '九月', + 'October' => '十月', + 'November' => '十一月', + 'December' => '十二月', + ); + $month = static::dateTime($max)->format('F'); + return isset($map[$month]) ? $map[$month] : $month; + } +} diff --git a/lib/faker/src/Faker/Provider/zh_TW/Internet.php b/lib/faker/src/Faker/Provider/zh_TW/Internet.php new file mode 100755 index 0000000..4035ea8 --- /dev/null +++ b/lib/faker/src/Faker/Provider/zh_TW/Internet.php @@ -0,0 +1,16 @@ +userName(); + } + + public function domainWord() + { + return \Faker\Factory::create('en_US')->domainWord(); + } +} diff --git a/lib/faker/src/Faker/Provider/zh_TW/Payment.php b/lib/faker/src/Faker/Provider/zh_TW/Payment.php new file mode 100755 index 0000000..6b1a582 --- /dev/null +++ b/lib/faker/src/Faker/Provider/zh_TW/Payment.php @@ -0,0 +1,11 @@ +creditCardDetails($valid); + } +} diff --git a/lib/faker/src/Faker/Provider/zh_TW/Person.php b/lib/faker/src/Faker/Provider/zh_TW/Person.php new file mode 100755 index 0000000..71f248b --- /dev/null +++ b/lib/faker/src/Faker/Provider/zh_TW/Person.php @@ -0,0 +1,132 @@ +unique() + */ +class UniqueGenerator +{ + protected $generator; + protected $maxRetries; + protected $uniques = array(); + + public function __construct(Generator $generator, $maxRetries) + { + $this->generator = $generator; + $this->maxRetries = $maxRetries; + } + + /** + * Catch and proxy all generator calls but return only unique values + */ + public function __get($attribute) + { + return $this->__call($attribute, array()); + } + + /** + * Catch and proxy all generator calls with arguments but return only unique values + */ + public function __call($name, $arguments) + { + if (!isset($this->uniques[$name])) { + $this->uniques[$name] = array(); + } + $i = 0; + do { + $res = call_user_func_array(array($this->generator, $name), $arguments); + $i++; + if ($i > $this->maxRetries) { + throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a unique value', $this->maxRetries)); + } + } while (array_key_exists($res, $this->uniques[$name])); + $this->uniques[$name][$res]= null; + + return $res; + } +} diff --git a/lib/faker/src/autoload.php b/lib/faker/src/autoload.php new file mode 100755 index 0000000..f55914d --- /dev/null +++ b/lib/faker/src/autoload.php @@ -0,0 +1,26 @@ +assertEquals($checksum, Iban::checksum($iban), $iban); + } + + public function validatorProvider() + { + return array( + array('AL47212110090000000235698741', true), + array('AD1200012030200359100100', true), + array('AT611904300234573201', true), + array('AZ21NABZ00000000137010001944', true), + array('BH67BMAG00001299123456', true), + array('BE68539007547034', true), + array('BA391290079401028494', true), + array('BR7724891749412660603618210F3', true), + array('BG80BNBG96611020345678', true), + array('CR0515202001026284066', true), + array('HR1210010051863000160', true), + array('CY17002001280000001200527600', true), + array('CZ6508000000192000145399', true), + array('DK5000400440116243', true), + array('DO28BAGR00000001212453611324', true), + array('EE382200221020145685', true), + array('FO6264600001631634', true), + array('FI2112345600000785', true), + array('FR1420041010050500013M02606', true), + array('GE29NB0000000101904917', true), + array('DE89370400440532013000', true), + array('GI75NWBK000000007099453', true), + array('GR1601101250000000012300695', true), + array('GL8964710001000206', true), + array('GT82TRAJ01020000001210029690', true), + array('HU42117730161111101800000000', true), + array('IS140159260076545510730339', true), + array('IE29AIBK93115212345678', true), + array('IL620108000000099999999', true), + array('IT60X0542811101000000123456', true), + array('KZ86125KZT5004100100', true), + array('KW81CBKU0000000000001234560101', true), + array('LV80BANK0000435195001', true), + array('LB62099900000001001901229114', true), + array('LI21088100002324013AA', true), + array('LT121000011101001000', true), + array('LU280019400644750000', true), + array('MK07250120000058984', true), + array('MT84MALT011000012345MTLCAST001S', true), + array('MR1300020001010000123456753', true), + array('MU17BOMM0101101030300200000MUR', true), + array('MD24AG000225100013104168', true), + array('MC5811222000010123456789030', true), + array('ME25505000012345678951', true), + array('NL91ABNA0417164300', true), + array('NO9386011117947', true), + array('PK36SCBL0000001123456702', true), + array('PL61109010140000071219812874', true), + array('PS92PALS000000000400123456702', true), + array('PT50000201231234567890154', true), + array('QA58DOHB00001234567890ABCDEFG', true), + array('RO49AAAA1B31007593840000', true), + array('SM86U0322509800000000270100', true), + array('SA0380000000608010167519', true), + array('RS35260005601001611379', true), + array('SK3112000000198742637541', true), + array('SI56263300012039086', true), + array('ES9121000418450200051332', true), + array('SE4550000000058398257466', true), + array('CH9300762011623852957', true), + array('TN5910006035183598478831', true), + array('TR330006100519786457841326', true), + array('AE070331234567890123456', true), + array('GB29NWBK60161331926819', true), + array('VG96VPVG0000012345678901', true), + array('YY24KIHB12476423125915947930915268', true), + array('ZZ25VLQT382332233206588011313776421', true), + + + array('AL4721211009000000023569874', false), + array('AD120001203020035910010', false), + array('AT61190430023457320', false), + array('AZ21NABZ0000000013701000194', false), + array('BH67BMAG0000129912345', false), + array('BE6853900754703', false), + array('BA39129007940102849', false), + array('BR7724891749412660603618210F', false), + array('BG80BNBG9661102034567', false), + array('CR051520200102628406', false), + array('HR121001005186300016', false), + array('CY1700200128000000120052760', false), + array('CZ650800000019200014539', false), + array('DK500040044011624', false), + array('DO28BAGR0000000121245361132', false), + array('EE38220022102014568', false), + array('FO626460000163163', false), + array('FI2112345600000780', false), + array('FR1420041010050500013M0260', false), + array('GE29NB000000010190491', false), + array('DE8937040044053201300', false), + array('GI75NWBK00000000709945', false), + array('GR160110125000000001230069', false), + array('GL896471000100020', false), + array('GT82TRAJ0102000000121002969', false), + array('HU4211773016111110180000000', false), + array('IS14015926007654551073033', false), + array('IE29AIBK9311521234567', false), + array('IL62010800000009999999', false), + array('IT60X054281110100000012345', false), + array('KZ86125KZT500410010', false), + array('KW81CBKU000000000000123456010', false), + array('LV80BANK000043519500', false), + array('LB6209990000000100190122911', false), + array('LI21088100002324013A', false), + array('LT12100001110100100', false), + array('LU28001940064475000', false), + array('MK0725012000005898', false), + array('MT84MALT011000012345MTLCAST001', false), + array('MR130002000101000012345675', false), + array('MU17BOMM0101101030300200000MU', false), + array('MD24AG00022510001310416', false), + array('MC58112220000101234567890', false), + array('ME2550500001234567895', false), + array('NL91ABNA041716430', false), + array('NO938601111794', false), + array('PK36SCBL000000112345670', false), + array('PL6110901014000007121981287', false), + array('PS92PALS00000000040012345670', false), + array('PT5000020123123456789015', false), + array('QA58DOHB00001234567890ABCDEF', false), + array('RO49AAAA1B3100759384000', false), + array('SM86U032250980000000027010', false), + array('SA038000000060801016751', false), + array('RS3526000560100161137', false), + array('SK311200000019874263754', false), + array('SI5626330001203908', false), + array('ES912100041845020005133', false), + array('SE455000000005839825746', false), + array('CH930076201162385295', false), + array('TN591000603518359847883', false), + array('TR33000610051978645784132', false), + array('AE07033123456789012345', false), + array('GB29NWBK6016133192681', false), + array('VG96VPVG000001234567890', false), + array('YY24KIHB1247642312591594793091526', false), + array('ZZ25VLQT38233223320658801131377642', false), + ); + } + + /** + * @dataProvider validatorProvider + */ + public function testIsValid($iban, $isValid) + { + $this->assertEquals($isValid, Iban::isValid($iban), $iban); + } + + public function alphaToNumberProvider() + { + return array( + array('A', 10), + array('B', 11), + array('C', 12), + array('D', 13), + array('E', 14), + array('F', 15), + array('G', 16), + array('H', 17), + array('I', 18), + array('J', 19), + array('K', 20), + array('L', 21), + array('M', 22), + array('N', 23), + array('O', 24), + array('P', 25), + array('Q', 26), + array('R', 27), + array('S', 28), + array('T', 29), + array('U', 30), + array('V', 31), + array('W', 32), + array('X', 33), + array('Y', 34), + array('Z', 35), + ); + } + + /** + * @dataProvider alphaToNumberProvider + */ + public function testAlphaToNumber($letter, $number) + { + $this->assertEquals($number, Iban::alphaToNumber($letter), $letter); + } + + public function mod97Provider() + { + // Large numbers + $return = array( + array('123456789123456789', 7), + array('111222333444555666', 73), + array('4242424242424242424242', 19), + array('271828182845904523536028', 68), + ); + + // 0-200 + for ($i = 0; $i < 200; $i++) { + $return[] = array((string)$i, $i % 97); + } + + return $return; + } + /** + * @dataProvider mod97Provider + */ + public function testMod97($number, $result) + { + $this->assertEquals($result, Iban::mod97($number), $number); + } +} diff --git a/lib/faker/test/Faker/Calculator/LuhnTest.php b/lib/faker/test/Faker/Calculator/LuhnTest.php new file mode 100755 index 0000000..c217017 --- /dev/null +++ b/lib/faker/test/Faker/Calculator/LuhnTest.php @@ -0,0 +1,62 @@ +assertInternalType('string', $checkDigit); + $this->assertEquals($checkDigit, Luhn::computeCheckDigit($partialNumber)); + } + + public function validatorProvider() + { + return array( + array('79927398710', false), + array('79927398711', false), + array('79927398712', false), + array('79927398713', true), + array('79927398714', false), + array('79927398715', false), + array('79927398716', false), + array('79927398717', false), + array('79927398718', false), + array('79927398719', false), + array(79927398713, true), + array(79927398714, false), + ); + } + + /** + * @dataProvider validatorProvider + */ + public function testIsValid($number, $isValid) + { + $this->assertEquals($isValid, Luhn::isValid($number)); + } +} diff --git a/lib/faker/test/Faker/DefaultGeneratorTest.php b/lib/faker/test/Faker/DefaultGeneratorTest.php new file mode 100755 index 0000000..262243d --- /dev/null +++ b/lib/faker/test/Faker/DefaultGeneratorTest.php @@ -0,0 +1,27 @@ +assertSame(null, $generator->value); + } + + public function testGeneratorReturnsDefaultValueForAnyPropertyGet() + { + $generator = new DefaultGenerator(123); + $this->assertSame(123, $generator->foo); + $this->assertNotSame(null, $generator->bar); + } + + public function testGeneratorReturnsDefaultValueForAnyMethodCall() + { + $generator = new DefaultGenerator(123); + $this->assertSame(123, $generator->foobar()); + } +} diff --git a/lib/faker/test/Faker/GeneratorTest.php b/lib/faker/test/Faker/GeneratorTest.php new file mode 100755 index 0000000..e437292 --- /dev/null +++ b/lib/faker/test/Faker/GeneratorTest.php @@ -0,0 +1,147 @@ +addProvider(new FooProvider()); + $generator->addProvider(new BarProvider()); + $this->assertEquals('barfoo', $generator->format('fooFormatter')); + } + + public function testGetFormatterReturnsCallable() + { + $generator = new Generator; + $provider = new FooProvider(); + $generator->addProvider($provider); + $this->assertTrue(is_callable($generator->getFormatter('fooFormatter'))); + } + + public function testGetFormatterReturnsCorrectFormatter() + { + $generator = new Generator; + $provider = new FooProvider(); + $generator->addProvider($provider); + $expected = array($provider, 'fooFormatter'); + $this->assertEquals($expected, $generator->getFormatter('fooFormatter')); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testGetFormatterThrowsExceptionOnIncorrectProvider() + { + $generator = new Generator; + $generator->getFormatter('fooFormatter'); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testGetFormatterThrowsExceptionOnIncorrectFormatter() + { + $generator = new Generator; + $provider = new FooProvider(); + $generator->addProvider($provider); + $generator->getFormatter('barFormatter'); + } + + public function testFormatCallsFormatterOnProvider() + { + $generator = new Generator; + $provider = new FooProvider(); + $generator->addProvider($provider); + $this->assertEquals('foobar', $generator->format('fooFormatter')); + } + + public function testFormatTransfersArgumentsToFormatter() + { + $generator = new Generator; + $provider = new FooProvider(); + $generator->addProvider($provider); + $this->assertEquals('bazfoo', $generator->format('fooFormatterWithArguments', array('foo'))); + } + + public function testParseReturnsSameStringWhenItContainsNoCurlyBraces() + { + $generator = new Generator(); + $this->assertEquals('fooBar#?', $generator->parse('fooBar#?')); + } + + public function testParseReturnsStringWithTokensReplacedByFormatters() + { + $generator = new Generator(); + $provider = new FooProvider(); + $generator->addProvider($provider); + $this->assertEquals('This is foobar a text with foobar', $generator->parse('This is {{fooFormatter}} a text with {{ fooFormatter }}')); + } + + public function testMagicGetCallsFormat() + { + $generator = new Generator; + $provider = new FooProvider(); + $generator->addProvider($provider); + $this->assertEquals('foobar', $generator->fooFormatter); + } + + public function testMagicCallCallsFormat() + { + $generator = new Generator; + $provider = new FooProvider(); + $generator->addProvider($provider); + $this->assertEquals('foobar', $generator->fooFormatter()); + } + + public function testMagicCallCallsFormatWithArguments() + { + $generator = new Generator; + $provider = new FooProvider(); + $generator->addProvider($provider); + $this->assertEquals('bazfoo', $generator->fooFormatterWithArguments('foo')); + } + + public function testSeed() + { + $generator = new Generator; + + $generator->seed(0); + $mtRandWithSeedZero = mt_rand(); + $generator->seed(0); + $this->assertEquals($mtRandWithSeedZero, mt_rand(), 'seed(0) should be deterministic.'); + + $generator->seed(); + $mtRandWithoutSeed = mt_rand(); + $this->assertNotEquals($mtRandWithSeedZero, $mtRandWithoutSeed, 'seed() should be different than seed(0)'); + $generator->seed(); + $this->assertNotEquals($mtRandWithoutSeed, mt_rand(), 'seed() should not be deterministic.'); + + $generator->seed('10'); + $this->assertTrue(true, 'seeding with a non int value doesn\'t throw an exception'); + } +} + +class FooProvider +{ + public function fooFormatter() + { + return 'foobar'; + } + + public function fooFormatterWithArguments($value = '') + { + return 'baz' . $value; + } +} + +class BarProvider +{ + public function fooFormatter() + { + return 'barfoo'; + } +} diff --git a/lib/faker/test/Faker/Provider/AddressTest.php b/lib/faker/test/Faker/Provider/AddressTest.php new file mode 100755 index 0000000..cbabce5 --- /dev/null +++ b/lib/faker/test/Faker/Provider/AddressTest.php @@ -0,0 +1,34 @@ +addProvider(new Address($faker)); + $this->faker = $faker; + } + + public function testLatitude() + { + $latitude = $this->faker->latitude(); + $this->assertInternalType('float', $latitude); + $this->assertGreaterThanOrEqual(-90, $latitude); + $this->assertLessThanOrEqual(90, $latitude); + } + + public function testLongitude() + { + $longitude = $this->faker->longitude(); + $this->assertInternalType('float', $longitude); + $this->assertGreaterThanOrEqual(-180, $longitude); + $this->assertLessThanOrEqual(180, $longitude); + } +} diff --git a/lib/faker/test/Faker/Provider/BarcodeTest.php b/lib/faker/test/Faker/Provider/BarcodeTest.php new file mode 100755 index 0000000..1373b2b --- /dev/null +++ b/lib/faker/test/Faker/Provider/BarcodeTest.php @@ -0,0 +1,45 @@ +addProvider(new Barcode($faker)); + $faker->seed(0); + $this->faker = $faker; + } + + public function testEan8() + { + $code = $this->faker->ean8(); + $this->assertRegExp('/^\d{8}$/i', $code); + $codeWithoutChecksum = substr($code, 0, -1); + $checksum = substr($code, -1); + $this->assertEquals(TestableBarcode::eanChecksum($codeWithoutChecksum), $checksum); + } + + public function testEan13() + { + $code = $this->faker->ean13(); + $this->assertRegExp('/^\d{13}$/i', $code); + $codeWithoutChecksum = substr($code, 0, -1); + $checksum = substr($code, -1); + $this->assertEquals(TestableBarcode::eanChecksum($codeWithoutChecksum), $checksum); + } +} + +class TestableBarcode extends Barcode +{ + public static function eanChecksum($input) + { + return parent::eanChecksum($input); + } +} diff --git a/lib/faker/test/Faker/Provider/BaseTest.php b/lib/faker/test/Faker/Provider/BaseTest.php new file mode 100755 index 0000000..4af3929 --- /dev/null +++ b/lib/faker/test/Faker/Provider/BaseTest.php @@ -0,0 +1,467 @@ +assertTrue(is_integer(BaseProvider::randomDigit())); + } + + public function testRandomDigitReturnsDigit() + { + $this->assertTrue(BaseProvider::randomDigit() >= 0); + $this->assertTrue(BaseProvider::randomDigit() < 10); + } + + public function testRandomDigitNotNullReturnsNotNullDigit() + { + $this->assertTrue(BaseProvider::randomDigitNotNull() > 0); + $this->assertTrue(BaseProvider::randomDigitNotNull() < 10); + } + + + public function testRandomDigitNotReturnsValidDigit() + { + for ($i = 0; $i <= 9; $i++) { + $this->assertTrue(BaseProvider::randomDigitNot($i) >= 0); + $this->assertTrue(BaseProvider::randomDigitNot($i) < 10); + $this->assertTrue(BaseProvider::randomDigitNot($i) !== $i); + } + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testRandomNumberThrowsExceptionWhenCalledWithAMax() + { + BaseProvider::randomNumber(5, 200); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testRandomNumberThrowsExceptionWhenCalledWithATooHighNumberOfDigits() + { + BaseProvider::randomNumber(10); + } + + public function testRandomNumberReturnsInteger() + { + $this->assertTrue(is_integer(BaseProvider::randomNumber())); + $this->assertTrue(is_integer(BaseProvider::randomNumber(5, false))); + } + + public function testRandomNumberReturnsDigit() + { + $this->assertTrue(BaseProvider::randomNumber(3) >= 0); + $this->assertTrue(BaseProvider::randomNumber(3) < 1000); + } + + public function testRandomNumberAcceptsStrictParamToEnforceNumberSize() + { + $this->assertEquals(5, strlen((string) BaseProvider::randomNumber(5, true))); + } + + public function testNumberBetween() + { + $min = 5; + $max = 6; + + $this->assertGreaterThanOrEqual($min, BaseProvider::numberBetween($min, $max)); + $this->assertGreaterThanOrEqual(BaseProvider::numberBetween($min, $max), $max); + } + + public function testNumberBetweenAcceptsZeroAsMax() + { + $this->assertEquals(0, BaseProvider::numberBetween(0, 0)); + } + + public function testRandomFloat() + { + $min = 4; + $max = 10; + $nbMaxDecimals = 8; + + $result = BaseProvider::randomFloat($nbMaxDecimals, $min, $max); + + $parts = explode('.', $result); + + $this->assertInternalType('float', $result); + $this->assertGreaterThanOrEqual($min, $result); + $this->assertLessThanOrEqual($max, $result); + $this->assertLessThanOrEqual($nbMaxDecimals, strlen($parts[1])); + } + + public function testRandomLetterReturnsString() + { + $this->assertTrue(is_string(BaseProvider::randomLetter())); + } + + public function testRandomLetterReturnsSingleLetter() + { + $this->assertEquals(1, strlen(BaseProvider::randomLetter())); + } + + public function testRandomLetterReturnsLowercaseLetter() + { + $lowercaseLetters = 'abcdefghijklmnopqrstuvwxyz'; + $this->assertTrue(strpos($lowercaseLetters, BaseProvider::randomLetter()) !== false); + } + + public function testRandomAsciiReturnsString() + { + $this->assertTrue(is_string(BaseProvider::randomAscii())); + } + + public function testRandomAsciiReturnsSingleCharacter() + { + $this->assertEquals(1, strlen(BaseProvider::randomAscii())); + } + + public function testRandomAsciiReturnsAsciiCharacter() + { + $lowercaseLetters = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; + $this->assertTrue(strpos($lowercaseLetters, BaseProvider::randomAscii()) !== false); + } + + public function testRandomElementReturnsNullWhenArrayEmpty() + { + $this->assertNull(BaseProvider::randomElement(array())); + } + + public function testRandomElementReturnsElementFromArray() + { + $elements = array('23', 'e', 32, '#'); + $this->assertContains(BaseProvider::randomElement($elements), $elements); + } + + public function testRandomElementReturnsElementFromAssociativeArray() + { + $elements = array('tata' => '23', 'toto' => 'e', 'tutu' => 32, 'titi' => '#'); + $this->assertContains(BaseProvider::randomElement($elements), $elements); + } + + public function testShuffleReturnsStringWhenPassedAStringArgument() + { + $this->assertInternalType('string', BaseProvider::shuffle('foo')); + } + + public function testShuffleReturnsArrayWhenPassedAnArrayArgument() + { + $this->assertInternalType('array', BaseProvider::shuffle(array(1, 2, 3))); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testShuffleThrowsExceptionWhenPassedAnInvalidArgument() + { + BaseProvider::shuffle(false); + } + + public function testShuffleArraySupportsEmptyArrays() + { + $this->assertEquals(array(), BaseProvider::shuffleArray(array())); + } + + public function testShuffleArrayReturnsAnArrayOfTheSameSize() + { + $array = array(1, 2, 3, 4, 5); + $this->assertSameSize($array, BaseProvider::shuffleArray($array)); + } + + public function testShuffleArrayReturnsAnArrayWithSameElements() + { + $array = array(2, 4, 6, 8, 10); + $shuffleArray = BaseProvider::shuffleArray($array); + $this->assertContains(2, $shuffleArray); + $this->assertContains(4, $shuffleArray); + $this->assertContains(6, $shuffleArray); + $this->assertContains(8, $shuffleArray); + $this->assertContains(10, $shuffleArray); + } + + public function testShuffleArrayReturnsADifferentArrayThanTheOriginal() + { + $arr = array(1, 2, 3, 4, 5); + $shuffledArray = BaseProvider::shuffleArray($arr); + $this->assertNotEquals($arr, $shuffledArray); + } + + public function testShuffleArrayLeavesTheOriginalArrayUntouched() + { + $arr = array(1, 2, 3, 4, 5); + BaseProvider::shuffleArray($arr); + $this->assertEquals($arr, array(1, 2, 3, 4, 5)); + } + + public function testShuffleStringSupportsEmptyStrings() + { + $this->assertEquals('', BaseProvider::shuffleString('')); + } + + public function testShuffleStringReturnsAnStringOfTheSameSize() + { + $string = 'abcdef'; + $this->assertEquals(strlen($string), strlen(BaseProvider::shuffleString($string))); + } + + public function testShuffleStringReturnsAnStringWithSameElements() + { + $string = 'acegi'; + $shuffleString = BaseProvider::shuffleString($string); + $this->assertContains('a', $shuffleString); + $this->assertContains('c', $shuffleString); + $this->assertContains('e', $shuffleString); + $this->assertContains('g', $shuffleString); + $this->assertContains('i', $shuffleString); + } + + public function testShuffleStringReturnsADifferentStringThanTheOriginal() + { + $string = 'abcdef'; + $shuffledString = BaseProvider::shuffleString($string); + $this->assertNotEquals($string, $shuffledString); + } + + public function testShuffleStringLeavesTheOriginalStringUntouched() + { + $string = 'abcdef'; + BaseProvider::shuffleString($string); + $this->assertEquals($string, 'abcdef'); + } + + public function testNumerifyReturnsSameStringWhenItContainsNoHashSign() + { + $this->assertEquals('fooBar?', BaseProvider::numerify('fooBar?')); + } + + public function testNumerifyReturnsStringWithHashSignsReplacedByDigits() + { + $this->assertRegExp('/foo\dBa\dr/', BaseProvider::numerify('foo#Ba#r')); + } + + public function testNumerifyReturnsStringWithPercentageSignsReplacedByDigits() + { + $this->assertRegExp('/foo\dBa\dr/', BaseProvider::numerify('foo%Ba%r')); + } + + public function testNumerifyReturnsStringWithPercentageSignsReplacedByNotNullDigits() + { + $this->assertNotEquals('0', BaseProvider::numerify('%')); + } + + public function testNumerifyCanGenerateALargeNumberOfDigits() + { + $largePattern = str_repeat('#', 20); // definitely larger than PHP_INT_MAX on all systems + $this->assertEquals(20, strlen(BaseProvider::numerify($largePattern))); + } + + public function testLexifyReturnsSameStringWhenItContainsNoQuestionMark() + { + $this->assertEquals('fooBar#', BaseProvider::lexify('fooBar#')); + } + + public function testLexifyReturnsStringWithQuestionMarksReplacedByLetters() + { + $this->assertRegExp('/foo[a-z]Ba[a-z]r/', BaseProvider::lexify('foo?Ba?r')); + } + + public function testBothifyCombinesNumerifyAndLexify() + { + $this->assertRegExp('/foo[a-z]Ba\dr/', BaseProvider::bothify('foo?Ba#r')); + } + + public function testBothifyAsterisk() + { + $this->assertRegExp('/foo([a-z]|\d)Ba([a-z]|\d)r/', BaseProvider::bothify('foo*Ba*r')); + } + + public function testBothifyUtf() + { + $utf = 'œ∑´®†¥¨ˆøπ“‘和製╯°□°╯︵ ┻━┻🐵 🙈 ﺚﻣ ﻦﻔﺳ ﺲﻘﻄﺗ ﻮﺑﺎﻠﺘﺣﺪﻳﺩ،, ﺝﺰﻳﺮﺘﻳ ﺏﺎﺴﺘﺧﺩﺎﻣ ﺄﻧ ﺪﻧﻭ. ﺇﺫ ﻪﻧﺍ؟ ﺎﻠﺴﺗﺍﺭ ﻮﺘ'; + $this->assertRegExp('/'.$utf.'foo\dB[a-z]a([a-z]|\d)r/u', BaseProvider::bothify($utf.'foo#B?a*r')); + } + + public function testAsciifyReturnsSameStringWhenItContainsNoStarSign() + { + $this->assertEquals('fooBar?', BaseProvider::asciify('fooBar?')); + } + + public function testAsciifyReturnsStringWithStarSignsReplacedByAsciiChars() + { + $this->assertRegExp('/foo.Ba.r/', BaseProvider::asciify('foo*Ba*r')); + } + + public function regexifyBasicDataProvider() + { + return array( + array('azeQSDF1234', 'azeQSDF1234', 'does not change non regex chars'), + array('foo(bar){1}', 'foobar', 'replaces regex characters'), + array('', '', 'supports empty string'), + array('/^foo(bar){1}$/', 'foobar', 'ignores regex delimiters') + ); + } + + /** + * @dataProvider regexifyBasicDataProvider + */ + public function testRegexifyBasicFeatures($input, $output, $message) + { + $this->assertEquals($output, BaseProvider::regexify($input), $message); + } + + public function regexifyDataProvider() + { + return array( + array('\d', 'numbers'), + array('\w', 'letters'), + array('(a|b)', 'alternation'), + array('[aeiou]', 'basic character class'), + array('[a-z]', 'character class range'), + array('[a-z1-9]', 'multiple character class range'), + array('a*b+c?', 'single character quantifiers'), + array('a{2}', 'brackets quantifiers'), + array('a{2,3}', 'min-max brackets quantifiers'), + array('[aeiou]{2,3}', 'brackets quantifiers on basic character class'), + array('[a-z]{2,3}', 'brackets quantifiers on character class range'), + array('(a|b){2,3}', 'brackets quantifiers on alternation'), + array('\.\*\?\+', 'escaped characters'), + array('[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}', 'complex regex') + ); + } + + /** + * @dataProvider regexifyDataProvider + */ + public function testRegexifySupportedRegexSyntax($pattern, $message) + { + $this->assertRegExp('/' . $pattern . '/', BaseProvider::regexify($pattern), 'Regexify supports ' . $message); + } + + public function testOptionalReturnsProviderValueWhenCalledWithWeight1() + { + $faker = new \Faker\Generator(); + $faker->addProvider(new \Faker\Provider\Base($faker)); + $this->assertNotNull($faker->optional(1)->randomDigit); + } + + public function testOptionalReturnsNullWhenCalledWithWeight0() + { + $faker = new \Faker\Generator(); + $faker->addProvider(new \Faker\Provider\Base($faker)); + $this->assertNull($faker->optional(0)->randomDigit); + } + + public function testOptionalAllowsChainingPropertyAccess() + { + $faker = new \Faker\Generator(); + $faker->addProvider(new \Faker\Provider\Base($faker)); + $faker->addProvider(new \ArrayObject(array(1))); // hack because method_exists forbids stubs + $this->assertEquals(1, $faker->optional(1)->count); + $this->assertNull($faker->optional(0)->count); + } + + public function testOptionalAllowsChainingMethodCall() + { + $faker = new \Faker\Generator(); + $faker->addProvider(new \Faker\Provider\Base($faker)); + $faker->addProvider(new \ArrayObject(array(1))); // hack because method_exists forbids stubs + $this->assertEquals(1, $faker->optional(1)->count()); + $this->assertNull($faker->optional(0)->count()); + } + + public function testOptionalAllowsChainingProviderCallRandomlyReturnNull() + { + $faker = new \Faker\Generator(); + $faker->addProvider(new \Faker\Provider\Base($faker)); + $values = array(); + for ($i=0; $i < 10; $i++) { + $values[]= $faker->optional()->randomDigit; + } + $this->assertContains(null, $values); + } + + public function testUniqueAllowsChainingPropertyAccess() + { + $faker = new \Faker\Generator(); + $faker->addProvider(new \Faker\Provider\Base($faker)); + $faker->addProvider(new \ArrayObject(array(1))); // hack because method_exists forbids stubs + $this->assertEquals(1, $faker->unique()->count); + } + + public function testUniqueAllowsChainingMethodCall() + { + $faker = new \Faker\Generator(); + $faker->addProvider(new \Faker\Provider\Base($faker)); + $faker->addProvider(new \ArrayObject(array(1))); // hack because method_exists forbids stubs + $this->assertEquals(1, $faker->unique()->count()); + } + + public function testUniqueReturnsOnlyUniqueValues() + { + $faker = new \Faker\Generator(); + $faker->addProvider(new \Faker\Provider\Base($faker)); + $values = array(); + for ($i=0; $i < 10; $i++) { + $values[]= $faker->unique()->randomDigit; + } + sort($values); + $this->assertEquals(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), $values); + } + + /** + * @expectedException OverflowException + */ + public function testUniqueThrowsExceptionWhenNoUniqueValueCanBeGenerated() + { + $faker = new \Faker\Generator(); + $faker->addProvider(new \Faker\Provider\Base($faker)); + for ($i=0; $i < 11; $i++) { + $faker->unique()->randomDigit; + } + } + + public function testUniqueCanResetUniquesWhenPassedTrueAsArgument() + { + $faker = new \Faker\Generator(); + $faker->addProvider(new \Faker\Provider\Base($faker)); + $values = array(); + for ($i=0; $i < 10; $i++) { + $values[]= $faker->unique()->randomDigit; + } + $values[]= $faker->unique(true)->randomDigit; + for ($i=0; $i < 9; $i++) { + $values[]= $faker->unique()->randomDigit; + } + sort($values); + $this->assertEquals(array(0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9), $values); + } + + /** + * @expectedException LengthException + * @expectedExceptionMessage Cannot get 2 elements, only 1 in array + */ + public function testRandomElementsThrowsWhenRequestingTooManyKeys() + { + BaseProvider::randomElements(array('foo'), 2); + } + + public function testRandomElements() + { + $this->assertCount(1, BaseProvider::randomElements(), 'Should work without any input'); + + $empty = BaseProvider::randomElements(array(), 0); + $this->assertInternalType('array', $empty); + $this->assertCount(0, $empty); + + $shuffled = BaseProvider::randomElements(array('foo', 'bar', 'baz'), 3); + $this->assertContains('foo', $shuffled); + $this->assertContains('bar', $shuffled); + $this->assertContains('baz', $shuffled); + } +} diff --git a/lib/faker/test/Faker/Provider/BiasedTest.php b/lib/faker/test/Faker/Provider/BiasedTest.php new file mode 100755 index 0000000..1f7a99a --- /dev/null +++ b/lib/faker/test/Faker/Provider/BiasedTest.php @@ -0,0 +1,73 @@ +generator = new Generator(); + $this->generator->addProvider(new Biased($this->generator)); + + $this->results = array_fill(1, self::MAX, 0); + } + + public function performFake($function) + { + for($i = 0; $i < self::NUMBERS; $i++) { + $this->results[$this->generator->biasedNumberBetween(1, self::MAX, $function)]++; + } + } + + public function testUnbiased() + { + $this->performFake(array('\Faker\Provider\Biased', 'unbiased')); + + // assert that all numbers are near the expected unbiased value + foreach ($this->results as $number => $amount) { + // integral + $assumed = (1 / self::MAX * $number) - (1 / self::MAX * ($number - 1)); + // calculate the fraction of the whole area + $assumed /= 1; + $this->assertGreaterThan(self::NUMBERS * $assumed * .95, $amount, "Value was more than 5 percent under the expected value"); + $this->assertLessThan(self::NUMBERS * $assumed * 1.05, $amount, "Value was more than 5 percent over the expected value"); + } + } + + public function testLinearHigh() + { + $this->performFake(array('\Faker\Provider\Biased', 'linearHigh')); + + foreach ($this->results as $number => $amount) { + // integral + $assumed = 0.5 * pow(1 / self::MAX * $number, 2) - 0.5 * pow(1 / self::MAX * ($number - 1), 2); + // calculate the fraction of the whole area + $assumed /= pow(1, 2) * .5; + $this->assertGreaterThan(self::NUMBERS * $assumed * .9, $amount, "Value was more than 10 percent under the expected value"); + $this->assertLessThan(self::NUMBERS * $assumed * 1.1, $amount, "Value was more than 10 percent over the expected value"); + } + } + + public function testLinearLow() + { + $this->performFake(array('\Faker\Provider\Biased', 'linearLow')); + + foreach ($this->results as $number => $amount) { + // integral + $assumed = -0.5 * pow(1 / self::MAX * $number, 2) - -0.5 * pow(1 / self::MAX * ($number - 1), 2); + // shift the graph up + $assumed += 1 / self::MAX; + // calculate the fraction of the whole area + $assumed /= pow(1, 2) * .5; + $this->assertGreaterThan(self::NUMBERS * $assumed * .9, $amount, "Value was more than 10 percent under the expected value"); + $this->assertLessThan(self::NUMBERS * $assumed * 1.1, $amount, "Value was more than 10 percent over the expected value"); + } + } +} diff --git a/lib/faker/test/Faker/Provider/ColorTest.php b/lib/faker/test/Faker/Provider/ColorTest.php new file mode 100755 index 0000000..07cd965 --- /dev/null +++ b/lib/faker/test/Faker/Provider/ColorTest.php @@ -0,0 +1,53 @@ +assertRegExp('/^#[a-f0-9]{6}$/i', Color::hexColor()); + } + + public function testSafeHexColor() + { + $this->assertRegExp('/^#[a-f0-9]{6}$/i', Color::safeHexColor()); + } + + public function testRgbColorAsArray() + { + $this->assertEquals(3, count(Color::rgbColorAsArray())); + } + + public function testRgbColor() + { + $regexp = '([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])'; + $this->assertRegExp('/^' . $regexp . ',' . $regexp . ',' . $regexp . '$/i', Color::rgbColor()); + } + + public function testRgbCssColor() + { + $regexp = '([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])'; + $this->assertRegExp('/^rgb\(' . $regexp . ',' . $regexp . ',' . $regexp . '\)$/i', Color::rgbCssColor()); + } + + public function testRgbaCssColor() + { + $regexp = '([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])'; + $regexpAlpha = '([01]?\.[0-9])'; + $this->assertRegExp('/^rgba\(' . $regexp . ',' . $regexp . ',' . $regexp . ',' . $regexpAlpha . '\)$/i', Color::rgbaCssColor()); + } + + public function testSafeColorName() + { + $this->assertRegExp('/^[\w]+$/', Color::safeColorName()); + } + + public function testColorName() + { + $this->assertRegExp('/^[\w]+$/', Color::colorName()); + } +} diff --git a/lib/faker/test/Faker/Provider/DateTimeTest.php b/lib/faker/test/Faker/Provider/DateTimeTest.php new file mode 100755 index 0000000..667dd8b --- /dev/null +++ b/lib/faker/test/Faker/Provider/DateTimeTest.php @@ -0,0 +1,151 @@ +assertInternalType('int', $timestamp); + $this->assertTrue($timestamp >= 0); + $this->assertTrue($timestamp <= time()); + } + + public function testDateTime() + { + $date = DateTimeProvider::dateTime(); + $this->assertInstanceOf('\DateTime', $date); + $this->assertGreaterThanOrEqual(new \DateTime('@0'), $date); + $this->assertLessThanOrEqual(new \DateTime(), $date); + } + + public function testDateTimeAD() + { + $date = DateTimeProvider::dateTimeAD(); + $this->assertInstanceOf('\DateTime', $date); + $this->assertGreaterThanOrEqual(new \DateTime('0000-01-01 00:00:00'), $date); + $this->assertLessThanOrEqual(new \DateTime(), $date); + } + + public function testIso8601() + { + $date = DateTimeProvider::iso8601(); + $this->assertRegExp('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-Z](\d{4})?$/', $date); + $this->assertGreaterThanOrEqual(new \DateTime('@0'), new \DateTime($date)); + $this->assertLessThanOrEqual(new \DateTime(), new \DateTime($date)); + } + + public function testDate() + { + $date = DateTimeProvider::date(); + $this->assertRegExp('/^\d{4}-\d{2}-\d{2}$/', $date); + $this->assertGreaterThanOrEqual(new \DateTime('@0'), new \DateTime($date)); + $this->assertLessThanOrEqual(new \DateTime(), new \DateTime($date)); + } + + public function testTime() + { + $date = DateTimeProvider::time(); + $this->assertRegExp('/^\d{2}:\d{2}:\d{2}$/', $date); + } + + /** + * + * @dataProvider providerDateTimeBetween + */ + public function testDateTimeBetween($start, $end) + { + $date = DateTimeProvider::dateTimeBetween($start, $end); + $this->assertInstanceOf('\DateTime', $date); + $this->assertGreaterThanOrEqual(new \DateTime($start), $date); + $this->assertLessThanOrEqual(new \DateTime($end), $date); + } + + public function providerDateTimeBetween() + { + return array( + array('-1 year', false), + array('-1 year', null), + array('-1 day', '-1 hour'), + array('-1 day', 'now'), + ); + } + + /** + * + * @dataProvider providerDateTimeInInterval + */ + public function testDateTimeInInterval($start, $interval = "+5 days", $isInFutur) + { + $date = DateTimeProvider::dateTimeInInterval($start, $interval); + $this->assertInstanceOf('\DateTime', $date); + + $_interval = \DateInterval::createFromDateString($interval); + $_start = new \DateTime($start); + if($isInFutur){ + $this->assertGreaterThanOrEqual($_start, $date); + $this->assertLessThanOrEqual($_start->add($_interval), $date); + }else{ + $this->assertLessThanOrEqual($_start, $date); + $this->assertGreaterThanOrEqual($_start->add($_interval), $date); + } + } + + public function providerDateTimeInInterval() + { + return array( + array('-1 year', '+5 days', true), + array('-1 day', '-1 hour', false), + array('-1 day', '+1 hour', true), + ); + } + + public function testFixedSeedWithMaximumTimestamp() + { + $max = '2018-03-01 12:00:00'; + + mt_srand(1); + $unixTime = DateTimeProvider::unixTime($max); + $datetimeAD = DateTimeProvider::dateTimeAD($max); + $dateTime1 = DateTimeProvider::dateTime($max); + $dateTimeBetween = DateTimeProvider::dateTimeBetween('2014-03-01 06:00:00', $max); + $date = DateTimeProvider::date('Y-m-d', $max); + $time = DateTimeProvider::time('H:i:s', $max); + $iso8601 = DateTimeProvider::iso8601($max); + $dateTimeThisCentury = DateTimeProvider::dateTimeThisCentury($max); + $dateTimeThisDecade = DateTimeProvider::dateTimeThisDecade($max); + $dateTimeThisMonth = DateTimeProvider::dateTimeThisMonth($max); + $amPm = DateTimeProvider::amPm($max); + $dayOfMonth = DateTimeProvider::dayOfMonth($max); + $dayOfWeek = DateTimeProvider::dayOfWeek($max); + $month = DateTimeProvider::month($max); + $monthName = DateTimeProvider::monthName($max); + $year = DateTimeProvider::year($max); + $dateTimeThisYear = DateTimeProvider::dateTimeThisYear($max); + mt_srand(); + + //regenerate Random Date with same seed and same maximum end timestamp + mt_srand(1); + $this->assertEquals($unixTime, DateTimeProvider::unixTime($max)); + $this->assertEquals($datetimeAD, DateTimeProvider::dateTimeAD($max)); + $this->assertEquals($dateTime1, DateTimeProvider::dateTime($max)); + $this->assertEquals($dateTimeBetween, DateTimeProvider::dateTimeBetween('2014-03-01 06:00:00', $max)); + $this->assertEquals($date, DateTimeProvider::date('Y-m-d', $max)); + $this->assertEquals($time, DateTimeProvider::time('H:i:s', $max)); + $this->assertEquals($iso8601, DateTimeProvider::iso8601($max)); + $this->assertEquals($dateTimeThisCentury, DateTimeProvider::dateTimeThisCentury($max)); + $this->assertEquals($dateTimeThisDecade, DateTimeProvider::dateTimeThisDecade($max)); + $this->assertEquals($dateTimeThisMonth, DateTimeProvider::dateTimeThisMonth($max)); + $this->assertEquals($amPm, DateTimeProvider::amPm($max)); + $this->assertEquals($dayOfMonth, DateTimeProvider::dayOfMonth($max)); + $this->assertEquals($dayOfWeek, DateTimeProvider::dayOfWeek($max)); + $this->assertEquals($month, DateTimeProvider::month($max)); + $this->assertEquals($monthName, DateTimeProvider::monthName($max)); + $this->assertEquals($year, DateTimeProvider::year($max)); + $this->assertEquals($dateTimeThisYear, DateTimeProvider::dateTimeThisYear($max)); + mt_srand(); + } +} diff --git a/lib/faker/test/Faker/Provider/ImageTest.php b/lib/faker/test/Faker/Provider/ImageTest.php new file mode 100755 index 0000000..0535d4d --- /dev/null +++ b/lib/faker/test/Faker/Provider/ImageTest.php @@ -0,0 +1,62 @@ +assertRegExp('#^http://lorempixel.com/640/480/#', Image::imageUrl()); + } + + public function testImageUrlAcceptsCustomWidthAndHeight() + { + $this->assertRegExp('#^http://lorempixel.com/800/400/#', Image::imageUrl(800, 400)); + } + + public function testImageUrlAcceptsCustomCategory() + { + $this->assertRegExp('#^http://lorempixel.com/800/400/nature/#', Image::imageUrl(800, 400, 'nature')); + } + + public function testImageUrlAcceptsCustomText() + { + $this->assertRegExp('#^http://lorempixel.com/800/400/nature/Faker#', Image::imageUrl(800, 400, 'nature', false, 'Faker')); + } + + public function testImageUrlAddsARandomGetParameterByDefault() + { + $url = Image::imageUrl(800, 400); + $splitUrl = preg_split('/\?/', $url); + + $this->assertEquals(count($splitUrl), 2); + $this->assertRegexp('#\d{5}#', $splitUrl[1]); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testUrlWithDimensionsAndBadCategory() + { + Image::imageUrl(800, 400, 'bullhonky'); + } + + public function testDownloadWithDefaults() + { + $file = Image::image(sys_get_temp_dir()); + $this->assertFileExists($file); + if (function_exists('getimagesize')) { + list($width, $height, $type, $attr) = getimagesize($file); + $this->assertEquals(640, $width); + $this->assertEquals(480, $height); + $this->assertEquals(constant('IMAGETYPE_JPEG'), $type); + } else { + $this->assertEquals('jpg', pathinfo($file, PATHINFO_EXTENSION)); + } + if (file_exists($file)) { + unlink($file); + } + } +} diff --git a/lib/faker/test/Faker/Provider/InternetTest.php b/lib/faker/test/Faker/Provider/InternetTest.php new file mode 100755 index 0000000..e715e82 --- /dev/null +++ b/lib/faker/test/Faker/Provider/InternetTest.php @@ -0,0 +1,130 @@ +addProvider(new Lorem($faker)); + $faker->addProvider(new Person($faker)); + $faker->addProvider(new Internet($faker)); + $faker->addProvider(new Company($faker)); + $this->faker = $faker; + } + + public function localeDataProvider() + { + $providerPath = realpath(__DIR__ . '/../../../src/Faker/Provider'); + $localePaths = array_filter(glob($providerPath . '/*', GLOB_ONLYDIR)); + foreach ($localePaths as $path) { + $parts = explode('/', $path); + $locales[] = array($parts[count($parts) - 1]); + } + + return $locales; + } + + /** + * @link http://stackoverflow.com/questions/12026842/how-to-validate-an-email-address-in-php + * + * @requires PHP 5.4 + * @dataProvider localeDataProvider + */ + public function testEmailIsValid($locale) + { + $this->loadLocalProviders($locale); + $pattern = '/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD'; + $emailAddress = $this->faker->email(); + $this->assertRegExp($pattern, $emailAddress); + } + + /** + * @requires PHP 5.4 + * @dataProvider localeDataProvider + */ + public function testUsernameIsValid($locale) + { + $this->loadLocalProviders($locale); + $pattern = '/^[A-Za-z0-9._]+$/'; + $username = $this->faker->username(); + $this->assertRegExp($pattern, $username); + } + + public function loadLocalProviders($locale) + { + $providerPath = realpath(__DIR__ . '/../../../src/Faker/Provider'); + if (file_exists($providerPath.'/'.$locale.'/Internet.php')) { + $internet = "\\Faker\\Provider\\$locale\\Internet"; + $this->faker->addProvider(new $internet($this->faker)); + } + if (file_exists($providerPath.'/'.$locale.'/Person.php')) { + $person = "\\Faker\\Provider\\$locale\\Person"; + $this->faker->addProvider(new $person($this->faker)); + } + if (file_exists($providerPath.'/'.$locale.'/Company.php')) { + $company = "\\Faker\\Provider\\$locale\\Company"; + $this->faker->addProvider(new $company($this->faker)); + } + } + + public function testPasswordIsValid() + { + $this->assertRegexp('/^.{6}$/', $this->faker->password(6, 6)); + } + + public function testSlugIsValid() + { + $pattern = '/^[a-z0-9-]+$/'; + $slug = $this->faker->slug(); + $this->assertSame(preg_match($pattern, $slug), 1); + } + + public function testUrlIsValid() + { + $url = $this->faker->url(); + $this->assertNotFalse(filter_var($url, FILTER_VALIDATE_URL)); + } + + public function testLocalIpv4() + { + $this->assertNotFalse(filter_var(Internet::localIpv4(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)); + } + + public function testIpv4() + { + $this->assertNotFalse(filter_var($this->faker->ipv4(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)); + } + + public function testIpv4NotLocalNetwork() + { + $this->assertNotRegExp('/\A1\./', $this->faker->ipv4()); + } + + public function testIpv4NotBroadcast() + { + $this->assertNotEquals('255.255.255.255', $this->faker->ipv4()); + } + + public function testIpv6() + { + $this->assertNotFalse(filter_var($this->faker->ipv6(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); + } + + public function testMacAddress() + { + $this->assertRegExp('/^([0-9A-F]{2}[:]){5}([0-9A-F]{2})$/i', Internet::macAddress()); + } +} diff --git a/lib/faker/test/Faker/Provider/LocalizationTest.php b/lib/faker/test/Faker/Provider/LocalizationTest.php new file mode 100755 index 0000000..347b135 --- /dev/null +++ b/lib/faker/test/Faker/Provider/LocalizationTest.php @@ -0,0 +1,26 @@ +assertNotNull($faker->name(), 'Localized Name Provider ' . $matches[1] . ' does not throw errors'); + } + } + + public function testLocalizedAddressProvidersDoNotThrowErrors() + { + foreach (glob(__DIR__ . '/../../../src/Faker/Provider/*/Address.php') as $localizedAddress) { + preg_match('#/([a-zA-Z_]+)/Address\.php#', $localizedAddress, $matches); + $faker = Factory::create($matches[1]); + $this->assertNotNull($faker->address(), 'Localized Address Provider ' . $matches[1] . ' does not throw errors'); + } + } +} diff --git a/lib/faker/test/Faker/Provider/LoremTest.php b/lib/faker/test/Faker/Provider/LoremTest.php new file mode 100755 index 0000000..62785d4 --- /dev/null +++ b/lib/faker/test/Faker/Provider/LoremTest.php @@ -0,0 +1,108 @@ +assertEquals('Word word word word.', TestableLorem::text(24)); + } + + public function testTextReturnsSentencesWhenAskedSizeLessThan100() + { + $this->assertEquals('This is a test sentence. This is a test sentence. This is a test sentence.', TestableLorem::text(99)); + } + + public function testTextReturnsParagraphsWhenAskedSizeGreaterOrEqualThanThan100() + { + $this->assertEquals('This is a test paragraph. It has three sentences. Exactly three.', TestableLorem::text(100)); + } + + public function testSentenceWithZeroNbWordsReturnsEmptyString() + { + $this->assertEquals('', Lorem::sentence(0)); + } + + public function testSentenceWithNegativeNbWordsReturnsEmptyString() + { + $this->assertEquals('', Lorem::sentence(-1)); + } + + public function testParagraphWithZeroNbSentencesReturnsEmptyString() + { + $this->assertEquals('', Lorem::paragraph(0)); + } + + public function testParagraphWithNegativeNbSentencesReturnsEmptyString() + { + $this->assertEquals('', Lorem::paragraph(-1)); + } + + public function testSentenceWithPositiveNbWordsReturnsAtLeastOneWord() + { + $sentence = Lorem::sentence(1); + + $this->assertGreaterThan(1, strlen($sentence)); + $this->assertGreaterThanOrEqual(1, count(explode(' ', $sentence))); + } + + public function testParagraphWithPositiveNbSentencesReturnsAtLeastOneWord() + { + $paragraph = Lorem::paragraph(1); + + $this->assertGreaterThan(1, strlen($paragraph)); + $this->assertGreaterThanOrEqual(1, count(explode(' ', $paragraph))); + } + + public function testWordssAsText() + { + $words = TestableLorem::words(2, true); + + $this->assertEquals('word word', $words); + } + + public function testSentencesAsText() + { + $sentences = TestableLorem::sentences(2, true); + + $this->assertEquals('This is a test sentence. This is a test sentence.', $sentences); + } + + public function testParagraphsAsText() + { + $paragraphs = TestableLorem::paragraphs(2, true); + + $expected = "This is a test paragraph. It has three sentences. Exactly three.\n\nThis is a test paragraph. It has three sentences. Exactly three."; + $this->assertEquals($expected, $paragraphs); + } +} + +class TestableLorem extends Lorem +{ + + public static function word() + { + return 'word'; + } + + public static function sentence($nbWords = 5, $variableNbWords = true) + { + return 'This is a test sentence.'; + } + + public static function paragraph($nbSentences = 3, $variableNbSentences = true) + { + return 'This is a test paragraph. It has three sentences. Exactly three.'; + } +} diff --git a/lib/faker/test/Faker/Provider/MiscellaneousTest.php b/lib/faker/test/Faker/Provider/MiscellaneousTest.php new file mode 100755 index 0000000..6a4c559 --- /dev/null +++ b/lib/faker/test/Faker/Provider/MiscellaneousTest.php @@ -0,0 +1,54 @@ +assertContains(Miscellaneous::boolean(), array(true, false)); + } + + public function testMd5() + { + $this->assertRegExp('/^[a-z0-9]{32}$/', Miscellaneous::md5()); + } + + public function testSha1() + { + $this->assertRegExp('/^[a-z0-9]{40}$/', Miscellaneous::sha1()); + } + + public function testSha256() + { + $this->assertRegExp('/^[a-z0-9]{64}$/', Miscellaneous::sha256()); + } + + public function testLocale() + { + $this->assertRegExp('/^[a-z]{2,3}_[A-Z]{2}$/', Miscellaneous::locale()); + } + + public function testCountryCode() + { + $this->assertRegExp('/^[A-Z]{2}$/', Miscellaneous::countryCode()); + } + + public function testCountryISOAlpha3() + { + $this->assertRegExp('/^[A-Z]{3}$/', Miscellaneous::countryISOAlpha3()); + } + + public function testLanguage() + { + $this->assertRegExp('/^[a-z]{2}$/', Miscellaneous::languageCode()); + } + + public function testCurrencyCode() + { + $this->assertRegExp('/^[A-Z]{3}$/', Miscellaneous::currencyCode()); + } +} diff --git a/lib/faker/test/Faker/Provider/PaymentTest.php b/lib/faker/test/Faker/Provider/PaymentTest.php new file mode 100755 index 0000000..4e22e2c --- /dev/null +++ b/lib/faker/test/Faker/Provider/PaymentTest.php @@ -0,0 +1,206 @@ +addProvider(new BaseProvider($faker)); + $faker->addProvider(new DateTimeProvider($faker)); + $faker->addProvider(new PersonProvider($faker)); + $faker->addProvider(new PaymentProvider($faker)); + $this->faker = $faker; + } + + public function localeDataProvider() + { + $providerPath = realpath(__DIR__ . '/../../../src/Faker/Provider'); + $localePaths = array_filter(glob($providerPath . '/*', GLOB_ONLYDIR)); + foreach ($localePaths as $path) { + $parts = explode('/', $path); + $locales[] = array($parts[count($parts) - 1]); + } + + return $locales; + } + + public function loadLocalProviders($locale) + { + $providerPath = realpath(__DIR__ . '/../../../src/Faker/Provider'); + if (file_exists($providerPath.'/'.$locale.'/Payment.php')) { + $payment = "\\Faker\\Provider\\$locale\\Payment"; + $this->faker->addProvider(new $payment($this->faker)); + } + } + + public function testCreditCardTypeReturnsValidVendorName() + { + $this->assertTrue(in_array($this->faker->creditCardType, array('Visa', 'MasterCard', 'American Express', 'Discover Card'))); + } + + public function creditCardNumberProvider() + { + return array( + array('Discover Card', '/^6011\d{12}$/'), + array('Visa', '/^4\d{12,15}$/'), + array('MasterCard', '/^5[1-5]\d{14}$/') + ); + } + + /** + * @dataProvider creditCardNumberProvider + */ + public function testCreditCardNumberReturnsValidCreditCardNumber($type, $regexp) + { + $cardNumber = $this->faker->creditCardNumber($type); + $this->assertRegExp($regexp, $cardNumber); + $this->assertTrue(Luhn::isValid($cardNumber)); + } + + public function testCreditCardNumberCanFormatOutput() + { + $this->assertRegExp('/^6011-\d{4}-\d{4}-\d{4}$/', $this->faker->creditCardNumber('Discover Card', true)); + } + + public function testCreditCardExpirationDateReturnsValidDateByDefault() + { + $expirationDate = $this->faker->creditCardExpirationDate; + $this->assertTrue(intval($expirationDate->format('U')) > strtotime('now')); + $this->assertTrue(intval($expirationDate->format('U')) < strtotime('+36 months')); + } + + public function testRandomCard() + { + $cardDetails = $this->faker->creditCardDetails; + $this->assertEquals(count($cardDetails), 4); + $this->assertEquals(array('type', 'number', 'name', 'expirationDate'), array_keys($cardDetails)); + } + + protected $ibanFormats = array( + 'AD' => '/^AD\d{2}\d{4}\d{4}[A-Z0-9]{12}$/', + 'AE' => '/^AE\d{2}\d{3}\d{16}$/', + 'AL' => '/^AL\d{2}\d{8}[A-Z0-9]{16}$/', + 'AT' => '/^AT\d{2}\d{5}\d{11}$/', + 'AZ' => '/^AZ\d{2}[A-Z]{4}[A-Z0-9]{20}$/', + 'BA' => '/^BA\d{2}\d{3}\d{3}\d{8}\d{2}$/', + 'BE' => '/^BE\d{2}\d{3}\d{7}\d{2}$/', + 'BG' => '/^BG\d{2}[A-Z]{4}\d{4}\d{2}[A-Z0-9]{8}$/', + 'BH' => '/^BH\d{2}[A-Z]{4}[A-Z0-9]{14}$/', + 'BR' => '/^BR\d{2}\d{8}\d{5}\d{10}[A-Z]{1}[A-Z0-9]{1}$/', + 'CH' => '/^CH\d{2}\d{5}[A-Z0-9]{12}$/', + 'CR' => '/^CR\d{2}\d{3}\d{14}$/', + 'CY' => '/^CY\d{2}\d{3}\d{5}[A-Z0-9]{16}$/', + 'CZ' => '/^CZ\d{2}\d{4}\d{6}\d{10}$/', + 'DE' => '/^DE\d{2}\d{8}\d{10}$/', + 'DK' => '/^DK\d{2}\d{4}\d{9}\d{1}$/', + 'DO' => '/^DO\d{2}[A-Z0-9]{4}\d{20}$/', + 'EE' => '/^EE\d{2}\d{2}\d{2}\d{11}\d{1}$/', + 'ES' => '/^ES\d{2}\d{4}\d{4}\d{1}\d{1}\d{10}$/', + 'FR' => '/^FR\d{2}\d{5}\d{5}[A-Z0-9]{11}\d{2}$/', + 'GB' => '/^GB\d{2}[A-Z]{4}\d{6}\d{8}$/', + 'GE' => '/^GE\d{2}[A-Z]{2}\d{16}$/', + 'GI' => '/^GI\d{2}[A-Z]{4}[A-Z0-9]{15}$/', + 'GR' => '/^GR\d{2}\d{3}\d{4}[A-Z0-9]{16}$/', + 'GT' => '/^GT\d{2}[A-Z0-9]{4}[A-Z0-9]{20}$/', + 'HR' => '/^HR\d{2}\d{7}\d{10}$/', + 'HU' => '/^HU\d{2}\d{3}\d{4}\d{1}\d{15}\d{1}$/', + 'IE' => '/^IE\d{2}[A-Z]{4}\d{6}\d{8}$/', + 'IL' => '/^IL\d{2}\d{3}\d{3}\d{13}$/', + 'IS' => '/^IS\d{2}\d{4}\d{2}\d{6}\d{10}$/', + 'IT' => '/^IT\d{2}[A-Z]{1}\d{5}\d{5}[A-Z0-9]{12}$/', + 'KW' => '/^KW\d{2}[A-Z]{4}\d{22}$/', + 'KZ' => '/^KZ\d{2}\d{3}[A-Z0-9]{13}$/', + 'LB' => '/^LB\d{2}\d{4}[A-Z0-9]{20}$/', + 'LI' => '/^LI\d{2}\d{5}[A-Z0-9]{12}$/', + 'LT' => '/^LT\d{2}\d{5}\d{11}$/', + 'LU' => '/^LU\d{2}\d{3}[A-Z0-9]{13}$/', + 'LV' => '/^LV\d{2}[A-Z]{4}[A-Z0-9]{13}$/', + 'MC' => '/^MC\d{2}\d{5}\d{5}[A-Z0-9]{11}\d{2}$/', + 'MD' => '/^MD\d{2}[A-Z0-9]{2}[A-Z0-9]{18}$/', + 'ME' => '/^ME\d{2}\d{3}\d{13}\d{2}$/', + 'MK' => '/^MK\d{2}\d{3}[A-Z0-9]{10}\d{2}$/', + 'MR' => '/^MR\d{2}\d{5}\d{5}\d{11}\d{2}$/', + 'MT' => '/^MT\d{2}[A-Z]{4}\d{5}[A-Z0-9]{18}$/', + 'MU' => '/^MU\d{2}[A-Z]{4}\d{2}\d{2}\d{12}\d{3}[A-Z]{3}$/', + 'NL' => '/^NL\d{2}[A-Z]{4}\d{10}$/', + 'NO' => '/^NO\d{2}\d{4}\d{6}\d{1}$/', + 'PK' => '/^PK\d{2}[A-Z]{4}[A-Z0-9]{16}$/', + 'PL' => '/^PL\d{2}\d{8}\d{16}$/', + 'PS' => '/^PS\d{2}[A-Z]{4}[A-Z0-9]{21}$/', + 'PT' => '/^PT\d{2}\d{4}\d{4}\d{11}\d{2}$/', + 'RO' => '/^RO\d{2}[A-Z]{4}[A-Z0-9]{16}$/', + 'RS' => '/^RS\d{2}\d{3}\d{13}\d{2}$/', + 'SA' => '/^SA\d{2}\d{2}[A-Z0-9]{18}$/', + 'SE' => '/^SE\d{2}\d{3}\d{16}\d{1}$/', + 'SI' => '/^SI\d{2}\d{5}\d{8}\d{2}$/', + 'SK' => '/^SK\d{2}\d{4}\d{6}\d{10}$/', + 'SM' => '/^SM\d{2}[A-Z]{1}\d{5}\d{5}[A-Z0-9]{12}$/', + 'TN' => '/^TN\d{2}\d{2}\d{3}\d{13}\d{2}$/', + 'TR' => '/^TR\d{2}\d{5}\d{1}[A-Z0-9]{16}$/', + 'VG' => '/^VG\d{2}[A-Z]{4}\d{16}$/', + ); + + /** + * @dataProvider localeDataProvider + */ + public function testBankAccountNumber($locale) + { + $parts = explode('_', $locale); + $countryCode = array_pop($parts); + + if (!isset($this->ibanFormats[$countryCode])) { + // No IBAN format available + return; + } + + $this->loadLocalProviders($locale); + + try { + $iban = $this->faker->bankAccountNumber; + } catch (\InvalidArgumentException $e) { + // Not implemented, nothing to test + $this->markTestSkipped("bankAccountNumber not implemented for $locale"); + return; + } + + // Test format + $this->assertRegExp($this->ibanFormats[$countryCode], $iban); + + // Test checksum + $this->assertTrue(Iban::isValid($iban), "Checksum for $iban is invalid"); + } + + public function ibanFormatProvider() + { + $return = array(); + foreach ($this->ibanFormats as $countryCode => $regex) { + $return[] = array($countryCode, $regex); + } + return $return; + } + /** + * @dataProvider ibanFormatProvider + */ + public function testIban($countryCode, $regex) + { + $iban = $this->faker->iban($countryCode); + + // Test format + $this->assertRegExp($regex, $iban); + + // Test checksum + $this->assertTrue(Iban::isValid($iban), "Checksum for $iban is invalid"); + } +} diff --git a/lib/faker/test/Faker/Provider/PersonTest.php b/lib/faker/test/Faker/Provider/PersonTest.php new file mode 100755 index 0000000..a8d1c0f --- /dev/null +++ b/lib/faker/test/Faker/Provider/PersonTest.php @@ -0,0 +1,86 @@ +addProvider(new Person($faker)); + $this->assertContains($faker->firstName($gender), $expected); + } + + public function firstNameProvider() + { + return array( + array(null, array('John', 'Jane')), + array('foobar', array('John', 'Jane')), + array('male', array('John')), + array('female', array('Jane')), + ); + } + + public function testFirstNameMale() + { + $this->assertContains(Person::firstNameMale(), array('John')); + } + + public function testFirstNameFemale() + { + $this->assertContains(Person::firstNameFemale(), array('Jane')); + } + + /** + * @dataProvider titleProvider + */ + public function testTitle($gender, $expected) + { + $faker = new Generator(); + $faker->addProvider(new Person($faker)); + $this->assertContains($faker->title($gender), $expected); + } + + public function titleProvider() + { + return array( + array(null, array('Mr.', 'Mrs.', 'Ms.', 'Miss', 'Dr.', 'Prof.')), + array('foobar', array('Mr.', 'Mrs.', 'Ms.', 'Miss', 'Dr.', 'Prof.')), + array('male', array('Mr.', 'Dr.', 'Prof.')), + array('female', array('Mrs.', 'Ms.', 'Miss', 'Dr.', 'Prof.')), + ); + } + + public function testTitleMale() + { + $this->assertContains(Person::titleMale(), array('Mr.', 'Dr.', 'Prof.')); + } + + public function testTitleFemale() + { + $this->assertContains(Person::titleFemale(), array('Mrs.', 'Ms.', 'Miss', 'Dr.', 'Prof.')); + } + + public function testLastNameReturnsDoe() + { + $faker = new Generator(); + $faker->addProvider(new Person($faker)); + $this->assertEquals($faker->lastName(), 'Doe'); + } + + public function testNameReturnsFirstNameAndLastName() + { + $faker = new Generator(); + $faker->addProvider(new Person($faker)); + $this->assertContains($faker->name(), array('John Doe', 'Jane Doe')); + $this->assertContains($faker->name('foobar'), array('John Doe', 'Jane Doe')); + $this->assertContains($faker->name('male'), array('John Doe')); + $this->assertContains($faker->name('female'), array('Jane Doe')); + } +} diff --git a/lib/faker/test/Faker/Provider/ProviderOverrideTest.php b/lib/faker/test/Faker/Provider/ProviderOverrideTest.php new file mode 100755 index 0000000..68f75ae --- /dev/null +++ b/lib/faker/test/Faker/Provider/ProviderOverrideTest.php @@ -0,0 +1,189 @@ + + */ + +namespace Faker\Test\Provider; + +use Faker; + +/** + * Class ProviderOverrideTest + * + * @package Faker\Test\Provider + * + * This class tests a large portion of all locale specific providers. It does not test the entire stack, because each + * locale specific provider (can) has specific implementations. The goal of this test is to test the common denominator + * and to try to catch possible invalid multi-byte sequences. + */ +class ProviderOverrideTest extends \PHPUnit_Framework_TestCase +{ + /** + * Constants with regular expression patterns for testing the output. + * + * Regular expressions are sensitive for malformed strings (e.g.: strings with incorrect encodings) so by using + * PCRE for the tests, even though they seem fairly pointless, we test for incorrect encodings also. + */ + const TEST_STRING_REGEX = '/.+/u'; + + /** + * Slightly more specific for e-mail, the point isn't to properly validate e-mails. + */ + const TEST_EMAIL_REGEX = '/^(.+)@(.+)$/ui'; + + /** + * @dataProvider localeDataProvider + * @param string $locale + */ + public function testAddress($locale = null) + { + $faker = Faker\Factory::create($locale); + + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->city); + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->postcode); + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->address); + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->country); + } + + + /** + * @dataProvider localeDataProvider + * @param string $locale + */ + public function testCompany($locale = null) + { + $faker = Faker\Factory::create($locale); + + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->company); + } + + + /** + * @dataProvider localeDataProvider + * @param string $locale + */ + public function testDateTime($locale = null) + { + $faker = Faker\Factory::create($locale); + + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->century); + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->timezone); + } + + + /** + * @dataProvider localeDataProvider + * @param string $locale + */ + public function testInternet($locale = null) + { + $faker = Faker\Factory::create($locale); + + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->userName); + + $this->assertRegExp(static::TEST_EMAIL_REGEX, $faker->email); + $this->assertRegExp(static::TEST_EMAIL_REGEX, $faker->safeEmail); + $this->assertRegExp(static::TEST_EMAIL_REGEX, $faker->freeEmail); + $this->assertRegExp(static::TEST_EMAIL_REGEX, $faker->companyEmail); + } + + + /** + * @dataProvider localeDataProvider + * @param string $locale + */ + public function testPerson($locale = null) + { + $faker = Faker\Factory::create($locale); + + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->name); + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->title); + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->firstName); + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->lastName); + } + + + /** + * @dataProvider localeDataProvider + * @param string $locale + */ + public function testPhoneNumber($locale = null) + { + $faker = Faker\Factory::create($locale); + + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->phoneNumber); + } + + + /** + * @dataProvider localeDataProvider + * @param string $locale + */ + public function testUserAgent($locale = null) + { + $faker = Faker\Factory::create($locale); + + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->userAgent); + } + + + /** + * @dataProvider localeDataProvider + * + * @param null $locale + * @param string $locale + */ + public function testUuid($locale = null) + { + $faker = Faker\Factory::create($locale); + + $this->assertRegExp(static::TEST_STRING_REGEX, $faker->uuid); + } + + + /** + * @return array + */ + public function localeDataProvider() + { + $locales = $this->getAllLocales(); + $data = array(); + + foreach ($locales as $locale) { + $data[] = array( + $locale + ); + } + + return $data; + } + + + /** + * Returns all locales as array values + * + * @return array + */ + private function getAllLocales() + { + static $locales = array(); + + if ( ! empty($locales)) { + return $locales; + } + + // Finding all PHP files in the xx_XX directories + $providerDir = __DIR__ .'/../../../src/Faker/Provider'; + foreach (glob($providerDir .'/*_*/*.php') as $file) { + $localisation = basename(dirname($file)); + + if (isset($locales[ $localisation ])) { + continue; + } + + $locales[ $localisation ] = $localisation; + } + + return $locales; + } +} diff --git a/lib/faker/test/Faker/Provider/TextTest.php b/lib/faker/test/Faker/Provider/TextTest.php new file mode 100755 index 0000000..3baf49f --- /dev/null +++ b/lib/faker/test/Faker/Provider/TextTest.php @@ -0,0 +1,54 @@ +addProvider(new Text($generator)); + $generator->seed(0); + + $lengths = array(10, 20, 50, 70, 90, 120, 150, 200, 500); + + foreach ($lengths as $length) { + $this->assertLessThan($length, $generator->realText($length)); + } + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testTextMaxIndex() + { + $generator = new Generator(); + $generator->addProvider(new Text($generator)); + $generator->seed(0); + $generator->realText(200, 11); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testTextMinIndex() + { + $generator = new Generator(); + $generator->addProvider(new Text($generator)); + $generator->seed(0); + $generator->realText(200, 0); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testTextMinLength() + { + $generator = new Generator(); + $generator->addProvider(new Text($generator)); + $generator->seed(0); + $generator->realText(9); + } +} diff --git a/lib/faker/test/Faker/Provider/UserAgentTest.php b/lib/faker/test/Faker/Provider/UserAgentTest.php new file mode 100755 index 0000000..b45b9f8 --- /dev/null +++ b/lib/faker/test/Faker/Provider/UserAgentTest.php @@ -0,0 +1,38 @@ +assertNotNull(UserAgent::userAgent()); + } + + public function testFirefoxUserAgent() + { + $this->stringContains(' Firefox/', UserAgent::firefox()); + } + + public function testSafariUserAgent() + { + $this->stringContains('Safari/', UserAgent::safari()); + } + + public function testInternetExplorerUserAgent() + { + $this->assertStringStartsWith('Mozilla/5.0 (compatible; MSIE ', UserAgent::internetExplorer()); + } + + public function testOperaUserAgent() + { + $this->assertStringStartsWith('Opera/', UserAgent::opera()); + } + + public function testChromeUserAgent() + { + $this->stringContains('(KHTML, like Gecko) Chrome/', UserAgent::chrome()); + } +} diff --git a/lib/faker/test/Faker/Provider/UuidTest.php b/lib/faker/test/Faker/Provider/UuidTest.php new file mode 100755 index 0000000..fceb8df --- /dev/null +++ b/lib/faker/test/Faker/Provider/UuidTest.php @@ -0,0 +1,26 @@ +assertTrue($this->isUuid($uuid)); + } + + public function testUuidExpectedSeed() + { + mt_srand(123); + $this->assertEquals("8e2e0c84-50dd-367c-9e66-f3ab455c78d6", BaseProvider::uuid()); + $this->assertEquals("073eb60a-902c-30ab-93d0-a94db371f6c8", BaseProvider::uuid()); + } + + protected function isUuid($uuid) + { + return is_string($uuid) && (bool) preg_match('/^[a-f0-9]{8,8}-(?:[a-f0-9]{4,4}-){3,3}[a-f0-9]{12,12}$/i', $uuid); + } +} diff --git a/lib/faker/test/Faker/Provider/at_AT/PaymentTest.php b/lib/faker/test/Faker/Provider/at_AT/PaymentTest.php new file mode 100755 index 0000000..afc8c27 --- /dev/null +++ b/lib/faker/test/Faker/Provider/at_AT/PaymentTest.php @@ -0,0 +1,30 @@ +addProvider(new Payment($faker)); + $this->faker = $faker; + } + + public function testVatIsValid() + { + $vat = $this->faker->vat(); + $unspacedVat = $this->faker->vat(false); + $this->assertRegExp('/^(AT U\d{8})$/', $vat); + $this->assertRegExp('/^(ATU\d{8})$/', $unspacedVat); + } +} diff --git a/lib/faker/test/Faker/Provider/be_BE/PaymentTest.php b/lib/faker/test/Faker/Provider/be_BE/PaymentTest.php new file mode 100755 index 0000000..d253b05 --- /dev/null +++ b/lib/faker/test/Faker/Provider/be_BE/PaymentTest.php @@ -0,0 +1,30 @@ +addProvider(new Payment($faker)); + $this->faker = $faker; + } + + public function testVatIsValid() + { + $vat = $this->faker->vat(); + $unspacedVat = $this->faker->vat(false); + $this->assertRegExp('/^(BE 0\d{9})$/', $vat); + $this->assertRegExp('/^(BE0\d{9})$/', $unspacedVat); + } +} diff --git a/lib/faker/test/Faker/Provider/bg_BG/PaymentTest.php b/lib/faker/test/Faker/Provider/bg_BG/PaymentTest.php new file mode 100755 index 0000000..31c6325 --- /dev/null +++ b/lib/faker/test/Faker/Provider/bg_BG/PaymentTest.php @@ -0,0 +1,30 @@ +addProvider(new Payment($faker)); + $this->faker = $faker; + } + + public function testVatIsValid() + { + $vat = $this->faker->vat(); + $unspacedVat = $this->faker->vat(false); + $this->assertRegExp('/^(BG \d{9,10})$/', $vat); + $this->assertRegExp('/^(BG\d{9,10})$/', $unspacedVat); + } +} diff --git a/lib/faker/test/Faker/Provider/cs_CZ/PersonTest.php b/lib/faker/test/Faker/Provider/cs_CZ/PersonTest.php new file mode 100755 index 0000000..bd33c3d --- /dev/null +++ b/lib/faker/test/Faker/Provider/cs_CZ/PersonTest.php @@ -0,0 +1,46 @@ +addProvider(new Person($faker)); + $faker->addProvider(new Miscellaneous($faker)); + + for ($i = 0; $i < 1000; $i++) { + $birthNumber = $faker->birthNumber(); + $birthNumber = str_replace('/', '', $birthNumber); + + // check date + $year = intval(substr($birthNumber, 0, 2), 10); + $month = intval(substr($birthNumber, 2, 2), 10); + $day = intval(substr($birthNumber, 4, 2), 10); + + // make 4 digit year from 2 digit representation + $year += $year < 54 ? 2000 : 1900; + + // adjust special cases for month + if ($month > 50) $month -= 50; + if ($year >= 2004 && $month > 20) $month -= 20; + + $this->assertTrue(checkdate($month, $day, $year), "Birth number $birthNumber: date $year/$month/$day is invalid."); + + // check CRC if presented + if (strlen($birthNumber) == 10) { + $crc = intval(substr($birthNumber, -1), 10); + $refCrc = intval(substr($birthNumber, 0, -1), 10) % 11; + if ($refCrc == 10) { + $refCrc = 0; + } + $this->assertEquals($crc, $refCrc, "Birth number $birthNumber: checksum $crc doesn't match expected $refCrc.");; + } + } + } +} diff --git a/lib/faker/test/Faker/Provider/de_AT/InternetTest.php b/lib/faker/test/Faker/Provider/de_AT/InternetTest.php new file mode 100755 index 0000000..91ce5ca --- /dev/null +++ b/lib/faker/test/Faker/Provider/de_AT/InternetTest.php @@ -0,0 +1,32 @@ +addProvider(new Person($faker)); + $faker->addProvider(new Internet($faker)); + $faker->addProvider(new Company($faker)); + $this->faker = $faker; + } + + public function testEmailIsValid() + { + $email = $this->faker->email(); + $this->assertNotFalse(filter_var($email, FILTER_VALIDATE_EMAIL)); + } +} diff --git a/lib/faker/test/Faker/Provider/de_AT/PhoneNumberTest.php b/lib/faker/test/Faker/Provider/de_AT/PhoneNumberTest.php new file mode 100755 index 0000000..2d61ad5 --- /dev/null +++ b/lib/faker/test/Faker/Provider/de_AT/PhoneNumberTest.php @@ -0,0 +1,28 @@ +addProvider(new PhoneNumber($faker)); + $this->faker = $faker; + } + + public function testPhoneNumberFormat() + { + $number = $this->faker->phoneNumber; + $this->assertRegExp('/^06\d{2} \d{7}|\+43 \d{4} \d{4}(-\d{2})?$/', $number); + } +} diff --git a/lib/faker/test/Faker/Provider/en_US/PhoneNumberTest.php b/lib/faker/test/Faker/Provider/en_US/PhoneNumberTest.php new file mode 100755 index 0000000..ae2951a --- /dev/null +++ b/lib/faker/test/Faker/Provider/en_US/PhoneNumberTest.php @@ -0,0 +1,84 @@ +addProvider(new PhoneNumber($faker)); + $this->faker = $faker; + } + + public function testPhoneNumber() + { + for ($i = 0; $i < 100; $i++) { + $number = $this->faker->phoneNumber; + $baseNumber = preg_replace('/ *x.*$/', '', $number); // Remove possible extension + $digits = array_values(array_filter(str_split($baseNumber), 'ctype_digit')); + + // Prefix '1' allowed + if (count($digits) === 11) { + $this->assertEquals('1', $digits[0]); + $digits = array_slice($digits, 1); + } + + // 10 digits + $this->assertEquals(10, count($digits)); + + // Last two digits of area code cannot be identical + $this->assertNotEquals($digits[1], $digits[2]); + + // Last two digits of exchange code cannot be 1 + if ($digits[4] === 1) { + $this->assertNotEquals($digits[4], $digits[5]); + } + + // Test format + $this->assertRegExp('/^(\+?1)?([ -.]*\d{3}[ -.]*| *\(\d{3}\) *)\d{3}[-.]?\d{4}$/', $baseNumber); + } + } + + public function testTollFreeAreaCode() + { + $this->assertContains($this->faker->tollFreeAreaCode, array(800, 822, 833, 844, 855, 866, 877, 888, 880, 887, 889)); + } + + public function testTollFreePhoneNumber() + { + for ($i = 0; $i < 100; $i++) { + $number = $this->faker->tollFreePhoneNumber; + $digits = array_values(array_filter(str_split($number), 'ctype_digit')); + + // Prefix '1' allowed + if (count($digits) === 11) { + $this->assertEquals('1', $digits[0]); + $digits = array_slice($digits, 1); + } + + // 10 digits + $this->assertEquals(10, count($digits)); + + $areaCode = $digits[0] . $digits[1] . $digits[2]; + $this->assertContains($areaCode, array('800', '822', '833', '844', '855', '866', '877', '888', '880', '887', '889')); + + // Last two digits of exchange code cannot be 1 + if ($digits[4] === 1) { + $this->assertNotEquals($digits[4], $digits[5]); + } + + // Test format + $this->assertRegExp('/^(\+?1)?([ -.]*\d{3}[ -.]*| *\(\d{3}\) *)\d{3}[-.]?\d{4}$/', $number); + } + } +} diff --git a/lib/faker/test/Faker/Provider/fr_FR/CompanyTest.php b/lib/faker/test/Faker/Provider/fr_FR/CompanyTest.php new file mode 100755 index 0000000..5486cf9 --- /dev/null +++ b/lib/faker/test/Faker/Provider/fr_FR/CompanyTest.php @@ -0,0 +1,74 @@ +addProvider(new Company($faker)); + $this->faker = $faker; + } + + public function testSiretReturnsAValidSiret() + { + $siret = $this->faker->siret(false); + $this->assertRegExp("/^\d{14}$/", $siret); + $this->assertTrue(Luhn::isValid($siret)); + } + + public function testSiretReturnsAWellFormattedSiret() + { + $siret = $this->faker->siret(); + $this->assertRegExp("/^\d{3}\s\d{3}\s\d{3}\s\d{5}$/", $siret); + $siret = str_replace(' ', '', $siret); + $this->assertTrue(Luhn::isValid($siret)); + } + + public function testSirenReturnsAValidSiren() + { + $siren = $this->faker->siren(false); + $this->assertRegExp("/^\d{9}$/", $siren); + $this->assertTrue(Luhn::isValid($siren)); + } + + public function testSirenReturnsAWellFormattedSiren() + { + $siren = $this->faker->siren(); + $this->assertRegExp("/^\d{3}\s\d{3}\s\d{3}$/", $siren); + $siren = str_replace(' ', '', $siren); + $this->assertTrue(Luhn::isValid($siren)); + } + + public function testCatchPhraseReturnsValidCatchPhrase() + { + $this->assertTrue(TestableCompany::isCatchPhraseValid($this->faker->catchPhrase())); + } + + public function testIsCatchPhraseValidReturnsFalseWhenAWordsAppearsTwice() + { + $isCatchPhraseValid = TestableCompany::isCatchPhraseValid('La sécurité de rouler en toute sécurité'); + $this->assertFalse($isCatchPhraseValid); + } + + public function testIsCatchPhraseValidReturnsTrueWhenNoWordAppearsTwice() + { + $isCatchPhraseValid = TestableCompany::isCatchPhraseValid('La sécurité de rouler en toute simplicité'); + $this->assertTrue($isCatchPhraseValid); + } +} + +class TestableCompany extends Company +{ + public static function isCatchPhraseValid($catchPhrase) + { + return parent::isCatchPhraseValid($catchPhrase); + } +} diff --git a/lib/faker/test/Faker/Provider/id_ID/PersonTest.php b/lib/faker/test/Faker/Provider/id_ID/PersonTest.php new file mode 100755 index 0000000..abd039f --- /dev/null +++ b/lib/faker/test/Faker/Provider/id_ID/PersonTest.php @@ -0,0 +1,40 @@ +addProvider(new Person($faker)); + $this->faker = $faker; + } + + public function testIfFirstNameMaleCanReturnData() + { + $firstNameMale = $this->faker->firstNameMale(); + $this->assertNotEmpty($firstNameMale); + } + + public function testIfLastNameMaleCanReturnData() + { + $lastNameMale = $this->faker->lastNameMale(); + $this->assertNotEmpty($lastNameMale); + } + + public function testIfFirstNameFemaleCanReturnData() + { + $firstNameFemale = $this->faker->firstNameFemale(); + $this->assertNotEmpty($firstNameFemale); + } + + public function testIfLastNameFemaleCanReturnData() + { + $lastNameFemale = $this->faker->lastNameFemale(); + $this->assertNotEmpty($lastNameFemale); + } +} diff --git a/lib/faker/test/Faker/Provider/ja_JP/PersonTest.php b/lib/faker/test/Faker/Provider/ja_JP/PersonTest.php new file mode 100755 index 0000000..97fc566 --- /dev/null +++ b/lib/faker/test/Faker/Provider/ja_JP/PersonTest.php @@ -0,0 +1,36 @@ +addProvider(new Person($faker)); + $faker->seed(1); + + $this->assertEquals('アオタ ミノル', $faker->kanaName); + } + + public function testFirstKanaNameReturnsHaruka() + { + $faker = new Generator(); + $faker->addProvider(new Person($faker)); + $faker->seed(1); + + $this->assertEquals('ハルカ', $faker->firstKanaName); + } + + public function testLastKanaNameReturnsNakajima() + { + $faker = new Generator(); + $faker->addProvider(new Person($faker)); + $faker->seed(1); + + $this->assertEquals('ナカジマ', $faker->lastKanaName); + } +} diff --git a/lib/faker/test/Faker/Provider/pt_BR/CompanyTest.php b/lib/faker/test/Faker/Provider/pt_BR/CompanyTest.php new file mode 100755 index 0000000..f59142b --- /dev/null +++ b/lib/faker/test/Faker/Provider/pt_BR/CompanyTest.php @@ -0,0 +1,25 @@ +addProvider(new Company($faker)); + $this->faker = $faker; + } + + public function testCnpjFormatIsValid() + { + $cnpj = $this->faker->cnpj(false); + $this->assertRegExp('/\d{8}\d{4}\d{2}/', $cnpj); + $cnpj = $this->faker->cnpj(true); + $this->assertRegExp('/\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}/', $cnpj); + } +} diff --git a/lib/faker/test/Faker/Provider/pt_BR/PersonTest.php b/lib/faker/test/Faker/Provider/pt_BR/PersonTest.php new file mode 100755 index 0000000..767c188 --- /dev/null +++ b/lib/faker/test/Faker/Provider/pt_BR/PersonTest.php @@ -0,0 +1,33 @@ +addProvider(new Person($faker)); + $this->faker = $faker; + } + + public function testCpfFormatIsValid() + { + $cpf = $this->faker->cpf(false); + $this->assertRegExp('/\d{9}\d{2}/', $cpf); + $cpf = $this->faker->cpf(true); + $this->assertRegExp('/\d{3}\.\d{3}\.\d{3}-\d{2}/', $cpf); + } + + public function testRgFormatIsValid() + { + $rg = $this->faker->rg(false); + $this->assertRegExp('/\d{8}\d/', $rg); + $rg = $this->faker->rg(true); + $this->assertRegExp('/\d{2}\.\d{3}\.\d{3}-[0-9X]/', $rg); + } +} diff --git a/lib/faker/test/Faker/Provider/pt_PT/AddressTest.php b/lib/faker/test/Faker/Provider/pt_PT/AddressTest.php new file mode 100755 index 0000000..d2adc15 --- /dev/null +++ b/lib/faker/test/Faker/Provider/pt_PT/AddressTest.php @@ -0,0 +1,30 @@ +addProvider(new Address($faker)); + $this->faker = $faker; + } + + public function testPostCodeIsValid() + { + $main = '[1-9]{1}[0-9]{2}[0,1,4,5,9]{1}'; + $pattern = "/^($main)|($main-[0-9]{3})+$/"; + $postcode = $this->faker->postcode(); + $this->assertSame(preg_match($pattern, $postcode), 1, $postcode); + } +} diff --git a/lib/faker/test/Faker/Provider/pt_PT/PersonTest.php b/lib/faker/test/Faker/Provider/pt_PT/PersonTest.php new file mode 100755 index 0000000..9bfb7a2 --- /dev/null +++ b/lib/faker/test/Faker/Provider/pt_PT/PersonTest.php @@ -0,0 +1,52 @@ +addProvider(new Person($faker)); + $this->faker = $faker; + } + + public function testTaxpayerIdentificationNumberIsValid() + { + $tin = $this->faker->taxpayerIdentificationNumber(); + $this->assertTrue($this->isValidTin($tin), $tin); + } + + /** + * + * @link http://pt.wikipedia.org/wiki/N%C3%BAmero_de_identifica%C3%A7%C3%A3o_fiscal + * + * @param type $tin + * + * @return boolean + */ + public static function isValidTin($tin) + { + $regex = '(([1,2,3,5,6,8]{1}[0-9]{8})|((45)|(70)|(71)|(72)|(77)|(79)|(90|(98|(99))))[0-9]{7})'; + if (is_null($tin) || !is_numeric($tin) || !strlen($tin) == 9 || preg_match("/$regex/", $tin) !== 1) { + return false; + } + $n = str_split($tin); + // cd - Control Digit + $cd = ($n[0] * 9 + $n[1] * 8 + $n[2] * 7 + $n[3] * 6 + $n[4] * 5 + $n[5] * 4 + $n[6] * 3 + $n[7] * 2) % 11; + if ($cd === 0 || $cd === 1) { + $cd = 0; + } else { + $cd = 11 - $cd; + } + if ($cd === intval($n[8])) { + return true; + } + + return false; + } +} diff --git a/lib/faker/test/Faker/Provider/pt_PT/PhoneNumberTest.php b/lib/faker/test/Faker/Provider/pt_PT/PhoneNumberTest.php new file mode 100755 index 0000000..04b2f63 --- /dev/null +++ b/lib/faker/test/Faker/Provider/pt_PT/PhoneNumberTest.php @@ -0,0 +1,25 @@ +addProvider(new PhoneNumber($faker)); + $this->faker = $faker; + } + + public function testPhoneNumberReturnsPhoneNumberWithOrWithoutPrefix() + { + $this->assertRegExp('/^(9[1,2,3,6][0-9]{7})|(2[0-9]{8})|(\+351 [2][0-9]{8})|(\+351 9[1,2,3,6][0-9]{7})/', $this->faker->phoneNumber()); + } + public function testMobileNumberReturnsMobileNumberWithOrWithoutPrefix() + { + $this->assertRegExp('/^(9[1,2,3,6][0-9]{7})/', $this->faker->mobileNumber()); + } +} diff --git a/lib/faker/test/Faker/Provider/ro_RO/PersonTest.php b/lib/faker/test/Faker/Provider/ro_RO/PersonTest.php new file mode 100755 index 0000000..5816b63 --- /dev/null +++ b/lib/faker/test/Faker/Provider/ro_RO/PersonTest.php @@ -0,0 +1,95 @@ +seed(1); + $faker->addProvider(new DateTime($faker)); + $faker->addProvider(new Person($faker)); + $this->faker = $faker; + } + + public function testCnpReturnsValidCnp() + { + $cnp = $this->faker->cnp; + $this->assertTrue($this->isValidCnp($cnp)); + } + + public function testCnpReturnsMaleCnp() + { + $cnp = $this->faker->cnp('m'); + $this->assertRegExp('/^[1357]\d{12}$/', $cnp); + } + + public function testCnpReturnsFemaleCnp() + { + $cnp = $this->faker->cnp('f'); + $this->assertRegExp('/^[2468]\d{12}$/', $cnp); + } + + public function testCnpReturns1800sCnp() + { + $cnp = $this->faker->cnp(null, 1800); + $this->assertRegExp('/^[34]\d{12}$/', $cnp); + } + + public function testCnpReturns1900sCnp() + { + $cnp = $this->faker->cnp(null, 1900); + $this->assertRegExp('/^[12]\d{12}$/', $cnp); + } + + public function testCnpReturns2000sCnp() + { + $cnp = $this->faker->cnp(null, 2000); + $this->assertRegExp('/^[56]\d{12}$/', $cnp); + } + + public function testCnpReturnsBrasovCnp() + { + $cnp = $this->faker->cnp(null, null, 'BV'); + $this->assertRegExp('/^\d{7}08\d{4}$/', $cnp); + } + + public function testCnpReturns2000sClujFemaleCnp() + { + $cnp = $this->faker->cnp('f', 2000, 'CJ'); + $this->assertRegExp('/^6\d{6}12\d{4}$/', $cnp); + } + + protected function isValidCnp($cnp) + { + if ( + is_string($cnp) + && (bool) preg_match(static::TEST_CNP_REGEX, $cnp) + && checkdate(substr($cnp, 3, 2), substr($cnp, 5, 2), substr($cnp, 1, 2)) + ){ + $checkNumber = 279146358279; + + $checksum = 0; + foreach (range(0, 11) as $digit) { + $checksum += substr($cnp, $digit, 1) * substr($checkNumber, $digit, 1); + } + $checksum = $checksum % 11; + + if ( + ($checksum < 10 && $checksum == substr($cnp, -1)) + || ($checksum == 10 && substr($cnp, -1) == 1) + ){ + return true; + } + } + + return false; + } +} diff --git a/lib/faker/test/Faker/Provider/ro_RO/PhoneNumberTest.php b/lib/faker/test/Faker/Provider/ro_RO/PhoneNumberTest.php new file mode 100755 index 0000000..97314d5 --- /dev/null +++ b/lib/faker/test/Faker/Provider/ro_RO/PhoneNumberTest.php @@ -0,0 +1,31 @@ +addProvider(new PhoneNumber($faker)); + $this->faker = $faker; + } + + public function testPhoneNumberReturnsNormalPhoneNumber() + { + $this->assertRegExp('/^0(?:[23][13-7]|7\d)\d{7}$/', $this->faker->phoneNumber()); + } + + public function testTollFreePhoneNumberReturnsTollFreePhoneNumber() + { + $this->assertRegExp('/^08(?:0[1267]|70)\d{6}$/', $this->faker->tollFreePhoneNumber()); + } + + public function testPremiumRatePhoneNumberReturnsPremiumRatePhoneNumber() + { + $this->assertRegExp('/^090[036]\d{6}$/', $this->faker->premiumRatePhoneNumber()); + } +} diff --git a/lib/faker/test/Faker/Provider/sv_SE/PersonTest.php b/lib/faker/test/Faker/Provider/sv_SE/PersonTest.php new file mode 100755 index 0000000..623723a --- /dev/null +++ b/lib/faker/test/Faker/Provider/sv_SE/PersonTest.php @@ -0,0 +1,60 @@ +addProvider(new Person($faker)); + $this->faker = $faker; + } + + public function provideSeedAndExpectedReturn() + { + return array( + array(1, '720727', '720727-5798'), + array(2, '710414', '710414-5664'), + array(3, '591012', '591012-4519'), + array(4, '180307', '180307-0356'), + array(5, '820904', '820904-7748') + ); + } + + /** + * @dataProvider provideSeedAndExpectedReturn + */ + public function testPersonalIdentityNumberUsesBirthDateIfProvided($seed, $birthdate, $expected) + { + $faker = $this->faker; + $faker->seed($seed); + $pin = $faker->personalIdentityNumber(\DateTime::createFromFormat('ymd', $birthdate)); + $this->assertEquals($expected, $pin); + } + + public function testPersonalIdentityNumberGeneratesLuhnCompliantNumbers() + { + $pin = str_replace('-', '', $this->faker->personalIdentityNumber()); + $this->assertTrue(Luhn::isValid($pin)); + } + + public function testPersonalIdentityNumberGeneratesOddValuesForMales() + { + $pin = $this->faker->personalIdentityNumber(null, 'male'); + $this->assertEquals(1, $pin{9} % 2); + } + + public function testPersonalIdentityNumberGeneratesEvenValuesForFemales() + { + $pin = $this->faker->personalIdentityNumber(null, 'female'); + $this->assertEquals(0, $pin{9} % 2); + } +} diff --git a/lib/faker/test/Faker/Provider/uk_UA/AddressTest.php b/lib/faker/test/Faker/Provider/uk_UA/AddressTest.php new file mode 100755 index 0000000..a3e38d7 --- /dev/null +++ b/lib/faker/test/Faker/Provider/uk_UA/AddressTest.php @@ -0,0 +1,80 @@ +addProvider(new Address($faker)); + $this->faker = $faker; + } + + public function testPostCodeIsValid() + { + $main = '[0-9]{5}'; + $pattern = "/^($main)|($main-[0-9]{3})+$/"; + $postcode = $this->faker->postcode; + $this->assertRegExp($pattern, $postcode, 'Post code ' . $postcode . ' is wrong!'); + } + + public function testEmptySuffixes() + { + $this->assertEmpty($this->faker->citySuffix, 'City suffix should be empty!'); + $this->assertEmpty($this->faker->streetSuffix, 'Street suffix should be empty!'); + } + + public function testStreetCyrOnly() + { + $pattern = "/[0-9А-ЩЯІЇЄЮа-щяіїєюьIVXCM][0-9А-ЩЯІЇЄЮа-щяіїєюь \'-.]*[А-Яа-я.]/u"; + $streetName = $this->faker->streetName; + $this->assertSame( + preg_match($pattern, $streetName), + 1, + 'Street name ' . $streetName . ' is wrong!' + ); + } + + public function testCityNameCyrOnly() + { + $pattern = "/[А-ЩЯІЇЄЮа-щяіїєюь][0-9А-ЩЯІЇЄЮа-щяіїєюь \'-]*[А-Яа-я]/u"; + $city = $this->faker->city; + $this->assertSame( + preg_match($pattern, $city), + 1, + 'City name ' . $city . ' is wrong!' + ); + } + + public function testRegionNameCyrOnly() + { + $pattern = "/[А-ЩЯІЇЄЮ][А-ЩЯІЇЄЮа-щяіїєюь]*а$/u"; + $regionName = $this->faker->region; + $this->assertSame( + preg_match($pattern, $regionName), + 1, + 'Region name ' . $regionName . ' is wrong!' + ); + } + + public function testCountryCyrOnly() + { + $pattern = "/[А-ЩЯІЇЄЮа-щяіїєюьIVXCM][А-ЩЯІЇЄЮа-щяіїєюь \'-]*[А-Яа-я.]/u"; + $country = $this->faker->country; + $this->assertSame( + preg_match($pattern, $country), + 1, + 'Country name ' . $country . ' is wrong!' + ); + } +} diff --git a/lib/faker/test/Faker/Provider/uk_UA/PhoneNumberTest.php b/lib/faker/test/Faker/Provider/uk_UA/PhoneNumberTest.php new file mode 100755 index 0000000..13620c7 --- /dev/null +++ b/lib/faker/test/Faker/Provider/uk_UA/PhoneNumberTest.php @@ -0,0 +1,35 @@ +addProvider(new PhoneNumber($faker)); + $this->faker = $faker; + } + + public function testPhoneNumberFormat() + { + $pattern = "/((\+38)(((\(\d{3}\))\d{7}|(\(\d{4}\))\d{6})|(\d{8})))|0\d{9}/"; + $phoneNumber = $this->faker->phoneNumber; + $this->assertSame( + preg_match($pattern, $phoneNumber), + 1, + 'Phone number format ' . $phoneNumber . ' is wrong!' + ); + + } + +} diff --git a/lib/faker/test/documentor.php b/lib/faker/test/documentor.php new file mode 100755 index 0000000..1051ea2 --- /dev/null +++ b/lib/faker/test/documentor.php @@ -0,0 +1,16 @@ +seed(1); +$documentor = new Faker\Documentor($generator); +?> +getFormatters() as $provider => $formatters): ?> + +### `` + + $example): ?> + // + + +seed(5); + +echo ''; +?> + + + + +boolean(25)): ?> + + +
    + streetAddress ?> + city ?> + postcode ?> + state ?> +
    + +boolean(33)): ?> + bs ?> + +boolean(33)): ?> + + + +boolean(15)): ?> +
    +text(400) ?> +]]> +
    + +
    + +
    diff --git a/lib/mobiledetect/index.php b/lib/mobiledetect/index.php new file mode 100644 index 0000000..2f77e94 --- /dev/null +++ b/lib/mobiledetect/index.php @@ -0,0 +1,1447 @@ + + * Nick Ilyin + * + * Original author: Victor Stanciu + * + * @license Code and contributions have 'MIT License' + * More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt + * + * @link Homepage: http://mobiledetect.net + * GitHub Repo: https://github.com/serbanghita/Mobile-Detect + * Google Code: http://code.google.com/p/php-mobile-detect/ + * README: https://github.com/serbanghita/Mobile-Detect/blob/master/README.md + * HOWTO: https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples + * + * @version 2.8.22 + */ + +class Mobile_Detect +{ + /** + * Mobile detection type. + * + * @deprecated since version 2.6.9 + */ + const DETECTION_TYPE_MOBILE = 'mobile'; + + /** + * Extended detection type. + * + * @deprecated since version 2.6.9 + */ + const DETECTION_TYPE_EXTENDED = 'extended'; + + /** + * A frequently used regular expression to extract version #s. + * + * @deprecated sincee version 2.6.9 + */ + const VER = '([\w._\+]+)'; + + /** + * Top-level device. + */ + const MOBILE_GRADE_A = 'A'; + + /** + * Mid-level device. + */ + const MOBILE_GRADE_B = 'B'; + + /** + * Low-level device. + */ + const MOBILE_GRADE_C = 'C'; + + /** + * Stores the version number of the current release. + */ + const VERSION = '2.8.22'; + + /** + * A type for the version() method indicating a string return value. + */ + const VERSION_TYPE_STRING = 'text'; + + /** + * A type for the version() method indicating a float return value. + */ + const VERSION_TYPE_FLOAT = 'float'; + + /** + * A cache for resolved matches + * @var array + */ + protected $cache = array(); + + /** + * The User-Agent HTTP header is stored in here. + * @var string + */ + protected $userAgent = null; + + /** + * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE. + * @var array + */ + protected $httpHeaders = array(); + + /** + * CloudFront headers. E.g. CloudFront-Is-Desktop-Viewer, CloudFront-Is-Mobile-Viewer & CloudFront-Is-Tablet-Viewer. + * @var array + */ + protected $cloudfrontHeaders = array(); + + /** + * The matching Regex. + * This is good for debug. + * @var string + */ + protected $matchingRegex = null; + + /** + * The matches extracted from the regex expression. + * This is good for debug. + * @var string + */ + protected $matchesArray = null; + + /** + * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED. + * + * @deprecated since version 2.6.9 + * + * @var string + */ + protected $detectionType = self::DETECTION_TYPE_MOBILE; + + /** + * HTTP headers that trigger the 'isMobile' detection + * to be true. + * + * @var array + */ + protected static $mobileHeaders = array( + + 'HTTP_ACCEPT' => array('matches' => array( + // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/ + 'application/x-obml2d', + // BlackBerry devices. + 'application/vnd.rim.html', + 'text/vnd.wap.wml', + 'application/vnd.wap.xhtml+xml' + )), + 'HTTP_X_WAP_PROFILE' => null, + 'HTTP_X_WAP_CLIENTID' => null, + 'HTTP_WAP_CONNECTION' => null, + 'HTTP_PROFILE' => null, + // Reported by Opera on Nokia devices (eg. C3). + 'HTTP_X_OPERAMINI_PHONE_UA' => null, + 'HTTP_X_NOKIA_GATEWAY_ID' => null, + 'HTTP_X_ORANGE_ID' => null, + 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null, + 'HTTP_X_HUAWEI_USERID' => null, + // Reported by Windows Smartphones. + 'HTTP_UA_OS' => null, + // Reported by Verizon, Vodafone proxy system. + 'HTTP_X_MOBILE_GATEWAY' => null, + // Seen this on HTC Sensation. SensationXE_Beats_Z715e. + 'HTTP_X_ATT_DEVICEID' => null, + // Seen this on a HTC. + 'HTTP_UA_CPU' => array('matches' => array('ARM')), + ); + + /** + * List of mobile devices (phones). + * + * @var array + */ + protected static $phoneDevices = array( + 'iPhone' => '\biPhone\b|\biPod\b', // |\biTunes + 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+', + 'HTC' => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m', + 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6', + // @todo: Is 'Dell Streak' a tablet or a phone? ;) + 'Dell' => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b', + 'Motorola' => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\bMoto E\b', + 'Samsung' => 'Samsung|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F', + 'LG' => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323)', + 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533', + 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile', + 'NokiaLumia' => 'Lumia [0-9]{3,4}', + // http://www.micromaxinfo.com/mobiles/smartphones + // Added because the codes might conflict with Acer Tablets. + 'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b', + // @todo Complete the regex. + 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ; + 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;) + // http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH) + // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android. + 'Pantech' => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790', + // http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones. + 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250', + // http://fr.wikomobile.com + 'Wiko' => 'KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLIM|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM', + 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)', + // Added simvalley mobile just for fun. They have some interesting devices. + // http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html + 'SimValley' => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b', + // Wolfgang - a brand that is sold by Aldi supermarkets. + // http://www.wolfgangmobile.com/ + 'Wolfgang' => 'AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q', + 'Alcatel' => 'Alcatel', + 'Nintendo' => 'Nintendo 3DS', + // http://en.wikipedia.org/wiki/Amoi + 'Amoi' => 'Amoi', + // http://en.wikipedia.org/wiki/INQ + 'INQ' => 'INQ', + // @Tapatalk is a mobile app; http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039 + 'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser', + ); + + /** + * List of tablet devices. + * + * @var array + */ + protected static $tabletDevices = array( + // @todo: check for mobile friendly emails topic. + 'iPad' => 'iPad|iPad.*Mobile', + // Removed |^.*Android.*Nexus(?!(?:Mobile).)*$ + // @see #442 + 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)', + 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone. + // http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html + 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI)\b', + // Only the Surface tablets with Windows RT are considered mobile. + // http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx + 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)', + // http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT + 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10', + // Watch out for PadFone, see #132. + // http://www.asus.com/de/Tablets_Mobile/Memo_Pad_Products/ + 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K017 |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA', + 'BlackBerryTablet' => 'PlayBook|RIM Tablet', + 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410', + 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617', + 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2', + // http://www.acer.ro/ac/ro/RO/content/drivers + // http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer) + // http://us.acer.com/ac/en/US/content/group/tablets + // http://www.acer.de/ac/de/DE/content/models/tablets/ + // Can conflict with Micromax and Motorola phones codes. + 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\b|W3-810|\bA3-A10\b|\bA3-A11\b|\bA3-A20', + // http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/ + // http://us.toshiba.com/tablets/tablet-finder + // http://www.toshiba.co.jp/regza/tablet/ + 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO', + // http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html + // http://www.lg.com/us/tablets + 'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b', + 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b', + // Prestigio Tablets http://www.prestigio.com/support + 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002', + // http://support.lenovo.com/en_GB/downloads/default.page?# + 'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)', + // http://www.dell.com/support/home/us/en/04/Products/tab_mob/tablets + 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7', + // http://www.yarvik.com/en/matrix/tablets/ + 'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b', + 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB', + 'ArnovaTablet' => 'AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2', + // http://www.intenso.de/kategorie_en.php?kategorie=33 + // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate + 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004', + // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/ + 'IRUTablet' => 'M702pro', + 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b', + // http://www.e-boda.ro/tablete-pc.html + 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)', + // http://www.allview.ro/produse/droseries/lista-tablete-pc/ + 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)', + // http://wiki.archosfans.com/index.php?title=Main_Page + 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|Archos5|\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\b', + // http://www.ainol.com/plugin.php?identifier=ainol&module=product + 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark', + 'NokiaLumiaTablet' => 'Lumia 2520', + // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER + // Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser + // http://www.sony.jp/support/tablet/ + 'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP612|SOT31', + // http://www.support.philips.com/support/catalog/worldproducts.jsp?userLanguage=en&userCountry=cn&categoryid=3G_LTE_TABLET_SU_CN_CARE&title=3G%20tablets%20/%20LTE%20range&_dyncharset=UTF-8 + 'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b', + // db + http://www.cube-tablet.com/buy-products.html + 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT', + // http://www.cobyusa.com/?p=pcat&pcat_id=3001 + 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010', + // http://www.match.net.cn/products.asp + 'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10', + // http://www.msi.com/support + // @todo Research the Windows Tablets. + 'MSITablet' => 'MSI \b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\b', + // @todo http://www.kyoceramobile.com/support/drivers/ + // 'KyoceraTablet' => null, + // @todo http://intexuae.com/index.php/category/mobile-devices/tablets-products/ + // 'IntextTablet' => null, + // http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets) + // http://www.imp3.net/14/show.php?itemid=20454 + 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)', + // http://www.rock-chips.com/index.php?do=prod&pid=2 + 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A', + // http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/ + 'FlyTablet' => 'IQ310|Fly Vision', + // http://www.bqreaders.com/gb/tablets-prices-sale.html + 'bqTablet' => 'Android.*(bq)?.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris E10)|Maxwell.*Lite|Maxwell.*Plus', + // http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290 + // http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets) + 'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim', + // Nec or Medias Tab + 'NecTablet' => '\bN-06D|\bN-08D', + // Pantech Tablets: http://www.pantechusa.com/phones/ + 'PantechTablet' => 'Pantech.*P4100', + // Broncho Tablets: http://www.broncho.cn/ (hard to find) + 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)', + // http://versusuk.com/support.html + 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b', + // http://www.zync.in/index.php/our-products/tablet-phablets + 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900', + // http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/ + 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA', + // https://www.nabitablet.com/ + 'NabiTablet' => 'Android.*\bNabi', + 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build', + // French Danew Tablets http://www.danew.com/produits-tablette.php + 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b', + // Texet Tablets and Readers http://www.texet.ru/tablet/ + 'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE', + // Avoid detecting 'PLAYSTATION 3' as mobile. + 'PlaystationTablet' => 'Playstation.*(Portable|Vita)', + // http://www.trekstor.de/surftabs.html + 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab', + // http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets + 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b', + // http://www.advandigital.com/index.php?link=content-product&jns=JP001 + // because of the short codenames we have to include whitespaces to reduce the possible conflicts. + 'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ', + // http://www.danytech.com/category/tablet-pc + 'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1', + // http://www.galapad.net/product.html + 'GalapadTablet' => 'Android.*\bG1\b', + // http://www.micromaxinfo.com/tablet/funbook + 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b', + // http://www.karbonnmobiles.com/products_tablet.php + 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b', + // http://www.myallfine.com/Products.asp + 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide', + // http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr= + 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b', + // http://www.yonesnav.com/products/products.php + 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026', + // http://www.cjshowroom.com/eproducts.aspx?classcode=004001001 + // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html) + 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503', + // http://www.gloryunion.cn/products.asp + // http://www.allwinnertech.com/en/apply/mobile.html + // http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB) + // @todo: Softwiner tablets? + // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions. + 'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G + // http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118 + 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10', + // http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/ + // @todo: add more tests. + 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)', + // http://hclmetablet.com/India/index.php + 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync', + // http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html + 'DPSTablet' => 'DPS Dream 9|DPS Dual 7', + // http://www.visture.com/index.asp + 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10', + // http://www.mijncresta.nl/tablet + 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989', + // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309 + 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b', + // Concorde tab + 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan', + // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/ + 'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042', + // Modecom Tablets - http://www.modecom.eu/tablets/portal/ + 'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003', + // Vonino Tablets - http://www.vonino.eu/tablets + 'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b', + // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0 + 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1', + // Storex Tablets - http://storex.fr/espace_client/support.html + // @note: no need to add all the tablet codes since they are guided by the first regex. + 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab', + // Generic Vodafone tablets. + 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7', + // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb + // Aka: http://www.essentielb.fr/ + 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2', + // Ross & Moor - http://ross-moor.ru/ + 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711', + // i-mobile http://product.i-mobilephone.com/Mobile_Device + 'iMobileTablet' => 'i-mobile i-note', + // http://www.tolino.de/de/vergleichen/ + 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine', + // AudioSonic - a Kmart brand + // http://www.kmart.com.au/webapp/wcs/stores/servlet/Search?langId=-1&storeId=10701&catalogId=10001&categoryId=193001&pageSize=72¤tPage=1&searchCategory=193001%2b4294965664&sortBy=p_MaxPrice%7c1 + 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b', + // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/ + // @todo: add them gradually to avoid conflicts. + 'AMPETablet' => 'Android.* A78 ', + // Skk Mobile - http://skkmobile.com.ph/product_tablets.php + 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)', + // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1 + 'TecnoTablet' => 'TECNO P9', + // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3 + 'JXDTablet' => 'Android.* \b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b', + // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/ + 'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)', + // http://www.intracon.eu/tablet + 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10', + // http://www.xoro.de/produkte/ + // @note: Might be the same brand with 'Simply tablets' + 'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151', + // http://www1.viewsonic.com/products/computing/tablets/ + 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a', + // http://www.odys.de/web/internet-tablet_en.html + 'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10', + // http://www.captiva-power.de/products.html#tablets-en + 'CaptivaTablet' => 'CAPTIVA PAD', + // IconBIT - http://www.iconbit.com/products/tablets/ + 'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S', + // http://www.teclast.com/topic.php?channelID=70&topicID=140&pid=63 + 'TeclastTablet' => 'T98 4G|\bP80\b|\bX90HD\b|X98 Air|X98 Air 3G|\bX89\b|P80 3G|\bX80h\b|P98 Air|\bX89HD\b|P98 3G|\bP90HD\b|P89 3G|X98 3G|\bP70h\b|P79HD 3G|G18d 3G|\bP79HD\b|\bP89s\b|\bA88\b|\bP10HD\b|\bP19HD\b|G18 3G|\bP78HD\b|\bA78\b|\bP75\b|G17s 3G|G17h 3G|\bP85t\b|\bP90\b|\bP11\b|\bP98t\b|\bP98HD\b|\bG18d\b|\bP85s\b|\bP11HD\b|\bP88s\b|\bA80HD\b|\bA80se\b|\bA10h\b|\bP89\b|\bP78s\b|\bG18\b|\bP85\b|\bA70h\b|\bA70\b|\bG17\b|\bP18\b|\bA80s\b|\bA11s\b|\bP88HD\b|\bA80h\b|\bP76s\b|\bP76h\b|\bP98\b|\bA10HD\b|\bP78\b|\bP88\b|\bA11\b|\bA10t\b|\bP76a\b|\bP76t\b|\bP76e\b|\bP85HD\b|\bP85a\b|\bP86\b|\bP75HD\b|\bP76v\b|\bA12\b|\bP75a\b|\bA15\b|\bP76Ti\b|\bP81HD\b|\bA10\b|\bT760VE\b|\bT720HD\b|\bP76\b|\bP73\b|\bP71\b|\bP72\b|\bT720SE\b|\bC520Ti\b|\bT760\b|\bT720VE\b|T720-3GE|T720-WiFi', + // Onda - http://www.onda-tablet.com/buy-android-onda.html?dir=desc&limit=all&order=price + 'OndaTablet' => '\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\b[\s]+', + 'JaytechTablet' => 'TPC-PA762', + 'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010', + // http://www.digma.ru/support/download/ + // @todo: Ebooks also (if requested) + 'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b', + // http://www.evolioshop.com/ro/tablete-pc.html + // http://www.evolio.ro/support/downloads_static.html?cat=2 + // @todo: Research some more + 'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b', + // @todo http://www.lavamobiles.com/tablets-data-cards + 'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY|\bE-TAB\b', + // http://www.breezetablet.com/ + 'AocTablet' => 'MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712', + // http://www.mpmaneurope.com/en/products/internet-tablets-14/android-tablets-14/ + 'MpmanTablet' => 'MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\bMPG7\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010', + // https://www.celkonmobiles.com/?_a=categoryphones&sid=2 + 'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b', + // http://www.wolderelectronics.com/productos/manuales-y-guias-rapidas/categoria-2-miTab + 'WolderTablet' => 'miTab \b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\b', + // http://www.mi.com/en + 'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b', + // http://www.nbru.cn/index.html + 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One', + // http://navroad.com/products/produkty/tablety/ + 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI', + // http://leader-online.com/new_site/product-category/tablets/ + // http://www.leader-online.net.au/List/Tablet + 'LeaderTablet' => 'TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100', + // http://www.datawind.com/ubislate/ + 'UbislateTablet' => 'UbiSlate[\s]?7C', + // http://www.pocketbook-int.com/ru/support + 'PocketBookTablet' => 'Pocketbook', + // http://www.kocaso.com/product_tablet.html + 'KocasoTablet' => '\b(TB-1207)\b', + // http://www.tesco.com/direct/hudl/ + 'Hudl' => 'Hudl HT7S3|Hudl 2', + // http://www.telstra.com.au/home-phone/thub-2/ + 'TelstraTablet' => 'T-Hub2', + 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bJolla\b|\bTP750\b' + ); + + /** + * List of mobile Operating Systems. + * + * @var array + */ + protected static $operatingSystems = array( + 'AndroidOS' => 'Android', + 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os', + 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino', + 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b', + // @reference: http://en.wikipedia.org/wiki/Windows_Mobile + 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;', + // @reference: http://en.wikipedia.org/wiki/Windows_Phone + // http://wifeng.cn/?r=blog&a=view&id=106 + // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx + // http://msdn.microsoft.com/library/ms537503.aspx + // https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx + 'WindowsPhoneOS' => 'Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;', + 'iOS' => '\biPhone.*Mobile|\biPod|\biPad', + // http://en.wikipedia.org/wiki/MeeGo + // @todo: research MeeGo in UAs + 'MeeGoOS' => 'MeeGo', + // http://en.wikipedia.org/wiki/Maemo + // @todo: research Maemo in UAs + 'MaemoOS' => 'Maemo', + 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135 + 'webOS' => 'webOS|hpwOS', + 'badaOS' => '\bBada\b', + 'BREWOS' => 'BREW', + ); + + /** + * List of mobile User Agents. + * + * @var array + */ + protected static $browsers = array( + // @reference: https://developers.google.com/chrome/mobile/docs/user-agent + 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?', + 'Dolfin' => '\bDolfin\b', + 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+', + 'Skyfire' => 'Skyfire', + 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+ + 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile', + 'Bolt' => 'bolt', + 'TeaShark' => 'teashark', + 'Blazer' => 'Blazer', + // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3 + 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari', + // http://en.wikipedia.org/wiki/Midori_(web_browser) + //'Midori' => 'midori', + 'Tizen' => 'Tizen', + 'UCBrowser' => 'UC.*Browser|UCWEB', + 'baiduboxapp' => 'baiduboxapp', + 'baidubrowser' => 'baidubrowser', + // https://github.com/serbanghita/Mobile-Detect/issues/7 + 'DiigoBrowser' => 'DiigoBrowser', + // http://www.puffinbrowser.com/index.php + 'Puffin' => 'Puffin', + // http://mercury-browser.com/index.html + 'Mercury' => '\bMercury\b', + // http://en.wikipedia.org/wiki/Obigo_Browser + 'ObigoBrowser' => 'Obigo', + // http://en.wikipedia.org/wiki/NetFront + 'NetFront' => 'NF-Browser', + // @reference: http://en.wikipedia.org/wiki/Minimo + // http://en.wikipedia.org/wiki/Vision_Mobile_Browser + 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger', + // @reference: https://en.wikipedia.org/wiki/Pale_Moon_(web_browser) + 'PaleMoon' => 'Android.*PaleMoon|Mobile.*PaleMoon', + ); + + /** + * Utilities. + * + * @var array + */ + protected static $utilities = array( + // Experimental. When a mobile device wants to switch to 'Desktop Mode'. + // http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/ + // https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011 + // https://developers.facebook.com/docs/sharing/best-practices + 'Bot' => 'Googlebot|facebookexternalhit|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom', + 'MobileBot' => 'Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2', + 'DesktopMode' => 'WPDesktop', + 'TV' => 'SonyDTV|HbbTV', // experimental + 'WebKit' => '(webkit)[ /]([\w.]+)', + // @todo: Include JXD consoles. + 'Console' => '\b(Nintendo|Nintendo WiiU|Nintendo 3DS|PLAYSTATION|Xbox)\b', + 'Watch' => 'SM-V700', + ); + + /** + * All possible HTTP headers that represent the + * User-Agent string. + * + * @var array + */ + protected static $uaHttpHeaders = array( + // The default User-Agent string. + 'HTTP_USER_AGENT', + // Header can occur on devices using Opera Mini. + 'HTTP_X_OPERAMINI_PHONE_UA', + // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/ + 'HTTP_X_DEVICE_USER_AGENT', + 'HTTP_X_ORIGINAL_USER_AGENT', + 'HTTP_X_SKYFIRE_PHONE', + 'HTTP_X_BOLT_PHONE_UA', + 'HTTP_DEVICE_STOCK_UA', + 'HTTP_X_UCBROWSER_DEVICE_UA' + ); + + /** + * The individual segments that could exist in a User-Agent string. VER refers to the regular + * expression defined in the constant self::VER. + * + * @var array + */ + protected static $properties = array( + + // Build + 'Mobile' => 'Mobile/[VER]', + 'Build' => 'Build/[VER]', + 'Version' => 'Version/[VER]', + 'VendorID' => 'VendorID/[VER]', + + // Devices + 'iPad' => 'iPad.*CPU[a-z ]+[VER]', + 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]', + 'iPod' => 'iPod.*CPU[a-z ]+[VER]', + //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'), + 'Kindle' => 'Kindle/[VER]', + + // Browser + 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'), + 'Coast' => array('Coast/[VER]'), + 'Dolfin' => 'Dolfin/[VER]', + // @reference: https://developer.mozilla.org/en-US/docs/User_Agent_Strings_Reference + 'Firefox' => 'Firefox/[VER]', + 'Fennec' => 'Fennec/[VER]', + // http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx + // https://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx + 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];', 'Trident/[0-9.]+;.*rv:[VER]'), + // http://en.wikipedia.org/wiki/NetFront + 'NetFront' => 'NetFront/[VER]', + 'NokiaBrowser' => 'NokiaBrowser/[VER]', + 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ), + 'Opera Mini' => 'Opera Mini/[VER]', + 'Opera Mobi' => 'Version/[VER]', + 'UC Browser' => 'UC Browser[VER]', + 'MQQBrowser' => 'MQQBrowser/[VER]', + 'MicroMessenger' => 'MicroMessenger/[VER]', + 'baiduboxapp' => 'baiduboxapp/[VER]', + 'baidubrowser' => 'baidubrowser/[VER]', + 'Iron' => 'Iron/[VER]', + // @note: Safari 7534.48.3 is actually Version 5.1. + // @note: On BlackBerry the Version is overwriten by the OS. + 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ), + 'Skyfire' => 'Skyfire/[VER]', + 'Tizen' => 'Tizen/[VER]', + 'Webkit' => 'webkit[ /][VER]', + 'PaleMoon' => 'PaleMoon/[VER]', + + // Engine + 'Gecko' => 'Gecko/[VER]', + 'Trident' => 'Trident/[VER]', + 'Presto' => 'Presto/[VER]', + 'Goanna' => 'Goanna/[VER]', + + // OS + 'iOS' => ' \bi?OS\b [VER][ ;]{1}', + 'Android' => 'Android [VER]', + 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'), + 'BREW' => 'BREW [VER]', + 'Java' => 'Java/[VER]', + // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx + // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases + 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'), + 'Windows Phone' => 'Windows Phone [VER]', + 'Windows CE' => 'Windows CE/[VER]', + // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd + 'Windows NT' => 'Windows NT [VER]', + 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'), + 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'), + ); + + /** + * Construct an instance of this class. + * + * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored. + * If left empty, will use the global _SERVER['HTTP_*'] vars instead. + * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT + * from the $headers array instead. + */ + public function __construct( + array $headers = null, + $userAgent = null + ) { + $this->setHttpHeaders($headers); + $this->setUserAgent($userAgent); + } + + /** + * Get the current script version. + * This is useful for the demo.php file, + * so people can check on what version they are testing + * for mobile devices. + * + * @return string The version number in semantic version format. + */ + public static function getScriptVersion() + { + return self::VERSION; + } + + /** + * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers. + * + * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract + * the headers. The default null is left for backwards compatibility. + */ + public function setHttpHeaders($httpHeaders = null) + { + // use global _SERVER if $httpHeaders aren't defined + if (!is_array($httpHeaders) || !count($httpHeaders)) { + $httpHeaders = $_SERVER; + } + + // clear existing headers + $this->httpHeaders = array(); + + // Only save HTTP headers. In PHP land, that means only _SERVER vars that + // start with HTTP_. + foreach ($httpHeaders as $key => $value) { + if (substr($key, 0, 5) === 'HTTP_') { + $this->httpHeaders[$key] = $value; + } + } + + // In case we're dealing with CloudFront, we need to know. + $this->setCfHeaders($httpHeaders); + } + + /** + * Retrieves the HTTP headers. + * + * @return array + */ + public function getHttpHeaders() + { + return $this->httpHeaders; + } + + /** + * Retrieves a particular header. If it doesn't exist, no exception/error is caused. + * Simply null is returned. + * + * @param string $header The name of the header to retrieve. Can be HTTP compliant such as + * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the + * all-caps, HTTP_ prefixed, underscore seperated awesomeness. + * + * @return string|null The value of the header. + */ + public function getHttpHeader($header) + { + // are we using PHP-flavored headers? + if (strpos($header, '_') === false) { + $header = str_replace('-', '_', $header); + $header = strtoupper($header); + } + + // test the alternate, too + $altHeader = 'HTTP_' . $header; + + //Test both the regular and the HTTP_ prefix + if (isset($this->httpHeaders[$header])) { + return $this->httpHeaders[$header]; + } elseif (isset($this->httpHeaders[$altHeader])) { + return $this->httpHeaders[$altHeader]; + } + + return null; + } + + public function getMobileHeaders() + { + return self::$mobileHeaders; + } + + /** + * Get all possible HTTP headers that + * can contain the User-Agent string. + * + * @return array List of HTTP headers. + */ + public function getUaHttpHeaders() + { + return self::$uaHttpHeaders; + } + + + /** + * Set CloudFront headers + * http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web-device + * + * @param array $cfHeaders List of HTTP headers + * + * @return boolean If there were CloudFront headers to be set + */ + public function setCfHeaders($cfHeaders = null) { + // use global _SERVER if $cfHeaders aren't defined + if (!is_array($cfHeaders) || !count($cfHeaders)) { + $cfHeaders = $_SERVER; + } + + // clear existing headers + $this->cloudfrontHeaders = array(); + + // Only save CLOUDFRONT headers. In PHP land, that means only _SERVER vars that + // start with cloudfront-. + $response = false; + foreach ($cfHeaders as $key => $value) { + if (substr(strtolower($key), 0, 16) === 'http_cloudfront_') { + $this->cloudfrontHeaders[strtoupper($key)] = $value; + $response = true; + } + } + + return $response; + } + + /** + * Retrieves the cloudfront headers. + * + * @return array + */ + public function getCfHeaders() + { + return $this->cloudfrontHeaders; + } + + /** + * Set the User-Agent to be used. + * + * @param string $userAgent The user agent string to set. + * + * @return string|null + */ + public function setUserAgent($userAgent = null) + { + // Invalidate cache due to #375 + $this->cache = array(); + + if (false === empty($userAgent)) { + return $this->userAgent = $userAgent; + } else { + $this->userAgent = null; + foreach ($this->getUaHttpHeaders() as $altHeader) { + if (false === empty($this->httpHeaders[$altHeader])) { // @todo: should use getHttpHeader(), but it would be slow. (Serban) + $this->userAgent .= $this->httpHeaders[$altHeader] . " "; + } + } + + if (!empty($this->userAgent)) { + return $this->userAgent = trim($this->userAgent); + } + } + + if (count($this->getCfHeaders()) > 0) { + return $this->userAgent = 'Amazon CloudFront'; + } + return $this->userAgent = null; + } + + /** + * Retrieve the User-Agent. + * + * @return string|null The user agent if it's set. + */ + public function getUserAgent() + { + return $this->userAgent; + } + + /** + * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or + * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set. + * + * @deprecated since version 2.6.9 + * + * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default + * parameter is null which will default to self::DETECTION_TYPE_MOBILE. + */ + public function setDetectionType($type = null) + { + if ($type === null) { + $type = self::DETECTION_TYPE_MOBILE; + } + + if ($type !== self::DETECTION_TYPE_MOBILE && $type !== self::DETECTION_TYPE_EXTENDED) { + return; + } + + $this->detectionType = $type; + } + + public function getMatchingRegex() + { + return $this->matchingRegex; + } + + public function getMatchesArray() + { + return $this->matchesArray; + } + + /** + * Retrieve the list of known phone devices. + * + * @return array List of phone devices. + */ + public static function getPhoneDevices() + { + return self::$phoneDevices; + } + + /** + * Retrieve the list of known tablet devices. + * + * @return array List of tablet devices. + */ + public static function getTabletDevices() + { + return self::$tabletDevices; + } + + /** + * Alias for getBrowsers() method. + * + * @return array List of user agents. + */ + public static function getUserAgents() + { + return self::getBrowsers(); + } + + /** + * Retrieve the list of known browsers. Specifically, the user agents. + * + * @return array List of browsers / user agents. + */ + public static function getBrowsers() + { + return self::$browsers; + } + + /** + * Retrieve the list of known utilities. + * + * @return array List of utilities. + */ + public static function getUtilities() + { + return self::$utilities; + } + + /** + * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*(). + * + * @deprecated since version 2.6.9 + * + * @return array All the rules (but not extended). + */ + public static function getMobileDetectionRules() + { + static $rules; + + if (!$rules) { + $rules = array_merge( + self::$phoneDevices, + self::$tabletDevices, + self::$operatingSystems, + self::$browsers + ); + } + + return $rules; + + } + + /** + * Method gets the mobile detection rules + utilities. + * The reason this is separate is because utilities rules + * don't necessary imply mobile. This method is used inside + * the new $detect->is('stuff') method. + * + * @deprecated since version 2.6.9 + * + * @return array All the rules + extended. + */ + public function getMobileDetectionRulesExtended() + { + static $rules; + + if (!$rules) { + // Merge all rules together. + $rules = array_merge( + self::$phoneDevices, + self::$tabletDevices, + self::$operatingSystems, + self::$browsers, + self::$utilities + ); + } + + return $rules; + } + + /** + * Retrieve the current set of rules. + * + * @deprecated since version 2.6.9 + * + * @return array + */ + public function getRules() + { + if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) { + return self::getMobileDetectionRulesExtended(); + } else { + return self::getMobileDetectionRules(); + } + } + + /** + * Retrieve the list of mobile operating systems. + * + * @return array The list of mobile operating systems. + */ + public static function getOperatingSystems() + { + return self::$operatingSystems; + } + + /** + * Check the HTTP headers for signs of mobile. + * This is the fastest mobile check possible; it's used + * inside isMobile() method. + * + * @return bool + */ + public function checkHttpHeadersForMobile() + { + + foreach ($this->getMobileHeaders() as $mobileHeader => $matchType) { + if (isset($this->httpHeaders[$mobileHeader])) { + if (is_array($matchType['matches'])) { + foreach ($matchType['matches'] as $_match) { + if (strpos($this->httpHeaders[$mobileHeader], $_match) !== false) { + return true; + } + } + + return false; + } else { + return true; + } + } + } + + return false; + + } + + /** + * Magic overloading method. + * + * @method boolean is[...]() + * @param string $name + * @param array $arguments + * @return mixed + * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is' + */ + public function __call($name, $arguments) + { + // make sure the name starts with 'is', otherwise + if (substr($name, 0, 2) !== 'is') { + throw new BadMethodCallException("No such method exists: $name"); + } + + $this->setDetectionType(self::DETECTION_TYPE_MOBILE); + + $key = substr($name, 2); + + return $this->matchUAAgainstKey($key); + } + + /** + * Find a detection rule that matches the current User-agent. + * + * @param null $userAgent deprecated + * @return boolean + */ + protected function matchDetectionRulesAgainstUA($userAgent = null) + { + // Begin general search. + foreach ($this->getRules() as $_regex) { + if (empty($_regex)) { + continue; + } + + if ($this->match($_regex, $userAgent)) { + return true; + } + } + + return false; + } + + /** + * Search for a certain key in the rules array. + * If the key is found then try to match the corresponding + * regex against the User-Agent. + * + * @param string $key + * + * @return boolean + */ + protected function matchUAAgainstKey($key) + { + // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc. + $key = strtolower($key); + if (false === isset($this->cache[$key])) { + + // change the keys to lower case + $_rules = array_change_key_case($this->getRules()); + + if (false === empty($_rules[$key])) { + $this->cache[$key] = $this->match($_rules[$key]); + } + + if (false === isset($this->cache[$key])) { + $this->cache[$key] = false; + } + } + + return $this->cache[$key]; + } + + /** + * Check if the device is mobile. + * Returns true if any type of mobile device detected, including special ones + * @param null $userAgent deprecated + * @param null $httpHeaders deprecated + * @return bool + */ + public function isMobile($userAgent = null, $httpHeaders = null) + { + + if ($httpHeaders) { + $this->setHttpHeaders($httpHeaders); + } + + if ($userAgent) { + $this->setUserAgent($userAgent); + } + + // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront' + if ($this->getUserAgent() === 'Amazon CloudFront') { + $cfHeaders = $this->getCfHeaders(); + if(array_key_exists('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_MOBILE_VIEWER'] === 'true') { + return true; + } + } + + $this->setDetectionType(self::DETECTION_TYPE_MOBILE); + + if ($this->checkHttpHeadersForMobile()) { + return true; + } else { + return $this->matchDetectionRulesAgainstUA(); + } + + } + + /** + * Check if the device is a tablet. + * Return true if any type of tablet device is detected. + * + * @param string $userAgent deprecated + * @param array $httpHeaders deprecated + * @return bool + */ + public function isTablet($userAgent = null, $httpHeaders = null) + { + // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront' + if ($this->getUserAgent() === 'Amazon CloudFront') { + $cfHeaders = $this->getCfHeaders(); + if(array_key_exists('HTTP_CLOUDFRONT_IS_TABLET_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_TABLET_VIEWER'] === 'true') { + return true; + } + } + + $this->setDetectionType(self::DETECTION_TYPE_MOBILE); + + foreach (self::$tabletDevices as $_regex) { + if ($this->match($_regex, $userAgent)) { + return true; + } + } + + return false; + } + + /** + * This method checks for a certain property in the + * userAgent. + * @todo: The httpHeaders part is not yet used. + * + * @param string $key + * @param string $userAgent deprecated + * @param string $httpHeaders deprecated + * @return bool|int|null + */ + public function is($key, $userAgent = null, $httpHeaders = null) + { + // Set the UA and HTTP headers only if needed (eg. batch mode). + if ($httpHeaders) { + $this->setHttpHeaders($httpHeaders); + } + + if ($userAgent) { + $this->setUserAgent($userAgent); + } + + $this->setDetectionType(self::DETECTION_TYPE_EXTENDED); + + return $this->matchUAAgainstKey($key); + } + + /** + * Some detection rules are relative (not standard), + * because of the diversity of devices, vendors and + * their conventions in representing the User-Agent or + * the HTTP headers. + * + * This method will be used to check custom regexes against + * the User-Agent string. + * + * @param $regex + * @param string $userAgent + * @return bool + * + * @todo: search in the HTTP headers too. + */ + public function match($regex, $userAgent = null) + { + $match = (bool) preg_match(sprintf('#%s#is', $regex), (false === empty($userAgent) ? $userAgent : $this->userAgent), $matches); + // If positive match is found, store the results for debug. + if ($match) { + $this->matchingRegex = $regex; + $this->matchesArray = $matches; + } + + return $match; + } + + /** + * Get the properties array. + * + * @return array + */ + public static function getProperties() + { + return self::$properties; + } + + /** + * Prepare the version number. + * + * @todo Remove the error supression from str_replace() call. + * + * @param string $ver The string version, like "2.6.21.2152"; + * + * @return float + */ + public function prepareVersionNo($ver) + { + $ver = str_replace(array('_', ' ', '/'), '.', $ver); + $arrVer = explode('.', $ver, 2); + + if (isset($arrVer[1])) { + $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions. + } + + return (float) implode('.', $arrVer); + } + + /** + * Check the version of the given property in the User-Agent. + * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31) + * + * @param string $propertyName The name of the property. See self::getProperties() array + * keys for all possible properties. + * @param string $type Either self::VERSION_TYPE_STRING to get a string value or + * self::VERSION_TYPE_FLOAT indicating a float value. This parameter + * is optional and defaults to self::VERSION_TYPE_STRING. Passing an + * invalid parameter will default to the this type as well. + * + * @return string|float The version of the property we are trying to extract. + */ + public function version($propertyName, $type = self::VERSION_TYPE_STRING) + { + if (empty($propertyName)) { + return false; + } + + // set the $type to the default if we don't recognize the type + if ($type !== self::VERSION_TYPE_STRING && $type !== self::VERSION_TYPE_FLOAT) { + $type = self::VERSION_TYPE_STRING; + } + + $properties = self::getProperties(); + + // Check if the property exists in the properties array. + if (true === isset($properties[$propertyName])) { + + // Prepare the pattern to be matched. + // Make sure we always deal with an array (string is converted). + $properties[$propertyName] = (array) $properties[$propertyName]; + + foreach ($properties[$propertyName] as $propertyMatchString) { + + $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString); + + // Identify and extract the version. + preg_match(sprintf('#%s#is', $propertyPattern), $this->userAgent, $match); + + if (false === empty($match[1])) { + $version = ($type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1]); + + return $version; + } + + } + + } + + return false; + } + + /** + * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants. + * + * @return string One of the self::MOBILE_GRADE_* constants. + */ + public function mobileGrade() + { + $isMobile = $this->isMobile(); + + if ( + // Apple iOS 4-7.0 – Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3 / 5.1 / 6.1), iPad 3 (5.1 / 6.0), iPad Mini (6.1), iPad Retina (7.0), iPhone 3GS (4.3), iPhone 4 (4.3 / 5.1), iPhone 4S (5.1 / 6.0), iPhone 5 (6.0), and iPhone 5S (7.0) + $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) >= 4.3 || + $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) >= 4.3 || + $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) >= 4.3 || + + // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5) + // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM + // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices + // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7 + ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) || + + // Windows Phone 7.5-8 - Tested on the HTC Surround (7.5), HTC Trophy (7.5), LG-E900 (7.5), Nokia 800 (7.8), HTC Mazaa (7.8), Nokia Lumia 520 (8), Nokia Lumia 920 (8), HTC 8x (8) + $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT) >= 7.5 || + + // Tested on the Torch 9800 (6) and Style 9670 (6), BlackBerry® Torch 9810 (7), BlackBerry Z10 (10) + $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 6.0 || + // Blackberry Playbook (1.0-2.0) - Tested on PlayBook + $this->match('Playbook.*Tablet') || + + // Palm WebOS (1.4-3.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0), HP TouchPad (3.0) + ( $this->version('webOS', self::VERSION_TYPE_FLOAT) >= 1.4 && $this->match('Palm|Pre|Pixi') ) || + // Palm WebOS 3.0 - Tested on HP TouchPad + $this->match('hp.*TouchPad') || + + // Firefox Mobile 18 - Tested on Android 2.3 and 4.1 devices + ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 18 ) || + + // Chrome for Android - Tested on Android 4.0, 4.1 device + ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 4.0 ) || + + // Skyfire 4.1 - Tested on Android 2.3 device + ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT) >= 4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) || + + // Opera Mobile 11.5-12: Tested on Android 2.3 + ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11.5 && $this->is('AndroidOS') ) || + + // Meego 1.2 - Tested on Nokia 950 and N9 + $this->is('MeeGoOS') || + + // Tizen (pre-release) - Tested on early hardware + $this->is('Tizen') || + + // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser + // @todo: more tests here! + $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT) >= 2.0 || + + // UC Browser - Tested on Android 2.3 device + ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) || + + // Kindle 3 and Fire - Tested on the built-in WebKit browser for each + ( $this->match('Kindle Fire') || + $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT) >= 3.0 ) || + + // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet + $this->is('AndroidOS') && $this->is('NookTablet') || + + // Chrome Desktop 16-24 - Tested on OS X 10.7 and Windows 7 + $this->version('Chrome', self::VERSION_TYPE_FLOAT) >= 16 && !$isMobile || + + // Safari Desktop 5-6 - Tested on OS X 10.7 and Windows 7 + $this->version('Safari', self::VERSION_TYPE_FLOAT) >= 5.0 && !$isMobile || + + // Firefox Desktop 10-18 - Tested on OS X 10.7 and Windows 7 + $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 10.0 && !$isMobile || + + // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7 + $this->version('IE', self::VERSION_TYPE_FLOAT) >= 7.0 && !$isMobile || + + // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7 + $this->version('Opera', self::VERSION_TYPE_FLOAT) >= 10 && !$isMobile + ){ + return self::MOBILE_GRADE_A; + } + + if ( + $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 || + $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<4.3 || + $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT)<4.3 || + + // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770 + $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 || + + //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3 + ($this->version('Opera Mini', self::VERSION_TYPE_FLOAT) >= 5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT) <= 7.0 && + ($this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 || $this->is('iOS')) ) || + + // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1) + $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') || + + // @todo: report this (tested on Nokia N71) + $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11 && $this->is('SymbianOS') + ){ + return self::MOBILE_GRADE_B; + } + + if ( + // Blackberry 4.x - Tested on the Curve 8330 + $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) <= 5.0 || + // Windows Mobile - Tested on the HTC Leo (WinMo 5.2) + $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT) <= 5.2 || + + // Tested on original iPhone (3.1), iPhone 3 (3.2) + $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) <= 3.2 || + $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) <= 3.2 || + $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) <= 3.2 || + + // Internet Explorer 7 and older - Tested on Windows XP + $this->version('IE', self::VERSION_TYPE_FLOAT) <= 7.0 && !$isMobile + ){ + return self::MOBILE_GRADE_C; + } + + // All older smartphone platforms and featurephones - Any device that doesn't support media queries + // will receive the basic, C grade experience. + return self::MOBILE_GRADE_C; + } +} diff --git a/lib/simple_html_dom/simple_html_dom.php b/lib/simple_html_dom/simple_html_dom.php new file mode 100644 index 0000000..67c7c9d --- /dev/null +++ b/lib/simple_html_dom/simple_html_dom.php @@ -0,0 +1,1742 @@ +size is the "real" number of bytes the dom was created from. + * but for most purposes, it's a really good estimation. + * Paperg - Added the forceTagsClosed to the dom constructor. Forcing tags closed is great for malformed html, but it CAN lead to parsing errors. + * Allow the user to tell us how much they trust the html. + * Paperg add the text and plaintext to the selectors for the find syntax. plaintext implies text in the innertext of a node. text implies that the tag is a text node. + * This allows for us to find tags based on the text they contain. + * Create find_ancestor_tag to see if a tag is - at any level - inside of another specific tag. + * Paperg: added parse_charset so that we know about the character set of the source document. + * NOTE: If the user's system has a routine called get_last_retrieve_url_contents_content_type availalbe, we will assume it's returning the content-type header from the + * last transfer or curl_exec, and we will parse that and use it in preference to any other method of charset detection. + * + * Found infinite loop in the case of broken html in restore_noise. Rewrote to protect from that. + * PaperG (John Schlick) Added get_display_size for "IMG" tags. + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @author S.C. Chen + * @author John Schlick + * @author Rus Carroll + * @version 1.5 ($Rev: 210 $) + * @package PlaceLocalInclude + * @subpackage simple_html_dom + */ + +/** + * All of the Defines for the classes below. + * @author S.C. Chen + */ +define('HDOM_TYPE_ELEMENT', 1); +define('HDOM_TYPE_COMMENT', 2); +define('HDOM_TYPE_TEXT', 3); +define('HDOM_TYPE_ENDTAG', 4); +define('HDOM_TYPE_ROOT', 5); +define('HDOM_TYPE_UNKNOWN', 6); +define('HDOM_QUOTE_DOUBLE', 0); +define('HDOM_QUOTE_SINGLE', 1); +define('HDOM_QUOTE_NO', 3); +define('HDOM_INFO_BEGIN', 0); +define('HDOM_INFO_END', 1); +define('HDOM_INFO_QUOTE', 2); +define('HDOM_INFO_SPACE', 3); +define('HDOM_INFO_TEXT', 4); +define('HDOM_INFO_INNER', 5); +define('HDOM_INFO_OUTER', 6); +define('HDOM_INFO_ENDSPACE',7); +define('DEFAULT_TARGET_CHARSET', 'UTF-8'); +define('DEFAULT_BR_TEXT', "\r\n"); +define('DEFAULT_SPAN_TEXT', " "); +define('MAX_FILE_SIZE', 600000); +// helper functions +// ----------------------------------------------------------------------------- +// get html dom from file +// $maxlen is defined in the code as PHP_STREAM_COPY_ALL which is defined as -1. +function file_get_html($url, $use_include_path = false, $context=null, $offset = -1, $maxLen=-1, $lowercase = true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) +{ + // We DO force the tags to be terminated. + $dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText); + // For sourceforge users: uncomment the next line and comment the retreive_url_contents line 2 lines down if it is not already done. + $contents = file_get_contents($url, $use_include_path, $context, $offset); + // Paperg - use our own mechanism for getting the contents as we want to control the timeout. + //$contents = retrieve_url_contents($url); + if (empty($contents) || strlen($contents) > MAX_FILE_SIZE) + { + return false; + } + // The second parameter can force the selectors to all be lowercase. + $dom->load($contents, $lowercase, $stripRN); + return $dom; +} + +// get html dom from string +function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) +{ + $dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText); + if (empty($str) || strlen($str) > MAX_FILE_SIZE) + { + $dom->clear(); + return false; + } + $dom->load($str, $lowercase, $stripRN); + return $dom; +} + +// dump html dom tree +function dump_html_tree($node, $show_attr=true, $deep=0) +{ + $node->dump($node); +} + + +/** + * simple html dom node + * PaperG - added ability for "find" routine to lowercase the value of the selector. + * PaperG - added $tag_start to track the start position of the tag in the total byte index + * + * @package PlaceLocalInclude + */ +class simple_html_dom_node +{ + public $nodetype = HDOM_TYPE_TEXT; + public $tag = 'text'; + public $attr = array(); + public $children = array(); + public $nodes = array(); + public $parent = null; + // The "info" array - see HDOM_INFO_... for what each element contains. + public $_ = array(); + public $tag_start = 0; + private $dom = null; + + function __construct($dom) + { + $this->dom = $dom; + $dom->nodes[] = $this; + } + + function __destruct() + { + $this->clear(); + } + + function __toString() + { + return $this->outertext(); + } + + // clean up memory due to php5 circular references memory leak... + function clear() + { + $this->dom = null; + $this->nodes = null; + $this->parent = null; + $this->children = null; + } + + // dump node's tree + function dump($show_attr=true, $deep=0) + { + $lead = str_repeat(' ', $deep); + + echo $lead.$this->tag; + if ($show_attr && count($this->attr)>0) + { + echo '('; + foreach ($this->attr as $k=>$v) + echo "[$k]=>\"".$this->$k.'", '; + echo ')'; + } + echo "\n"; + + if ($this->nodes) + { + foreach ($this->nodes as $c) + { + $c->dump($show_attr, $deep+1); + } + } + } + + + // Debugging function to dump a single dom node with a bunch of information about it. + function dump_node($echo=true) + { + + $string = $this->tag; + if (count($this->attr)>0) + { + $string .= '('; + foreach ($this->attr as $k=>$v) + { + $string .= "[$k]=>\"".$this->$k.'", '; + } + $string .= ')'; + } + if (count($this->_)>0) + { + $string .= ' $_ ('; + foreach ($this->_ as $k=>$v) + { + if (is_array($v)) + { + $string .= "[$k]=>("; + foreach ($v as $k2=>$v2) + { + $string .= "[$k2]=>\"".$v2.'", '; + } + $string .= ")"; + } else { + $string .= "[$k]=>\"".$v.'", '; + } + } + $string .= ")"; + } + + if (isset($this->text)) + { + $string .= " text: (" . $this->text . ")"; + } + + $string .= " HDOM_INNER_INFO: '"; + if (isset($node->_[HDOM_INFO_INNER])) + { + $string .= $node->_[HDOM_INFO_INNER] . "'"; + } + else + { + $string .= ' NULL '; + } + + $string .= " children: " . count($this->children); + $string .= " nodes: " . count($this->nodes); + $string .= " tag_start: " . $this->tag_start; + $string .= "\n"; + + if ($echo) + { + echo $string; + return; + } + else + { + return $string; + } + } + + // returns the parent of node + // If a node is passed in, it will reset the parent of the current node to that one. + function parent($parent=null) + { + // I am SURE that this doesn't work properly. + // It fails to unset the current node from it's current parents nodes or children list first. + if ($parent !== null) + { + $this->parent = $parent; + $this->parent->nodes[] = $this; + $this->parent->children[] = $this; + } + + return $this->parent; + } + + // verify that node has children + function has_child() + { + return !empty($this->children); + } + + // returns children of node + function children($idx=-1) + { + if ($idx===-1) + { + return $this->children; + } + if (isset($this->children[$idx])) + { + return $this->children[$idx]; + } + return null; + } + + // returns the first child of node + function first_child() + { + if (count($this->children)>0) + { + return $this->children[0]; + } + return null; + } + + // returns the last child of node + function last_child() + { + if (($count=count($this->children))>0) + { + return $this->children[$count-1]; + } + return null; + } + + // returns the next sibling of node + function next_sibling() + { + if ($this->parent===null) + { + return null; + } + + $idx = 0; + $count = count($this->parent->children); + while ($idx<$count && $this!==$this->parent->children[$idx]) + { + ++$idx; + } + if (++$idx>=$count) + { + return null; + } + return $this->parent->children[$idx]; + } + + // returns the previous sibling of node + function prev_sibling() + { + if ($this->parent===null) return null; + $idx = 0; + $count = count($this->parent->children); + while ($idx<$count && $this!==$this->parent->children[$idx]) + ++$idx; + if (--$idx<0) return null; + return $this->parent->children[$idx]; + } + + // function to locate a specific ancestor tag in the path to the root. + function find_ancestor_tag($tag) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + // Start by including ourselves in the comparison. + $returnDom = $this; + + while (!is_null($returnDom)) + { + if (is_object($debug_object)) { $debug_object->debug_log(2, "Current tag is: " . $returnDom->tag); } + + if ($returnDom->tag == $tag) + { + break; + } + $returnDom = $returnDom->parent; + } + return $returnDom; + } + + // get dom node's inner html + function innertext() + { + if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; + if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + + $ret = ''; + foreach ($this->nodes as $n) + $ret .= $n->outertext(); + return $ret; + } + + // get dom node's outer text (with tag) + function outertext() + { + global $debug_object; + if (is_object($debug_object)) + { + $text = ''; + if ($this->tag == 'text') + { + if (!empty($this->text)) + { + $text = " with text: " . $this->text; + } + } + $debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text); + } + + if ($this->tag==='root') return $this->innertext(); + + // trigger callback + if ($this->dom && $this->dom->callback!==null) + { + call_user_func_array($this->dom->callback, array($this)); + } + + if (isset($this->_[HDOM_INFO_OUTER])) return $this->_[HDOM_INFO_OUTER]; + if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + + // render begin tag + if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) + { + $ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup(); + } else { + $ret = ""; + } + + // render inner text + if (isset($this->_[HDOM_INFO_INNER])) + { + // If it's a br tag... don't return the HDOM_INNER_INFO that we may or may not have added. + if ($this->tag != "br") + { + $ret .= $this->_[HDOM_INFO_INNER]; + } + } else { + if ($this->nodes) + { + foreach ($this->nodes as $n) + { + $ret .= $this->convert_text($n->outertext()); + } + } + } + + // render end tag + if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END]!=0) + $ret .= 'tag.'>'; + return $ret; + } + + // get dom node's plain text + function text() + { + if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; + switch ($this->nodetype) + { + case HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + case HDOM_TYPE_COMMENT: return ''; + case HDOM_TYPE_UNKNOWN: return ''; + } + if (strcasecmp($this->tag, 'script')===0) return ''; + if (strcasecmp($this->tag, 'style')===0) return ''; + + $ret = ''; + // In rare cases, (always node type 1 or HDOM_TYPE_ELEMENT - observed for some span tags, and some p tags) $this->nodes is set to NULL. + // NOTE: This indicates that there is a problem where it's set to NULL without a clear happening. + // WHY is this happening? + if (!is_null($this->nodes)) + { + foreach ($this->nodes as $n) + { + $ret .= $this->convert_text($n->text()); + } + + // If this node is a span... add a space at the end of it so multiple spans don't run into each other. This is plaintext after all. + if ($this->tag == "span") + { + $ret .= $this->dom->default_span_text; + } + + + } + return $ret; + } + + function xmltext() + { + $ret = $this->innertext(); + $ret = str_ireplace('', '', $ret); + return $ret; + } + + // build node's text with tag + function makeup() + { + // text, comment, unknown + if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + + $ret = '<'.$this->tag; + $i = -1; + + foreach ($this->attr as $key=>$val) + { + ++$i; + + // skip removed attribute + if ($val===null || $val===false) + continue; + + $ret .= $this->_[HDOM_INFO_SPACE][$i][0]; + //no value attr: nowrap, checked selected... + if ($val===true) + $ret .= $key; + else { + switch ($this->_[HDOM_INFO_QUOTE][$i]) + { + case HDOM_QUOTE_DOUBLE: $quote = '"'; break; + case HDOM_QUOTE_SINGLE: $quote = '\''; break; + default: $quote = ''; + } + $ret .= $key.$this->_[HDOM_INFO_SPACE][$i][1].'='.$this->_[HDOM_INFO_SPACE][$i][2].$quote.$val.$quote; + } + } + $ret = $this->dom->restore_noise($ret); + return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>'; + } + + // find elements by css selector + //PaperG - added ability for find to lowercase the value of the selector. + function find($selector, $idx=null, $lowercase=false) + { + $selectors = $this->parse_selector($selector); + if (($count=count($selectors))===0) return array(); + $found_keys = array(); + + // find each selector + for ($c=0; $c<$count; ++$c) + { + // The change on the below line was documented on the sourceforge code tracker id 2788009 + // used to be: if (($levle=count($selectors[0]))===0) return array(); + if (($levle=count($selectors[$c]))===0) return array(); + if (!isset($this->_[HDOM_INFO_BEGIN])) return array(); + + $head = array($this->_[HDOM_INFO_BEGIN]=>1); + + // handle descendant selectors, no recursive! + for ($l=0; $l<$levle; ++$l) + { + $ret = array(); + foreach ($head as $k=>$v) + { + $n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k]; + //PaperG - Pass this optional parameter on to the seek function. + $n->seek($selectors[$c][$l], $ret, $lowercase); + } + $head = $ret; + } + + foreach ($head as $k=>$v) + { + if (!isset($found_keys[$k])) + { + $found_keys[$k] = 1; + } + } + } + + // sort keys + ksort($found_keys); + + $found = array(); + foreach ($found_keys as $k=>$v) + $found[] = $this->dom->nodes[$k]; + + // return nth-element or array + if (is_null($idx)) return $found; + else if ($idx<0) $idx = count($found) + $idx; + return (isset($found[$idx])) ? $found[$idx] : null; + } + + // seek for given conditions + // PaperG - added parameter to allow for case insensitive testing of the value of a selector. + protected function seek($selector, &$ret, $lowercase=false) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + list($tag, $key, $val, $exp, $no_key) = $selector; + + // xpath index + if ($tag && $key && is_numeric($key)) + { + $count = 0; + foreach ($this->children as $c) + { + if ($tag==='*' || $tag===$c->tag) { + if (++$count==$key) { + $ret[$c->_[HDOM_INFO_BEGIN]] = 1; + return; + } + } + } + return; + } + + $end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0; + if ($end==0) { + $parent = $this->parent; + while (!isset($parent->_[HDOM_INFO_END]) && $parent!==null) { + $end -= 1; + $parent = $parent->parent; + } + $end += $parent->_[HDOM_INFO_END]; + } + + for ($i=$this->_[HDOM_INFO_BEGIN]+1; $i<$end; ++$i) { + $node = $this->dom->nodes[$i]; + + $pass = true; + + if ($tag==='*' && !$key) { + if (in_array($node, $this->children, true)) + $ret[$i] = 1; + continue; + } + + // compare tag + if ($tag && $tag!=$node->tag && $tag!=='*') {$pass=false;} + // compare key + if ($pass && $key) { + if ($no_key) { + if (isset($node->attr[$key])) $pass=false; + } else { + if (($key != "plaintext") && !isset($node->attr[$key])) $pass=false; + } + } + // compare value + if ($pass && $key && $val && $val!=='*') { + // If they have told us that this is a "plaintext" search then we want the plaintext of the node - right? + if ($key == "plaintext") { + // $node->plaintext actually returns $node->text(); + $nodeKeyValue = $node->text(); + } else { + // this is a normal search, we want the value of that attribute of the tag. + $nodeKeyValue = $node->attr[$key]; + } + if (is_object($debug_object)) {$debug_object->debug_log(2, "testing node: " . $node->tag . " for attribute: " . $key . $exp . $val . " where nodes value is: " . $nodeKeyValue);} + + //PaperG - If lowercase is set, do a case insensitive test of the value of the selector. + if ($lowercase) { + $check = $this->match($exp, strtolower($val), strtolower($nodeKeyValue)); + } else { + $check = $this->match($exp, $val, $nodeKeyValue); + } + if (is_object($debug_object)) {$debug_object->debug_log(2, "after match: " . ($check ? "true" : "false"));} + + // handle multiple class + if (!$check && strcasecmp($key, 'class')===0) { + foreach (explode(' ',$node->attr[$key]) as $k) { + // Without this, there were cases where leading, trailing, or double spaces lead to our comparing blanks - bad form. + if (!empty($k)) { + if ($lowercase) { + $check = $this->match($exp, strtolower($val), strtolower($k)); + } else { + $check = $this->match($exp, $val, $k); + } + if ($check) break; + } + } + } + if (!$check) $pass = false; + } + if ($pass) $ret[$i] = 1; + unset($node); + } + // It's passed by reference so this is actually what this function returns. + if (is_object($debug_object)) {$debug_object->debug_log(1, "EXIT - ret: ", $ret);} + } + + protected function match($exp, $pattern, $value) { + global $debug_object; + if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} + + switch ($exp) { + case '=': + return ($value===$pattern); + case '!=': + return ($value!==$pattern); + case '^=': + return preg_match("/^".preg_quote($pattern,'/')."/", $value); + case '$=': + return preg_match("/".preg_quote($pattern,'/')."$/", $value); + case '*=': + if ($pattern[0]=='/') { + return preg_match($pattern, $value); + } + return preg_match("/".$pattern."/i", $value); + } + return false; + } + + protected function parse_selector($selector_string) { + global $debug_object; + if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} + + // pattern of CSS selectors, modified from mootools + // Paperg: Add the colon to the attrbute, so that it properly finds like google does. + // Note: if you try to look at this attribute, yo MUST use getAttribute since $dom->x:y will fail the php syntax check. +// Notice the \[ starting the attbute? and the @? following? This implies that an attribute can begin with an @ sign that is not captured. +// This implies that an html attribute specifier may start with an @ sign that is NOT captured by the expression. +// farther study is required to determine of this should be documented or removed. +// $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is"; + $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-:]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is"; + preg_match_all($pattern, trim($selector_string).' ', $matches, PREG_SET_ORDER); + if (is_object($debug_object)) {$debug_object->debug_log(2, "Matches Array: ", $matches);} + + $selectors = array(); + $result = array(); + //print_r($matches); + + foreach ($matches as $m) { + $m[0] = trim($m[0]); + if ($m[0]==='' || $m[0]==='/' || $m[0]==='//') continue; + // for browser generated xpath + if ($m[1]==='tbody') continue; + + list($tag, $key, $val, $exp, $no_key) = array($m[1], null, null, '=', false); + if (!empty($m[2])) {$key='id'; $val=$m[2];} + if (!empty($m[3])) {$key='class'; $val=$m[3];} + if (!empty($m[4])) {$key=$m[4];} + if (!empty($m[5])) {$exp=$m[5];} + if (!empty($m[6])) {$val=$m[6];} + + // convert to lowercase + if ($this->dom->lowercase) {$tag=strtolower($tag); $key=strtolower($key);} + //elements that do NOT have the specified attribute + if (isset($key[0]) && $key[0]==='!') {$key=substr($key, 1); $no_key=true;} + + $result[] = array($tag, $key, $val, $exp, $no_key); + if (trim($m[7])===',') { + $selectors[] = $result; + $result = array(); + } + } + if (count($result)>0) + $selectors[] = $result; + return $selectors; + } + + function __get($name) + { + if (isset($this->attr[$name])) + { + return $this->convert_text($this->attr[$name]); + } + switch ($name) + { + case 'outertext': return $this->outertext(); + case 'innertext': return $this->innertext(); + case 'plaintext': return $this->text(); + case 'xmltext': return $this->xmltext(); + default: return array_key_exists($name, $this->attr); + } + } + + function __set($name, $value) + { + global $debug_object; + if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} + + switch ($name) + { + case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value; + case 'innertext': + if (isset($this->_[HDOM_INFO_TEXT])) return $this->_[HDOM_INFO_TEXT] = $value; + return $this->_[HDOM_INFO_INNER] = $value; + } + if (!isset($this->attr[$name])) + { + $this->_[HDOM_INFO_SPACE][] = array(' ', '', ''); + $this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; + } + $this->attr[$name] = $value; + } + + function __isset($name) + { + switch ($name) + { + case 'outertext': return true; + case 'innertext': return true; + case 'plaintext': return true; + } + //no value attr: nowrap, checked selected... + return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]); + } + + function __unset($name) { + if (isset($this->attr[$name])) + unset($this->attr[$name]); + } + + // PaperG - Function to convert the text from one character set to another if the two sets are not the same. + function convert_text($text) + { + global $debug_object; + if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} + + $converted_text = $text; + + $sourceCharset = ""; + $targetCharset = ""; + + if ($this->dom) + { + $sourceCharset = strtoupper($this->dom->_charset); + $targetCharset = strtoupper($this->dom->_target_charset); + } + if (is_object($debug_object)) {$debug_object->debug_log(3, "source charset: " . $sourceCharset . " target charaset: " . $targetCharset);} + + if (!empty($sourceCharset) && !empty($targetCharset) && (strcasecmp($sourceCharset, $targetCharset) != 0)) + { + // Check if the reported encoding could have been incorrect and the text is actually already UTF-8 + if ((strcasecmp($targetCharset, 'UTF-8') == 0) && ($this->is_utf8($text))) + { + $converted_text = $text; + } + else + { + $converted_text = iconv($sourceCharset, $targetCharset, $text); + } + } + + // Lets make sure that we don't have that silly BOM issue with any of the utf-8 text we output. + if ($targetCharset == 'UTF-8') + { + if (substr($converted_text, 0, 3) == "\xef\xbb\xbf") + { + $converted_text = substr($converted_text, 3); + } + if (substr($converted_text, -3) == "\xef\xbb\xbf") + { + $converted_text = substr($converted_text, 0, -3); + } + } + + return $converted_text; + } + + /** + * Returns true if $string is valid UTF-8 and false otherwise. + * + * @param mixed $str String to be tested + * @return boolean + */ + static function is_utf8($str) + { + $c=0; $b=0; + $bits=0; + $len=strlen($str); + for($i=0; $i<$len; $i++) + { + $c=ord($str[$i]); + if($c > 128) + { + if(($c >= 254)) return false; + elseif($c >= 252) $bits=6; + elseif($c >= 248) $bits=5; + elseif($c >= 240) $bits=4; + elseif($c >= 224) $bits=3; + elseif($c >= 192) $bits=2; + else return false; + if(($i+$bits) > $len) return false; + while($bits > 1) + { + $i++; + $b=ord($str[$i]); + if($b < 128 || $b > 191) return false; + $bits--; + } + } + } + return true; + } + /* + function is_utf8($string) + { + //this is buggy + return (utf8_encode(utf8_decode($string)) == $string); + } + */ + + /** + * Function to try a few tricks to determine the displayed size of an img on the page. + * NOTE: This will ONLY work on an IMG tag. Returns FALSE on all other tag types. + * + * @author John Schlick + * @version April 19 2012 + * @return array an array containing the 'height' and 'width' of the image on the page or -1 if we can't figure it out. + */ + function get_display_size() + { + global $debug_object; + + $width = -1; + $height = -1; + + if ($this->tag !== 'img') + { + return false; + } + + // See if there is aheight or width attribute in the tag itself. + if (isset($this->attr['width'])) + { + $width = $this->attr['width']; + } + + if (isset($this->attr['height'])) + { + $height = $this->attr['height']; + } + + // Now look for an inline style. + if (isset($this->attr['style'])) + { + // Thanks to user gnarf from stackoverflow for this regular expression. + $attributes = array(); + preg_match_all("/([\w-]+)\s*:\s*([^;]+)\s*;?/", $this->attr['style'], $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $attributes[$match[1]] = $match[2]; + } + + // If there is a width in the style attributes: + if (isset($attributes['width']) && $width == -1) + { + // check that the last two characters are px (pixels) + if (strtolower(substr($attributes['width'], -2)) == 'px') + { + $proposed_width = substr($attributes['width'], 0, -2); + // Now make sure that it's an integer and not something stupid. + if (filter_var($proposed_width, FILTER_VALIDATE_INT)) + { + $width = $proposed_width; + } + } + } + + // If there is a width in the style attributes: + if (isset($attributes['height']) && $height == -1) + { + // check that the last two characters are px (pixels) + if (strtolower(substr($attributes['height'], -2)) == 'px') + { + $proposed_height = substr($attributes['height'], 0, -2); + // Now make sure that it's an integer and not something stupid. + if (filter_var($proposed_height, FILTER_VALIDATE_INT)) + { + $height = $proposed_height; + } + } + } + + } + + // Future enhancement: + // Look in the tag to see if there is a class or id specified that has a height or width attribute to it. + + // Far future enhancement + // Look at all the parent tags of this image to see if they specify a class or id that has an img selector that specifies a height or width + // Note that in this case, the class or id will have the img subselector for it to apply to the image. + + // ridiculously far future development + // If the class or id is specified in a SEPARATE css file thats not on the page, go get it and do what we were just doing for the ones on the page. + + $result = array('height' => $height, + 'width' => $width); + return $result; + } + + // camel naming conventions + function getAllAttributes() {return $this->attr;} + function getAttribute($name) {return $this->__get($name);} + function setAttribute($name, $value) {$this->__set($name, $value);} + function hasAttribute($name) {return $this->__isset($name);} + function removeAttribute($name) {$this->__set($name, null);} + function getElementById($id) {return $this->find("#$id", 0);} + function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);} + function getElementByTagName($name) {return $this->find($name, 0);} + function getElementsByTagName($name, $idx=null) {return $this->find($name, $idx);} + function parentNode() {return $this->parent();} + function childNodes($idx=-1) {return $this->children($idx);} + function firstChild() {return $this->first_child();} + function lastChild() {return $this->last_child();} + function nextSibling() {return $this->next_sibling();} + function previousSibling() {return $this->prev_sibling();} + function hasChildNodes() {return $this->has_child();} + function nodeName() {return $this->tag;} + function appendChild($node) {$node->parent($this); return $node;} + +} + +/** + * simple html dom parser + * Paperg - in the find routine: allow us to specify that we want case insensitive testing of the value of the selector. + * Paperg - change $size from protected to public so we can easily access it + * Paperg - added ForceTagsClosed in the constructor which tells us whether we trust the html or not. Default is to NOT trust it. + * + * @package PlaceLocalInclude + */ +class simple_html_dom +{ + public $root = null; + public $nodes = array(); + public $callback = null; + public $lowercase = false; + // Used to keep track of how large the text was when we started. + public $original_size; + public $size; + protected $pos; + protected $doc; + protected $char; + protected $cursor; + protected $parent; + protected $noise = array(); + protected $token_blank = " \t\r\n"; + protected $token_equal = ' =/>'; + protected $token_slash = " />\r\n\t"; + protected $token_attr = ' >'; + // Note that this is referenced by a child node, and so it needs to be public for that node to see this information. + public $_charset = ''; + public $_target_charset = ''; + protected $default_br_text = ""; + public $default_span_text = ""; + + // use isset instead of in_array, performance boost about 30%... + protected $self_closing_tags = array('img'=>1, 'br'=>1, 'input'=>1, 'meta'=>1, 'link'=>1, 'hr'=>1, 'base'=>1, 'embed'=>1, 'spacer'=>1); + protected $block_tags = array('root'=>1, 'body'=>1, 'form'=>1, 'div'=>1, 'span'=>1, 'table'=>1); + // Known sourceforge issue #2977341 + // B tags that are not closed cause us to return everything to the end of the document. + protected $optional_closing_tags = array( + 'tr'=>array('tr'=>1, 'td'=>1, 'th'=>1), + 'th'=>array('th'=>1), + 'td'=>array('td'=>1), + 'li'=>array('li'=>1), + 'dt'=>array('dt'=>1, 'dd'=>1), + 'dd'=>array('dd'=>1, 'dt'=>1), + 'dl'=>array('dd'=>1, 'dt'=>1), + 'p'=>array('p'=>1), + 'nobr'=>array('nobr'=>1), + 'b'=>array('b'=>1), + 'option'=>array('option'=>1), + ); + + function __construct($str=null, $lowercase=true, $forceTagsClosed=true, $target_charset=DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) + { + if ($str) + { + if (preg_match("/^http:\/\//i",$str) || is_file($str)) + { + $this->load_file($str); + } + else + { + $this->load($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText); + } + } + // Forcing tags to be closed implies that we don't trust the html, but it can lead to parsing errors if we SHOULD trust the html. + if (!$forceTagsClosed) { + $this->optional_closing_array=array(); + } + $this->_target_charset = $target_charset; + } + + function __destruct() + { + $this->clear(); + } + + // load html from string + function load($str, $lowercase=true, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) + { + global $debug_object; + + // prepare + $this->prepare($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText); + // strip out cdata + $this->remove_noise("''is", true); + // strip out comments + $this->remove_noise("''is"); + // Per sourceforge http://sourceforge.net/tracker/?func=detail&aid=2949097&group_id=218559&atid=1044037 + // Script tags removal now preceeds style tag removal. + // strip out + + + + diff --git a/templates/layouts/empty.php b/templates/layouts/empty.php new file mode 100644 index 0000000..bc5ca49 --- /dev/null +++ b/templates/layouts/empty.php @@ -0,0 +1,6 @@ +get('UI').$template); + +?> \ No newline at end of file diff --git a/templates/layouts/login.php b/templates/layouts/login.php new file mode 100644 index 0000000..5ab9c82 --- /dev/null +++ b/templates/layouts/login.php @@ -0,0 +1,42 @@ + + + + + + + + + + <?php echo $f3->get('title'); ?> + + + + get('env')!="dev") { ?> + + + + + + + +
    +
    +
    +

    BackendAdmin

    +
    +
    +
    + +
    +
    + + +
    + + +
    +
    + + + + diff --git a/templates/views/index.php b/templates/views/index.php new file mode 100644 index 0000000..945c9b4 --- /dev/null +++ b/templates/views/index.php @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/templates/views/pages/terms.php b/templates/views/pages/terms.php new file mode 100644 index 0000000..e968b83 --- /dev/null +++ b/templates/views/pages/terms.php @@ -0,0 +1,43 @@ +
    + +
    +
    + +
    + +
    + Rules of the game +

    Rules of the game

    + +
    + + +

    Your e-mail address will be used to identify your submitted survey to contact you if you are one of the winners of the lottery. Five gift cards will be awarded worth € 100 that can be spend on Formal Friday products. You will be personally contacted over e-mail if you won one of these cards. The gift cards are valid for one year (January 2017 – January 2018) and can be used on purchases in the web-shop or in the Formal Friday store.

    + +

    The lottery will be organised in January 2017. Participants will be randomly selected by their e-mail from the pool of participants. The selection will be done in the office of Bomler in Germany. Five e-mail addresses will be randomly selected by using software. Afterwards, the winners will be informed over e-mail.

    +
      +
    • Surveys submitted in the month of December 2016 are counted as valid.
    • +
    • Multiple or duplicate submissions from one e-mail address will be disqualified from the lottery.
    • +
    • Employees from Bomler and Formal Friday are barred from participation.
    • +
    +

    If you have any questions or suggestions about the rules or our privacy policy, do not hesitate to contact us over e-mail: marketing@bomler.com.

    +

    +Srcd.it GmbH
    +Adelhauser Straße 22
    +79098 Freiburg im Breisgau
    +Germany +

    + +
    + +
    + + + +
    +
    + +
    +
    + +
    \ No newline at end of file diff --git a/tmp/.gitkeep b/tmp/.gitkeep new file mode 100644 index 0000000..1ec6b8a --- /dev/null +++ b/tmp/.gitkeep @@ -0,0 +1 @@ +EMPTY \ No newline at end of file diff --git a/vendor/autoload.php b/vendor/autoload.php new file mode 100644 index 0000000..82f7f25 --- /dev/null +++ b/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + + private $classMapAuthoritative = false; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative) { + return false; + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if ($file === null && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if ($file === null) { + // Remember that this class does not exist. + return $this->classMap[$class] = false; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirsPsr4[$prefix] as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE new file mode 100644 index 0000000..c8d57af --- /dev/null +++ b/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) 2015 Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..7a91153 --- /dev/null +++ b/vendor/composer/autoload_classmap.php @@ -0,0 +1,9 @@ + $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + + $loader->register(true); + + return $loader; + } +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json new file mode 100644 index 0000000..2e441ae --- /dev/null +++ b/vendor/composer/installed.json @@ -0,0 +1,48 @@ +[ + { + "name": "heroku/heroku-buildpack-php", + "version": "v120", + "version_normalized": "120.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/heroku/heroku-buildpack-php.git", + "reference": "e0499a7fdffd56f46534a037a6c48d65cef4e645" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/heroku/heroku-buildpack-php/zipball/e0499a7fdffd56f46534a037a6c48d65cef4e645", + "reference": "e0499a7fdffd56f46534a037a6c48d65cef4e645", + "shasum": "" + }, + "time": "2017-02-20 15:05:49", + "bin": [ + "bin/heroku-hhvm-apache2", + "bin/heroku-hhvm-nginx", + "bin/heroku-php-apache2", + "bin/heroku-php-nginx" + ], + "type": "library", + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David Zuelke", + "email": "dz@heroku.com" + } + ], + "description": "Toolkit for starting a PHP application locally, with or without foreman, using the same config for PHP/HHVM and Apache2/Nginx as on Heroku", + "homepage": "https://github.com/heroku/heroku-buildpack-php", + "keywords": [ + "apache", + "apache2", + "foreman", + "heroku", + "hhvm", + "nginx", + "php" + ] + } +] diff --git a/vendor/heroku/heroku-buildpack-php/.gitignore b/vendor/heroku/heroku-buildpack-php/.gitignore new file mode 100644 index 0000000..d40fd3e --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +composer.lock +vendor \ No newline at end of file diff --git a/vendor/heroku/heroku-buildpack-php/.travis.yml b/vendor/heroku/heroku-buildpack-php/.travis.yml new file mode 100644 index 0000000..0a3316f --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/.travis.yml @@ -0,0 +1,2 @@ +sudo: false +script: exit 0 diff --git a/vendor/heroku/heroku-buildpack-php/CHANGELOG.md b/vendor/heroku/heroku-buildpack-php/CHANGELOG.md new file mode 100644 index 0000000..cf994b9 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/CHANGELOG.md @@ -0,0 +1,750 @@ +# heroku-buildpack-php CHANGELOG + +## v120 (2017-02-20) + +### ADD + +- ext-blackfire/1.14.3 [David Zuelke] +- ext-mongodb/1.2.5 [David Zuelke] +- ext-redis/3.1.1 [David Zuelke] +- ext-imagick/3.4.3 [David Zuelke] +- ext-rdkafka/3.0.1 [David Zuelke] +- PHP/7.0.16 [David Zuelke] +- PHP/7.1.2 [David Zuelke] +- ext-memcached/3.0.3 [David Zuelke] + +### CHG + +- Allow overwriting of Apache access log format (now named `heroku`) in config include [David Zuelke] +- Composer/1.3.2 [David Zuelke] +- Use system libmcrypt and libmemcached on heroku-16 [David Zuelke] +- librdkafka/0.9.3 [David Zuelke] +- Enable `mod_proxy_wstunnel` in Apache config [David Zuelke] + +## v119 (2017-01-21) + +### FIX + +- Revert: ext-redis/3.1.0 [David Zuelke] +- Revert: Composer/1.3.1 [David Zuelke] + +## v118 (2017-01-20) + +### ADD + +- ext-redis/3.1.0 [David Zuelke] +- ext-rdkafka/3.0.0 [David Zuelke] +- ext-phalcon/3.0.3 [David Zuelke] +- ext-blackfire/1.14.2 [David Zuelke] +- ext-apcu/5.1.8 [David Zuelke] +- ext-mongodb/1.2.3 [David Zuelke] +- PHP/5.6.30 [David Zuelke] +- PHP/7.0.15 [David Zuelke] +- PHP/7.1.1 [David Zuelke] +- ext-newrelic/6.9.0 [David Zuelke] + +### CHG + +- Composer/1.3.1 [David Zuelke] +- Ignore `WEB_CONCURRENCY` values with leading zeroes [David Zuelke] +- Default `NEW_RELIC_APP_NAME` to `HEROKU_APP_NAME` [Christophe Coevoet] + +## v117 (2016-12-09) + +### ADD + +- ext-ev/1.0.4 [David Zuelke] +- ext-mongodb/1.2.1 [David Zuelke] +- PHP/7.0.14 [David Zuelke] +- PHP/5.6.29 [David Zuelke] + +### CHG + +- Composer/1.2.4 [David Zuelke] + +## v116 (2016-12-01) + +### ADD + +- PHP/7.1.0 [David Zuelke] +- ext-phalcon/3.0.2 [David Zuelke] +- ext-rdkafka/2.0.1 [David Zuelke] +- ext-mongodb/1.2.0 [David Zuelke] + +### FIX + +- Implicit and explicit stability flags for platform packages got ignored [David Zuelke] + +## v115 (2016-11-23) + +### ADD + +- ext-blackfire/1.14.1 [David Zuelke] + +### CHG + +- composer.json "require" or dependencies must now contain a runtime version requirement if "require-dev" or dependencies contain one [David Zuelke] + +## v114 (2016-11-10) + +### ADD + +- ext-apcu/5.1.7 [David Zuelke] +- ext-mongodb/1.1.9 [David Zuelke] +- ext-newrelic/6.8.0.177 [David Zuelke] +- PHP/7.0.13 [David Zuelke] +- PHP/5.6.28 [David Zuelke] +- ext-event/2.2.1 [David Zuelke] + +### CHG + +- Composer/1.2.2 [David Zuelke] +- Update to librdkafka-0.9.2 final for ext-rdkafka [David Zuelke] + +## v113 (2016-10-19) + +### ADD + +- ext-newrelic/6.7.0 [David Zuelke] +- ext-blackfire/1.13.0 [David Zuelke] +- ext-apcu/5.1.6 [David Zuelke] +- PHP/5.6.27 [David Zuelke] +- PHP/7.0.12 [David Zuelke] +- ext-rdkafka/1.0.0 [David Zuelke] +- ext-rdkafka/2.0.0 [David Zuelke] + +## v112 (2016-09-20) + +### FIX + +- Use Composer/1.2.1 [David Zuelke] + +## v111 (2016-09-20) + +### ADD + +- ext-newrelic/6.6.1.172 [David Zuelke] +- PHP/5.6.26 [David Zuelke] +- PHP/7.0.11 [David Zuelke] + +### CHG + +- Use Composer/1.2.1 [David Zuelke] + +## v110 (2016-08-26) + +### ADD + +- ext-ev/1.0.3 [David Zuelke] +- ext-phalcon/2.0.13 [David Zuelke] +- ext-cassandra/1.2.2 [David Zuelke] +- ext-blackfire/1.12.0 [David Zuelke] +- ext-newrelic/6.6.0 [David Zuelke] +- PHP/5.6.25 [David Zuelke] +- PHP/7.0.10 [David Zuelke] +- ext-phalcon/3.0.1 [David Zuelke] + +### CHG + +- Retry downloads up to three times during bootstrapping [David Zuelke] +- Composer/1.2.0 [David Zuelke] + +## v109 (2016-07-21) + +### ADD + +- PHP/7.0.9 [David Zuelke] +- PHP/5.6.24 [David Zuelke] +- PHP/5.5.38 [David Zuelke] + +## v108 (2016-07-08) + +### ADD + +- ext-oauth/2.0.2 [David Zuelke] +- ext-mongodb/1.1.8 [David Zuelke] +- ext-blackfire/1.11.1 [David Zuelke] +- PHP/5.5.37 [David Zuelke] +- PHP/5.6.23 [David Zuelke] +- PHP/7.0.8 [David Zuelke] + +### CHG + +- Composer/1.1.3 [David Zuelke] + +### FIX + +- Revert to ext-redis/2.2.7 due to reported segfaults/memleaks [David Zuelke] + +## v107 (2016-06-18) + +### ADD + +- ext-redis/2.2.8 [David Zuelke] +- ext-redis/3.0.0 [David Zuelke] +- ext-newrelic/6.4.0 [David Zuelke] +- ext-blackfire/1.10.6 [David Zuelke] + +### FIX + +- Custom `COMPOSER` env var breaks platform installs [David Zuelke] + +## v106 (2016-06-08) + +### ADD + +- ext-mongodb/1.1.7 [David Zuelke] +- ext-cassandra/1.1.0 [David Zuelke] +- ext-apcu/5.1.5 [David Zuelke] +- ext-event/2.1.0 [David Zuelke] + +### CHG + +- Use Composer/1.1.2 [David Zuelke] + +## v105 (2016-05-27) + +### ADD + +- PHP/5.5.36 [David Zuelke] +- PHP/5.6.22 [David Zuelke] +- PHP/7.0.7 [David Zuelke] + +## v104 (2016-05-20) + +### ADD + +- ext-pq/1.1.1 and 2.1.1 [David Zuelke] + +## v103 (2016-05-20) + +### ADD + +- ext-pq/1.0.1 and 2.0.1 [David Zuelke] +- ext-apcu/5.1.4 [David Zuelke] +- ext-newrelic/6.3.0.161 [David Zuelke] +- ext-ev/1.0.0 [David Zuelke] + +### CHG + +- Composer/1.1.1 [David Zuelke] + +## v102 (2016-04-29) + +### ADD + +- ext-newrelic/6.2.0 [David Zuelke] +- ext-blackfire/1.10.5 [David Zuelke] +- ext-apcu/4.0.11 [David Zuelke] +- ext-event/2.0.4 [David Zuelke] +- ext-imagick/3.4.2 [David Zuelke] +- ext-mongo/1.6.14 [David Zuelke] +- PHP/5.5.35 [David Zuelke] +- PHP/5.6.21 [David Zuelke] +- PHP/7.0.6 [David Zuelke] + +### CHG + +- Bundle `blackfire` CLI binary with ext-blackfire [David Zuelke] +- Build PHP with `php-cgi` executable [David Zuelke] +- Composer/1.0.3 [David Zuelke] + +## v101 (2016-04-12) + +### ADD + +- ext-event/2.0.2 [David Zuelke] +- ext-mongodb/1.1.6 [David Zuelke] +- Apache/2.4.20 [David Zuelke] +- ext-blackfire/1.10.3 [David Zuelke] + +### CHG + +- Use Composer/1.0.0 stable [David Zuelke] + +## v100 (2016-03-31) + +### ADD + +- ext-imap for all PHP versions [David Zuelke] +- ext-pq/1.0.0 and 2.0.0 [David Zuelke] +- PHP/7.0.5 [David Zuelke] +- PHP/5.6.20 [David Zuelke] +- PHP/5.5.34 [David Zuelke] + +### CHG + +- Return to using built-in default value for the `pcre.jit` PHP INI setting [David Zuelke] +- Use Composer/1.0.0beta2 [David Zuelke] +- Use first configured platform repository to load components for bootstrapping [David Zuelke] + +## v99 (2016-03-23) + +### FIX + +- Automatic extensions (blackfire, newrelic) may fail to get installed with many dependencies [David Zuelke] + +## v98 (2016-03-21) + +### ADD + +- ext-event/2.0.1 [David Zuelke] +- ext-mongo/1.6.13 [David Zuelke] +- ext-mongodb/1.1.5 [David Zuelke] +- ext-oauth/2.0.1 [David Zuelke] +- ext-newrelic/6.1.0.157 [David Zuelke] +- ext-blackfire/1.10.0 [David Zuelke] + +### CHG + +- Remove GitHub API rate limit checks during build time [David Zuelke] +- Change pcre.jit to 0 in php.ini [David Zuelke] + +## v97 (2016-03-10) + +### CHG + +- Temporarily downgrade to ext-newrelic/5.1.1.130 [David Zuelke] + +## v96 (2016-03-10) + +### ADD + +- ext-imagick/3.4.1 for all PHP versions, with platform imagemagick [David Zuelke] +- ext-mongodb/1.1.3 [David Zuelke] +- ext-ldap, with SASL, for PHP builds (#131) [David Zuelke] +- ext-gmp for PHP builds (#117) [David Zuelke] +- ext-event/2.0.0 [David Zuelke] +- apcu_bc for ext-apcu on PHP 7 (#137) [David Zuelke] +- ext-newrelic/6.0.1.156 (#153) [David Zuelke] + +### CHG + +- Use Composer/1.0.0beta1 [David Zuelke] +- Remove vendored ICU library and use platform ICU52 for PHP [David Zuelke] +- Remove vendored zlib and use platform version for PHP and Apache [David Zuelke] +- Remove vendored pcre library and use platform version for Apache [David Zuelke] +- Use platform pcre and zlib for Nginx [David Zuelke] +- Update vendored gettext to 0.19.7 and build only its runtime parts [David Zuelke] +- Use platform libsasl for libmemcached [David Zuelke] +- Strip platform packages on build install [David Zuelke] +- Ignore platform package replace/provide/conflict from root `composer.json` on platform package install [David Zuelke] + +### FIX + +- Platform installer is incompatible with PHP 5.5 [David Zuelke] + +## v95 (2016-03-03) + +### ADD + +- PHP/5.5.33 [David Zuelke] +- PHP/5.6.19 [David Zuelke] +- PHP/7.0.4 [David Zuelke] +- ext-blackfire/1.9.2 [David Zuelke] +- Nginx/1.8.1 [David Zuelke] +- Apache/2.4.18 [David Zuelke] + +## v94 (2016-02-26) + +### FIX + +- No web servers get selected when a `composer.lock` is missing [David Zuelke] + +## v93 (2016-02-26) + +### ADD + +- Support custom platform repositories via space separated `HEROKU_PHP_PLATFORM_REPOSITORIES` env var; leading "-" entry disables default repository [David Zuelke] + +### CHG + +- A `composer.phar` in the project root will no longer be aliased to `composer` on dyno startup [David Zuelke] +- Runtimes, extensions and web servers are now installed as fully self-contained Composer packages [David Zuelke] +- Perform boot script startup checks without loading unnecessary PHP configs or extensions [David Zuelke] +- ext-blackfire builds are now explicitly versioned (currently v1.9.1) [David Zuelke] +- Append `composer config bin-dir` to `$PATH` for runtime [David Zuelke] +- Check for lock file freshness using `composer validate` (#141) [David Zuelke] +- Change PHP `expose_php` to `off`, Apache `ServerTokens` to `Prod` and Nginx `server_tokens` to `off` for builds (#91, #92) [David Zuelke] +- Respect "provide", "replace" and "conflict" platform packages in dependencies and composer.json for platform package installs [David Zuelke] + +### FIX + +- Internal `php-min` symlink ends up in root of built apps [David Zuelke] +- Manifest for ext-apcu/4.0.10 does not declare ext-apc replacement [David Zuelke] +- Boot scripts exit with status 0 when given invalid flag as argument [David Zuelke] +- Manifest for ext-memcached/2.2.0 declares wrong PHP requirement for PHP 5.6 build [David Zuelke] +- Setting `NEW_RELIC_CONFIG_FILE` breaks HHVM builds (#149) [David Zuelke] + +## v92 (2016-02-09) + +### ADD + +- ext-apcu/5.1.3 [David Zuelke] +- PHP/5.5.32 [David Zuelke] +- PHP/5.6.18 [David Zuelke] +- PHP/7.0.3 [David Zuelke] +- ext-phalcon/2.0.10 [David Zuelke] +- ext-blackfire for PHP 7 [David Zuelke] + +### CHG + +- Refactor and improve build manifest helpers, add bucket sync tooling [David Zuelke] +- Use Bob 0.0.7 for builds [David Zuelke] + +### FIX + +- PHP 7 extension formulae use wrong API version in folder name [David Zuelke] +- Composer build formula depends on removed PHP formula [Stefan Siegl] + +## v91 (2016-01-08) + +### ADD + +- ext-phalcon/2.0.9 [David Zuelke] +- PHP/7.0.2 [David Zuelke] +- PHP/5.6.17 [David Zuelke] +- PHP/5.5.31 [David Zuelke] +- ext-apcu/5.1.2 [David Zuelke] +- ext-mongodb/1.1.2 [David Zuelke] +- ext-oauth/2.0.0 [David Zuelke] + +## v90 (2015-12-18) + +### ADD + +- PHP/7.0.1 [David Zuelke] + +### CHG + +- Double default INI setting values for `opcache.memory_consumption`, `opcache.interned_strings_buffer` and `opcache.max_accelerated_files` [David Zuelke] + +## v89 (2015-12-15) + +### FIX + +- HHVM builds failing when trying to install New Relic or Blackfire [David Zuelke] + +## v88 (2015-12-15) + +### CHG + +- Big loud warnings if `composer.lock` is outdated (or even broken) [David Zuelke] +- Auto-install `ext-blackfire` and `ext-newrelic` at the very end of the build to avoid them instrumenting build steps or cluttering output with startup messages [David Zuelke] + +### FIX + +- Buildpack does not export PATH for multi-buildpack usage [David Zuelke] +- Composer limitation leads to lower than possible PHP versions getting resolved [David Zuelke] +- `lib-` platform package requirements may prevent dependency resolution [David Zuelke] +- Invalid/broken `composer.lock` produces confusing error message [David Zuelke] + +## v87 (2015-12-11) + +### CHG + +- Further improve error information on failed system package install [David Zuelke] +- Notice if implicit version selection based on dependencies' requirements is made [David Zuelke] + +### FIX + +- "`|`" operators in `composer.lock` platform package requirements break system package dependency resolution [David Zuelke] +- Notice about missing runtime version selector does not show up in all cases [David Zuelke] + +## v86 (2015-12-10) + +### ADD + +- PHP/7.0.0 [David Zuelke] +- PHP/5.6.16 [David Zuelke] +- ext-apcu/4.0.10 [David Zuelke] +- ext-mongo/1.6.12 [David Zuelke] +- ext-imagick/3.3.0 [David Zuelke] +- ext-blackfire/1.7.0 [David Zuelke] + +### CHG + +- Rewrite most of the build process; system packages are now installed using a custom Composer installer and Composer repository [David Zuelke] + +## v83 (2015-11-16) + +### ADD + +- Composer/1.0.0-alpha11 [David Zuelke] +- PHP/7.0.0RC7 [David Zuelke] + +### CHG + +- Improve Composer vendor and bin dir detection in build sources [David Zuelke] +- Deprecate concurrent installs of HHVM and PHP [David Zuelke] +- Start New Relic daemon manually on Dyno boot to ensure correct behavior with non web PHP programs [David Zuelke] + +### FIX + +- Wrong Apache dist URL in support/build [David Zuelke] +- Build failure if `heroku-*-*` boot scripts are committed to Git in Composer bin dir [David Zuelke] +- Broken signal handling in boot scripts on Linux [David Zuelke] + +## v82 (2015-10-31) + +### CHG + +- Downgrade Apache 2.4.17 to Apache 2.4.16 due to `REDIRECT_URL` regression [David Zuelke] + +## v81 (2015-10-30) + +### ADD + +- PHP/7.0.0RC6 [David Zuelke] +- PHP/5.6.15 [David Zuelke] + +## v80 (2015-10-15) + +### ADD + +- Nginx/1.8.0 [David Zuelke] +- Apache/2.4.17 [David Zuelke] +- PHP/7.0.0RC5 [David Zuelke] + +### CHG + +- Use system default php.ini config instead of buildpacks' if no custom config given [David Zuelke] + +## v79 (2015-10-08) + +### CHG + +- Enable Apache modules `ssl_module` and `mod_proxy_html` (with `mod_xml2enc` dependency) by default [David Zuelke] + +## v78 (2015-10-01) + +### ADD + +- PHP/7.0.0RC4 [David Zuelke] +- PHP/5.5.30 [David Zuelke] +- PHP/5.6.14 [David Zuelke] + +## v77 (2015-09-17) + +### ADD + +- PHP/7.0.0RC3 [David Zuelke] + +## v76 (2015-09-08) + +### ADD + +- ext-mongo/1.6.11 [David Zuelke] +- PHP/7.0.0RC2 [David Zuelke] +- PHP/5.5.29 [David Zuelke] +- PHP/5.6.13 [David Zuelke] + +## v75 (2015-08-21) + +### FIX + +- Prevent potential (benign) Python notice during builds + +## v74 (2015-08-21) + +### FIX + +- Warning about missing composer.lock is thrown incorrectly for some composer.json files + +## v72 (2015-08-21) + +### ADD + +- PHP/5.6.12 [David Zuelke] +- PHP/5.5.28 [David Zuelke] +- ext-newrelic/4.23.4.113 [David Zuelke] +- PHP/7.0.0RC1 [David Zuelke] +- Support custom `composer.json`/`composer.lock` file names via `$COMPOSER` env var [David Zuelke] + +### CHG + +- A composer.lock is now required if there is any entry in the "require" section of composer.json [David Zuelke] + +## v71 (2015-07-14) + +### ADD + +- ext-newrelic/4.23.1.107 [David Zuelke] + +### FIX + +- Apache `mod_proxy_fgci`'s "disablereuse=off" config flag causes intermittent blank pages with HTTPD 2.4.11+ [David Zuelke] +- Applications on cedar-10 can select non-existing PHP 7.0.0beta1 package via composer.json [David Zuelke] + +## v70 (2015-07-10) + +### ADD + +- PHP/7.0.0beta1 [David Zuelke] +- PHP/5.6.11 [David Zuelke] +- PHP/5.5.27 [David Zuelke] +- ext-newrelic/4.23.0.102 [David Zuelke] +- ext-mongo/1.6.10 [David Zuelke] +- Support auto-tuning for IX dyno type [David Zuelke] + +### CHG + +- Warn about missing extensions for "blackfire" and "newrelic" add-ons during startup [David Zuelke] + +## v69 (2015-06-12) + +### ADD + +- PHP/5.5.26 [David Zuelke] +- PHP/5.6.10 [David Zuelke] +- ext-newrelic/4.22.0.99 [David Zuelke] +- ext-mongo/1.6.9 [David Zuelke] + +## v68 (2015-05-18) + +### ADD + +- PHP/5.6.9 [David Zuelke] +- PHP/5.5.25 [David Zuelke] +- ext-newrelic/4.21.0.97 [David Zuelke] +- ext-mongo/1.6.8 [David Zuelke] + +### CHG + +- Use Composer/1.0.0alpha10 [David Zuelke] +- Link only `.heroku/php/` subfolder and not all of `.heroku/` during compile to prevent potential collisions in multi BP scenarios [David Zuelke] + +### FIX + +- Typo in log messages [Christophe Coevoet] +- Newrelic 4.21 agent startup complaining about missing pidfile location config [David Zuelke] + +## v67 (2015-03-24) + +### ADD + +- ext-mongo/1.6.6 [David Zuelke] +- PHP/5.6.7 [David Zuelke] +- PHP/5.5.23 [David Zuelke] + +### CHG + +- Don't run composer install for empty composer.json [David Zuelke] +- Unset GIT_DIR at beginning of compile [David Zuelke] + +## v66 (2015-03-05) + +### ADD + +- ext-newrelic/4.19.0.90 [David Zuelke] + +## v65 (2015-03-03) + +### ADD + +- ext-redis/2.2.7 [David Zuelke] +- ext-mongo/1.6.4 [David Zuelke] +- HHVM/3.3.4 [David Zuelke] + +### CHG + +- Composer uses stderr now for most output, indent that accordingly [David Zuelke] + +## v64 (2015-02-19) + +### ADD + +- HHVM/3.5.1 [David Zuelke] +- PHP/5.6.6 [David Zuelke] +- PHP/5.5.22 [David Zuelke] +- ext-newrelic/4.18.0.89 [David Zuelke] +- ext-mongo/1.6.3 [David Zuelke] + +## v63 (2015-02-11) + +### ADD + +- ext-mongo/1.6.2 [David Zuelke] + +### CHG + +- Tweak auto-tuning messages (tag: v63) [David Zuelke] +- Move 'booting...' message to after startup has finished [David Zuelke] +- Ignore SIGINT when running under foreman etc to ensure clean shutdown [David Zuelke] +- Prevent redundant messages when loading HHVM configs [David Zuelke] +- Echo "running workers..." message to stderr on boot [David Zuelke] + +### FIX + +- Incorrect 'child 123 said into stderr' removal for lines that are deemed to long by FPM and cut off using a terminating '...' sequence instead of closing double quotes [David Zuelke] + +## v62 (2015-02-04) + +### FIX + +- Broken PHP memlimit check [David Zuelke] + +## v61 (2015-02-04) + +### CHG + +- Port autotuning to HHVM-Nginx [David Zuelke] + +### FIX + +- Workaround for Composer's complaining about outdated version warnings on stdout instead of stderr, breaking calls in a few places under certain circumstances [David Zuelke] + +## v60 (2015-02-04) + +### ADD + +- Auto-tune number of workers based on dyno size and configured memory limit [David Zuelke] + +## v59 (2015-01-29) + +### ADD + +- ext-mongo/1.6.0 (tag: v59) [David Zuelke] + +### CHG + +- Improvements to INI handling for HHVM, including new `-I` switch to allow passing additional INI files at boot [David Zuelke] +- Massively improved subprocess and signal handling in boot scripts [David Zuelke] + +## v58 (2015-01-26) + +### ADD + +- HHVM/3.5.0 [David Zuelke] +- PHP/5.6.5 [David Zuelke] +- PHP/5.5.21 [David Zuelke] + +## v57 (2015-01-19) + +### CHG + +- Update to Composer dev version for `^` selector support [David Zuelke] + +## v56 (2015-01-13) + +### ADD + +- ext/oauth 1.2.3 [David Zuelke] +- HHVM/3.3.3 [David Zuelke] +- Run 'composer compile' for custom scripts at the end of deploy [David Zuelke] + +## v55 (2015-01-07) + +### FIX + +- Standard logs have the wrong $PORT in the file name if the -p option is used in boot scripts [David Zuelke] + +## v54 (2015-01-05) + +### ADD + +- ext-newrelic/4.17.0.83 [David Zuelke] + +### CHG + +- Auto-set and follow (but not enable, for now) the FPM slowlog [David Zuelke] diff --git a/vendor/heroku/heroku-buildpack-php/LICENSE b/vendor/heroku/heroku-buildpack-php/LICENSE new file mode 100644 index 0000000..22c3fcd --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Heroku, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/heroku/heroku-buildpack-php/README.md b/vendor/heroku/heroku-buildpack-php/README.md new file mode 100644 index 0000000..5ebd7f6 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/README.md @@ -0,0 +1,55 @@ +# Heroku buildpack: PHP [![Build Status](https://travis-ci.org/heroku/heroku-buildpack-php.svg?branch=master)](https://travis-ci.org/heroku/heroku-buildpack-php) + +![php](https://cloud.githubusercontent.com/assets/51578/8882982/73ea501a-3219-11e5-8f87-311e6b8a86fc.jpg) + + +This is the official [Heroku buildpack](http://devcenter.heroku.com/articles/buildpacks) for PHP applications. + +It uses Composer for dependency management, supports PHP or HHVM (experimental) as runtimes, and offers a choice of Apache2 or Nginx web servers. + +## Usage + +You'll need to use at least an empty `composer.json` in your application. + + $ echo '{}' > composer.json + $ git add composer.json + $ git commit -m "add composer.json for PHP app detection" + +If you also have files from other frameworks or languages that could trigger another buildpack to detect your application as one of its own, e.g. a `package.json` which might cause your code to be detected as a Node.js application even if it is a PHP application, then you need to manually set your application to use this buildpack: + + $ heroku buildpacks:set heroku/php + +This will use the officially published version. To use the `master` branch from GitHub instead: + + $ heroku buildpacks:set https://github.com/heroku/heroku-buildpack-php + +Please refer to [Dev Center](https://devcenter.heroku.com/categories/php) for further usage instructions. + +## Custom Platform Repositories + +The buildpack uses Composer repositories to resolve platform (`php`, `hhvm`, `ext-something`, ...) dependencies. + +To use a custom Composer repository with additional or different platform packages, add the URL to its `packages.json` to the `HEROKU_PHP_PLATFORM_REPOSITORIES` config var: + + $ heroku config:set HEROKU_PHP_PLATFORM_REPOSITORIES="https://mybucket.s3.amazonaws.com/cedar-14/packages.json" + +To allow the use of multiple custom repositories, the config var may hold a list of multiple repository URLs, separated by a space character, in ascending order of precedence. + +If the first entry in the list is "`-`" instead of a URL, the default platform repository is disabled entirely. This can be useful when testing development repositories, or to forcefully prevent the use of unwanted packages from the default platform repository. + +For instructions on how to build custom platform packages (and a repository to hold them), please refer to the instructions [further below](#custom-platform-packages-and-repositories). + +**Please note that Heroku cannot provide support for issues related to custom platform repositories and packages.** + +## Development + +The following information only applies if you're forking and hacking on this buildpack for your own purposes. + +### Pull Requests + +Please submit all pull requests against `develop` as the base branch. + +### Custom Platform Packages and Repositories + +Please refer to the [README in `support/build/`](support/build/README.md) for instructions. + diff --git a/vendor/heroku/heroku-buildpack-php/bin/compile b/vendor/heroku/heroku-buildpack-php/bin/compile new file mode 100755 index 0000000..dbd969b --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/compile @@ -0,0 +1,302 @@ +#!/usr/bin/env bash + +# bin/compile + +# fail hard +set -o pipefail +# fail harder +set -eu +# move hidden files too, just in case +shopt -s dotglob + +STACK=${STACK:-cedar-14} # Anvil has none +build_dir=$1 +cache_dir=$2/php +mkdir -p "$cache_dir" +env_dir=${3:-} # Anvil has none +bp_dir=$(cd $(dirname $0); cd ..; pwd) + +# convenience functions +source $bp_dir/bin/util/common.sh + +# for extensions that need special treatment +source $bp_dir/bin/util/newrelic.sh +source $bp_dir/bin/util/blackfire.sh + +# if this is set it prevents Git clones (e.g. for Composer installs from source) during the build in some circumstances, and it is set in SSH Git deploys to Heroku +unset GIT_DIR + +cd $build_dir + +export_env_dir "$env_dir" '^COMPOSER$' +if [[ -n ${COMPOSER:-} ]]; then + status "Using '$COMPOSER' (from "'$COMPOSER env var) for installation.' +else + export COMPOSER="composer.json" +fi +export COMPOSER_LOCK=$(basename "$COMPOSER" ".json")".lock" # replace .json with .lock if it exists, append .lock otherwise + +# a bunch of sanity checks first +if [[ -s "$COMPOSER" ]]; then + cat "$COMPOSER" | python -mjson.tool &> /dev/null || error "Could not parse '$COMPOSER'; make sure it's valid!" + if [[ ! -f "$COMPOSER_LOCK" ]]; then + cat "$COMPOSER" | python -c 'import sys, json; sys.exit(bool(json.load(sys.stdin).get("require", {})))' 2> /dev/null || error "Your '$COMPOSER' lists dependencies inside 'require', +but no '$COMPOSER_LOCK' was found. Please run 'composer update' to +re-generate '$COMPOSER_LOCK' if necessary, and commit it into your +repository. For more information, please refer to the docs at +https://devcenter.heroku.com/articles/php-support#activation" + else + cat "$COMPOSER_LOCK" | python -mjson.tool &> /dev/null || error "Could not parse '$COMPOSER_LOCK'; make sure it's valid!" + cat "$COMPOSER_LOCK" | python -c 'import sys, json; l = json.load(sys.stdin); sys.exit(not(l["minimum-stability"] == "stable"));' 2> /dev/null || warning "Your '$COMPOSER' contains a non-'stable' setting +for 'minimum-stability'. This may cause the installation of +unstable versions of runtimes and extensions during this deploy. +It is recommended that you always use stability flags instead, +even if you have 'prefer-stable' enabled. For more information, +see https://getcomposer.org/doc/01-basic-usage.md#stability" + fi +else + if [[ ! -f "$COMPOSER" ]]; then + warning "No '$COMPOSER' found. +Using 'index.php' to declare app type as PHP is considered legacy +functionality and may lead to unexpected behavior." + else + notice "Your '$COMPOSER' is completely empty. +Please change its contents to at least '{}' so it is valid JSON." + fi + echo "{}" > $COMPOSER +fi + +# PHP expects to be installed in /app/.heroku/php because of compiled paths, let's set that up! +mkdir -p /app/.heroku +# all system packages live in there +mkdir -p $build_dir/.heroku/php +# set up Composer +export COMPOSER_HOME=$cache_dir/.composer +mkdir -p $COMPOSER_HOME + +# if the build dir is not "/app", we symlink in the .heroku/php subdir (and only that, to avoid problems with other buildpacks) so that PHP correctly finds its INI files etc +[[ $build_dir == '/app' ]] || ln -s $build_dir/.heroku/php /app/.heroku/php + +status "Bootstrapping..." + +s3_url="https://lang-php.s3.amazonaws.com/dist-${STACK}-stable/" +# prepend the default repo to the list configured by the user +# list of repositories to use is in ascening order of precedence +export_env_dir "$env_dir" '^HEROKU_PHP_PLATFORM_REPOSITORIES$' +HEROKU_PHP_PLATFORM_REPOSITORIES="${s3_url} ${HEROKU_PHP_PLATFORM_REPOSITORIES:-}" +if [[ "${HEROKU_PHP_PLATFORM_REPOSITORIES}" == *" - "* ]]; then + # a single "-" in the user supplied string removes everything to the left of it; can be used to delete the default repo + notice_inline "Default platform repository disabled." + HEROKU_PHP_PLATFORM_REPOSITORIES=${HEROKU_PHP_PLATFORM_REPOSITORIES#*" - "} + s3_url=$(echo "$HEROKU_PHP_PLATFORM_REPOSITORIES" | cut -f1 -d" " | sed 's/[^/]*$//') + notice_inline "Bootstrapping using ${s3_url}..." +fi + + +# minimal PHP needed for installs, and make "composer" invocations use that for now +mkdir -p $build_dir/.heroku/php-min +ln -s $build_dir/.heroku/php-min /app/.heroku/php-min + +curl_retry_on_18 --silent --location -o $build_dir/.heroku/php-min.tar.gz "${s3_url}php-min-7.0.16.tar.gz" || error "Failed to download minimal PHP for bootstrapping. +Please try again, or contact support if this problem persists." +tar xzf $build_dir/.heroku/php-min.tar.gz -C $build_dir/.heroku/php-min +rm $build_dir/.heroku/php-min.tar.gz + +curl_retry_on_18 --silent --location -o $build_dir/.heroku/composer.tar.gz "${s3_url}composer-1.3.2.tar.gz" || error "Failed to download Composer. Please try again, or contact support if this problem persists." +tar xzf $build_dir/.heroku/composer.tar.gz -C $build_dir/.heroku/php +rm $build_dir/.heroku/composer.tar.gz + +# this alias is just for now while we install platform packages +composer() { + /app/.heroku/php-min/bin/php /app/.heroku/php/bin/composer "$@" +} +export -f composer + +composer_vendordir=$(composer config vendor-dir) +composer_bindir=$(composer config bin-dir) + +# packages that get installed will add to this file, it's both for us and for buildpacks that follow +# composer bin-dir goes last to avoid any conflicts +echo "export PATH=/app/.heroku/php/bin:\$PATH:/app/$composer_bindir" > $bp_dir/export +# make sure Composer and binaries for it are on the path at runtime +# composer bin-dir goes last to avoid any conflicts +mkdir -p $build_dir/.profile.d +echo "export PATH=\$HOME/.heroku/php/bin:\$PATH:\$HOME/$composer_bindir" > $build_dir/.profile.d/100-composer.sh + +status "Installing platform packages..." + +# extract requirements from composer.lock +/app/.heroku/php-min/bin/php $bp_dir/bin/util/platform.php "$bp_dir/support/installer/" $HEROKU_PHP_PLATFORM_REPOSITORIES 2>&1 >$build_dir/.heroku/php/composer.json | indent || error "Couldn't load '$COMPOSER_LOCK'; it must be a valid lock +file generated by Composer and be in a consistent state. +Check above for any parse errors and address them if necessary. +Run 'composer update', add/commit the change, then push again." + +# reset COMPOSER for the platform install step +COMPOSER_bak="$COMPOSER" +export COMPOSER=composer.json + +# pass export_file_path and profile_dir_path to composer install; they will be used by the installer plugin +# they are also used in later install attempts for add-on extensions (blackfire, newrelic, ...) +export export_file_path=$bp_dir/export +export profile_dir_path=$build_dir/.profile.d +if composer install -d "$build_dir/.heroku/php" ${HEROKU_PHP_INSTALL_DEV-"--no-dev"} 2>&1 | tee $build_dir/.heroku/php/install.log | grep --line-buffered -E '^ - (Instal|Enab)ling heroku-sys/' | sed -u -E -e 's/^ - (Instal|Enab)ling /- /' -e 's/heroku-sys\///g' | indent; then + : +else + error "Failed to install system packages. + +Your platform requirements (for runtimes and extensions) could +not be resolved to an installable set of dependencies, or a +repository was unreachable. + +Full error information from installation attempt: + +$(cat $build_dir/.heroku/php/install.log | sed -e 's/heroku-sys\///g' -e 's/^Loading composer repositories with package information/Loading repositories with available runtimes and extensions/' -e 's/^Installing dependencies.*//' -e '/^Potential causes:/,$d' -e 's/^/> /') + +Please verify that all requirements for runtime versions in +'$COMPOSER_LOCK' are compatible with the list below, and ensure +all required extensions are available for the desired runtimes. + +For reference, the following runtimes are currently available: + +PHP: $(composer show -d "$build_dir/.heroku/php" --available heroku-sys/php 2>&1 | sed -n 's/^versions : //p' | fold -s -w 58 || true) +HHVM: $(composer show -d "$build_dir/.heroku/php" --available heroku-sys/hhvm 2>&1 | sed -n 's/^versions : //p' | fold -s -w 58 || true) + +For a list of supported runtimes & extensions on Heroku, please +refer to: https://devcenter.heroku.com/articles/php-support" +fi + +if composer show -d "$build_dir/.heroku/php" --installed --quiet heroku-sys/php 2>/dev/null; then + engine="php" + engine_r="php -r" +elif composer show -d "$build_dir/.heroku/php" --installed --quiet heroku-sys/hhvm 2>/dev/null; then + engine="hhvm" + engine_r="hhvm --php -r" +fi + +# done with platform installs; restore COMPOSER from previous value +export COMPOSER="$COMPOSER_bak" +unset COMPOSER_bak + +composer validate --no-check-publish --no-check-all --quiet "$COMPOSER" 2>/dev/null || warning "Your '$COMPOSER_LOCK' is not up to date with the latest +changes in '$COMPOSER'. To ensure you are not getting stale +dependencies, run 'composer update' on your machine and commit +any changes to Git before pushing again." + +# clean up +rm -rf /app/.heroku/php-min $build_dir/.heroku/php-min +unset -f composer + +# earlier we wrote at least one $PATH entry that we'll need now, and installed packages will likely have added to it too +source $bp_dir/export + +composer() { + $engine $(which composer) "$@" +} +export -f composer + +status "Installing dependencies..." + +# check if we should use a composer.phar version bundled with the project +if [[ -f "composer.phar" ]]; then + [[ -x "composer.phar" ]] || error "File '/composer.phar' isn't executable; please 'chmod +x'!" + $engine_r 'new Phar("composer.phar");' &> /dev/null || error "File '/composer.phar' is not a valid PHAR archive!" + composer() { + $engine composer.phar "$@" + } + export -f composer + composer --version 2>&1 | grep "^Composer version" > /dev/null || error "File '/composer.phar' is not a Composer executable!" + notice_inline "Using '/composer.phar' to install dependencies." +fi +# echo composer version for info purposes +# tail to get rid of outdated version warnings (Composer sends those to STDOUT instead of STDERR) +composer --version 2> /dev/null | tail -n 1 | indent + +# throw a notice if people have added their vendor dir to Git; that's bad practice and makes everything slow and cluttered +if [[ -f "$composer_vendordir/autoload.php" && -d "$composer_vendordir/composer" ]]; then + # we should not do this check separately; there is no reliable way of telling whether or not it really is the real Composer bin dir or if it comes from somewhere else + composer_warn_bindir="" + if [[ ! "$composer_bindir/" == "$composer_vendordir"/* && -d "$composer_bindir" ]]; then + composer_warn_bindir=" +Your Composer bin dir is configured to reside outside of vendor +dir, so please repeat the two steps above for '$composer_bindir/'." + fi + warning "Your Composer vendor dir is part of your Git repository. +This directory should not be under version control; only your +'$COMPOSER' and '$COMPOSER_LOCK' files should be added, which +will let Composer handle installation of dependencies on deploy. +To suppress this notice, first remove the folder from your index +by running 'git rm -r --cached $composer_vendordir/'. +Next, edit your project's '.gitignore' file and add the folder +'/$composer_vendordir/' to the list.$composer_warn_bindir +For more info, refer to the Composer FAQ: http://bit.ly/1rlCSZU" +fi + +# handle custom oauth keys +export_env_dir "$env_dir" '^COMPOSER_GITHUB_OAUTH_TOKEN$' +COMPOSER_GITHUB_OAUTH_TOKEN=${COMPOSER_GITHUB_OAUTH_TOKEN:-} +if [[ -n "$COMPOSER_GITHUB_OAUTH_TOKEN" ]]; then + if curl --fail --silent -H "Authorization: token $COMPOSER_GITHUB_OAUTH_TOKEN" https://api.github.com/rate_limit > /dev/null; then + composer config -g github-oauth.github.com "$COMPOSER_GITHUB_OAUTH_TOKEN" &> /dev/null # redirect outdated version warnings (Composer sends those to STDOUT instead of STDERR) + notice_inline 'Using $COMPOSER_GITHUB_OAUTH_TOKEN for GitHub OAuth.' + else + error 'Invalid $COMPOSER_GITHUB_OAUTH_TOKEN for GitHub OAuth!' + fi +else + # don't forget to remove any stored key if it's gone from the env + composer config -g --unset github-oauth.github.com &> /dev/null # redirect outdated version warnings (Composer sends those to STDOUT instead of STDERR) +fi +# no need for the token to stay around in the env +unset COMPOSER_GITHUB_OAUTH_TOKEN + +# install dependencies unless composer.json is completely empty (in which case it'd talk to packagist.org which may be slow and is unnecessary) +export_env_dir "$env_dir" '^[A-Z_][A-Z0-9_]*$' '^(HOME|PATH|GIT_DIR|CPATH|CPPATH|LD_PRELOAD|LIBRARY_PATH|LD_LIBRARY_PATH|STACK|REQUEST_ID|IFS|HEROKU_PHP_INSTALL_DEV)$' +cat "$COMPOSER" | python -c 'import sys,json; sys.exit(not json.load(sys.stdin));' && composer install ${HEROKU_PHP_INSTALL_DEV-"--no-dev"} --prefer-dist --optimize-autoloader --no-interaction 2>&1 | indent + +composer show --installed heroku/heroku-buildpack-php &> /dev/null && error "Your '$COMPOSER' requires 'heroku/heroku-buildpack-php'. +This package may only be used as a dependency in 'require-dev'!" + +if cat "$COMPOSER" | python -c 'import sys,json; sys.exit("compile" not in json.load(sys.stdin).get("scripts", {}));'; then + status "Running 'composer compile'..." + composer run-script ${HEROKU_PHP_INSTALL_DEV-"--no-dev"} --no-interaction compile 2>&1 | indent +fi + +status "Preparing runtime environment..." + +# install this buildpack like a composer package +# it will contain the apache/nginx/php configs and the boot script +# TODO: warn if require-dev has the package using a different branch +shopt -u dotglob # we don't want .git, .gitignore et al +# figure out the package dir name to write to and copy to it +hbpdir="$composer_vendordir/$(cat $bp_dir/composer.json | python -c 'import sys, json; print(json.load(sys.stdin)["name"])')" +mkdir -p "$build_dir/$hbpdir" +cp -r "$bp_dir"/* "$build_dir/$hbpdir/" +# make bin dir, just in case +mkdir -p "$build_dir/$composer_bindir" +# figure out shortest relative path from vendor/heroku/heroku-buildpack-php to vendor/bin (or whatever the bin dir is) +relbin=$(python -c "import os.path; print(os.path.relpath('$hbpdir', '$composer_bindir'))") +# collect bin names from composer.json +relbins=$(cat $bp_dir/composer.json | python -c 'from __future__ import print_function; import sys, json; { print(sys.argv[1]+"/"+bin) for bin in json.load(sys.stdin)["bin"] }' $relbin) +# link to bins +cd $build_dir/$composer_bindir +ln -fs $relbins . +cd $build_dir + +if [[ ! -f "Procfile" ]]; then + echo "web: $composer_bindir/heroku-$engine-apache2" > Procfile + notice_inline "No Procfile, using 'web: $composer_bindir/heroku-$engine-apache2'." +fi + +# reset COMPOSER for the platform install step +COMPOSER_bak="$COMPOSER" +export COMPOSER=composer.json + +status "Checking for additional extensions to install..." +# special treatment for Blackfire; we enable it if we detect a server id and a server token for it +install_blackfire_ext +# special treatment for New Relic; we enable it if we detect a license key for it +install_newrelic_ext +install_newrelic_userini + +# done with platform installs; restore COMPOSER from previous value +export COMPOSER="$COMPOSER_bak" +unset COMPOSER_bak diff --git a/vendor/heroku/heroku-buildpack-php/bin/detect b/vendor/heroku/heroku-buildpack-php/bin/detect new file mode 100755 index 0000000..8cecf66 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/detect @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +if [[ -f "$1/composer.json" || -f "$1/index.php" ]]; then + echo "PHP" && exit 0 +else + exit 1 +fi + diff --git a/vendor/heroku/heroku-buildpack-php/bin/heroku-hhvm-apache2 b/vendor/heroku/heroku-buildpack-php/bin/heroku-hhvm-apache2 new file mode 100755 index 0000000..48a72bd --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/heroku-hhvm-apache2 @@ -0,0 +1,374 @@ +#!/usr/bin/env bash + +# fail hard +set -o pipefail +# fail harder +set -eu +# for ${DOCUMENT_ROOT%%*(/)} pattern further down +shopt -s extglob +# for detecting when -l 'logs/*.log' matches nothing +shopt -s nullglob + +verbose= + +php_passthrough() { + local dir=$(dirname "$1") + local file=$(basename "$1") + local out=$(basename "$file" .php) + if [[ "$out" != "$file" ]]; then + [[ $verbose ]] && echo "Interpreting ${1#$HEROKU_APP_DIR/} to $out" >&2 + out="$dir/$out" + hhvm "$1" > "$out" + echo "$out" + else + echo "$1" + fi +} + +check_exists() { + if [[ ! -f "$HEROKU_APP_DIR/$1" ]]; then + echo "Cannot read -$2 '$1' (relative to '$HEROKU_APP_DIR')" >&2 + exit 1 + else + echo "$HEROKU_APP_DIR/$1" + fi +} + +touch_log() { + mkdir -p $(dirname "$1") && touch "$1" +} + +print_help() { +echo "\ +${1:-Boots HHVM together with Apache2 on Heroku and for local development.} + +Usage: + heroku-hhvm-apache2 [options] [] + +Options: + -C The path to the configuration file to include inside + the Apache2 VHost config (see option -c below). Will + be included inside the '' section just + after the '' & 'ProxyPassMatch' directives. + Recommended approach when customizing Apache2's config + in most cases, unless you need to set fundamental + server level options. + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/default_include.conf] + -c The path to the full VHost configuration file that is + included after Heroku's (or your local) Apache2 config + is loaded. Must contain a 'Listen \${PORT}' directive + and should have a '' and likely also a + '' section (see option -C above). + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/heroku.conf] + -h, --help Display this help screen and exit. + -I The path to an extra php.ini to use in addition to the + default HHVM php.ini (see option -i below). + -i The path to the php.ini file to use. It is highly + recommended to use the -I option (see above) instead. + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/hhvm/php.ini.php] + -l Path to additional log file to tail to STDERR so its + contents appear in 'heroku logs'. If the file does not + exist, it will be created. Wildcards are allowed, but + must be quoted and must match already existing files. + Note: this option can be repeated multiple times. + -p Port to listen on for HTTP traffic. If this argument + is not given, then the port number to use is read from + the \$PORT environment variable, or a random port is + chosen if that variable does not exist. + -v, --verbose Be more verbose during startup. + +All file paths must be relative to '$HEROKU_APP_DIR'. + +Any file name that ends in '.php' will be run through the PHP interpreter first. +You may use this for templating although this is less useful than e.g. for Nginx +where unlike in Apache2, you cannot reference environment variables in config +files using a '\${VARNAME}' syntax. + +If you would like to use the -C and -c options together, make sure you retain +the appropriate include mechanisms (see default configs for details). +" >&2 +} + +# we need this in configs +export HEROKU_APP_DIR=$(pwd) +export DOCUMENT_ROOT="$HEROKU_APP_DIR" +# set a default port if none is given +export PORT=${PORT:-$(( $RANDOM+1024 ))} + +# init logs array here as empty before parsing options; -l could append to it, but the default list gets added later since we use $PORT in there and that can be set using -p +declare -a logs + +optstring=":-:C:c:I:i:l:p:vh" + +# process flags first +while getopts "$optstring" opt; do + case $opt in + -) + case "$OPTARG" in + verbose) + verbose=1 + ;; + help) + print_help 2>&1 + exit 2 + ;; + *) + echo "Invalid option: --$OPTARG" >&2 + exit + ;; + esac + ;; + v) + verbose=1 + ;; + h) + print_help 2>&1 + exit + ;; + esac +done + +OPTIND=1 # start over with options parsing +while getopts "$optstring" opt; do + case $opt in + C) + httpd_config_include=$(check_exists "$OPTARG" "C") + ;; + c) + httpd_config=$(check_exists "$OPTARG" "c") + ;; + I) + hhvm_config_extra=$(check_exists "$OPTARG" "I") + ;; + i) + php_config=$(check_exists "$OPTARG" "i") + ;; + l) + logarg=( $OPTARG ) # must not quote this or wildcards won't get expanded into individual values + if [[ ${#logarg[@]} -eq 0 ]]; then # we set nullglob to detect if a pattern matched nothing (then the array is empty) + echo "Pattern '$OPTARG' passed to option -l matched no files" >&2 + exit 1 + fi + for logfile in "${logarg[@]}"; do + if [[ -d "$logfile" ]]; then + echo "-l '$logfile': is a directory" >&2 + exit 1 + fi + touch_log "$logfile" || { echo "Could not touch '$logfile'; permissions problem?" >&2; exit 1; } + [[ $verbose ]] && echo "Tailing '$logfile' to stderr" >&2 + logs+=("$logfile") # must quote here in case a wildcard matched a file with a space in the name + done + ;; + p) + PORT="$OPTARG" + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 2 + ;; + :) + echo "Option -$OPTARG requires an argument" >&2 + exit 2 + ;; + esac +done +# clear processed arguments +shift $((OPTIND-1)) + +if [[ "$#" -gt "1" ]]; then + print_help "$0: too many arguments. If you're using options, +make sure to list them before any document root argument you're providing." + exit 2 +fi + +# our standard logs +logs+=( "/tmp/heroku.apache2_error.$PORT.log" "/tmp/heroku.apache2_access.$PORT.log" ) + +hhvm --php -r 'exit((int)version_compare(HHVM_VERSION, "3.0.1", "<"));' || { echo "This program requires HHVM 3.0.1 or newer" >&2; exit 1; } +{ { httpd -v | hhvm --php -r 'exit((int)version_compare(preg_replace("#^Server version: Apache/(\S+).+$#sm", "\\1", file_get_contents("php://stdin")), "2.4.10", "<"));'; } && { httpd -t -D DUMP_MODULES | grep 'proxy_fcgi_module' > /dev/null; }; } || { echo "This program requires Apache 2.4.10 or newer with mod_proxy and mod_proxy_fcgi enabled; check your 'httpd' command." >&2; exit 1; } + +# make sure we run a local composer.phar if present, or global composer if not +composer() { + local composer_bin=$(which ./composer.phar composer | head -n1) + # check if we the composer binary is executable by PHP + if file --brief --dereference $composer_bin | grep -e "shell" -e "bash" > /dev/null ; then # newer versions of file return "data" for .phar + # run it directly; it's probably a bash script or similar (homebrew-php does this) + $composer_bin "$@" + else + hhvm $composer_bin "$@" + fi +} +COMPOSER_VENDOR_DIR=$(composer config vendor-dir 2> /dev/null | tail -n 1) && export COMPOSER_VENDOR_DIR || { echo "Unable to determine Composer vendor-dir setting; is 'composer' executable on path or 'composer.phar' in current working directory?" >&2; exit 1; } # tail, as composer echos outdated version warnings to STDOUT; export after the assignment or exit status will that be of 'export +COMPOSER_BIN_DIR=$(composer config bin-dir 2> /dev/null | tail -n 1) && export COMPOSER_BIN_DIR || { echo "Unable to determine Composer bin-dir setting; is 'composer' executable on path or 'composer.phar' in current working directory?" >&2; exit 1; } # tail, as composer echos outdated version warnings to STDOUT; export after the assignment or exit status will that be of 'export + +if [[ "$#" == "1" ]]; then + DOCUMENT_ROOT="$HEROKU_APP_DIR/$1" + if [[ ! -d "$DOCUMENT_ROOT" ]]; then + echo "DOCUMENT_ROOT '$1' does not exist" >&2 + exit 1 + else + # strip trailing slashes if present + DOCUMENT_ROOT=${DOCUMENT_ROOT%%*(/)} # powered by extglob + if [[ $verbose ]]; then + echo "DOCUMENT_ROOT changed to '$DOCUMENT_ROOT'" >&2 + else + echo "DOCUMENT_ROOT changed to '${1%%*(/)}/'" >&2 + fi + fi +fi + +function prepare_hhvm_ini() { # we have to do this twice, as the WEB_CONCURRENCY setting is evaluated using PHP code, not ${...} syntax which HHVM does not support; if a value for $1 is passed then it won't echo messages upon second invocation +if [[ ( -n ${php_config:-} && ! ${1:-} ) || ( ${php_config:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/hhvm/php.ini.php"} && $verbose && ! ${1:-} ) ]]; then + echo "Using HHVM configuration (php.ini) file '${php_config#$HEROKU_APP_DIR/}'" >&2 +fi +php_configs=( "-c" "$(php_passthrough "$php_config")" ) + +if [[ -n ${hhvm_config_extra:-} ]]; then + [[ ${1:-} ]] || echo "Using additional HHVM configuration (php.ini) file '${hhvm_config_extra#$HEROKU_APP_DIR/}'" >&2 + php_configs+=( "-c" "$(php_passthrough "$hhvm_config_extra")" ) +fi +} +prepare_hhvm_ini + +if [[ -n ${httpd_config_include:-} || ( ${httpd_config_include:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/default_include.conf"} && $verbose ) ]]; then + echo "Using Apache2 VirtualHost-level configuration include '${httpd_config_include#$HEROKU_APP_DIR/}'" >&2 +fi +httpd_config_include=$(php_passthrough "$httpd_config_include") +export HEROKU_PHP_HTTPD_CONFIG_INCLUDE="$httpd_config_include" + +if [[ -n ${httpd_config:-} || ( ${httpd_config:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/heroku.conf"} && $verbose) ]]; then + echo "Using Apache2 configuration file '${httpd_config#$HEROKU_APP_DIR/}'" >&2 +fi +httpd_config=$(php_passthrough "$httpd_config") + +# if WEB_CONCURRENCY starts with a 0, then that's a default value which comes from another buildpack (e.g. Node), so we ignore it +if [[ -z ${WEB_CONCURRENCY:-} || "${WEB_CONCURRENCY}" == 0* ]]; then + maxprocs=$(ulimit -u) + ram="512M" + if [[ -n ${DYNO:-} && "$maxprocs" == "32768" ]]; then + echo "Optimizing defaults for PX dyno...." >&2 + ram="6G" + elif [[ -n ${DYNO:-} && "$maxprocs" == "16384" ]]; then + echo "Optimizing defaults for IX dyno...." >&2 + ram="2560M" + elif [[ -n ${DYNO:-} && "$maxprocs" == "512" ]]; then + echo "Optimizing defaults for 2X dyno..." >&2 + ram="1G" + elif [[ -n ${DYNO:-} && "$maxprocs" == "256" ]]; then + echo "Optimizing defaults for 1X dyno..." >&2 + elif [[ -n ${DYNO:-} || $verbose ]]; then + echo "No dyno detected; using defaults for 1X..." >&2 + fi + + # determine number of HHVM threads to run + read WEB_CONCURRENCY php_memory_limit <<<$(hhvm "${php_configs[@]}" $(composer config vendor-dir 2> /dev/null | tail -n 1)/heroku/heroku-buildpack-php/bin/util/autotune.php "$ram") # tail, as composer echos outdated version warnings to STDOUT + [[ $WEB_CONCURRENCY -lt 1 ]] && WEB_CONCURRENCY=1 + export WEB_CONCURRENCY + + echo "${WEB_CONCURRENCY} threads at ${php_memory_limit}B memory limit." >&2 +else + echo "Using WEB_CONCURRENCY=${WEB_CONCURRENCY} threads." >&2 +fi + +# we changed WEB_CONCURRENCY; now we need to re-evaluate the configs as HHVM doesn't support ${...} syntax, so the configs contain PHP getenv() calls and are templated; we pass an argument to it to avoid it echoing "using HHVM config ..." messages again because that already happened +prepare_hhvm_ini no_messages + +# make a shared pipe; we'll write the name of the process that exits to it once that happens, and wait for that event below +# this particular call works on Linux and Mac OS (will create a literal ".XXXXXX" on Mac, but that doesn't matter). +wait_pipe=$(mktemp -t "heroku.waitpipe-$PORT.XXXXXX" -u) +rm -f $wait_pipe +mkfifo $wait_pipe +exec 3<> $wait_pipe + +pids=() + +# trap SIGQUIT (ctrl+\ on the console), SIGTERM (when we get killed) and EXIT (upon failure of any command due to set -e, or because of the exit 1 at the very end), we then +# 1) restore the trap for the signal in question so it doesn't fire again due to the kill at the end of the trap, as well as for EXIT, because that would fire too +# 2) call cleanup() to +# 2a) remove our FIFO from above +# 2b) kill all the subshells we've spawned - they in turn have their own traps to kill their respective subprocesses, and because we use SIGUSR1, they know it's the parent's cleanup and can handle it differently from an external SIGKILL +# 2c) send STDERR to /dev/null so we don't see "no such process" errors - after all, one of the subshells may be gone +# 2d) || true so that set -e doesn't cause a mess if the kill returns 1 on "no such process" cases (which is likely on Heroku where all processes get killed and not just this top level one) +# 2e) do that in the background and 'wait' on those processes, sending wait's output to /dev/null - this prevents the logs getting cluttered with "vendor/bin/heroku-...: line 309: 96 Terminated" messages (we can't use 'disown' after launching programs for that purpose because that removes the jobs from the shell's jobs table and the we can no longer 'wait' on the program) +# 3) kill ourselves with the correct signal in case we're handling SIGQUIT or SIGTERM (http://www.cons.org/cracauer/sigint.html and http://mywiki.wooledge.org/SignalTrap#Special_Note_On_SIGINT1) +cleanup() { echo "Going down, terminating child processes..." >&2; rm -f ${wait_pipe} || true; kill -USR1 "${pids[@]}" 2> /dev/null || true; } +trap 'trap - QUIT EXIT; cleanup; kill -QUIT $$' QUIT +trap 'trap - TERM EXIT; cleanup; kill -TERM $$' TERM +trap 'trap - EXIT; cleanup' EXIT +# if FD 1 is a TTY (that's the -t 1 check), trap SIGINT/Ctrl+C, then same procedure as for QUIT and TERM above +if [[ -t 1 ]]; then + trap 'trap - INT EXIT; cleanup; kill -INT $$' INT; +# if FD 1 is not a TTY (e.g. when we're run through 'foreman start'), do nothing on SIGINT; the assumption is that the parent will send us a SIGTERM or something when this happens. With the trap above, Ctrl+C-ing out of a 'foreman start' run would trigger the INT trap both in Foreman and here (because Ctrl+C sends SIGINT to the entire process group, but there is no way to tell the two cases apart), and while the trap is still doing its shutdown work triggered by the SIGTERM from the Ctrl+C, Foreman would then send a SIGTERM because that's what it does when it receives a SIGINT itself. +else + trap '' INT; +fi + +# we are now launching a subshell for each of the tasks (log tail, app server, web server) +# 1) each subshell has a trap on EXIT that echos the command name to FD 3 (see the FIFO set up above) +# 1a) a 'read' at the end of the script will block on reading from that FD and then trigger the exit trap further above, which does the cleanup +# 2) each subshell also has a trap on TERM that +# 2a) kills $! (the last process executed) +# 2b) ... which in turn will hit the EXIT trap and that unblocks the 'wait' in 5) which will cause the parent to clean up when the exit at the end of the script is hit +# 2c) the 'kill' is done in the background and we immediately 'wait' on $!, sending wait's output to /dev/null - this prevents the logs getting cluttered with "vendor/bin/heroku-...: line 309: 96 Terminated" messages (we can't use 'disown' after launching programs for that purpose because that removes the jobs from the shell's jobs table and the we can no longer 'wait' on the program) +# 2d) finally, if $BASHPID exists, the subshell kills itself using the right signal for maximum compliance ($$ doesn't work in subshells, and $BASHPID is not available in Bash 3, but unlike with the parent, it's not that critical to have this) +# 3) each subshell has another trap on USR1 which gets sent when the parent is cleaning up; it works like 2a) but doesn't trigger the EXIT trap to avoid multiple cleanup runs by the parent +# 4) execute the command in the background +# 5) 'wait' on the command (wait is interrupted by an incoming TERM to the subshell, whereas running 4) in the foreground would wait for that process to finish before triggering the trap) +# 6) add the PID of the subshell to the array that the EXIT trap further above uses to clean everything up + +[[ $verbose ]] && echo "Starting log redirection..." >&2 +( + trap '' INT; + trap 'echo "tail" >&3;' EXIT + trap 'trap - TERM; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + touch "${logs[@]}" + + tail -qF -n 0 "${logs[@]}" 1>&2 & pid=$! + + wait +) & pids+=($!) +disown $! + +echo "Starting hhvm..." >&2 +( + trap '' INT; + trap 'echo "hhvm" >&3;' EXIT + trap 'trap - TERM; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + hhvm --mode server "${php_configs[@]}" & pid=$! + + wait +) & pids+=($!) +disown $! + +# wait a few seconds for HHVM to finish initializing; otherwise an early request might break Apache with the FastCGI pipe not being ready +sleep 2 + +echo "Starting httpd..." >&2 +( + trap '' INT; + trap 'echo "httpd" >&3;' EXIT + trap 'trap - TERM; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + httpd -D NO_DETACH -c "Include $httpd_config" & pid=$! + + wait +) & pids+=($!) +disown $! + +# on Heroku, there is a "state changed from starting to up", but for local execution, we want a "ready" message +[[ -z ${DYNO:-} || $verbose ]] && echo "Application ready for connections on port $PORT." >&2 + +# wait for something to come from the FIFO attached to FD 3, which means that the given process was killed or has failed +# this will be interrupted by a SIGTERM or SIGINT in the traps further up +# if the pipe unblocks and this executes, then we won't read it again, so if the traps further up kill the remaining subshells above, their writing to FD 3 will have no effect +read exitproc <&3 +# we'll only reach this if one of the processes above has terminated +echo "Process exited unexpectedly: $exitproc" >&2 + +# this will trigger the EXIT trap further up and kill all remaining children +exit 1 diff --git a/vendor/heroku/heroku-buildpack-php/bin/heroku-hhvm-nginx b/vendor/heroku/heroku-buildpack-php/bin/heroku-hhvm-nginx new file mode 100755 index 0000000..8d10342 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/heroku-hhvm-nginx @@ -0,0 +1,374 @@ +#!/usr/bin/env bash + +# fail hard +set -o pipefail +# fail harder +set -eu +# for ${DOCUMENT_ROOT%%*(/)} pattern further down +shopt -s extglob +# for detecting when -l 'logs/*.log' matches nothing +shopt -s nullglob + +verbose= + +php_passthrough() { + local dir=$(dirname "$1") + local file=$(basename "$1") + local out=$(basename "$file" .php) + if [[ "$out" != "$file" ]]; then + [[ $verbose ]] && echo "Interpreting ${1#$HEROKU_APP_DIR/} to $out" >&2 + out="$dir/$out" + hhvm "$1" > "$out" + echo "$out" + else + echo "$1" + fi +} + +check_exists() { + if [[ ! -f "$HEROKU_APP_DIR/$1" ]]; then + echo "Cannot read -$2 '$1' (relative to '$HEROKU_APP_DIR')" >&2 + exit 1 + else + echo "$HEROKU_APP_DIR/$1" + fi +} + +touch_log() { + mkdir -p $(dirname "$1") && touch "$1" +} + +print_help() { +echo "\ +${1:-Boots HHVM together with Nginx on Heroku and for local development.} + +Usage: + heroku-hhvm-nginx [options] [] + +Options: + -C The path to the configuration file to include inside + the Nginx server config (see option -c below). Will + be included inside the 'server { ... }' block just + after the 'listen', 'root' etc directives. + Recommended approach when customizing Nginx's config + in most cases, unless you need to set http or + fundamental server level options. + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/nginx/default_include.conf.php] + -c The path to the full configuration file that is + included after Heroku's (or your local) Nginx config + is loaded. It must contain an 'http { ... }' block + with a 'server { ... }' inside that contains 'listen' + and 'root' (see option -C above), but no global, + directives (globals are read from the system's default + Nginx configuration files). + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/nginx/heroku.conf.php] + -h, --help Display this help screen and exit. + -I The path to an extra php.ini to use in addition to the + default HHVM php.ini (see option -i below). + -i The path to the php.ini file to use. It is highly + recommended to use the -I option (see above) instead. + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/hhvm/php.ini.php] + -l Path to additional log file to tail to STDERR so its + contents appear in 'heroku logs'. If the file does not + exist, it will be created. Wildcards are allowed, but + must be quoted and must match already existing files. + Note: this option can be repeated multiple times. + -p Port to listen on for HTTP traffic. If this argument + is not given, then the port number to use is read from + the \$PORT environment variable, or a random port is + chosen if that variable does not exist. + -v, --verbose Be more verbose during startup. + +All file paths must be relative to '$HEROKU_APP_DIR'. + +Any file name that ends in '.php' will be run through the PHP interpreter first. +You may use this for templating; this is, for instance, necessary for Nginx, +where environment variables cannot be referenced in configuration files. + +If you would like to use the -C and -c options together, make sure you retain +the appropriate include mechanisms (see default configs for details). +" >&2 +} + +# we need this in configs +export HEROKU_APP_DIR=$(pwd) +export DOCUMENT_ROOT="$HEROKU_APP_DIR" +# set a default port if none is given +export PORT=${PORT:-$(( $RANDOM+1024 ))} + +# init logs array here as empty before parsing options; -l could append to it, but the default list gets added later since we use $PORT in there and that can be set using -p +declare -a logs + +optstring=":-:C:c:I:i:l:p:vh" + +# process flags first +while getopts "$optstring" opt; do + case $opt in + -) + case "$OPTARG" in + verbose) + verbose=1 + ;; + help) + print_help 2>&1 + exit + ;; + *) + echo "Invalid option: --$OPTARG" >&2 + exit 2 + ;; + esac + ;; + v) + verbose=1 + ;; + h) + print_help 2>&1 + exit + ;; + esac +done + +OPTIND=1 # start over with options parsing +while getopts "$optstring" opt; do + case $opt in + C) + nginx_config_include=$(check_exists "$OPTARG" "C") + ;; + c) + nginx_config=$(check_exists "$OPTARG" "c") + ;; + I) + hhvm_config_extra=$(check_exists "$OPTARG" "I") + ;; + i) + php_config=$(check_exists "$OPTARG" "i") + ;; + l) + logarg=( $OPTARG ) # must not quote this or wildcards won't get expanded into individual values + if [[ ${#logarg[@]} -eq 0 ]]; then # we set nullglob to detect if a pattern matched nothing (then the array is empty) + echo "Pattern '$OPTARG' passed to option -l matched no files" >&2 + exit 1 + fi + for logfile in "${logarg[@]}"; do + if [[ -d "$logfile" ]]; then + echo "-l '$logfile': is a directory" >&2 + exit 1 + fi + touch_log "$logfile" || { echo "Could not touch '$logfile'; permissions problem?" >&2; exit 1; } + [[ $verbose ]] && echo "Tailing '$logfile' to stderr" >&2 + logs+=("$logfile") # must quote here in case a wildcard matched a file with a space in the name + done + ;; + p) + PORT="$OPTARG" + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 2 + ;; + :) + echo "Option -$OPTARG requires an argument" >&2 + exit 2 + ;; + esac +done +# clear processed arguments +shift $((OPTIND-1)) + +if [[ "$#" -gt "1" ]]; then + print_help "$0: too many arguments. If you're using options, +make sure to list them before any document root argument you're providing." + exit 2 +fi + +# our standard logs +logs+=( "/tmp/heroku.nginx_access.$PORT.log" ) + +hhvm --php -r 'exit((int)version_compare(HHVM_VERSION, "3.0.1", "<"));' || { echo "This program requires HHVM 3.0.1 or newer" >&2; exit 1; } + +# make sure we run a local composer.phar if present, or global composer if not +composer() { + local composer_bin=$(which ./composer.phar composer | head -n1) + # check if we the composer binary is executable by HHVM + if file --brief --dereference $composer_bin | grep -e "shell" -e "bash" > /dev/null ; then # newer versions of file return "data" for .phar + # run it directly; it's probably a bash script or similar (homebrew-php does this) + $composer_bin "$@" + else + hhvm $composer_bin "$@" + fi +} +COMPOSER_VENDOR_DIR=$(composer config vendor-dir 2> /dev/null | tail -n 1) && export COMPOSER_VENDOR_DIR || { echo "Unable to determine Composer vendor-dir setting; is 'composer' executable on path or 'composer.phar' in current working directory?" >&2; exit 1; } # tail, as composer echos outdated version warnings to STDOUT; export after the assignment or exit status will that be of 'export +COMPOSER_BIN_DIR=$(composer config bin-dir 2> /dev/null | tail -n 1) && export COMPOSER_BIN_DIR || { echo "Unable to determine Composer bin-dir setting; is 'composer' executable on path or 'composer.phar' in current working directory?" >&2; exit 1; } # tail, as composer echos outdated version warnings to STDOUT; export after the assignment or exit status will that be of 'export + +if [[ "$#" == "1" ]]; then + DOCUMENT_ROOT="$HEROKU_APP_DIR/$1" + if [[ ! -d "$DOCUMENT_ROOT" ]]; then + echo "DOCUMENT_ROOT '$1' does not exist" >&2 + exit 1 + else + # strip trailing slashes if present + DOCUMENT_ROOT=${DOCUMENT_ROOT%%*(/)} # powered by extglob + if [[ $verbose ]]; then + echo "DOCUMENT_ROOT changed to '$DOCUMENT_ROOT'" >&2 + else + echo "DOCUMENT_ROOT changed to '${1%%*(/)}/'" >&2 + fi + fi +fi + +function prepare_hhvm_ini() { # we have to do this twice, as the WEB_CONCURRENCY setting is evaluated using PHP code, not ${...} syntax which HHVM does not support; if a value for $1 is passed then it won't echo messages upon second invocation +if [[ ( -n ${php_config:-} && ! ${1:-} ) || ( ${php_config:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/hhvm/php.ini.php"} && $verbose && ! ${1:-} ) ]]; then + echo "Using HHVM configuration (php.ini) file '${php_config#$HEROKU_APP_DIR/}'" >&2 +fi +php_configs=( "-c" "$(php_passthrough "$php_config")" ) + +if [[ -n ${hhvm_config_extra:-} ]]; then + [[ ${1:-} ]] || echo "Using additional HHVM configuration (php.ini) file '${hhvm_config_extra#$HEROKU_APP_DIR/}'" >&2 + php_configs+=( "-c" "$(php_passthrough "$hhvm_config_extra")" ) +fi +} +prepare_hhvm_ini + +if [[ -n ${nginx_config_include:-} || ( ${nginx_config_include:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/nginx/default_include.conf.php"} && $verbose ) ]]; then + echo "Using Nginx server-level configuration include '${nginx_config_include#$HEROKU_APP_DIR/}'" >&2 +fi +nginx_config_include=$(php_passthrough "$nginx_config_include") +export HEROKU_PHP_NGINX_CONFIG_INCLUDE="$nginx_config_include" + +if [[ -n ${nginx_config:-} || ( ${nginx_config:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/nginx/heroku.conf.php"} && $verbose) ]]; then + echo "Using Nginx configuration file '${nginx_config#$HEROKU_APP_DIR/}'" >&2 +fi +nginx_config=$(php_passthrough "$nginx_config") + +# if WEB_CONCURRENCY starts with a 0, then that's a default value which comes from another buildpack (e.g. Node), so we ignore it +if [[ -z ${WEB_CONCURRENCY:-} || "${WEB_CONCURRENCY}" == 0* ]]; then + maxprocs=$(ulimit -u) + ram="512M" + if [[ -n ${DYNO:-} && "$maxprocs" == "32768" ]]; then + echo "Optimizing defaults for PX dyno...." >&2 + ram="6G" + elif [[ -n ${DYNO:-} && "$maxprocs" == "16384" ]]; then + echo "Optimizing defaults for IX dyno...." >&2 + ram="2560M" + elif [[ -n ${DYNO:-} && "$maxprocs" == "512" ]]; then + echo "Optimizing defaults for 2X dyno..." >&2 + ram="1G" + elif [[ -n ${DYNO:-} && "$maxprocs" == "256" ]]; then + echo "Optimizing defaults for 1X dyno..." >&2 + elif [[ -n ${DYNO:-} || $verbose ]]; then + echo "No dyno detected; using defaults for 1X..." >&2 + fi + + # determine number of HHVM threads to run + read WEB_CONCURRENCY php_memory_limit <<<$(hhvm "${php_configs[@]}" $(composer config vendor-dir 2> /dev/null | tail -n 1)/heroku/heroku-buildpack-php/bin/util/autotune.php "$ram") # tail, as composer echos outdated version warnings to STDOUT + [[ $WEB_CONCURRENCY -lt 1 ]] && WEB_CONCURRENCY=1 + export WEB_CONCURRENCY + + echo "${WEB_CONCURRENCY} threads at ${php_memory_limit}B memory limit." >&2 +else + echo "Using WEB_CONCURRENCY=${WEB_CONCURRENCY} threads." >&2 +fi + +# we changed WEB_CONCURRENCY; now we need to re-evaluate the configs as HHVM doesn't support ${...} syntax, so the configs contain PHP getenv() calls and are templated; we pass an argument to it to avoid it echoing "using HHVM config ..." messages again because that already happened +prepare_hhvm_ini no_messages + +# make a shared pipe; we'll write the name of the process that exits to it once that happens, and wait for that event below +# this particular call works on Linux and Mac OS (will create a literal ".XXXXXX" on Mac, but that doesn't matter). +wait_pipe=$(mktemp -t "heroku.waitpipe-$PORT.XXXXXX" -u) +rm -f $wait_pipe +mkfifo $wait_pipe +exec 3<> $wait_pipe + +pids=() + +# trap SIGQUIT (ctrl+\ on the console), SIGTERM (when we get killed) and EXIT (upon failure of any command due to set -e, or because of the exit 1 at the very end), we then +# 1) restore the trap for the signal in question so it doesn't fire again due to the kill at the end of the trap, as well as for EXIT, because that would fire too +# 2) call cleanup() to +# 2a) remove our FIFO from above +# 2b) kill all the subshells we've spawned - they in turn have their own traps to kill their respective subprocesses, and because we use SIGUSR1, they know it's the parent's cleanup and can handle it differently from an external SIGKILL +# 2c) send STDERR to /dev/null so we don't see "no such process" errors - after all, one of the subshells may be gone +# 2d) || true so that set -e doesn't cause a mess if the kill returns 1 on "no such process" cases (which is likely on Heroku where all processes get killed and not just this top level one) +# 2e) do that in the background and 'wait' on those processes, sending wait's output to /dev/null - this prevents the logs getting cluttered with "vendor/bin/heroku-...: line 309: 96 Terminated" messages (we can't use 'disown' after launching programs for that purpose because that removes the jobs from the shell's jobs table and the we can no longer 'wait' on the program) +# 3) kill ourselves with the correct signal in case we're handling SIGQUIT or SIGTERM (http://www.cons.org/cracauer/sigint.html and http://mywiki.wooledge.org/SignalTrap#Special_Note_On_SIGINT1) +cleanup() { echo "Going down, terminating child processes..." >&2; rm -f ${wait_pipe} || true; kill -USR1 "${pids[@]}" 2> /dev/null || true; } +trap 'trap - QUIT EXIT; cleanup; kill -QUIT $$' QUIT +trap 'trap - TERM EXIT; cleanup; kill -TERM $$' TERM +trap 'trap - EXIT; cleanup' EXIT +# if FD 1 is a TTY (that's the -t 1 check), trap SIGINT/Ctrl+C, then same procedure as for QUIT and TERM above +if [[ -t 1 ]]; then + trap 'trap - INT EXIT; cleanup; kill -INT $$' INT; +# if FD 1 is not a TTY (e.g. when we're run through 'foreman start'), do nothing on SIGINT; the assumption is that the parent will send us a SIGTERM or something when this happens. With the trap above, Ctrl+C-ing out of a 'foreman start' run would trigger the INT trap both in Foreman and here (because Ctrl+C sends SIGINT to the entire process group, but there is no way to tell the two cases apart), and while the trap is still doing its shutdown work triggered by the SIGTERM from the Ctrl+C, Foreman would then send a SIGTERM because that's what it does when it receives a SIGINT itself. +else + trap '' INT; +fi + +# we are now launching a subshell for each of the tasks (log tail, app server, web server) +# 1) each subshell has a trap on EXIT that echos the command name to FD 3 (see the FIFO set up above) +# 1a) a 'read' at the end of the script will block on reading from that FD and then trigger the exit trap further above, which does the cleanup +# 2) each subshell also has a trap on TERM that +# 2a) kills $! (the last process executed) +# 2b) ... which in turn will hit the EXIT trap and that unblocks the 'wait' in 5) which will cause the parent to clean up when the exit at the end of the script is hit +# 2c) the 'kill' is done in the background and we immediately 'wait' on $!, sending wait's output to /dev/null - this prevents the logs getting cluttered with "vendor/bin/heroku-...: line 309: 96 Terminated" messages (we can't use 'disown' after launching programs for that purpose because that removes the jobs from the shell's jobs table and the we can no longer 'wait' on the program) +# 2d) finally, if $BASHPID exists, the subshell kills itself using the right signal for maximum compliance ($$ doesn't work in subshells, and $BASHPID is not available in Bash 3, but unlike with the parent, it's not that critical to have this) +# 3) each subshell has another trap on USR1 which gets sent when the parent is cleaning up; it works like 2a) but doesn't trigger the EXIT trap to avoid multiple cleanup runs by the parent +# 4) execute the command in the background +# 5) 'wait' on the command (wait is interrupted by an incoming TERM to the subshell, whereas running 4) in the foreground would wait for that process to finish before triggering the trap) +# 6) add the PID of the subshell to the array that the EXIT trap further above uses to clean everything up + +[[ $verbose ]] && echo "Starting log redirection..." >&2 +( + trap '' INT; + trap 'echo "tail" >&3;' EXIT + trap 'trap - TERM; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + touch "${logs[@]}" + + tail -qF -n 0 "${logs[@]}" 1>&2 & pid=$! + + wait +) & pids+=($!) +disown $! + +echo "Starting hhvm..." >&2 +( + trap '' INT; + trap 'echo "hhvm" >&3;' EXIT + trap 'trap - TERM; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + hhvm --mode server "${php_configs[@]}" & pid=$! + + wait +) & pids+=($!) +disown $! + +# wait a few seconds for HHVM to finish initializing; otherwise an early request might break Apache with the FastCGI pipe not being ready +sleep 2 + +echo "Starting nginx..." >&2 +( + trap '' INT; + trap 'echo "nginx" >&3;' EXIT + trap 'trap - TERM; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + nginx -g "daemon off; include $nginx_config;" & pid=$! + + wait +) & pids+=($!) +disown $! + +# on Heroku, there is a "state changed from starting to up", but for local execution, we want a "ready" message +[[ -z ${DYNO:-} || $verbose ]] && echo "Application ready for connections on port $PORT." >&2 + +# wait for something to come from the FIFO attached to FD 3, which means that the given process was killed or has failed +# this will be interrupted by a SIGTERM or SIGINT in the traps further up +# if the pipe unblocks and this executes, then we won't read it again, so if the traps further up kill the remaining subshells above, their writing to FD 3 will have no effect +read exitproc <&3 +# we'll only reach this if one of the processes above has terminated +echo "Process exited unexpectedly: $exitproc" >&2 + +# this will trigger the EXIT trap further up and kill all remaining children +exit 1 diff --git a/vendor/heroku/heroku-buildpack-php/bin/heroku-php-apache2 b/vendor/heroku/heroku-buildpack-php/bin/heroku-php-apache2 new file mode 100755 index 0000000..91160c2 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/heroku-php-apache2 @@ -0,0 +1,405 @@ +#!/usr/bin/env bash + +# fail hard +set -o pipefail +# fail harder +set -eu +# for ${DOCUMENT_ROOT%%*(/)} pattern further down +shopt -s extglob +# for detecting when -l 'logs/*.log' matches nothing +shopt -s nullglob + +verbose= + +php_passthrough() { + local dir=$(dirname "$1") + local file=$(basename "$1") + local out=$(basename "$file" .php) + if [[ "$out" != "$file" ]]; then + [[ $verbose ]] && echo "Interpreting ${1#$HEROKU_APP_DIR/} to $out" >&2 + out="$dir/$out" + php -n "$1" > "$out" + echo "$out" + else + echo "$1" + fi +} + +check_exists() { + if [[ ! -f "$HEROKU_APP_DIR/$1" ]]; then + echo "Cannot read -$2 '$1' (relative to '$HEROKU_APP_DIR')" >&2 + exit 1 + else + echo "$HEROKU_APP_DIR/$1" + fi +} + +touch_log() { + mkdir -p $(dirname "$1") && touch "$1" +} + +print_help() { +echo "\ +${1:-Boots PHP-FPM together with Apache2 on Heroku and for local development.} + +Usage: + heroku-php-apache2 [options] [] + +Options: + -C The path to the configuration file to include inside + the Apache2 VHost config (see option -c below). Will + be included inside the '' section just + after the '' & 'ProxyPassMatch' directives. + Recommended approach when customizing Apache2's config + in most cases, unless you need to set fundamental + server level options. + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/default_include.conf] + -c The path to the full VHost configuration file that is + included after Heroku's (or your local) Apache2 config + is loaded. Must contain a 'Listen \${PORT}' directive + and should have a '' and likely also a + '' section (see option -C above). + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/heroku.conf] + -F The path to the configuration file to include at the + end of php-fpm.conf (see option -f below), in the + '[www]' pool section. Recommended approach when + customizing PHP-FPM's configuration in most cases, + unless you need to set global options. + -f The path to the full PHP-FPM configuration file. + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/php/php-fpm.conf] + -h, --help Display this help screen and exit. + -i The path to the php.ini file to use. + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/php/php.ini] + -l Path to additional log file to tail to STDERR so its + contents appear in 'heroku logs'. If the file does not + exist, it will be created. Wildcards are allowed, but + must be quoted and must match already existing files. + Note: this option can be repeated multiple times. + -p Port to listen on for HTTP traffic. If this argument + is not given, then the port number to use is read from + the \$PORT environment variable, or a random port is + chosen if that variable does not exist. + -v, --verbose Be more verbose during startup. + +All file paths must be relative to '$HEROKU_APP_DIR'. + +Any file name that ends in '.php' will be run through the PHP interpreter first. +You may use this for templating although this is less useful than e.g. for Nginx +where unlike in Apache2, you cannot reference environment variables in config +files using a '\${VARNAME}' syntax. + +If you would like to use the -C and -c or -F and -f options together, make sure +you retain the appropriate include mechanisms (see default configs for details). +" >&2 +} + +# we need this in configs +export HEROKU_APP_DIR=$(pwd) +export DOCUMENT_ROOT="$HEROKU_APP_DIR" +# set a default port if none is given +export PORT=${PORT:-$(( $RANDOM+1024 ))} + +# init logs array here as empty before parsing options; -l could append to it, but the default list gets added later since we use $PORT in there and that can be set using -p +declare -a logs + +optstring=":-:C:c:F:f:i:l:p:vh" + +# process flags first +while getopts "$optstring" opt; do + case $opt in + -) + case "$OPTARG" in + verbose) + verbose=1 + ;; + help) + print_help 2>&1 + exit + ;; + *) + echo "Invalid option: --$OPTARG" >&2 + exit 2 + ;; + esac + ;; + v) + verbose=1 + ;; + h) + print_help 2>&1 + exit + ;; + esac +done + +OPTIND=1 # start over with options parsing +while getopts "$optstring" opt; do + case $opt in + C) + httpd_config_include=$(check_exists "$OPTARG" "C") + ;; + c) + httpd_config=$(check_exists "$OPTARG" "c") + ;; + F) + fpm_config_include=$(check_exists "$OPTARG" "F") + ;; + f) + fpm_config=$(check_exists "$OPTARG" "f") + ;; + i) + php_config=$(check_exists "$OPTARG" "i") + ;; + l) + logarg=( $OPTARG ) # must not quote this or wildcards won't get expanded into individual values + if [[ ${#logarg[@]} -eq 0 ]]; then # we set nullglob to detect if a pattern matched nothing (then the array is empty) + echo "Pattern '$OPTARG' passed to option -l matched no files" >&2 + exit 1 + fi + for logfile in "${logarg[@]}"; do + if [[ -d "$logfile" ]]; then + echo "-l '$logfile': is a directory" >&2 + exit 1 + fi + touch_log "$logfile" || { echo "Could not touch '$logfile'; permissions problem?" >&2; exit 1; } + [[ $verbose ]] && echo "Tailing '$logfile' to stderr" >&2 + logs+=("$logfile") # must quote here in case a wildcard matched a file with a space in the name + done + ;; + p) + PORT="$OPTARG" + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 2 + ;; + :) + echo "Option -$OPTARG requires an argument" >&2 + exit 2 + ;; + esac +done +# clear processed arguments +shift $((OPTIND-1)) + +if [[ "$#" -gt "1" ]]; then + print_help "$0: too many arguments. If you're using options, +make sure to list them before any document root argument you're providing." + exit 2 +fi + +# our standard logs +logs+=( "/tmp/heroku.php-fpm.$PORT.log" "/tmp/heroku.php-fpm.www.$PORT.log" "/tmp/heroku.php-fpm.$PORT.www.slowlog" "/tmp/heroku.apache2_error.$PORT.log" "/tmp/heroku.apache2_access.$PORT.log" ) + +# a bunch of checks; don't load any INIs to prevent newrelic etc from loading, we don't need all that stuff +php -n -r 'exit((int)version_compare(PHP_VERSION, "5.5.11", "<"));' || { echo "This program requires PHP 5.5.11 or newer; check your 'php' command." >&2; exit 1; } +{ php-fpm -n -v | php -n -r 'exit((int)version_compare(preg_replace("#PHP (\S+) \(fpm-fcgi\).+$#sm", "\\1", file_get_contents("php://stdin")), "5.5.11", "<"));'; } || { echo "This program requires PHP 5.5.11 or newer; check your 'php-fpm' command." >&2; exit 1; } +{ { httpd -v | php -n -r 'exit((int)version_compare(preg_replace("#^Server version: Apache/(\S+).+$#sm", "\\1", file_get_contents("php://stdin")), "2.4.10", "<"));'; } && { httpd -t -D DUMP_MODULES | grep 'proxy_fcgi_module' > /dev/null; }; } || { echo "This program requires Apache 2.4.10 or newer with mod_proxy and mod_proxy_fcgi enabled; check your 'httpd' command." >&2; exit 1; } + +# make sure we run a local composer.phar if present, or global composer if not +composer() { + local composer_bin=$(which ./composer.phar composer | head -n1) + # check if we the composer binary is executable by PHP + if file --brief --dereference $composer_bin | grep -e "shell" -e "bash" > /dev/null ; then # newer versions of file return "data" for .phar + # run it directly; it's probably a bash script or similar (homebrew-php does this) + $composer_bin "$@" + else + php -n $composer_bin "$@" + fi +} +COMPOSER_VENDOR_DIR=$(composer config vendor-dir 2> /dev/null | tail -n 1) && export COMPOSER_VENDOR_DIR || { echo "Unable to determine Composer vendor-dir setting; is 'composer' executable on path or 'composer.phar' in current working directory?" >&2; exit 1; } # tail, as composer echos outdated version warnings to STDOUT; export after the assignment or exit status will that be of 'export +COMPOSER_BIN_DIR=$(composer config bin-dir 2> /dev/null | tail -n 1) && export COMPOSER_BIN_DIR || { echo "Unable to determine Composer bin-dir setting; is 'composer' executable on path or 'composer.phar' in current working directory?" >&2; exit 1; } # tail, as composer echos outdated version warnings to STDOUT; export after the assignment or exit status will that be of 'export + +if [[ "$#" == "1" ]]; then + DOCUMENT_ROOT="$HEROKU_APP_DIR/$1" + if [[ ! -d "$DOCUMENT_ROOT" ]]; then + echo "DOCUMENT_ROOT '$1' does not exist" >&2 + exit 1 + else + # strip trailing slashes if present + DOCUMENT_ROOT=${DOCUMENT_ROOT%%*(/)} # powered by extglob + if [[ $verbose ]]; then + echo "DOCUMENT_ROOT changed to '$DOCUMENT_ROOT'" >&2 + else + echo "DOCUMENT_ROOT changed to '${1%%*(/)}/'" >&2 + fi + fi +fi + +if [[ -n ${fpm_config_include:-} ]]; then + echo "Using PHP-FPM configuration include '${fpm_config_include#$HEROKU_APP_DIR/}'" >&2 + fpm_config_include=$(php_passthrough "$fpm_config_include") + export HEROKU_PHP_FPM_CONFIG_INCLUDE="$fpm_config_include" +fi + +if [[ -n ${fpm_config:-} || ( ${fpm_config:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/php/php-fpm.conf"} && $verbose ) ]]; then + echo "Using PHP-FPM configuration file '${fpm_config#$HEROKU_APP_DIR/}'" >&2 +fi +fpm_config=$(php_passthrough "$fpm_config") + +if [[ -n ${php_config:-} ]]; then + echo "Using PHP configuration (php.ini) file '${php_config#$HEROKU_APP_DIR/}'" >&2 + php_config=$(php_passthrough "$php_config") +fi + +if [[ -n ${httpd_config_include:-} || ( ${httpd_config_include:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/default_include.conf"} && $verbose ) ]]; then + echo "Using Apache2 VirtualHost-level configuration include '${httpd_config_include#$HEROKU_APP_DIR/}'" >&2 +fi +httpd_config_include=$(php_passthrough "$httpd_config_include") +export HEROKU_PHP_HTTPD_CONFIG_INCLUDE="$httpd_config_include" + +if [[ -n ${httpd_config:-} || ( ${httpd_config:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/apache2/heroku.conf"} && $verbose) ]]; then + echo "Using Apache2 configuration file '${httpd_config#$HEROKU_APP_DIR/}'" >&2 +fi +httpd_config=$(php_passthrough "$httpd_config") + +# if WEB_CONCURRENCY starts with a 0, then that's a default value which comes from another buildpack (e.g. Node), so we ignore it +if [[ -z ${WEB_CONCURRENCY:-} || "${WEB_CONCURRENCY}" == 0* ]]; then + maxprocs=$(ulimit -u) + ram="512M" + if [[ -n ${DYNO:-} && "$maxprocs" == "32768" ]]; then + echo "Optimizing defaults for PX dyno...." >&2 + ram="6G" + elif [[ -n ${DYNO:-} && "$maxprocs" == "16384" ]]; then + echo "Optimizing defaults for IX dyno...." >&2 + ram="2560M" + elif [[ -n ${DYNO:-} && "$maxprocs" == "512" ]]; then + echo "Optimizing defaults for 2X dyno..." >&2 + ram="1G" + elif [[ -n ${DYNO:-} && "$maxprocs" == "256" ]]; then + echo "Optimizing defaults for 1X dyno..." >&2 + elif [[ -n ${DYNO:-} || $verbose ]]; then + echo "No dyno detected; using defaults for 1X..." >&2 + fi + + # determine number of FPM processes to run + # prevent loading of extension INIs (and thus e.g. newrelic) using empty PHP_INI_SCAN_DIR + read WEB_CONCURRENCY php_memory_limit <<<$(PHP_INI_SCAN_DIR= php ${php_config:+-c "$php_config"} $(composer config vendor-dir 2> /dev/null | tail -n 1)/heroku/heroku-buildpack-php/bin/util/autotune.php -y "$fpm_config" -t "$DOCUMENT_ROOT" "$ram") # tail, as composer echos outdated version warnings to STDOUT + [[ $WEB_CONCURRENCY -lt 1 ]] && WEB_CONCURRENCY=1 + export WEB_CONCURRENCY + + echo "${WEB_CONCURRENCY} processes at ${php_memory_limit}B memory limit." >&2 +else + echo "Using WEB_CONCURRENCY=${WEB_CONCURRENCY} processes." >&2 +fi + +# make a shared pipe; we'll write the name of the process that exits to it once that happens, and wait for that event below +# this particular call works on Linux and Mac OS (will create a literal ".XXXXXX" on Mac, but that doesn't matter). +wait_pipe=$(mktemp -t "heroku.waitpipe-$PORT.XXXXXX" -u) +rm -f $wait_pipe +mkfifo $wait_pipe +exec 3<> $wait_pipe + +pids=() + +# trap SIGQUIT (ctrl+\ on the console), SIGTERM (when we get killed) and EXIT (upon failure of any command due to set -e, or because of the exit 1 at the very end), we then +# 1) restore the trap for the signal in question so it doesn't fire again due to the kill at the end of the trap, as well as for EXIT, because that would fire too +# 2) call cleanup() to +# 2a) remove our FIFO from above +# 2b) kill all the subshells we've spawned - they in turn have their own traps to kill their respective subprocesses, and because we use SIGUSR1, they know it's the parent's cleanup and can handle it differently from an external SIGKILL +# 2c) send STDERR to /dev/null so we don't see "no such process" errors - after all, one of the subshells may be gone +# 2d) || true so that set -e doesn't cause a mess if the kill returns 1 on "no such process" cases (which is likely on Heroku where all processes get killed and not just this top level one) +# 2e) do that in the background and 'wait' on those processes, sending wait's output to /dev/null - this prevents the logs getting cluttered with "vendor/bin/heroku-...: line 309: 96 Terminated" messages (we can't use 'disown' after launching programs for that purpose because that removes the jobs from the shell's jobs table and the we can no longer 'wait' on the program) +# 3) kill ourselves with the correct signal in case we're handling SIGQUIT or SIGTERM (http://www.cons.org/cracauer/sigint.html and http://mywiki.wooledge.org/SignalTrap#Special_Note_On_SIGINT1) +cleanup() { echo "Going down, terminating child processes..." >&2; rm -f ${wait_pipe} || true; kill -USR1 "${pids[@]}" 2> /dev/null || true; } +trap 'trap - QUIT EXIT; cleanup; kill -QUIT $$' QUIT +trap 'trap - TERM EXIT; cleanup; kill -TERM $$' TERM +trap 'trap - EXIT; cleanup' EXIT +# if FD 1 is a TTY (that's the -t 1 check), trap SIGINT/Ctrl+C, then same procedure as for QUIT and TERM above +if [[ -t 1 ]]; then + trap 'trap - INT EXIT; cleanup; kill -INT $$' INT; +# if FD 1 is not a TTY (e.g. when we're run through 'foreman start'), do nothing on SIGINT; the assumption is that the parent will send us a SIGTERM or something when this happens. With the trap above, Ctrl+C-ing out of a 'foreman start' run would trigger the INT trap both in Foreman and here (because Ctrl+C sends SIGINT to the entire process group, but there is no way to tell the two cases apart), and while the trap is still doing its shutdown work triggered by the SIGTERM from the Ctrl+C, Foreman would then send a SIGTERM because that's what it does when it receives a SIGINT itself. +else + trap '' INT; +fi + +# we are now launching a subshell for each of the tasks (log tail, app server, web server) +# 1) each subshell has a trap on EXIT that echos the command name to FD 3 (see the FIFO set up above) +# 1a) a 'read' at the end of the script will block on reading from that FD and then trigger the exit trap further above, which does the cleanup +# 2) each subshell also has a trap on TERM that +# 2a) kills $! (the last process executed) +# 2b) ... which in turn will hit the EXIT trap and that unblocks the 'wait' in 5) which will cause the parent to clean up when the exit at the end of the script is hit +# 2c) the 'kill' is done in the background and we immediately 'wait' on $!, sending wait's output to /dev/null - this prevents the logs getting cluttered with "vendor/bin/heroku-...: line 309: 96 Terminated" messages (we can't use 'disown' after launching programs for that purpose because that removes the jobs from the shell's jobs table and the we can no longer 'wait' on the program) +# 2d) finally, if $BASHPID exists, the subshell kills itself using the right signal for maximum compliance ($$ doesn't work in subshells, and $BASHPID is not available in Bash 3, but unlike with the parent, it's not that critical to have this) +# 3) each subshell has another trap on USR1 which gets sent when the parent is cleaning up; it works like 2a) but doesn't trigger the EXIT trap to avoid multiple cleanup runs by the parent +# 4) execute the command in the background +# 5) 'wait' on the command (wait is interrupted by an incoming TERM to the subshell, whereas running 4) in the foreground would wait for that process to finish before triggering the trap) +# 6) add the PID of the subshell to the array that the EXIT trap further above uses to clean everything up + +[[ $verbose ]] && echo "Starting log redirection..." >&2 +( + # the TERM trap here is special, because + # 1) there is a pipeline from tail to sed + # 2) we thus need to kill several children + # 3) kill $! will no longer do the job in that case + # 4) job control (set -m, where we could then kill %% instead) has weird side effects e.g. on ctrl+c (kills the parent terminal after that too) + # 5) so we try to kill all currently running jobs + # 5a) gracefully, by redirecting STDERR to /dev/null - one of the children will already be gone + # 6) the sed with the Darwin/GNU sed arg case used to be a function, but that was even worse with an extra wrapping subshell for sed + # FIXME: fires when the subshell or the tail is killed, but not when the sed is killed, because... pipes :( maybe we can do http://mywiki.wooledge.org/ProcessManagement#My_script_runs_a_pipeline.__When_the_script_is_killed.2C_I_want_the_pipeline_to_die_too. + logs_pipe=$(mktemp -t "heroku.logspipe-$$.XXXXXX" -u) + rm -f $logs_pipe + mkfifo $logs_pipe + unset logs_procs + + trap '' INT; + trap 'echo "tail" >&3;' EXIT + trap 'trap - TERM; kill -TERM "${logs_procs[@]}" 2> /dev/null || true & wait "${logs_procs[@]}" 2> /dev/null || true; rm -f $logs_pipe; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM "${logs_procs[@]}" 2> /dev/null || true & wait "${logs_procs[@]}" 2> /dev/null || true; rm -f $logs_pipe; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + touch "${logs[@]}" + + if [[ $(uname) == "Darwin" ]]; then + sedbufarg="-l" # mac/bsd sed: -l buffers on line boundaries + else + sedbufarg="-u" # unix/gnu sed: -u unbuffered (arbitrary) chunks of data + fi + + tail -qF -n 0 "${logs[@]}" > "$logs_pipe" & logs_procs+=($!) + sed $sedbufarg -E -e 's/^\[[^]]+\] WARNING: \[pool [^]]+\] child [0-9]+ said into std(err|out): "(.*)("|...)$/\2\3/' -e 's/"$//' < "$logs_pipe" 1>&2 & logs_procs+=($!) # messages that are too long are cut off using "..." by FPM instead of closing double quotation marks; we want to preserve those three dots but not the closing double quotes + + wait +) & pids+=($!) +disown $! + +echo "Starting php-fpm..." >&2 +( + trap '' INT; + trap 'echo "php-fpm" >&3;' EXIT + trap 'trap - TERM; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + php-fpm --nodaemonize -y "$fpm_config" ${php_config:+-c "$php_config"} & pid=$! + + wait +) & pids+=($!) +disown $! + +# wait a few seconds for FPM to finish initializing; otherwise an early request might break Apache with the FastCGI pipe not being ready +sleep 2 + +echo "Starting httpd..." >&2 +( + trap '' INT; + trap 'echo "httpd" >&3;' EXIT + trap 'trap - TERM; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + httpd -D NO_DETACH -c "Include $httpd_config" & pid=$! + + wait +) & pids+=($!) +disown $! + +# on Heroku, there is a "state changed from starting to up", but for local execution, we want a "ready" message +[[ -z ${DYNO:-} || $verbose ]] && echo "Application ready for connections on port $PORT." >&2 + +# wait for something to come from the FIFO attached to FD 3, which means that the given process was killed or has failed +# this will be interrupted by a SIGTERM or SIGINT in the traps further up +# if the pipe unblocks and this executes, then we won't read it again, so if the traps further up kill the remaining subshells above, their writing to FD 3 will have no effect +read exitproc <&3 +# we'll only reach this if one of the processes above has terminated +echo "Process exited unexpectedly: $exitproc" >&2 + +# this will trigger the EXIT trap further up and kill all remaining children +exit 1 diff --git a/vendor/heroku/heroku-buildpack-php/bin/heroku-php-nginx b/vendor/heroku/heroku-buildpack-php/bin/heroku-php-nginx new file mode 100755 index 0000000..34aba3b --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/heroku-php-nginx @@ -0,0 +1,406 @@ +#!/usr/bin/env bash + +# fail hard +set -o pipefail +# fail harder +set -eu +# for ${DOCUMENT_ROOT%%*(/)} pattern further down +shopt -s extglob +# for detecting when -l 'logs/*.log' matches nothing +shopt -s nullglob + +verbose= + +php_passthrough() { + local dir=$(dirname "$1") + local file=$(basename "$1") + local out=$(basename "$file" .php) + if [[ "$out" != "$file" ]]; then + [[ $verbose ]] && echo "Interpreting ${1#$HEROKU_APP_DIR/} to $out" >&2 + out="$dir/$out" + php -n "$1" > "$out" + echo "$out" + else + echo "$1" + fi +} + +check_exists() { + if [[ ! -f "$HEROKU_APP_DIR/$1" ]]; then + echo "Cannot read -$2 '$1' (relative to '$HEROKU_APP_DIR')" >&2 + exit 1 + else + echo "$HEROKU_APP_DIR/$1" + fi +} + +touch_log() { + mkdir -p $(dirname "$1") && touch "$1" +} + +print_help() { +echo "\ +${1:-Boots PHP-FPM together with Nginx on Heroku and for local development.} + +Usage: + heroku-php-nginx [options] [] + +Options: + -C The path to the configuration file to include inside + the Nginx server config (see option -c below). Will + be included inside the 'server { ... }' block just + after the 'listen', 'root' etc directives. + Recommended approach when customizing Nginx's config + in most cases, unless you need to set http or + fundamental server level options. + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/nginx/default_include.conf.php] + -c The path to the full configuration file that is + included after Heroku's (or your local) Nginx config + is loaded. It must contain an 'http { ... }' block + with a 'server { ... }' inside that contains 'listen' + and 'root' (see option -C above), but no global, + directives (globals are read from the system's default + Nginx configuration files). + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/nginx/heroku.conf.php] + -F The path to the configuration file to include at the + end of php-fpm.conf (see option -f below), in the + '[www]' pool section. Recommended approach when + customizing PHP-FPM's configuration in most cases, + unless you need to set global options. + -f The path to the full PHP-FPM configuration file. + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/php/php-fpm.conf] + -h, --help Display this help screen and exit. + -i The path to the php.ini file to use. + [default: \$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/php/php.ini] + -l Path to additional log file to tail to STDERR so its + contents appear in 'heroku logs'. If the file does not + exist, it will be created. Wildcards are allowed, but + must be quoted and must match already existing files. + Note: this option can be repeated multiple times. + -p Port to listen on for HTTP traffic. If this argument + is not given, then the port number to use is read from + the \$PORT environment variable, or a random port is + chosen if that variable does not exist. + -v, --verbose Be more verbose during startup. + +All file paths must be relative to '$HEROKU_APP_DIR'. + +Any file name that ends in '.php' will be run through the PHP interpreter first. +You may use this for templating; this is, for instance, necessary for Nginx, +where environment variables cannot be referenced in configuration files. + +If you would like to use the -C and -c or -F and -f options together, make sure +you retain the appropriate include mechanisms (see default configs for details). +" >&2 +} + +# we need this in configs +export HEROKU_APP_DIR=$(pwd) +export DOCUMENT_ROOT="$HEROKU_APP_DIR" +# set a default port if none is given +export PORT=${PORT:-$(( $RANDOM+1024 ))} + +# init logs array here as empty before parsing options; -l could append to it, but the default list gets added later since we use $PORT in there and that can be set using -p +declare -a logs + +optstring=":-:C:c:F:f:i:l:p:vh" + +# process flags first +while getopts "$optstring" opt; do + case $opt in + -) + case "$OPTARG" in + verbose) + verbose=1 + ;; + help) + print_help 2>&1 + exit + ;; + *) + echo "Invalid option: --$OPTARG" >&2 + exit 2 + ;; + esac + ;; + v) + verbose=1 + ;; + h) + print_help 2>&1 + exit + ;; + esac +done + +OPTIND=1 # start over with options parsing +while getopts "$optstring" opt; do + case $opt in + C) + nginx_config_include=$(check_exists "$OPTARG" "C") + ;; + c) + nginx_config=$(check_exists "$OPTARG" "c") + ;; + F) + fpm_config_include=$(check_exists "$OPTARG" "F") + ;; + f) + fpm_config=$(check_exists "$OPTARG" "f") + ;; + i) + php_config=$(check_exists "$OPTARG" "i") + ;; + l) + logarg=( $OPTARG ) # must not quote this or wildcards won't get expanded into individual values + if [[ ${#logarg[@]} -eq 0 ]]; then # we set nullglob to detect if a pattern matched nothing (then the array is empty) + echo "Pattern '$OPTARG' passed to option -l matched no files" >&2 + exit 1 + fi + for logfile in "${logarg[@]}"; do + if [[ -d "$logfile" ]]; then + echo "-l '$logfile': is a directory" >&2 + exit 1 + fi + touch_log "$logfile" || { echo "Could not touch '$logfile'; permissions problem?" >&2; exit 1; } + [[ $verbose ]] && echo "Tailing '$logfile' to stderr" >&2 + logs+=("$logfile") # must quote here in case a wildcard matched a file with a space in the name + done + ;; + p) + PORT="$OPTARG" + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 2 + ;; + :) + echo "Option -$OPTARG requires an argument" >&2 + exit 2 + ;; + esac +done +# clear processed arguments +shift $((OPTIND-1)) + +if [[ "$#" -gt "1" ]]; then + print_help "$0: too many arguments. If you're using options, +make sure to list them before any document root argument you're providing." + exit 2 +fi + +# our standard logs +logs+=( "/tmp/heroku.php-fpm.$PORT.log" "/tmp/heroku.php-fpm.www.$PORT.log" "/tmp/heroku.php-fpm.$PORT.www.slowlog" "/tmp/heroku.nginx_access.$PORT.log" ) + +# a bunch of checks; don't load any INIs to prevent newrelic etc from loading, we don't need all that stuff +php -n -r 'exit((int)version_compare(PHP_VERSION, "5.5.11", "<"));' || { echo "This program requires PHP 5.5.11 or newer; check your 'php' command." >&2; exit 1; } +{ php-fpm -n -v | php -n -r 'exit((int)version_compare(preg_replace("#PHP (\S+) \(fpm-fcgi\).+$#sm", "\\1", file_get_contents("php://stdin")), "5.5.11", "<"));'; } || { echo "This program requires PHP 5.5.11 or newer; check your 'php-fpm' command." >&2; exit 1; } +unset -f php-fpm # remove the alias we made earlier that would prevent newrelic from starting on php-fpm -v + +# make sure we run a local composer.phar if present, or global composer if not +composer() { + local composer_bin=$(which ./composer.phar composer | head -n1) + # check if we the composer binary is executable by PHP + if file --brief --dereference $composer_bin | grep -e "shell" -e "bash" > /dev/null ; then # newer versions of file return "data" for .phar + # run it directly; it's probably a bash script or similar (homebrew-php does this) + $composer_bin "$@" + else + php -n $composer_bin "$@" + fi +} +COMPOSER_VENDOR_DIR=$(composer config vendor-dir 2> /dev/null | tail -n 1) && export COMPOSER_VENDOR_DIR || { echo "Unable to determine Composer vendor-dir setting; is 'composer' executable on path or 'composer.phar' in current working directory?" >&2; exit 1; } # tail, as composer echos outdated version warnings to STDOUT; export after the assignment or exit status will that be of 'export +COMPOSER_BIN_DIR=$(composer config bin-dir 2> /dev/null | tail -n 1) && export COMPOSER_BIN_DIR || { echo "Unable to determine Composer bin-dir setting; is 'composer' executable on path or 'composer.phar' in current working directory?" >&2; exit 1; } # tail, as composer echos outdated version warnings to STDOUT; export after the assignment or exit status will that be of 'export + +if [[ "$#" == "1" ]]; then + DOCUMENT_ROOT="$HEROKU_APP_DIR/$1" + if [[ ! -d "$DOCUMENT_ROOT" ]]; then + echo "DOCUMENT_ROOT '$1' does not exist" >&2 + exit 1 + else + # strip trailing slashes if present + DOCUMENT_ROOT=${DOCUMENT_ROOT%%*(/)} # powered by extglob + if [[ $verbose ]]; then + echo "DOCUMENT_ROOT changed to '$DOCUMENT_ROOT'" >&2 + else + echo "DOCUMENT_ROOT changed to '${1%%*(/)}/'" >&2 + fi + fi +fi + +if [[ -n ${fpm_config_include:-} ]]; then + echo "Using PHP-FPM configuration include '${fpm_config_include#$HEROKU_APP_DIR/}'" >&2 + fpm_config_include=$(php_passthrough "$fpm_config_include") + export HEROKU_PHP_FPM_CONFIG_INCLUDE="$fpm_config_include" +fi + +if [[ -n ${fpm_config:-} || ( ${fpm_config:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/php/php-fpm.conf"} && $verbose ) ]]; then + echo "Using PHP-FPM configuration file '${fpm_config#$HEROKU_APP_DIR/}'" >&2 +fi +fpm_config=$(php_passthrough "$fpm_config") + +if [[ -n ${php_config:-} ]]; then + echo "Using PHP configuration (php.ini) file '${php_config#$HEROKU_APP_DIR/}'" >&2 + php_config=$(php_passthrough "$php_config") +fi + +if [[ -n ${nginx_config_include:-} || ( ${nginx_config_include:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/nginx/default_include.conf.php"} && $verbose ) ]]; then + echo "Using Nginx server-level configuration include '${nginx_config_include#$HEROKU_APP_DIR/}'" >&2 +fi +nginx_config_include=$(php_passthrough "$nginx_config_include") +export HEROKU_PHP_NGINX_CONFIG_INCLUDE="$nginx_config_include" + +if [[ -n ${nginx_config:-} || ( ${nginx_config:="$HEROKU_APP_DIR/$COMPOSER_VENDOR_DIR/heroku/heroku-buildpack-php/conf/nginx/heroku.conf.php"} && $verbose) ]]; then + echo "Using Nginx configuration file '${nginx_config#$HEROKU_APP_DIR/}'" >&2 +fi +nginx_config=$(php_passthrough "$nginx_config") + +# if WEB_CONCURRENCY starts with a 0, then that's a default value which comes from another buildpack (e.g. Node), so we ignore it +if [[ -z ${WEB_CONCURRENCY:-} || "${WEB_CONCURRENCY}" == 0* ]]; then + maxprocs=$(ulimit -u) + ram="512M" + if [[ -n ${DYNO:-} && "$maxprocs" == "32768" ]]; then + echo "Optimizing defaults for PX dyno...." >&2 + ram="6G" + elif [[ -n ${DYNO:-} && "$maxprocs" == "16384" ]]; then + echo "Optimizing defaults for IX dyno...." >&2 + ram="2560M" + elif [[ -n ${DYNO:-} && "$maxprocs" == "512" ]]; then + echo "Optimizing defaults for 2X dyno..." >&2 + ram="1G" + elif [[ -n ${DYNO:-} && "$maxprocs" == "256" ]]; then + echo "Optimizing defaults for 1X dyno..." >&2 + elif [[ -n ${DYNO:-} || $verbose ]]; then + echo "No dyno detected; using defaults for 1X..." >&2 + fi + + # determine number of FPM processes to run + # prevent loading of extension INIs (and thus e.g. newrelic) using empty PHP_INI_SCAN_DIR + read WEB_CONCURRENCY php_memory_limit <<<$(PHP_INI_SCAN_DIR= php ${php_config:+-c "$php_config"} $(composer config vendor-dir 2> /dev/null | tail -n 1)/heroku/heroku-buildpack-php/bin/util/autotune.php -y "$fpm_config" -t "$DOCUMENT_ROOT" "$ram") # tail, as composer echos outdated version warnings to STDOUT + [[ $WEB_CONCURRENCY -lt 1 ]] && WEB_CONCURRENCY=1 + export WEB_CONCURRENCY + + echo "${WEB_CONCURRENCY} processes at ${php_memory_limit}B memory limit." >&2 +else + echo "Using WEB_CONCURRENCY=${WEB_CONCURRENCY} processes." >&2 +fi + +# make a shared pipe; we'll write the name of the process that exits to it once that happens, and wait for that event below +# this particular call works on Linux and Mac OS (will create a literal ".XXXXXX" on Mac, but that doesn't matter). +wait_pipe=$(mktemp -t "heroku.waitpipe-$PORT.XXXXXX" -u) +rm -f $wait_pipe +mkfifo $wait_pipe +exec 3<> $wait_pipe + +pids=() + +# trap SIGQUIT (ctrl+\ on the console), SIGTERM (when we get killed) and EXIT (upon failure of any command due to set -e, or because of the exit 1 at the very end), we then +# 1) restore the trap for the signal in question so it doesn't fire again due to the kill at the end of the trap, as well as for EXIT, because that would fire too +# 2) call cleanup() to +# 2a) remove our FIFO from above +# 2b) kill all the subshells we've spawned - they in turn have their own traps to kill their respective subprocesses, and because we use SIGUSR1, they know it's the parent's cleanup and can handle it differently from an external SIGKILL +# 2c) send STDERR to /dev/null so we don't see "no such process" errors - after all, one of the subshells may be gone +# 2d) || true so that set -e doesn't cause a mess if the kill returns 1 on "no such process" cases (which is likely on Heroku where all processes get killed and not just this top level one) +# 2e) do that in the background and 'wait' on those processes, sending wait's output to /dev/null - this prevents the logs getting cluttered with "vendor/bin/heroku-...: line 309: 96 Terminated" messages (we can't use 'disown' after launching programs for that purpose because that removes the jobs from the shell's jobs table and the we can no longer 'wait' on the program) +# 3) kill ourselves with the correct signal in case we're handling SIGQUIT or SIGTERM (http://www.cons.org/cracauer/sigint.html and http://mywiki.wooledge.org/SignalTrap#Special_Note_On_SIGINT1) +cleanup() { echo "Going down, terminating child processes..." >&2; rm -f ${wait_pipe} || true; kill -USR1 "${pids[@]}" 2> /dev/null || true; } +trap 'trap - QUIT EXIT; cleanup; kill -QUIT $$' QUIT +trap 'trap - TERM EXIT; cleanup; kill -TERM $$' TERM +trap 'trap - EXIT; cleanup' EXIT +# if FD 1 is a TTY (that's the -t 1 check), trap SIGINT/Ctrl+C, then same procedure as for QUIT and TERM above +if [[ -t 1 ]]; then + trap 'trap - INT EXIT; cleanup; kill -INT $$' INT; +# if FD 1 is not a TTY (e.g. when we're run through 'foreman start'), do nothing on SIGINT; the assumption is that the parent will send us a SIGTERM or something when this happens. With the trap above, Ctrl+C-ing out of a 'foreman start' run would trigger the INT trap both in Foreman and here (because Ctrl+C sends SIGINT to the entire process group, but there is no way to tell the two cases apart), and while the trap is still doing its shutdown work triggered by the SIGTERM from the Ctrl+C, Foreman would then send a SIGTERM because that's what it does when it receives a SIGINT itself. +else + trap '' INT; +fi + +# we are now launching a subshell for each of the tasks (log tail, app server, web server) +# 1) each subshell has a trap on EXIT that echos the command name to FD 3 (see the FIFO set up above) +# 1a) a 'read' at the end of the script will block on reading from that FD and then trigger the exit trap further above, which does the cleanup +# 2) each subshell also has a trap on TERM that +# 2a) kills $! (the last process executed) +# 2b) ... which in turn will hit the EXIT trap and that unblocks the 'wait' in 5) which will cause the parent to clean up when the exit at the end of the script is hit +# 2c) the 'kill' is done in the background and we immediately 'wait' on $!, sending wait's output to /dev/null - this prevents the logs getting cluttered with "vendor/bin/heroku-...: line 309: 96 Terminated" messages (we can't use 'disown' after launching programs for that purpose because that removes the jobs from the shell's jobs table and the we can no longer 'wait' on the program) +# 2d) finally, if $BASHPID exists, the subshell kills itself using the right signal for maximum compliance ($$ doesn't work in subshells, and $BASHPID is not available in Bash 3, but unlike with the parent, it's not that critical to have this) +# 3) each subshell has another trap on USR1 which gets sent when the parent is cleaning up; it works like 2a) but doesn't trigger the EXIT trap to avoid multiple cleanup runs by the parent +# 4) execute the command in the background +# 5) 'wait' on the command (wait is interrupted by an incoming TERM to the subshell, whereas running 4) in the foreground would wait for that process to finish before triggering the trap) +# 6) add the PID of the subshell to the array that the EXIT trap further above uses to clean everything up + +[[ $verbose ]] && echo "Starting log redirection..." >&2 +( + # the TERM trap here is special, because + # 1) there is a pipeline from tail to sed + # 2) we thus need to kill several children + # 3) kill $! will no longer do the job in that case + # 4) job control (set -m, where we could then kill %% instead) has weird side effects e.g. on ctrl+c (kills the parent terminal after that too) + # 5) so we try to kill all currently running jobs + # 5a) gracefully, by redirecting STDERR to /dev/null - one of the children will already be gone + # 6) the sed with the Darwin/GNU sed arg case used to be a function, but that was even worse with an extra wrapping subshell for sed + # FIXME: fires when the subshell or the tail is killed, but not when the sed is killed, because... pipes :( maybe we can do http://mywiki.wooledge.org/ProcessManagement#My_script_runs_a_pipeline.__When_the_script_is_killed.2C_I_want_the_pipeline_to_die_too. + logs_pipe=$(mktemp -t "heroku.logspipe-$$.XXXXXX" -u) + rm -f $logs_pipe + mkfifo $logs_pipe + unset logs_procs + + trap '' INT; + trap 'echo "tail" >&3;' EXIT + trap 'trap - TERM; kill -TERM "${logs_procs[@]}" 2> /dev/null || true & wait "${logs_procs[@]}" 2> /dev/null || true; rm -f $logs_pipe; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM "${logs_procs[@]}" 2> /dev/null || true & wait "${logs_procs[@]}" 2> /dev/null || true; rm -f $logs_pipe; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + touch "${logs[@]}" + + if [[ $(uname) == "Darwin" ]]; then + sedbufarg="-l" # mac/bsd sed: -l buffers on line boundaries + else + sedbufarg="-u" # unix/gnu sed: -u unbuffered (arbitrary) chunks of data + fi + + tail -qF -n 0 "${logs[@]}" > "$logs_pipe" & logs_procs+=($!) + sed $sedbufarg -E -e 's/^\[[^]]+\] WARNING: \[pool [^]]+\] child [0-9]+ said into std(err|out): "(.*)("|...)$/\2\3/' -e 's/"$//' < "$logs_pipe" 1>&2 & logs_procs+=($!) # messages that are too long are cut off using "..." by FPM instead of closing double quotation marks; we want to preserve those three dots but not the closing double quotes + + wait +) & pids+=($!) +disown $! + +echo "Starting php-fpm..." >&2 +( + trap '' INT; + trap 'echo "php-fpm" >&3;' EXIT + trap 'trap - TERM; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + php-fpm --nodaemonize -y "$fpm_config" ${php_config:+-c "$php_config"} & pid=$! + + wait +) & pids+=($!) +disown $! + +# wait a few seconds for FPM to finish initializing; otherwise an early request might break Apache with the FastCGI pipe not being ready +sleep 2 + +echo "Starting nginx..." >&2 +( + trap '' INT; + trap 'echo "nginx" >&3;' EXIT + trap 'trap - TERM; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -TERM $BASHPID' TERM + trap 'trap - USR1 EXIT; kill -TERM $pid 2> /dev/null || true & wait $pid 2> /dev/null || true; [[ ${BASHPID:-} ]] && kill -USR1 $BASHPID' USR1 + + nginx -g "daemon off; include $nginx_config;" & pid=$! + + wait +) & pids+=($!) +disown $! + +# on Heroku, there is a "state changed from starting to up", but for local execution, we want a "ready" message +[[ -z ${DYNO:-} || $verbose ]] && echo "Application ready for connections on port $PORT." >&2 + +# wait for something to come from the FIFO attached to FD 3, which means that the given process was killed or has failed +# this will be interrupted by a SIGTERM or SIGINT in the traps further up +# if the pipe unblocks and this executes, then we won't read it again, so if the traps further up kill the remaining subshells above, their writing to FD 3 will have no effect +read exitproc <&3 +# we'll only reach this if one of the processes above has terminated +echo "Process exited unexpectedly: $exitproc" >&2 + +# this will trigger the EXIT trap further up and kill all remaining children +exit 1 diff --git a/vendor/heroku/heroku-buildpack-php/bin/release b/vendor/heroku/heroku-buildpack-php/bin/release new file mode 100755 index 0000000..58221c3 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/release @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# bin/release + +cat < + +# fail hard +set -o pipefail +# fail harder +set -eu + +# this will cause bin/compile to install dev platform and user dependencies +export HEROKU_PHP_INSTALL_DEV="" # empty string is correct; it will be inserted into command strings, and Composer throws a deprecation warning if the explicit "--dev" is used + +bp_dir=$(cd $(dirname $0); cd ..; pwd) +source $bp_dir/bin/compile diff --git a/vendor/heroku/heroku-buildpack-php/bin/util/autotune.php b/vendor/heroku/heroku-buildpack-php/bin/util/autotune.php new file mode 100755 index 0000000..1d5bfad --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/util/autotune.php @@ -0,0 +1,79 @@ +#!/usr/bin/env php + $directives) { + foreach($directives as $key => $value) { + if($section == "www" && $key == "php_admin_value" && isset($value['memory_limit'])) { + $retval['php_admin_value'] = $value['memory_limit']; + } elseif($section == "www" && $key == "php_value" && isset($value['memory_limit']) && !isset($retval['php_value'])) { + // an existing value takes precedence + // we can only emulate that for includes; within the same file, the INI parser overwrites earlier values :( + $retval['php_value'] = $value['memory_limit']; + } elseif($key == "include") { + // values from the include don't overwrite existing values + $retval = array_merge(get_fpm_memory_limit($value, $section), $retval); + } + + if(isset($retval['php_admin_value'])) { + // done for good as nothing can change this anymore, bubble upwards + return $retval; + } + } + } + + return $retval; +} + +$opts = getopt("y:t:"); + +$limits = get_fpm_memory_limit(isset($opts["y"]) ? $opts["y"] : null); + +if( + !$limits /* .user.ini memory limit is ignored if one is set via FPM */ && + isset($opts['t']) && + is_readable($opts['t'].'/.user.ini') +) { + // we only read the topmost .user.ini inside document root + $userini = parse_ini_file($opts['t'].'/.user.ini'); + if(isset($userini['memory_limit'])) { + $limits['php_value'] = $userini['memory_limit']; + } +} + +if(isset($limits['php_admin_value'])) { + ini_set('memory_limit', $limits['php_admin_value']); +} elseif(isset($limits['php_value'])) { + ini_set('memory_limit', $limits['php_value']); +} + +$limit = ini_get('memory_limit'); +$ram = stringtobytes($argv[$argc-1]); // last arg is the available memory + +// assume 64 MB base overhead for web server and FPM, and 1 MB overhead for each worker +// echo floor(($ram-stringtobytes('64M'))/(stringtobytes($limit)+stringtobytes('1M'))) . " " . $limit; +echo floor($ram / (stringtobytes($limit)?:-1)) . " " . $limit; diff --git a/vendor/heroku/heroku-buildpack-php/bin/util/blackfire.sh b/vendor/heroku/heroku-buildpack-php/bin/util/blackfire.sh new file mode 100755 index 0000000..10deb01 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/util/blackfire.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +install_blackfire_ext() { + # special treatment for Blackfire; we enable it if we detect a server id and a server token for it + # otherwise users would have to have it in their require section, which is annoying in development environments + BLACKFIRE_SERVER_ID=${BLACKFIRE_SERVER_ID:-} + BLACKFIRE_SERVER_TOKEN=${BLACKFIRE_SERVER_TOKEN:-} + if [[ "$engine" == "php" && -n "$BLACKFIRE_SERVER_TOKEN" && -n "$BLACKFIRE_SERVER_ID" ]] && ! $engine -n $(which composer) show -d "$build_dir/.heroku/php" --installed --quiet heroku-sys/ext-blackfire 2>/dev/null; then + if $engine -n $(which composer) require --update-no-dev -d "$build_dir/.heroku/php" -- "heroku-sys/ext-blackfire:*" >> $build_dir/.heroku/php/install.log 2>&1; then + echo "- Blackfire detected, installed ext-blackfire" | indent + else + warning_inline "Blackfire detected, but no suitable extension available" + fi + fi +} diff --git a/vendor/heroku/heroku-buildpack-php/bin/util/common.sh b/vendor/heroku/heroku-buildpack-php/bin/util/common.sh new file mode 100755 index 0000000..c4507f9 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/util/common.sh @@ -0,0 +1,66 @@ +error() { + echo + echo " ! ERROR: $*" | indent no_first_line_indent + echo + exit 1 +} + +warning() { + echo + echo " ! WARNING: $*" | indent no_first_line_indent + echo +} + +warning_inline() { + echo " ! WARNING: $*" | indent no_first_line_indent +} + +status() { + echo "-----> $*" +} + +notice() { + echo + echo "NOTICE: $*" | indent + echo +} + +notice_inline() { + echo "NOTICE: $*" | indent +} + +# sed -l basically makes sed replace and buffer through stdin to stdout +# so you get updates while the command runs and dont wait for the end +# e.g. npm install | indent +indent() { + # if an arg is given it's a flag indicating we shouldn't indent the first line, so use :+ to tell SED accordingly if that parameter is set, otherwise null string for no range selector prefix (it selects from line 2 onwards and then every 1st line, meaning all lines) + local c="${1:+"2,999"} s/^/ /" + case $(uname) in + Darwin) sed -l "$c";; # mac/bsd sed: -l buffers on line boundaries + *) sed -u "$c";; # unix/gnu sed: -u unbuffered (arbitrary) chunks of data + esac +} + +export_env_dir() { + local env_dir=$1 + local whitelist_regex=${2:-''} + local blacklist_regex=${3:-'^(PATH|GIT_DIR|CPATH|CPPATH|LD_PRELOAD|LIBRARY_PATH|IFS)$'} + if [ -d "$env_dir" ]; then + for e in $(ls $env_dir); do + echo "$e" | grep -E "$whitelist_regex" | grep -qvE "$blacklist_regex" && + export "$e=$(cat $env_dir/$e)" + : + done + fi +} + +curl_retry_on_18() { + local ec=18; + local attempts=0; + while [[ $ec -eq 18 && $attempts -lt 3 ]]; do + ((attempts++)) + curl "$@" # -C - would return code 33 if unsupported by server + ec=$? + done + return $ec +} diff --git a/vendor/heroku/heroku-buildpack-php/bin/util/newrelic.sh b/vendor/heroku/heroku-buildpack-php/bin/util/newrelic.sh new file mode 100755 index 0000000..9e38cf7 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/util/newrelic.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +install_newrelic_ext() { + # special treatment for New Relic; we enable it if we detect a license key for it + # otherwise users would have to have it in their require section, which is annoying in development environments + NEW_RELIC_LICENSE_KEY=${NEW_RELIC_LICENSE_KEY:-} + if [[ "$engine" == "php" && -n "$NEW_RELIC_LICENSE_KEY" ]] && ! $engine -n $(which composer) show -d "$build_dir/.heroku/php" --installed --quiet heroku-sys/ext-newrelic 2>/dev/null; then + if $engine -n $(which composer) require --update-no-dev -d "$build_dir/.heroku/php" -- "heroku-sys/ext-newrelic:*" >> $build_dir/.heroku/php/install.log 2>&1; then + echo "- New Relic detected, installed ext-newrelic" | indent + else + warning_inline "New Relic detected, but no suitable extension available" + fi + fi +} + +install_newrelic_userini() { + if [[ "$engine" == "php" && -n "${NEW_RELIC_CONFIG_FILE:-}" ]]; then + if [[ ! -f "${NEW_RELIC_CONFIG_FILE}" ]]; then + error "Config var 'NEW_RELIC_CONFIG_FILE' points to non existing file +'${NEW_RELIC_CONFIG_FILE}'" + fi + notice_inline "Using custom New Relic config '${NEW_RELIC_CONFIG_FILE}'" + ( cd $build_dir/.heroku/php/etc/php/conf.d; ln -s "../../../../../${NEW_RELIC_CONFIG_FILE}" "ext-newrelic.user.ini" ) + fi +} diff --git a/vendor/heroku/heroku-buildpack-php/bin/util/platform.php b/vendor/heroku/heroku-buildpack-php/bin/util/platform.php new file mode 100755 index 0000000..d800a67 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/bin/util/platform.php @@ -0,0 +1,172 @@ +#!/usr/bin/env php + "stable", + 5 => "RC", + 10 => "beta", + 15 => "alpha", + 20 => "dev", + ]; + if(!isset($stabilityFlags[$number])) { + file_put_contents("php://stderr", "ERROR: invalid stability flag '$number' in $COMPOSER_LOCK"); + exit(1); + } + return "@".$stabilityFlags[$number]; +} + +function mkmetas($package, array &$metapaks, &$have_runtime_req = false) { + // filter platform reqs + $platfilter = function($v) { return preg_match("#^(hhvm$|php(-64bit)?$|ext-)#", $v); }; + + // extract only platform requires, replaces and provides + $preq = array_filter(isset($package["require"]) ? $package["require"] : [], $platfilter, ARRAY_FILTER_USE_KEY); + $prep = array_filter(isset($package["replace"]) ? $package["replace"] : [], $platfilter, ARRAY_FILTER_USE_KEY); + $ppro = array_filter(isset($package["provide"]) ? $package["provide"] : [], $platfilter, ARRAY_FILTER_USE_KEY); + $pcon = array_filter(isset($package["conflict"]) ? $package["conflict"] : [], $platfilter, ARRAY_FILTER_USE_KEY); + if(!$preq && !$prep && !$ppro && !$pcon) return false; + $have_runtime_req |= hasreq($preq); + $metapaks[] = [ + "type" => "metapackage", + // we re-use the dep name and version, makes for nice error messages if dependencies cannot be fulfilled :) + "name" => $package["name"], + "version" => $package["version"], + "require" => mkdep($preq), + "replace" => mkdep($prep), + "provide" => mkdep($ppro), + "conflict" => mkdep($pcon), + ]; + return true; +} + +// remove first arg (0) +array_shift($argv); +// base repos we need - no packagist, and the installer plugin path (first arg) +$repositories = [ + ["packagist" => false], + ["type" => "path", "url" => array_shift($argv), "options" => ["symlink" => false]], +]; +// all other args are repo URLs; they get passed in ascending order of precedence, so we reverse +foreach(array_reverse($argv) as $repo) $repositories[] = ["type" => "composer", "url" => $repo]; + +$json = json_decode(file_get_contents($COMPOSER), true); +if(!is_array($json)) exit(1); + +$have_runtime_req = false; +$have_dev_runtime_req = false; +$require = []; +$requireDev = []; +if(file_exists($COMPOSER_LOCK)) { + $lock = json_decode(file_get_contents($COMPOSER_LOCK), true); + // basic lock file validity check + if(!$lock || !isset($lock["platform"], $lock["platform-dev"], $lock["packages"], $lock["packages-dev"])) exit(1); + if(!isset($lock["content-hash"]) && !isset($lock["hash"])) exit(1); + $have_runtime_req |= hasreq($lock["platform"]); + $have_dev_runtime_req |= hasreq($lock["platform-dev"]); + // for each package that has platform requirements we build a meta-package that we then depend on + // we cannot simply join all those requirements together with " " or "," because of the precedence of the "|" operator: requirements "5.*," and "^5.3.9|^7.0", which should lead to a PHP 5 install, would combine into "5.*,^5.3.9|^7.0" (there is no way to group requirements), and that would give PHP 7 + $metapaks = []; + // whatever is in the lock "platform" key will be turned into a meta-package too, named "composer.json/composer.lock"; same for "platform-dev" + // this will result in an installer event for that meta-package, from which we can extract what extensions that are bundled (and hence "replace"d) with the runtime need to be enabled + // if we do not do this, then a require for e.g. ext-curl or ext-mbstring in the main composer.json cannot be found by the installer plugin + $root = [ + "name" => "$COMPOSER/$COMPOSER_LOCK", + "version" => "dev-".($lock["content-hash"] ?? $lock['hash']), + "require" => $lock["platform"], + ]; + $rootDev = [ + "name" => "$COMPOSER/$COMPOSER_LOCK-require-dev", + "version" => "dev-".($lock["content-hash"] ?? $lock['hash']), + "require" => $lock["platform-dev"], + ]; + // inject the root meta-packages into the read lock file so later code picks them up too + if($root["require"]) { + $lock["packages"][] = $root; + $require = [ + $root["name"] => $root["version"], + ]; + $sfr = []; + // for any root platform require with implicit or explicit stability flags we must create a dummy require for that flag in the new root + // the reason is that the actual requiring of the package version happens in the "composer.json/composer.lock" metapackage, but stability flags that allow e.g. an RC install are ignored there - they only take effect in the root "require" section so that dependencies don't push unstable stuff onto users + foreach($lock["platform"] as $name => $version) { + if(isset($lock["stability-flags"][$name])) { + $sfr[$name] = getflag($lock["stability-flags"][$name]); + } + } + $require = array_merge($require, mkdep($sfr)); + } + // same for platform-dev requirements, but they go into a require-dev section later, so only installs with --dev pull those in + if($rootDev["require"]) { + $lock["packages-dev"][] = $rootDev; + $requireDev = [ + $rootDev["name"] => $rootDev["version"], + ]; + $sfr = []; + // for any root platform require-dev with implicit or explicit stability flags we must create a dummy require-dev for that flag in the new root + // the reason is that the actual requiring of the package version happens in the "composer.json/composer.lock" metapackage, but stability flags that allow e.g. an RC install are ignored there - they only take effect in the root "require-dev" section so that dependencies don't push unstable stuff onto users + foreach($lock["platform-dev"] as $name => $version) { + if(isset($lock["stability-flags"][$name])) { + $sfr[$name] = getflag($lock["stability-flags"][$name]); + } + } + $requireDev = array_merge($requireDev, mkdep($sfr)); + } + + // collect platform requirements from regular packages in lock file + foreach($lock["packages"] as $package) { + if(mkmetas($package, $metapaks, $have_runtime_req)) { + $require[$package["name"]] = $package["version"]; + } + } + // collect platform requirements from dev packages in lock file + foreach($lock["packages-dev"] as $package) { + if(mkmetas($package, $metapaks, $have_dev_runtime_req)) { + $requireDev[$package["name"]] = $package["version"]; + } + } + + // add all meta-packages to one local package repo + if($metapaks) $repositories[] = ["type" => "package", "package" => $metapaks]; +} + +// if no PHP or HHVM is required anywhere, we need to add something +if(!$have_runtime_req) { + if($have_dev_runtime_req) { + // there is no requirement for a PHP or HHVM version in "require", nor in any dependencies therein, but there is one in "require-dev" + // that's problematic, because requirements in there may effectively result in a rule like "7.0.*", but we'd next write "^5.5.17" into our "require" to have a sane default, and that'd blow up in CI where dev dependenies are installed + // we can't compute a resulting version rule (that's the whole point of the custom installer that uses Composer's solver), so throwing an error is the best thing we can do here + file_put_contents("php://stderr", "ERROR: neither your $COMPOSER 'require' section nor any\ndependency therein requires a runtime version, but 'require-dev'\nor a dependency therein does. Heroku cannot automatically select\na default runtime version in this case.\nPlease add a version requirement for 'php' to section 'require'\nin $COMPOSER, 'composer update', commit, and deploy again."); + exit(3); + } + file_put_contents("php://stderr", "NOTICE: No runtime required in $COMPOSER_LOCK; using PHP ". ($require["heroku-sys/php"] = "^5.5.17") . "\n"); +} elseif(!isset($root["require"]["php"]) && !isset($root["require"]["hhvm"])) { + file_put_contents("php://stderr", "NOTICE: No runtime required in $COMPOSER; requirements\nfrom dependencies in $COMPOSER_LOCK will be used for selection\n"); +} + +$require["heroku-sys/apache"] = "^2.4.10"; +$require["heroku-sys/nginx"] = "~1.8.0"; + +preg_match("#^([^-]+)(?:-([0-9]+))?\$#", $STACK, $stack); +$provide = ["heroku-sys/".$stack[1] => (isset($stack[2])?$stack[2]:"1").gmdate(".Y.m.d")]; # cedar: 14.2016.02.16 etc +$json = [ + "config" => ["cache-files-ttl" => 0, "discard-changes" => true], + "minimum-stability" => isset($lock["minimum-stability"]) ? $lock["minimum-stability"] : "stable", + "prefer-stable" => isset($lock["prefer-stable"]) ? $lock["prefer-stable"] : false, + "provide" => $provide, + "require" => $require, + "require-dev" => (object)$requireDev, + // put require before repositories, or a large number of metapackages from above will cause Composer's regexes to hit PCRE limits for backtracking or JIT stack size + "repositories" => $repositories, +]; +echo json_encode($json, JSON_PRETTY_PRINT); diff --git a/vendor/heroku/heroku-buildpack-php/composer.json b/vendor/heroku/heroku-buildpack-php/composer.json new file mode 100644 index 0000000..81ea470 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/composer.json @@ -0,0 +1,20 @@ +{ + "name": "heroku/heroku-buildpack-php", + "description": "Toolkit for starting a PHP application locally, with or without foreman, using the same config for PHP/HHVM and Apache2/Nginx as on Heroku", + "keywords": ["heroku", "foreman", "php", "hhvm", "apache", "apache2", "nginx"], + "homepage": "https://github.com/heroku/heroku-buildpack-php", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "David Zuelke", + "email": "dz@heroku.com" + } + ], + "bin": [ + "bin/heroku-hhvm-apache2", + "bin/heroku-hhvm-nginx", + "bin/heroku-php-apache2", + "bin/heroku-php-nginx" + ] +} diff --git a/vendor/heroku/heroku-buildpack-php/conf/apache2/default_include.conf b/vendor/heroku/heroku-buildpack-php/conf/apache2/default_include.conf new file mode 100644 index 0000000..e2d575a --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/conf/apache2/default_include.conf @@ -0,0 +1 @@ +DirectoryIndex index.php index.html index.htm diff --git a/vendor/heroku/heroku-buildpack-php/conf/apache2/heroku.conf b/vendor/heroku/heroku-buildpack-php/conf/apache2/heroku.conf new file mode 100644 index 0000000..3e9f5e5 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/conf/apache2/heroku.conf @@ -0,0 +1,70 @@ +# define a short-hand to our fcgi proxy, for convenience +# Define heroku-fcgi fcgi://127.0.0.1:4999 +Define heroku-fcgi unix:/tmp/heroku.fcgi.${PORT}.sock|fcgi://heroku-fcgi + +# make sure the proxy is registered with the unix socket; we can then use just "fcgi://heroku-fcgi" in proxy and rewrites directives +# we have to do this because we can't rewrite to a UDS location and because PHP doesn't support the unix:...|fcgi://... syntax +# this is also a lot more convenient for users +# http://thread.gmane.org/gmane.comp.apache.devel/52892 + + # we must declare a parameter in here or it'll not register the proxy ahead of time + # min=0 is an obvious candidate since that's the default value already and sensible + ProxySet min=0 + + +Listen ${PORT} + + + + ServerName localhost + + ErrorLog /tmp/heroku.apache2_error.${PORT}.log + # redefine "combined" log format so includes can overwrite it + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" heroku + CustomLog /tmp/heroku.apache2_access.${PORT}.log heroku + + TraceEnable off + + + # lock it down fully by default + # if it's also the docroot, it'll be opened up again further below + Require all denied + + # explicitly deny these again, merged with the docroot later + Require all denied + + + # handle these separately; who knows where they are and whether they're accessible + + Require all denied + + + Require all denied + + + DocumentRoot "${DOCUMENT_ROOT}" + + + Options FollowSymLinks + + # allow .htaccess to do everything + AllowOverride All + + # no limits + Require all granted + + + # mod_proxy doesn't forward the Authorization header, must fix that ourselves + SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1 + + # pass requests to .php files to mod_proxy_fcgi + # this requires Apache 2.4.10+ and PHP 5.5.15+ to work properly + + # make sure the file exists so that if not, Apache will show its 404 page and not FPM + SetHandler proxy:fcgi://heroku-fcgi + + + + Include "${HEROKU_PHP_HTTPD_CONFIG_INCLUDE}" + + diff --git a/vendor/heroku/heroku-buildpack-php/conf/hhvm/php.ini.php b/vendor/heroku/heroku-buildpack-php/conf/hhvm/php.ini.php new file mode 100644 index 0000000..ad789f5 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/conf/hhvm/php.ini.php @@ -0,0 +1,16 @@ +; php options +date.timezone = UTC +expose_php = off + +; hhvm specific +hhvm.log.level = Warning +hhvm.log.always_log_unhandled_exceptions = true +hhvm.log.runtime_error_reporting_level = 8191 +hhvm.mysql.typed_results = false + +memory_limit = 128M + +; hhvm fcgi +hhvm.server.type = fastcgi +hhvm.server.file_socket = /tmp/heroku.fcgi..sock +hhvm.server.thread_count = diff --git a/vendor/heroku/heroku-buildpack-php/conf/nginx/default_include.conf.php b/vendor/heroku/heroku-buildpack-php/conf/nginx/default_include.conf.php new file mode 100644 index 0000000..23135a5 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/conf/nginx/default_include.conf.php @@ -0,0 +1,8 @@ +location / { + index index.php index.html index.htm; +} + +# for people with app root as doc root, restrict access to a few things +location ~ ^/(composer\.|Procfile$|/|/) { + deny all; +} diff --git a/vendor/heroku/heroku-buildpack-php/conf/nginx/heroku.conf.php b/vendor/heroku/heroku-buildpack-php/conf/nginx/heroku.conf.php new file mode 100644 index 0000000..4a044ba --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/conf/nginx/heroku.conf.php @@ -0,0 +1,72 @@ +http { + include mime.types; + default_type application/octet-stream; + + #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + # '$status $body_bytes_sent "$http_referer" ' + # '"$http_user_agent" "$http_x_forwarded_for"'; + + #access_log logs/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + + server_tokens off; + + fastcgi_buffers 256 4k; + + # define an easy to reference name that can be used in fastgi_pass + upstream heroku-fcgi { + #server 127.0.0.1:4999 max_fails=3 fail_timeout=3s; + server unix:/tmp/heroku.fcgi..sock max_fails=3 fail_timeout=3s; + keepalive 16; + } + + server { + # define an easy to reference name that can be used in try_files + location @heroku-fcgi { + include fastcgi_params; + + fastcgi_split_path_info ^(.+\.php)(/.*)$; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + # try_files resets $fastcgi_path_info, see http://trac.nginx.org/nginx/ticket/321, so we use the if instead + fastcgi_param PATH_INFO $fastcgi_path_info if_not_empty; + + if (!-f $document_root$fastcgi_script_name) { + # check if the script exists + # otherwise, /foo.jpg/bar.php would get passed to FPM, which wouldn't run it as it's not in the list of allowed extensions, but this check is a good idea anyway, just in case + return 404; + } + + fastcgi_pass heroku-fcgi; + } + + # TODO: use X-Forwarded-Host? http://comments.gmane.org/gmane.comp.web.nginx.english/2170 + server_name localhost; + listen ; + # FIXME: breaks redirects with foreman + port_in_redirect off; + + root ""; + + error_log stderr; + access_log /tmp/heroku.nginx_access..log; + + include ""; + + # restrict access to hidden files, just in case + location ~ /\. { + deny all; + } + + # default handling of .php + location ~ \.php { + try_files @heroku-fcgi @heroku-fcgi; + } + } +} diff --git a/vendor/heroku/heroku-buildpack-php/conf/php/php-fpm.conf b/vendor/heroku/heroku-buildpack-php/conf/php/php-fpm.conf new file mode 100644 index 0000000..e08cc34 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/conf/php/php-fpm.conf @@ -0,0 +1,533 @@ +;;;;;;;;;;;;;;;;;;;;; +; FPM Configuration ; +;;;;;;;;;;;;;;;;;;;;; + +; All relative paths in this configuration file are relative to PHP's install +; prefix (/app/.heroku/php). This prefix can be dynamically changed by using the +; '-p' argument from the command line. + +; Include one or more files. If glob(3) exists, it is used to include a bunch of +; files from a glob(3) pattern. This directive can be used everywhere in the +; file. +; Relative path can also be used. They will be prefixed by: +; - the global prefix if it's been set (-p argument) +; - /app/.heroku/php otherwise +;include=etc/fpm.d/*.conf + +;;;;;;;;;;;;;;;;;; +; Global Options ; +;;;;;;;;;;;;;;;;;; + +[global] +; Pid file +; Note: the default prefix is /app/.heroku/php/var +; Default Value: none +;pid = run/php-fpm.pid + +; Error log file +; If it's set to "syslog", log is sent to syslogd instead of being written +; in a local file. +; Note: the default prefix is /app/.heroku/php/var +; Default Value: log/php-fpm.log +error_log = /tmp/heroku.php-fpm.${PORT}.log + +; syslog_facility is used to specify what type of program is logging the +; message. This lets syslogd specify that messages from different facilities +; will be handled differently. +; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON) +; Default Value: daemon +;syslog.facility = daemon + +; syslog_ident is prepended to every message. If you have multiple FPM +; instances running on the same server, you can change the default value +; which must suit common needs. +; Default Value: php-fpm +;syslog.ident = php-fpm + +; Log level +; Possible Values: alert, error, warning, notice, debug +; Default Value: notice +log_level = warning + +; If this number of child processes exit with SIGSEGV or SIGBUS within the time +; interval set by emergency_restart_interval then FPM will restart. A value +; of '0' means 'Off'. +; Default Value: 0 +;emergency_restart_threshold = 0 + +; Interval of time used by emergency_restart_interval to determine when +; a graceful restart will be initiated. This can be useful to work around +; accidental corruptions in an accelerator's shared memory. +; Available Units: s(econds), m(inutes), h(ours), or d(ays) +; Default Unit: seconds +; Default Value: 0 +;emergency_restart_interval = 0 + +; Time limit for child processes to wait for a reaction on signals from master. +; Available units: s(econds), m(inutes), h(ours), or d(ays) +; Default Unit: seconds +; Default Value: 0 +;process_control_timeout = 0 + +; The maximum number of processes FPM will fork. This has been design to control +; the global number of processes when using dynamic PM within a lot of pools. +; Use it with caution. +; Note: A value of 0 indicates no limit +; Default Value: 0 +; process.max = 128 + +; Specify the nice(2) priority to apply to the master process (only if set) +; The value can vary from -19 (highest priority) to 20 (lower priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool process will inherit the master process priority +; unless it specified otherwise +; Default Value: no set +; process.priority = -19 + +; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging. +; Default Value: yes +daemonize = no + +; Set open file descriptor rlimit for the master process. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit for the master process. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Specify the event mechanism FPM will use. The following is available: +; - select (any POSIX os) +; - poll (any POSIX os) +; - epoll (linux >= 2.5.44) +; - kqueue (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0) +; - /dev/poll (Solaris >= 7) +; - port (Solaris >= 10) +; Default Value: not set (auto detection) +;events.mechanism = epoll + +; When FPM is build with systemd integration, specify the interval, +; in second, between health report notification to systemd. +; Set to 0 to disable. +; Available Units: s(econds), m(inutes), h(ours) +; Default Unit: seconds +; Default value: 10 +;systemd_interval = 10 + +;;;;;;;;;;;;;;;;;;;; +; Pool Definitions ; +;;;;;;;;;;;;;;;;;;;; + +; Multiple pools of child processes may be started with different listening +; ports and different management options. The name of the pool will be +; used in logs and stats. There is no limitation on the number of pools which +; FPM can handle. Your system will tell you anyway :) + +; Start a new pool named 'www'. +; the variable $pool can we used in any directive and will be replaced by the +; pool name ('www' here) +[www] + +; Per pool prefix +; It only applies on the following directives: +; - 'slowlog' +; - 'listen' (unixsocket) +; - 'chroot' +; - 'chdir' +; - 'php_values' +; - 'php_admin_values' +; When not set, the global prefix (or /app/.heroku/php) applies instead. +; Note: This directive can also be relative to the global prefix. +; Default Value: none +;prefix = /path/to/pools/$pool + +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +user = nobody +;group = nobody + +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses on a +; specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +; listen = 127.0.0.1:4999 +listen = /tmp/heroku.fcgi.${PORT}.sock + +; Set listen(2) backlog. +; Default Value: 65535 (-1 on FreeBSD and OpenBSD) +;listen.backlog = 65535 + +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. Many +; BSD-derived systems allow connections regardless of permissions. +; Default Values: user and group are set as the running user +; mode is set to 0666 +;listen.owner = nobody +;listen.group = nobody +;listen.mode = 0666 + +; List of ipv4 addresses of FastCGI clients which are allowed to connect. +; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original +; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address +; must be separated by a comma. If this value is left blank, connections will be +; accepted from any ip address. +; Default Value: any +;listen.allowed_clients = 127.0.0.1 + +; Specify the nice(2) priority to apply to the pool processes (only if set) +; The value can vary from -19 (highest priority) to 20 (lower priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool processes will inherit the master process priority +; unless it specified otherwise +; Default Value: no set +; priority = -19 + +; Choose how the process manager will control the number of child processes. +; Possible Values: +; static - a fixed number (pm.max_children) of child processes; +; dynamic - the number of child processes are set dynamically based on the +; following directives. With this process management, there will be +; always at least 1 children. +; pm.max_children - the maximum number of children that can +; be alive at the same time. +; pm.start_servers - the number of children created on startup. +; pm.min_spare_servers - the minimum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is less than this +; number then some children will be created. +; pm.max_spare_servers - the maximum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is greater than this +; number then some children will be killed. +; ondemand - no children are created at startup. Children will be forked when +; new requests will connect. The following parameter are used: +; pm.max_children - the maximum number of children that +; can be alive at the same time. +; pm.process_idle_timeout - The number of seconds after which +; an idle process will be killed. +; Note: This value is mandatory. +pm = static + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = ${WEB_CONCURRENCY} + +; The number of child processes created on startup. +; Note: Used only when pm is set to 'dynamic' +; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 +;pm.start_servers = 2 + +; The desired minimum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.min_spare_servers = 1 + +; The desired maximum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.max_spare_servers = 3 + +; The number of seconds after which an idle process will be killed. +; Note: Used only when pm is set to 'ondemand' +; Default Value: 10s +;pm.process_idle_timeout = 10s; + +; The number of requests each child process should execute before respawning. +; This can be useful to work around memory leaks in 3rd party libraries. For +; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. +; Default Value: 0 +;pm.max_requests = 500 + +; The URI to view the FPM status page. If this value is not set, no URI will be +; recognized as a status page. It shows the following informations: +; pool - the name of the pool; +; process manager - static, dynamic or ondemand; +; start time - the date and time FPM has started; +; start since - number of seconds since FPM has started; +; accepted conn - the number of request accepted by the pool; +; listen queue - the number of request in the queue of pending +; connections (see backlog in listen(2)); +; max listen queue - the maximum number of requests in the queue +; of pending connections since FPM has started; +; listen queue len - the size of the socket queue of pending connections; +; idle processes - the number of idle processes; +; active processes - the number of active processes; +; total processes - the number of idle + active processes; +; max active processes - the maximum number of active processes since FPM +; has started; +; max children reached - number of times, the process limit has been reached, +; when pm tries to start more children (works only for +; pm 'dynamic' and 'ondemand'); +; Value are updated in real time. +; Example output: +; pool: www +; process manager: static +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 62636 +; accepted conn: 190460 +; listen queue: 0 +; max listen queue: 1 +; listen queue len: 42 +; idle processes: 4 +; active processes: 11 +; total processes: 15 +; max active processes: 12 +; max children reached: 0 +; +; By default the status page output is formatted as text/plain. Passing either +; 'html', 'xml' or 'json' in the query string will return the corresponding +; output syntax. Example: +; http://www.foo.bar/status +; http://www.foo.bar/status?json +; http://www.foo.bar/status?html +; http://www.foo.bar/status?xml +; +; By default the status page only outputs short status. Passing 'full' in the +; query string will also return status for each pool process. +; Example: +; http://www.foo.bar/status?full +; http://www.foo.bar/status?json&full +; http://www.foo.bar/status?html&full +; http://www.foo.bar/status?xml&full +; The Full status returns for each process: +; pid - the PID of the process; +; state - the state of the process (Idle, Running, ...); +; start time - the date and time the process has started; +; start since - the number of seconds since the process has started; +; requests - the number of requests the process has served; +; request duration - the duration in µs of the requests; +; request method - the request method (GET, POST, ...); +; request URI - the request URI with the query string; +; content length - the content length of the request (only with POST); +; user - the user (PHP_AUTH_USER) (or '-' if not set); +; script - the main script called (or '-' if not set); +; last request cpu - the %cpu the last request consumed +; it's always 0 if the process is not in Idle state +; because CPU calculation is done when the request +; processing has terminated; +; last request memory - the max amount of memory the last request consumed +; it's always 0 if the process is not in Idle state +; because memory calculation is done when the request +; processing has terminated; +; If the process is in Idle state, then informations are related to the +; last request the process has served. Otherwise informations are related to +; the current request being served. +; Example output: +; ************************ +; pid: 31330 +; state: Running +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 63087 +; requests: 12808 +; request duration: 1250261 +; request method: GET +; request URI: /test_mem.php?N=10000 +; content length: 0 +; user: - +; script: /home/fat/web/docs/php/test_mem.php +; last request cpu: 0.00 +; last request memory: 0 +; +; Note: There is a real-time FPM status monitoring sample web page available +; It's available in: ${prefix}/share/fpm/status.html +; +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;pm.status_path = /status + +; The ping URI to call the monitoring page of FPM. If this value is not set, no +; URI will be recognized as a ping page. This could be used to test from outside +; that FPM is alive and responding, or to +; - create a graph of FPM availability (rrd or such); +; - remove a server from a group if it is not responding (load balancing); +; - trigger alerts for the operating team (24/7). +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;ping.path = /ping + +; This directive may be used to customize the response of a ping request. The +; response is formatted as text/plain with a 200 response code. +; Default Value: pong +;ping.response = pong + +; The access log file +; Default: not set +;access.log = log/$pool.access.log + +; The access log format. +; The following syntax is allowed +; %%: the '%' character +; %C: %CPU used by the request +; it can accept the following format: +; - %{user}C for user CPU only +; - %{system}C for system CPU only +; - %{total}C for user + system CPU (default) +; %d: time taken to serve the request +; it can accept the following format: +; - %{seconds}d (default) +; - %{miliseconds}d +; - %{mili}d +; - %{microseconds}d +; - %{micro}d +; %e: an environment variable (same as $_ENV or $_SERVER) +; it must be associated with embraces to specify the name of the env +; variable. Some exemples: +; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e +; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e +; %f: script filename +; %l: content-length of the request (for POST request only) +; %m: request method +; %M: peak of memory allocated by PHP +; it can accept the following format: +; - %{bytes}M (default) +; - %{kilobytes}M +; - %{kilo}M +; - %{megabytes}M +; - %{mega}M +; %n: pool name +; %o: output header +; it must be associated with embraces to specify the name of the header: +; - %{Content-Type}o +; - %{X-Powered-By}o +; - %{Transfert-Encoding}o +; - .... +; %p: PID of the child that serviced the request +; %P: PID of the parent of the child that serviced the request +; %q: the query string +; %Q: the '?' character if query string exists +; %r: the request URI (without the query string, see %q and %Q) +; %R: remote IP address +; %s: status (response code) +; %t: server time the request was received +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; %T: time the log has been written (the request has finished) +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; %u: remote user +; +; Default: "%R - %u %t \"%m %r\" %s" +;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" + +; The log file for slow requests +; Default Value: not set +; Note: slowlog is mandatory if request_slowlog_timeout is set +slowlog = /tmp/heroku.php-fpm.${PORT}.www.slowlog + +; The timeout for serving a single request after which a PHP backtrace will be +; dumped to the 'slowlog' file. A value of '0s' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_slowlog_timeout = 0 + +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_terminate_timeout = 0 + +; Set open file descriptor rlimit. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Chroot to this directory at the start. This value must be defined as an +; absolute path. When this value is not set, chroot is not used. +; Note: you can prefix with '$prefix' to chroot to the pool prefix or one +; of its subdirectories. If the pool prefix is not set, the global prefix +; will be used instead. +; Note: chrooting is a great security feature and should be used whenever +; possible. However, all PHP paths will be relative to the chroot +; (error_log, sessions.save_path, ...). +; Default Value: not set +;chroot = + +; Chdir to this directory at the start. +; Note: relative path can be used. +; Default Value: current directory or / when chroot +;chdir = /var/www + +; Redirect worker stdout and stderr into main error log. If not set, stdout and +; stderr will be redirected to /dev/null according to FastCGI specs. +; Note: on highloaded environement, this can cause some delay in the page +; process time (several ms). +; Default Value: no +catch_workers_output = yes + +; Clear environment in FPM workers +; Prevents arbitrary environment variables from reaching FPM worker processes +; by clearing the environment in workers before env vars specified in this +; pool configuration are added. +; Setting to "no" will make all environment variables available to PHP code +; via getenv(), $_ENV and $_SERVER. +; Default Value: yes +clear_env = no + +; Limits the extensions of the main script FPM will allow to parse. This can +; prevent configuration mistakes on the web server side. You should only limit +; FPM to .php extensions to prevent malicious users to use other extensions to +; exectute php code. +; Note: set an empty value to allow all extensions. +; Default Value: .php +;security.limit_extensions = .php .php3 .php4 .php5 + +; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from +; the current environment. +; Default Value: clean env +;env[HOSTNAME] = $HOSTNAME +;env[PATH] = /usr/local/bin:/usr/bin:/bin +;env[TMP] = /tmp +;env[TMPDIR] = /tmp +;env[TEMP] = /tmp + +; Additional php.ini defines, specific to this pool of workers. These settings +; overwrite the values previously defined in the php.ini. The directives are the +; same as the PHP SAPI: +; php_value/php_flag - you can set classic ini defines which can +; be overwritten from PHP call 'ini_set'. +; php_admin_value/php_admin_flag - these directives won't be overwritten by +; PHP call 'ini_set' +; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. + +; Defining 'extension' will load the corresponding shared extension from +; extension_dir. Defining 'disable_functions' or 'disable_classes' will not +; overwrite previously defined php.ini values, but will append the new value +; instead. + +; Note: path INI options can be relative and will be expanded with the prefix +; (pool, global or /app/.heroku/php) + +; Default Value: nothing is defined by default except the values in php.ini and +; specified at startup with the -d argument +;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com +;php_flag[display_errors] = off +;php_admin_value[error_log] = /var/log/fpm-php.www.log +;php_admin_flag[log_errors] = on +;php_admin_value[memory_limit] = 32M + +; log PHP errors to a file, otherwise they're bubbled up through FPM via stderr +php_value[error_log] = /tmp/heroku.php-fpm.www.${PORT}.log + +include=${HEROKU_PHP_FPM_CONFIG_INCLUDE} diff --git a/vendor/heroku/heroku-buildpack-php/requirements.txt b/vendor/heroku/heroku-buildpack-php/requirements.txt new file mode 100644 index 0000000..3e3754e --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/requirements.txt @@ -0,0 +1,2 @@ +bob-builder>=0.0.10 +s3cmd>=1.6.0 diff --git a/vendor/heroku/heroku-buildpack-php/support/build/README.md b/vendor/heroku/heroku-buildpack-php/support/build/README.md new file mode 100644 index 0000000..08319f0 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/README.md @@ -0,0 +1,215 @@ +# Building Custom Platform Packages and Repositories + +## Introduction + +**Please note that Heroku cannot provide support for issues related to custom platform repositories and packages.** + +### How it all works + +When an application is deployed, `bin/compile` extracts all platform dependencies from the application's `composer.lock` and constructs a new `composer.json` (with all package names prefixed with `heroku-sys/`, so `php` becomes `heroku-sys/php`), which gets `composer install`ed using a custom Composer repository. + +This `composer.json` gets written to `.heroku/php/` and is distinct from the application's `composer.json`. It only holds information on required platform packages. + +The custom Composer repository, running off an S3 bucket, provides all of these packages; the Composer installer plugin in `support/installer/` handles extraction, activation, configuration etc. + +### Custom platform packages and repositories + +To use custom platform packages (either new ones, or modifications of existing ones), a new Composer repository has to be created (see [the instructions in the main README](../../README.md#custom-platform-repositories) for usage info). All the tooling in here is designed to work with S3, since it is reliable and cheap. The bucket permissions should be set up so that a public listing is allowed. + +The folder `support/build` contains [Bob](http://github.com/kennethreitz/bob-builder) build formulae for all packages and their dependencies. + +These build formulae can have dependencies (e.g. an extension formula depends on the correct version of PHP needed to build it, and maybe on a vendored library); Bob handles downloading of dependencies prior to a build, and it's the responsibility of a build formula to remove these dependencies again if they're not needed e.g. in between running `make` and `make install`. + +The build formulae are also expected to generate a [manifest](#about-manifests), which is a `composer.json` containing all relevant information about a package. + +In `support/build/_util`, three scripts (`deploy.sh` to deploy a package with its [manifest](#about-manifests), `mkrepo.sh` to (re-)generate a [repository](#about-repositories) from all existing manifests, and `sync.sh` to [sync between repos](#syncing-repositories)) take care of most of the heavy lifting. + +## Preparations + +You may either build packages on a Heroku dyno, or locally using a Docker container. The instructions below use `heroku run`; simply replace them with the appropriate `docker run` call if you are using Docker. + +The following environment variables are required: + +- `WORKSPACE_DIR`, must be "`/app/support/build`" +- `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` with credentials for the S3 bucket +- `S3_BUCKET` with the name of the S3 bucket to use for builds +- `S3_PREFIX` (just a slash, or a prefix directory name **with a trailing, but no leading, slash**) +- `STACK` (currently, only "`cedar-14`" makes any sense) + +The following environment variables are highly recommended (see section *Understanding Upstream Buckets*): + +- `UPSTREAM_S3_BUCKET` where dependencies are pulled from if they can't be found in `S3_BUCKET+S3_PREFIX`, should probably be set to "`lang-php`", the official Heroku bucket +- `UPSTREAM_S3_PREFIX`, where dependencies are pulled from if they can't be found in `S3_BUCKET+S3_PREFIX` should probably be set to "`dist-cedar-14-stable/`", the official Heroku stable repository prefix for the [cedar-14 stack](https://devcenter.heroku.com/articles/stack#cedar). + +The following environment variables are optional: + +- `S3_REGION`, to be set to the AWS region name (e.g. "`s3-eu-west-1`") for any non-standard region, otherwise "`s3`" (for region "us-east-1") + +### Understanding Prefixes + +It is recommended to use a prefix like "`dist-cedar-14-develop/`" for `$S3_PREFIX`. The contents of this prefix will act as a development repository, where all building happens. The `support/build/_util/sync.sh` helper can later be used to synchronize to another prefix, e.g. "`dist-cedar-14-stable/`" that is used for production. For more info, see the [section on syncing repositories](#syncing-repositories) further below. + +### Understanding Upstream Buckets + +If you want to, for example, host only a few PECL extensions in a custom repository, your bucket would still have to contain the build-time dependencies for those extensions - that's PHP in its various versions. + +Due to the order in which Composer looks up packages from repositories, including PHP builds in your custom repositories may lead to those builds getting used on deploy, which is not what you want - you want to use Heroku's official PHP builds, but still have access to your custom-built extensions. + +That's where the `UPSTREAM_S3_BUCKET` and `UPSTREAM_S3_PREFIX` env vars come into play; you'll usually set them to "`lang-php`" and "`dist-cedar-14-stable/`", respectively. + +That way, if your Bob formula for an extension contains e.g. this dependency declaration at the top: + + # Build Path: /app/.heroku/php/ + # Build Deps: php-7.0.4 + +then on build, Bob will first look for "`php-7.0.4`" in your S3 bucket, and then fall back to pulling it from the upstream bucket. This frees you of the burden of hosting and maintaining unnecessary packages yourself. + +### Build Environment Setup + +#### Using Heroku + +To get started, create a Python app (*Bob* is a Python application) on Heroku inside a clone of this repository, and set your S3 config vars: + + $ heroku create --buildpack heroku/python + $ heroku config:set WORKSPACE_DIR=/app/support/build + $ heroku config:set AWS_ACCESS_KEY_ID= + $ heroku config:set AWS_SECRET_ACCESS_KEY= + $ heroku config:set S3_BUCKET= + $ heroku config:set S3_PREFIX= + $ heroku config:set UPSTREAM_S3_BUCKET=lang-php + $ heroku config:set UPSTREAM_S3_PREFIX=dist-cedar-14-stable/ + $ heroku config:set STACK=cedar-14 + $ git push heroku master + $ heroku ps:scale web=0 + +#### Using Docker + +Refer to the [README in `support/build/_docker/`](_docker/README.md) for setup instructions. + +## Building a Package + +To verify a formula, `bob build` can be used to build it: + + $ heroku run bash + Running `bash` attached to terminal... up, run.6880 + ~ $ bob build extensions/no-debug-non-zts-20121212/yourextension-1.2.3 + + Fetching dependencies... found 1: + - php-5.5.31 + Building formula extensions/no-debug-non-zts-20121212/yourextension-1.2.3 + ... + +If that works, a `bob deploy` would build it first, and then upload it to your bucket (you can specify `--overwrite` to overwrite existing packages). + +However, that alone is not enough - the *manifest* needs to be in place as well, and using that manifest, you can then generate a Composer repository metadata file. + +The next two sections contain important info about manifests and repositories; the *tl;dr* is: **do not use `bob deploy`, but `support/build/_util/deploy.sh`, to deploy a package**, because it will take care of manifest uploading: + + $ support/build/_util/deploy.sh extensions/no-debug-non-zts-20121212/yourextension-1.2.3 + +In addition to an `--overwrite` option, the `deploy.sh` script also accepts a `--publish` option that will cause the package to immediately be published into the repository by [re-generating that repo](#re-generating-repositories). **This should be used with caution**, as several parallel `deploy.sh` invocations could result in a race condition when re-generating the repository. + +## About Manifests + +After a `bob build` or `bob deploy`, you'll be prompted to upload a manifest. It obviously only makes sense to perform this upload after a `bob deploy`. + +To perform the deploy and the manifest upload in one step, **the `deploy.sh` utility in `support/build/_util/` should be used instead of `bob deploy`**: + + $ support/build/_util/deploy.sh extensions/no-debug-non-zts-20121212/yourextension-1.2.3 + +This will upload the manifest to the S3 bucket if the package build and deploy succeeded. Like `bob deploy`, this script accepts a `--overwrite` flag. + +The manifest is a `composer.json` specific to your built package, and it is **unrelated to Bob**, the utility that performs the builds. All manifests of your bucket together need to be combined into a [repository](#about-repositories). + +All packages in the official Heroku S3 bucket use manifests, even for packages that are not exposed as part of the repository, such as library dependencies, the minimal PHP used for bootstrapping a build, or Composer. + +### Manifest Contents + +A manifest looks roughly like this (example is for `ext-apcu/5.1.3` for PHP 7): + + { + "conflict": { + "heroku-sys/hhvm": "*" + }, + "dist": { + "type": "heroku-sys-tar", + "url": "https://lang-php.s3.amazonaws.com/dist-cedar-14-stable/extensions/no-debug-non-zts-20151012/apcu-5.1.3.tar.gz" + }, + "name": "heroku-sys/ext-apcu", + "require": { + "heroku-sys/cedar": "^14.0.0", + "heroku-sys/php": "7.0.*", + "heroku/installer-plugin": "^1.2.0" + }, + "time": "2016-02-16 01:18:50", + "type": "heroku-sys-php-extension", + "version": "5.1.3" + } + +Package `name`s must be prefixed with "`heroku-sys/`". Possible `type`s are `heroku-sys-php`, `heroku-sys-hhvm`, `heroku-sys-php-extension` or `heroku-sys-webserver`. The `dist` type must be "`heroku-sys-tar`". If the package is a `heroku-sys-php-extension`, it's important to specify a `conflict` with "`heroku-sys/hhvm`". + +The special package type `heroku-sys-php-package` is used for generic packages that should not be available to applications during app deploys (such as vendored libraries used to build PHP or an extension). + +The `require`d package `heroku/installer-plugin` will be available during install. Package `heroku-sys/cedar` is a virtual package `provide`d by the platform `composer.json` generated in `bin/compile` and has the right stack version; the selector for `heroku-sys/php` ensures that the package only applies to PHP 7.0.x. + +### Manifest Helpers + +All formulae use the `manifest.py` helper to generate the information above. **Use it for maximum reliability!** You can take a look at the existing formulae and the script to get a feeling for how it works. + +## About Repositories + +The repository is a `packages.json` of all manifests, which can be used by Composer as a `packagist` repository type. See [Usage in Applications](#usage-in-applications) for instructions on how to use such a repository with an application. + +**Important: due to a limitation of Composer, extensions of identical version but for different PHP versions must be ordered within the repository in descending PHP version order, i.e. `ext-mongodb:1.1.2` for `php:7.0.*` must appear before `ext-mongodb:1.1.2` for `php:5.6.*`. Otherwise, deploys may select a lower PHP version than possible. The `mkrepo.sh` script takes care of this ordering.** + +### (Re-)generating Repositories + +The normal flow is to run `support/build/_util/deploy.sh` first to deploy one or more packages, and then to use `support/build/_util/mkrepo.sh` to re-generate the repo: + + $ support/build/_util/mkrepo.sh --upload + +This will generate `packages.json` and upload it right away, or, if the `--upload` is not given, print upload instructions for `s3cmd`. + +Alternatively, `deploy.sh` can be called with `--publish` as the first argument, in which case `mkrepo.sh --upload` will be called after the package deploy and manifest upload was successful: + + $ support/build/_util/deploy.sh --publish php-6.0.0 + +**This should be used with caution, as several parallel `deploy.sh` invocations could result in a race condition when re-generating the repository.** + +### Syncing Repositories + +It is often desirable to have a bucket with two repositories under different prefixes, e.g. `dist-cedar-14-develop/` and `dist-cedar-14-stable/`, with the latter usually used by apps for deploys. The "develop" bucket prefix would be set via `S3_PREFIX` on the Heroku package builder app or Docker container, so all builds would always end up there. + +After testing builds, the contents of that "develop" repository can then be synced to "stable" using `support/build/_util/mkrepo.sh`: + + $ support/build/_util/sync.sh my-bucket dist-cedar-14-stable/ my-bucket dist-cedar-14-develop/ + +*The `sync.sh` script takes destination bucket info as arguments first, then source bucket info*. + +The `sync.sh` script automatically detects additions, updates and removals based on manifests. It will also warn if the source `packages.json` is not up to date with its manifests, and prompt for confirmation before syncing. + +#### Syncing from Upstream + +You will usually use an [Upstream Bucket](#understanding-upstream-buckets) to ensure that Bob will pull dependencies from Heroku's official bucket without having to worry about maintaining packages up the dependency tree, such as library or PHP prerequsites for an extension. + +However, in rare circumstances, such as when you want to fully host all platform packages including PHP yourself and have the official repository disabled for your app, you either need to build all packages from scratch, or sync the Heroku builds from the official repository: + + $ heroku run "support/build/_util/sync.sh $S3_BUCKET $S3_PREFIX $UPSTREAM_S3_BUCKET $UPSTREAM_S3_PREFIX" + +### Removing Packages + +The `support/build/_util/remove.sh` helper removes a package manifest and its tarball from a bucket, and re-generates the repository. It accepts one or more names of a JSON manifest file from the bucket (optionally without "`.composer.json`" suffix) as arguments: + + $ support/build/_util/remove.sh ext-imagick-3.3.0_php-5.5.composer.json ext-imagick-3.3.0_php-5.6.composer.json + +Unless the `--no-publish` option is given, the repository will be re-generated immediately after removal. Otherwise, the manifests and tarballs would be removed, but the main repository would remain in place, pointing to non-existing packages, so usage of this flag is only recommended for debugging purposes or similar. + +## Usage in Applications + +Please refer to [the instructions in the main README](../../README.md#custom-platform-repositories) for details on how to use a custom repository during application builds. + +## Tips & Tricks + +- To speed things up drastically during compilation, it'll usually be a good idea to `heroku run bash --size Performance-L`. +- All manifests generated by Bob formulas, by `support/build/_util/mkrepo.sh` and by `support/build/_util/sync.sh` use an S3 region of "s3" by default, so resulting URLs look like "`https://your-bucket.s3.amazonaws.com/your-prefix/...`". You can `heroku config:set S3_REGION` to change "s3" to another region such as "s3-eu-west-1". +- If any dependencies are not yet deployed, you need to deploy them first, or use `UPSTREAM_S3_BUCKET` and `UPSTREAM_S3_PREFIX` (recommended). diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_conf/apache2/httpd.conf b/vendor/heroku/heroku-buildpack-php/support/build/_conf/apache2/httpd.conf new file mode 100644 index 0000000..64819de --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_conf/apache2/httpd.conf @@ -0,0 +1,527 @@ +# +# This is the main Apache HTTP server configuration file. It contains the +# configuration directives that give the server its instructions. +# See for detailed information. +# In particular, see +# +# for a discussion of each configuration directive. +# +# Do NOT simply read the instructions in here without understanding +# what they do. They're here only as hints or reminders. If you are unsure +# consult the online docs. You have been warned. +# +# Configuration and logfile names: If the filenames you specify for many +# of the server's control files begin with "/" (or "drive:/" for Win32), the +# server will use that explicit path. If the filenames do *not* begin +# with "/", the value of ServerRoot is prepended -- so "logs/access_log" +# with ServerRoot set to "/usr/local/apache2" will be interpreted by the +# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log" +# will be interpreted as '/logs/access_log'. + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# Do not add a slash at the end of the directory path. If you point +# ServerRoot at a non-local disk, be sure to specify a local disk on the +# Mutex directive, if file-based mutexes are used. If you wish to share the +# same ServerRoot for multiple httpd daemons, you will need to change at +# least PidFile. +# +ServerRoot "/app/.heroku/php/" + +# +# Mutex: Allows you to set the mutex mechanism and mutex file directory +# for individual mutexes, or change the global defaults +# +# Uncomment and change the directory if mutexes are file-based and the default +# mutex file directory is not on a local disk or is not appropriate for some +# other reason. +# +# Mutex default:var/apache2/run + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, instead of the default. See also the +# directive. +# +# Change this to Listen on specific IP addresses as shown below to +# prevent Apache from glomming onto all bound IP addresses. +# +#Listen 12.34.56.78:80 +#Listen ${PORT} + +# +# Dynamic Shared Object (DSO) Support +# +# To be able to use the functionality of a module which was built as a DSO you +# have to place corresponding `LoadModule' lines at this location so the +# directives contained in it are actually available _before_ they are used. +# Statically compiled modules (those listed by `httpd -l') do not need +# to be loaded here. +# +# Example: +# LoadModule foo_module modules/mod_foo.so +# +LoadModule authn_file_module libexec/mod_authn_file.so +#LoadModule authn_dbm_module libexec/mod_authn_dbm.so +#LoadModule authn_anon_module libexec/mod_authn_anon.so +#LoadModule authn_dbd_module libexec/mod_authn_dbd.so +#LoadModule authn_socache_module libexec/mod_authn_socache.so +LoadModule authn_core_module libexec/mod_authn_core.so +LoadModule authz_host_module libexec/mod_authz_host.so +LoadModule authz_groupfile_module libexec/mod_authz_groupfile.so +LoadModule authz_user_module libexec/mod_authz_user.so +#LoadModule authz_dbm_module libexec/mod_authz_dbm.so +#LoadModule authz_owner_module libexec/mod_authz_owner.so +#LoadModule authz_dbd_module libexec/mod_authz_dbd.so +LoadModule authz_core_module libexec/mod_authz_core.so +LoadModule access_compat_module libexec/mod_access_compat.so +LoadModule auth_basic_module libexec/mod_auth_basic.so +#LoadModule auth_form_module libexec/mod_auth_form.so +#LoadModule auth_digest_module libexec/mod_auth_digest.so +#LoadModule allowmethods_module libexec/mod_allowmethods.so +#LoadModule file_cache_module libexec/mod_file_cache.so +#LoadModule cache_module libexec/mod_cache.so +#LoadModule cache_disk_module libexec/mod_cache_disk.so +#LoadModule cache_socache_module libexec/mod_cache_socache.so +#LoadModule socache_shmcb_module libexec/mod_socache_shmcb.so +#LoadModule socache_dbm_module libexec/mod_socache_dbm.so +#LoadModule socache_memcache_module libexec/mod_socache_memcache.so +#LoadModule watchdog_module libexec/mod_watchdog.so +#LoadModule macro_module libexec/mod_macro.so +#LoadModule dbd_module libexec/mod_dbd.so +#LoadModule dumpio_module libexec/mod_dumpio.so +#LoadModule echo_module libexec/mod_echo.so +#LoadModule buffer_module libexec/mod_buffer.so +#LoadModule data_module libexec/mod_data.so +#LoadModule ratelimit_module libexec/mod_ratelimit.so +LoadModule reqtimeout_module libexec/mod_reqtimeout.so +#LoadModule ext_filter_module libexec/mod_ext_filter.so +#LoadModule request_module libexec/mod_request.so +#LoadModule include_module libexec/mod_include.so +LoadModule filter_module libexec/mod_filter.so +#LoadModule reflector_module libexec/mod_reflector.so +#LoadModule substitute_module libexec/mod_substitute.so +#LoadModule sed_module libexec/mod_sed.so +#LoadModule charset_lite_module libexec/mod_charset_lite.so +LoadModule deflate_module libexec/mod_deflate.so +LoadModule xml2enc_module libexec/mod_xml2enc.so +LoadModule proxy_html_module libexec/mod_proxy_html.so +LoadModule mime_module libexec/mod_mime.so +LoadModule log_config_module libexec/mod_log_config.so +#LoadModule log_debug_module libexec/mod_log_debug.so +#LoadModule log_forensic_module libexec/mod_log_forensic.so +#LoadModule logio_module libexec/mod_logio.so +LoadModule env_module libexec/mod_env.so +#LoadModule mime_magic_module libexec/mod_mime_magic.so +LoadModule expires_module libexec/mod_expires.so +LoadModule headers_module libexec/mod_headers.so +#LoadModule usertrack_module libexec/mod_usertrack.so +#LoadModule unique_id_module libexec/mod_unique_id.so +LoadModule setenvif_module libexec/mod_setenvif.so +LoadModule version_module libexec/mod_version.so +LoadModule remoteip_module libexec/mod_remoteip.so +LoadModule proxy_module libexec/mod_proxy.so +#LoadModule proxy_connect_module libexec/mod_proxy_connect.so +#LoadModule proxy_ftp_module libexec/mod_proxy_ftp.so +LoadModule proxy_http_module libexec/mod_proxy_http.so +LoadModule proxy_fcgi_module libexec/mod_proxy_fcgi.so +#LoadModule proxy_scgi_module libexec/mod_proxy_scgi.so +#LoadModule proxy_fdpass_module libexec/mod_proxy_fdpass.so +LoadModule proxy_wstunnel_module libexec/mod_proxy_wstunnel.so +#LoadModule proxy_ajp_module libexec/mod_proxy_ajp.so +#LoadModule proxy_balancer_module libexec/mod_proxy_balancer.so +#LoadModule proxy_express_module libexec/mod_proxy_express.so +#LoadModule session_module libexec/mod_session.so +#LoadModule session_cookie_module libexec/mod_session_cookie.so +#LoadModule session_dbd_module libexec/mod_session_dbd.so +#LoadModule slotmem_shm_module libexec/mod_slotmem_shm.so +#LoadModule slotmem_plain_module libexec/mod_slotmem_plain.so +LoadModule ssl_module libexec/mod_ssl.so +#LoadModule dialup_module libexec/mod_dialup.so +LoadModule lbmethod_byrequests_module libexec/mod_lbmethod_byrequests.so +LoadModule lbmethod_bytraffic_module libexec/mod_lbmethod_bytraffic.so +LoadModule lbmethod_bybusyness_module libexec/mod_lbmethod_bybusyness.so +LoadModule lbmethod_heartbeat_module libexec/mod_lbmethod_heartbeat.so +LoadModule unixd_module libexec/mod_unixd.so +#LoadModule heartbeat_module libexec/mod_heartbeat.so +#LoadModule heartmonitor_module libexec/mod_heartmonitor.so +#LoadModule dav_module libexec/mod_dav.so +LoadModule status_module libexec/mod_status.so +LoadModule autoindex_module libexec/mod_autoindex.so +#LoadModule asis_module libexec/mod_asis.so +#LoadModule info_module libexec/mod_info.so +#LoadModule cgid_module libexec/mod_cgid.so +#LoadModule dav_fs_module libexec/mod_dav_fs.so +#LoadModule dav_lock_module libexec/mod_dav_lock.so +#LoadModule vhost_alias_module libexec/mod_vhost_alias.so +#LoadModule negotiation_module libexec/mod_negotiation.so +LoadModule dir_module libexec/mod_dir.so +#LoadModule actions_module libexec/mod_actions.so +#LoadModule speling_module libexec/mod_speling.so +#LoadModule userdir_module libexec/mod_userdir.so +LoadModule alias_module libexec/mod_alias.so +LoadModule rewrite_module libexec/mod_rewrite.so + + + # special treatment for Apache < 2.4.10 so we can SetHandler to mod_proxy_fcgi + # taken from https://gist.github.com/progandy/6ed4eeea60f6277c3e39 + # the functionality is included in Apache 2.4.10+ + LoadModule proxy_handler_module libexec/mod_proxy_handler.so + + + +# +# If you wish httpd to run as a different user or group, you must run +# httpd as root initially and it will switch. +# +# User/Group: The name (or #number) of the user/group to run httpd as. +# It is usually good practice to create a dedicated user and group for +# running httpd, as with most system services. +# +User daemon +Group daemon + + + +# 'Main' server configuration +# +# The directives in this section set up the values used by the 'main' +# server, which responds to any requests that aren't handled by a +# definition. These values also provide defaults for +# any containers you may define later in the file. +# +# All of these directives may appear inside containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# + +# +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. This address appears on some server-generated pages, such +# as error documents. e.g. admin@your-domain.com +# +ServerAdmin you@example.com + +# +# ServerName gives the name and port that the server uses to identify itself. +# This can often be determined automatically, but we recommend you specify +# it explicitly to prevent problems during startup. +# +# If your host doesn't have a registered DNS name, enter its IP address here. +# +ServerName localhost + +# +# Deny access to the entirety of your server's filesystem. You must +# explicitly permit access to web content directories in other +# blocks below. +# + + AllowOverride none + Require all denied + + +# +# Note that from this point forward you must specifically allow +# particular features to be enabled - so if something's not working as +# you might expect, make sure that you have specifically enabled it +# below. +# + +# +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. +# +DocumentRoot "/app/.heroku/php//share/apache2/htdocs" + + # + # Possible values for the Options directive are "None", "All", + # or any combination of: + # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews + # + # Note that "MultiViews" must be named *explicitly* --- "Options All" + # doesn't give it to you. + # + # The Options directive is both complicated and important. Please see + # http://httpd.apache.org/docs/2.4/mod/core.html#options + # for more information. + # + Options Indexes FollowSymLinks + + # + # AllowOverride controls what directives may be placed in .htaccess files. + # It can be "All", "None", or any combination of the keywords: + # AllowOverride FileInfo AuthConfig Limit + # + AllowOverride None + + # + # Controls who can get stuff from this server. + # + Require all denied + + +# +# DirectoryIndex: sets the file that Apache will serve if a directory +# is requested. +# + + DirectoryIndex index.html + + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# + + Require all denied + + +# +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog "var/apache2/log/error_log" + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + + + # + # The following directives define some format nicknames for use with + # a CustomLog directive (see below). + # + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + + + # You need to enable mod_logio.c to use %I and %O + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + + # + # The location and format of the access logfile (Common Logfile Format). + # If you do not define any access logfiles within a + # container, they will be logged here. Contrariwise, if you *do* + # define per- access logfiles, transactions will be + # logged therein and *not* in this file. + # + CustomLog "var/apache2/log/access_log" common + + # + # If you prefer a logfile with access, agent, and referer information + # (Combined Logfile Format) you can use the following directive. + # + #CustomLog "var/apache2/log/access_log" combined + + + + # + # Redirect: Allows you to tell clients about documents that used to + # exist in your server's namespace, but do not anymore. The client + # will make a new request for the document at its new location. + # Example: + # Redirect permanent /foo http://www.example.com/bar + + # + # Alias: Maps web paths into filesystem paths and is used to + # access content that does not live under the DocumentRoot. + # Example: + # Alias /webpath /full/filesystem/path + # + # If you include a trailing / on /webpath then the server will + # require it to be present in the URL. You will also likely + # need to provide a section to allow access to + # the filesystem path. + + # + # ScriptAlias: This controls which directories contain server scripts. + # ScriptAliases are essentially the same as Aliases, except that + # documents in the target directory are treated as applications and + # run by the server when requested rather than as documents sent to the + # client. The same rules about trailing "/" apply to ScriptAlias + # directives as to Alias. + # + # ScriptAlias /cgi-bin/ "/app/.heroku/php//share/apache2/cgi-bin/" + + + + + # + # ScriptSock: On threaded servers, designate the path to the UNIX + # socket used to communicate with the CGI daemon of mod_cgid. + # + #Scriptsock cgisock + + +# +# "/app/.heroku/php//share/apache2/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# +# +# AllowOverride None +# Options None +# Require all granted +# + + + # + # TypesConfig points to the file containing the list of mappings from + # filename extension to MIME-type. + # + TypesConfig etc/apache2/mime.types + + # + # AddType allows you to add to or override the MIME configuration + # file specified in TypesConfig for specific file types. + # + #AddType application/x-gzip .tgz + # + # AddEncoding allows you to have certain browsers uncompress + # information on the fly. Note: Not all browsers support this. + # + #AddEncoding x-compress .Z + #AddEncoding x-gzip .gz .tgz + # + # If the AddEncoding directives above are commented-out, then you + # probably should define those extensions to indicate media types: + # + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + + # + # AddHandler allows you to map certain file extensions to "handlers": + # actions unrelated to filetype. These can be either built into the server + # or added with the Action directive (see below) + # + # To use CGI scripts outside of ScriptAliased directories: + # (You will also need to add "ExecCGI" to the "Options" directive.) + # + #AddHandler cgi-script .cgi + + # For type maps (negotiated resources): + #AddHandler type-map var + + # + # Filters allow you to process content before it is sent to the client. + # + # To parse .shtml files for server-side includes (SSI): + # (You will also need to add "Includes" to the "Options" directive.) + # + #AddType text/html .shtml + #AddOutputFilter INCLUDES .shtml + + +# +# The mod_mime_magic module allows the server to use various hints from the +# contents of the file itself to determine its type. The MIMEMagicFile +# directive tells the module where the hint definitions are located. +# +#MIMEMagicFile etc/apache2/magic + +# +# Customizable error responses come in three flavors: +# 1) plain text 2) local redirects 3) external redirects +# +# Some examples: +#ErrorDocument 500 "The server made a boo boo." +#ErrorDocument 404 /missing.html +#ErrorDocument 404 "/cgi-bin/missing_handler.pl" +#ErrorDocument 402 http://www.example.com/subscription_info.html +# + +# +# MaxRanges: Maximum number of Ranges in a request before +# returning the entire resource, or one of the special +# values 'default', 'none' or 'unlimited'. +# Default setting is to accept 200 Ranges. +#MaxRanges unlimited + +# +# EnableMMAP and EnableSendfile: On systems that support it, +# memory-mapping or the sendfile syscall may be used to deliver +# files. This usually improves server performance, but must +# be turned off when serving from networked-mounted +# filesystems or if support for these functions is otherwise +# broken on your system. +# Defaults: EnableMMAP On, EnableSendfile Off +# +#EnableMMAP off +#EnableSendfile on + +# Supplemental configuration +# +# The configuration files in the etc/apache2/extra/ directory can be +# included to add extra features or to modify the default configuration of +# the server, or you may simply copy their contents here and change as +# necessary. + +# Server-pool management (MPM specific) +#Include etc/apache2/extra/httpd-mpm.conf + +# Multi-language error messages +#Include etc/apache2/extra/httpd-multilang-errordoc.conf + +# Fancy directory listings +#Include etc/apache2/extra/httpd-autoindex.conf + +# Language settings +#Include etc/apache2/extra/httpd-languages.conf + +# User home directories +#Include etc/apache2/extra/httpd-userdir.conf + +# Real-time info on requests and configuration +#Include etc/apache2/extra/httpd-info.conf + +# Virtual hosts +#Include etc/apache2/extra/httpd-vhosts.conf + +# Local access to the Apache HTTP Server Manual +#Include etc/apache2/extra/httpd-manual.conf + +# Distributed authoring and versioning (WebDAV) +#Include etc/apache2/extra/httpd-dav.conf + +# Various default settings +#Include etc/apache2/extra/httpd-default.conf + +# Configure mod_proxy_html to understand HTML4/XHTML1 + +Include etc/apache2/extra/proxy-html.conf + + +# Secure (SSL/TLS) connections +#Include etc/apache2/extra/httpd-ssl.conf +# +# Note: The following must must be present to support +# starting without SSL on platforms with no /dev/random equivalent +# but a statically compiled-in mod_ssl. +# + +SSLRandomSeed startup builtin +SSLRandomSeed connect builtin + +# +# uncomment out the below to deal with user agents that deliberately +# violate open standards by misusing DNT (DNT *must* be a specific +# end-user choice) +# +# +#BrowserMatch "MSIE 10.0;" bad_DNT +# +# +#RequestHeader unset DNT env=bad_DNT +# + +ServerTokens Prod diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_conf/nginx/nginx.conf b/vendor/heroku/heroku-buildpack-php/support/build/_conf/nginx/nginx.conf new file mode 100644 index 0000000..49589ef --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_conf/nginx/nginx.conf @@ -0,0 +1,36 @@ + +#user nobody; +worker_processes auto; + +error_log stderr; +#error_log logs/error.log notice; +#error_log logs/error.log info; + +#pid logs/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include mime.types; + default_type application/octet-stream; + + #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + # '$status $body_bytes_sent "$http_referer" ' + # '"$http_user_agent" "$http_x_forwarded_for"'; + + #access_log logs/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + + server_tokens off; +} diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_conf/php/conf.d/010-ext-zend_opcache.ini b/vendor/heroku/heroku-buildpack-php/support/build/_conf/php/conf.d/010-ext-zend_opcache.ini new file mode 100644 index 0000000..bf8db54 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_conf/php/conf.d/010-ext-zend_opcache.ini @@ -0,0 +1,7 @@ +zend_extension=opcache.so +opcache.enable_cli=1 +opcache.validate_timestamps=0 +opcache.fast_shutdown=0 +opcache.memory_consumption=128 +opcache.interned_strings_buffer=8 +opcache.max_accelerated_files=4000 diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_conf/php/php.ini b/vendor/heroku/heroku-buildpack-php/support/build/_conf/php/php.ini new file mode 100644 index 0000000..e0a2591 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_conf/php/php.ini @@ -0,0 +1,1900 @@ +[PHP] + +;;;;;;;;;;;;;;;;;;; +; About php.ini ; +;;;;;;;;;;;;;;;;;;; +; PHP's initialization file, generally called php.ini, is responsible for +; configuring many of the aspects of PHP's behavior. + +; PHP attempts to find and load this configuration from a number of locations. +; The following is a summary of its search order: +; 1. SAPI module specific location. +; 2. The PHPRC environment variable. (As of PHP 5.2.0) +; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) +; 4. Current working directory (except CLI) +; 5. The web server's directory (for SAPI modules), or directory of PHP +; (otherwise in Windows) +; 6. The directory from the --with-config-file-path compile time option, or the +; Windows directory (C:\windows or C:\winnt) +; See the PHP docs for more specific information. +; http://php.net/configuration.file + +; The syntax of the file is extremely simple. Whitespace and Lines +; beginning with a semicolon are silently ignored (as you probably guessed). +; Section headers (e.g. [Foo]) are also silently ignored, even though +; they might mean something in the future. + +; Directives following the section heading [PATH=/www/mysite] only +; apply to PHP files in the /www/mysite directory. Directives +; following the section heading [HOST=www.example.com] only apply to +; PHP files served from www.example.com. Directives set in these +; special sections cannot be overridden by user-defined INI files or +; at runtime. Currently, [PATH=] and [HOST=] sections only work under +; CGI/FastCGI. +; http://php.net/ini.sections + +; Directives are specified using the following syntax: +; directive = value +; Directive names are *case sensitive* - foo=bar is different from FOO=bar. +; Directives are variables used to configure PHP or PHP extensions. +; There is no name validation. If PHP can't find an expected +; directive because it is not set or is mistyped, a default value will be used. + +; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one +; of the INI constants (On, Off, True, False, Yes, No and None) or an expression +; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a +; previously set variable or directive (e.g. ${foo}) + +; Expressions in the INI file are limited to bitwise operators and parentheses: +; | bitwise OR +; ^ bitwise XOR +; & bitwise AND +; ~ bitwise NOT +; ! boolean NOT + +; Boolean flags can be turned on using the values 1, On, True or Yes. +; They can be turned off using the values 0, Off, False or No. + +; An empty string can be denoted by simply not writing anything after the equal +; sign, or by using the None keyword: + +; foo = ; sets foo to an empty string +; foo = None ; sets foo to an empty string +; foo = "None" ; sets foo to the string 'None' + +; If you use constants in your value, and these constants belong to a +; dynamically loaded extension (either a PHP extension or a Zend extension), +; you may only use these constants *after* the line that loads the extension. + +;;;;;;;;;;;;;;;;;;; +; About this file ; +;;;;;;;;;;;;;;;;;;; +; PHP comes packaged with two INI files. One that is recommended to be used +; in production environments and one that is recommended to be used in +; development environments. + +; php.ini-production contains settings which hold security, performance and +; best practices at its core. But please be aware, these settings may break +; compatibility with older or less security conscience applications. We +; recommending using the production ini in production and testing environments. + +; php.ini-development is very similar to its production variant, except it's +; much more verbose when it comes to errors. We recommending using the +; development version only in development environments as errors shown to +; application users can inadvertently leak otherwise secure information. + +;;;;;;;;;;;;;;;;;;; +; Quick Reference ; +;;;;;;;;;;;;;;;;;;; +; The following are all the settings which are different in either the production +; or development versions of the INIs with respect to PHP's default behavior. +; Please see the actual settings later in the document for more details as to why +; we recommend these changes in PHP's behavior. + +; allow_call_time_pass_reference +; Default Value: On +; Development Value: Off +; Production Value: Off + +; display_errors +; Default Value: On +; Development Value: On +; Production Value: Off + +; display_startup_errors +; Default Value: Off +; Development Value: On +; Production Value: Off + +; error_reporting +; Default Value: E_ALL & ~E_NOTICE +; Development Value: E_ALL | E_STRICT +; Production Value: E_ALL & ~E_DEPRECATED + +; html_errors +; Default Value: On +; Development Value: On +; Production value: Off + +; log_errors +; Default Value: Off +; Development Value: On +; Production Value: On + +; magic_quotes_gpc +; Default Value: On +; Development Value: Off +; Production Value: Off + +; max_input_time +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) + +; output_buffering +; Default Value: Off +; Development Value: 4096 +; Production Value: 4096 + +; register_argc_argv +; Default Value: On +; Development Value: Off +; Production Value: Off + +; register_long_arrays +; Default Value: On +; Development Value: Off +; Production Value: Off + +; request_order +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" + +; session.bug_compat_42 +; Default Value: On +; Development Value: On +; Production Value: Off + +; session.bug_compat_warn +; Default Value: On +; Development Value: On +; Production Value: Off + +; session.gc_divisor +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 + +; session.hash_bits_per_character +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 + +; short_open_tag +; Default Value: On +; Development Value: Off +; Production Value: Off + +; track_errors +; Default Value: Off +; Development Value: On +; Production Value: Off + +; url_rewriter.tags +; Default Value: "a=href,area=href,frame=src,form=,fieldset=" +; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" + +; variables_order +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS" + +;;;;;;;;;;;;;;;;;;;; +; php.ini Options ; +;;;;;;;;;;;;;;;;;;;; +; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini" +;user_ini.filename = ".user.ini" + +; To disable this feature set this option to empty value +;user_ini.filename = + +; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) +user_ini.cache_ttl = 86400 + +;;;;;;;;;;;;;;;;;;;; +; Language Options ; +;;;;;;;;;;;;;;;;;;;; + +; Enable the PHP scripting language engine under Apache. +; http://php.net/engine +engine = On + +; This directive determines whether or not PHP will recognize code between +; tags as PHP source which should be processed as such. It's been +; recommended for several years that you not use the short tag "short cut" and +; instead to use the full tag combination. With the wide spread use +; of XML and use of these tags by other languages, the server can become easily +; confused and end up parsing the wrong code in the wrong context. But because +; this short cut has been a feature for such a long time, it's currently still +; supported for backwards compatibility, but we recommend you don't use them. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/short-open-tag +short_open_tag = On + +; Allow ASP-style <% %> tags. +; http://php.net/asp-tags +asp_tags = Off + +; The number of significant digits displayed in floating point numbers. +; http://php.net/precision +precision = 14 + +; Enforce year 2000 compliance (will cause problems with non-compliant browsers) +; http://php.net/y2k-compliance +y2k_compliance = On + +; Output buffering is a mechanism for controlling how much output data +; (excluding headers and cookies) PHP should keep internally before pushing that +; data to the client. If your application's output exceeds this setting, PHP +; will send that data in chunks of roughly the size you specify. +; Turning on this setting and managing its maximum buffer size can yield some +; interesting side-effects depending on your application and web server. +; You may be able to send headers and cookies after you've already sent output +; through print or echo. You also may see performance benefits if your server is +; emitting less packets due to buffered output versus PHP streaming the output +; as it gets it. On production servers, 4096 bytes is a good setting for performance +; reasons. +; Note: Output buffering can also be controlled via Output Buffering Control +; functions. +; Possible Values: +; On = Enabled and buffer is unlimited. (Use with caution) +; Off = Disabled +; Integer = Enables the buffer and sets its maximum size in bytes. +; Note: This directive is hardcoded to Off for the CLI SAPI +; Default Value: Off +; Development Value: 4096 +; Production Value: 4096 +; http://php.net/output-buffering +output_buffering = 4096 + +; You can redirect all of the output of your scripts to a function. For +; example, if you set output_handler to "mb_output_handler", character +; encoding will be transparently converted to the specified encoding. +; Setting any output handler automatically turns on output buffering. +; Note: People who wrote portable scripts should not depend on this ini +; directive. Instead, explicitly set the output handler using ob_start(). +; Using this ini directive may cause problems unless you know what script +; is doing. +; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler" +; and you cannot use both "ob_gzhandler" and "zlib.output_compression". +; Note: output_handler must be empty if this is set 'On' !!!! +; Instead you must use zlib.output_handler. +; http://php.net/output-handler +;output_handler = + +; Transparent output compression using the zlib library +; Valid values for this option are 'off', 'on', or a specific buffer size +; to be used for compression (default is 4KB) +; Note: Resulting chunk size may vary due to nature of compression. PHP +; outputs chunks that are few hundreds bytes each as a result of +; compression. If you prefer a larger chunk size for better +; performance, enable output_buffering in addition. +; Note: You need to use zlib.output_handler instead of the standard +; output_handler, or otherwise the output will be corrupted. +; http://php.net/zlib.output-compression +zlib.output_compression = Off + +; http://php.net/zlib.output-compression-level +;zlib.output_compression_level = -1 + +; You cannot specify additional output handlers if zlib.output_compression +; is activated here. This setting does the same as output_handler but in +; a different order. +; http://php.net/zlib.output-handler +;zlib.output_handler = + +; Implicit flush tells PHP to tell the output layer to flush itself +; automatically after every output block. This is equivalent to calling the +; PHP function flush() after each and every call to print() or echo() and each +; and every HTML block. Turning this option on has serious performance +; implications and is generally recommended for debugging purposes only. +; http://php.net/implicit-flush +; Note: This directive is hardcoded to On for the CLI SAPI +implicit_flush = Off + +; The unserialize callback function will be called (with the undefined class' +; name as parameter), if the unserializer finds an undefined class +; which should be instantiated. A warning appears if the specified function is +; not defined, or if the function doesn't include/implement the missing class. +; So only set this entry, if you really want to implement such a +; callback-function. +unserialize_callback_func = + +; When floats & doubles are serialized store serialize_precision significant +; digits after the floating point. The default value ensures that when floats +; are decoded with unserialize, the data will remain the same. +serialize_precision = 17 + +; This directive allows you to enable and disable warnings which PHP will issue +; if you pass a value by reference at function call time. Passing values by +; reference at function call time is a deprecated feature which will be removed +; from PHP at some point in the near future. The acceptable method for passing a +; value by reference to a function is by declaring the reference in the functions +; definition, not at call time. This directive does not disable this feature, it +; only determines whether PHP will warn you about it or not. These warnings +; should enabled in development environments only. +; Default Value: On (Suppress warnings) +; Development Value: Off (Issue warnings) +; Production Value: Off (Issue warnings) +; http://php.net/allow-call-time-pass-reference +allow_call_time_pass_reference = Off + +; Safe Mode +; http://php.net/safe-mode +safe_mode = Off + +; By default, Safe Mode does a UID compare check when +; opening files. If you want to relax this to a GID compare, +; then turn on safe_mode_gid. +; http://php.net/safe-mode-gid +safe_mode_gid = Off + +; When safe_mode is on, UID/GID checks are bypassed when +; including files from this directory and its subdirectories. +; (directory must also be in include_path or full path must +; be used when including) +; http://php.net/safe-mode-include-dir +safe_mode_include_dir = + +; When safe_mode is on, only executables located in the safe_mode_exec_dir +; will be allowed to be executed via the exec family of functions. +; http://php.net/safe-mode-exec-dir +safe_mode_exec_dir = + +; Setting certain environment variables may be a potential security breach. +; This directive contains a comma-delimited list of prefixes. In Safe Mode, +; the user may only alter environment variables whose names begin with the +; prefixes supplied here. By default, users will only be able to set +; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR). +; Note: If this directive is empty, PHP will let the user modify ANY +; environment variable! +; http://php.net/safe-mode-allowed-env-vars +safe_mode_allowed_env_vars = PHP_ + +; This directive contains a comma-delimited list of environment variables that +; the end user won't be able to change using putenv(). These variables will be +; protected even if safe_mode_allowed_env_vars is set to allow to change them. +; http://php.net/safe-mode-protected-env-vars +safe_mode_protected_env_vars = LD_LIBRARY_PATH + +; open_basedir, if set, limits all file operations to the defined directory +; and below. This directive makes most sense if used in a per-directory +; or per-virtualhost web server configuration file. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/open-basedir +;open_basedir = + +; This directive allows you to disable certain functions for security reasons. +; It receives a comma-delimited list of function names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/disable-functions +disable_functions = + +; This directive allows you to disable certain classes for security reasons. +; It receives a comma-delimited list of class names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/disable-classes +disable_classes = + +; Colors for Syntax Highlighting mode. Anything that's acceptable in +; would work. +; http://php.net/syntax-highlighting +;highlight.string = #DD0000 +;highlight.comment = #FF9900 +;highlight.keyword = #007700 +;highlight.bg = #FFFFFF +;highlight.default = #0000BB +;highlight.html = #000000 + +; If enabled, the request will be allowed to complete even if the user aborts +; the request. Consider enabling it if executing long requests, which may end up +; being interrupted by the user or a browser timing out. PHP's default behavior +; is to disable this feature. +; http://php.net/ignore-user-abort +;ignore_user_abort = On + +; Determines the size of the realpath cache to be used by PHP. This value should +; be increased on systems where PHP opens many files to reflect the quantity of +; the file operations performed. +; http://php.net/realpath-cache-size +;realpath_cache_size = 16k + +; Duration of time, in seconds for which to cache realpath information for a given +; file or directory. For systems with rarely changing files, consider increasing this +; value. +; http://php.net/realpath-cache-ttl +;realpath_cache_ttl = 120 + +;;;;;;;;;;;;;;;;; +; Miscellaneous ; +;;;;;;;;;;;;;;;;; + +; Decides whether PHP may expose the fact that it is installed on the server +; (e.g. by adding its signature to the Web server header). It is no security +; threat in any way, but it makes it possible to determine whether you use PHP +; on your server or not. +; http://php.net/expose-php +expose_php = Off + +;;;;;;;;;;;;;;;;;;; +; Resource Limits ; +;;;;;;;;;;;;;;;;;;; + +; Maximum execution time of each script, in seconds +; http://php.net/max-execution-time +; Note: This directive is hardcoded to 0 for the CLI SAPI +max_execution_time = 30 + +; Maximum amount of time each script may spend parsing request data. It's a good +; idea to limit this time on productions servers in order to eliminate unexpectedly +; long running scripts. +; Note: This directive is hardcoded to -1 for the CLI SAPI +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) +; http://php.net/max-input-time +max_input_time = 60 + +; Maximum input variable nesting level +; http://php.net/max-input-nesting-level +;max_input_nesting_level = 64 + +; Maximum amount of memory a script may consume (128MB) +; http://php.net/memory-limit +memory_limit = 128M + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Error handling and logging ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; This directive informs PHP of which errors, warnings and notices you would like +; it to take action for. The recommended way of setting values for this +; directive is through the use of the error level constants and bitwise +; operators. The error level constants are below here for convenience as well as +; some common settings and their meanings. +; By default, PHP is set to take action on all errors, notices and warnings EXCEPT +; those related to E_NOTICE and E_STRICT, which together cover best practices and +; recommended coding standards in PHP. For performance reasons, this is the +; recommend error reporting setting. Your production server shouldn't be wasting +; resources complaining about best practices and coding standards. That's what +; development servers and development settings are for. +; Note: The php.ini-development file has this setting as E_ALL | E_STRICT. This +; means it pretty much reports everything which is exactly what you want during +; development and early testing. +; +; Error Level Constants: +; E_ALL - All errors and warnings (includes E_STRICT as of PHP 6.0.0) +; E_ERROR - fatal run-time errors +; E_RECOVERABLE_ERROR - almost fatal run-time errors +; E_WARNING - run-time warnings (non-fatal errors) +; E_PARSE - compile-time parse errors +; E_NOTICE - run-time notices (these are warnings which often result +; from a bug in your code, but it's possible that it was +; intentional (e.g., using an uninitialized variable and +; relying on the fact it's automatically initialized to an +; empty string) +; E_STRICT - run-time notices, enable to have PHP suggest changes +; to your code which will ensure the best interoperability +; and forward compatibility of your code +; E_CORE_ERROR - fatal errors that occur during PHP's initial startup +; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's +; initial startup +; E_COMPILE_ERROR - fatal compile-time errors +; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) +; E_USER_ERROR - user-generated error message +; E_USER_WARNING - user-generated warning message +; E_USER_NOTICE - user-generated notice message +; E_DEPRECATED - warn about code that will not work in future versions +; of PHP +; E_USER_DEPRECATED - user-generated deprecation warnings +; +; Common Values: +; E_ALL & ~E_NOTICE (Show all errors, except for notices and coding standards warnings.) +; E_ALL & ~E_NOTICE | E_STRICT (Show all errors, except for notices) +; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors) +; E_ALL | E_STRICT (Show all errors, warnings and notices including coding standards.) +; Default Value: E_ALL & ~E_NOTICE +; Development Value: E_ALL | E_STRICT +; Production Value: E_ALL & ~E_DEPRECATED +; http://php.net/error-reporting +error_reporting = E_ALL & ~E_NOTICE + +; This directive controls whether or not and where PHP will output errors, +; notices and warnings too. Error output is very useful during development, but +; it could be very dangerous in production environments. Depending on the code +; which is triggering the error, sensitive information could potentially leak +; out of your application such as database usernames and passwords or worse. +; It's recommended that errors be logged on production servers rather than +; having the errors sent to STDOUT. +; Possible Values: +; Off = Do not display any errors +; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) +; On or stdout = Display errors to STDOUT +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/display-errors +display_errors = Off + +; The display of errors which occur during PHP's startup sequence are handled +; separately from display_errors. PHP's default behavior is to suppress those +; errors from clients. Turning the display of startup errors on can be useful in +; debugging configuration problems. But, it's strongly recommended that you +; leave this setting off on production servers. +; Default Value: Off +; Development Value: On +; Production Value: Off +; http://php.net/display-startup-errors +display_startup_errors = Off + +; Besides displaying errors, PHP can also log errors to locations such as a +; server-specific log, STDERR, or a location specified by the error_log +; directive found below. While errors should not be displayed on productions +; servers they should still be monitored and logging is a great way to do that. +; Default Value: Off +; Development Value: On +; Production Value: On +; http://php.net/log-errors +log_errors = On + +; Set maximum length of log_errors. In error_log information about the source is +; added. The default is 1024 and 0 allows to not apply any maximum length at all. +; http://php.net/log-errors-max-len +log_errors_max_len = 1024 + +; Do not log repeated messages. Repeated errors must occur in same file on same +; line unless ignore_repeated_source is set true. +; http://php.net/ignore-repeated-errors +ignore_repeated_errors = Off + +; Ignore source of message when ignoring repeated messages. When this setting +; is On you will not log errors with repeated messages from different files or +; source lines. +; http://php.net/ignore-repeated-source +ignore_repeated_source = Off + +; If this parameter is set to Off, then memory leaks will not be shown (on +; stdout or in the log). This has only effect in a debug compile, and if +; error reporting includes E_WARNING in the allowed list +; http://php.net/report-memleaks +report_memleaks = On + +; This setting is on by default. +;report_zend_debug = 0 + +; Store the last error/warning message in $php_errormsg (boolean). Setting this value +; to On can assist in debugging and is appropriate for development servers. It should +; however be disabled on production servers. +; Default Value: Off +; Development Value: On +; Production Value: Off +; http://php.net/track-errors +track_errors = Off + +; Turn off normal error reporting and emit XML-RPC error XML +; http://php.net/xmlrpc-errors +;xmlrpc_errors = 0 + +; An XML-RPC faultCode +;xmlrpc_error_number = 0 + +; When PHP displays or logs an error, it has the capability of inserting html +; links to documentation related to that error. This directive controls whether +; those HTML links appear in error messages or not. For performance and security +; reasons, it's recommended you disable this on production servers. +; Note: This directive is hardcoded to Off for the CLI SAPI +; Default Value: On +; Development Value: On +; Production value: Off +; http://php.net/html-errors +html_errors = Off + +; If html_errors is set On PHP produces clickable error messages that direct +; to a page describing the error or function causing the error in detail. +; You can download a copy of the PHP manual from http://php.net/docs +; and change docref_root to the base URL of your local copy including the +; leading '/'. You must also specify the file extension being used including +; the dot. PHP's default behavior is to leave these settings empty. +; Note: Never use this feature for production boxes. +; http://php.net/docref-root +; Examples +;docref_root = "/phpmanual/" + +; http://php.net/docref-ext +;docref_ext = .html + +; String to output before an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-prepend-string +; Example: +;error_prepend_string = "" + +; String to output after an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-append-string +; Example: +;error_append_string = "" + +; Log errors to specified file. PHP's default behavior is to leave this value +; empty. +; http://php.net/error-log +; Example: +;error_log = php_errors.log +; Log errors to syslog (Event Log on NT, not valid in Windows 95). +;error_log = syslog + +;;;;;;;;;;;;;;;;; +; Data Handling ; +;;;;;;;;;;;;;;;;; + +; The separator used in PHP generated URLs to separate arguments. +; PHP's default setting is "&". +; http://php.net/arg-separator.output +; Example: +;arg_separator.output = "&" + +; List of separator(s) used by PHP to parse input URLs into variables. +; PHP's default setting is "&". +; NOTE: Every character in this directive is considered as separator! +; http://php.net/arg-separator.input +; Example: +;arg_separator.input = ";&" + +; This directive determines which super global arrays are registered when PHP +; starts up. If the register_globals directive is enabled, it also determines +; what order variables are populated into the global space. G,P,C,E & S are +; abbreviations for the following respective super globals: GET, POST, COOKIE, +; ENV and SERVER. There is a performance penalty paid for the registration of +; these arrays and because ENV is not as commonly used as the others, ENV is +; is not recommended on productions servers. You can still get access to +; the environment variables through getenv() should you need to. +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS"; +; http://php.net/variables-order +variables_order = "EGPCS" + +; This directive determines which super global data (G,P,C,E & S) should +; be registered into the super global array REQUEST. If so, it also determines +; the order in which that data is registered. The values for this directive are +; specified in the same manner as the variables_order directive, EXCEPT one. +; Leaving this value empty will cause PHP to use the value set in the +; variables_order directive. It does not mean it will leave the super globals +; array REQUEST empty. +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" +; http://php.net/request-order +request_order = "GP" + +; Whether or not to register the EGPCS variables as global variables. You may +; want to turn this off if you don't want to clutter your scripts' global scope +; with user data. +; You should do your best to write your scripts so that they do not require +; register_globals to be on; Using form variables as globals can easily lead +; to possible security problems, if the code is not very well thought of. +; http://php.net/register-globals +register_globals = Off + +; Determines whether the deprecated long $HTTP_*_VARS type predefined variables +; are registered by PHP or not. As they are deprecated, we obviously don't +; recommend you use them. They are on by default for compatibility reasons but +; they are not recommended on production servers. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/register-long-arrays +register_long_arrays = Off + +; This directive determines whether PHP registers $argv & $argc each time it +; runs. $argv contains an array of all the arguments passed to PHP when a script +; is invoked. $argc contains an integer representing the number of arguments +; that were passed when the script was invoked. These arrays are extremely +; useful when running scripts from the command line. When this directive is +; enabled, registering these variables consumes CPU cycles and memory each time +; a script is executed. For performance reasons, this feature should be disabled +; on production servers. +; Note: This directive is hardcoded to On for the CLI SAPI +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/register-argc-argv +register_argc_argv = Off + +; When enabled, the SERVER and ENV variables are created when they're first +; used (Just In Time) instead of when the script starts. If these variables +; are not used within a script, having this directive on will result in a +; performance gain. The PHP directives register_globals, register_long_arrays, +; and register_argc_argv must be disabled for this directive to have any affect. +; http://php.net/auto-globals-jit +auto_globals_jit = On + +; Maximum size of POST data that PHP will accept. +; http://php.net/post-max-size +post_max_size = 8M + +; Magic quotes are a preprocessing feature of PHP where PHP will attempt to +; escape any character sequences in GET, POST, COOKIE and ENV data which might +; otherwise corrupt data being placed in resources such as databases before +; making that data available to you. Because of character encoding issues and +; non-standard SQL implementations across many databases, it's not currently +; possible for this feature to be 100% accurate. PHP's default behavior is to +; enable the feature. We strongly recommend you use the escaping mechanisms +; designed specifically for the database your using instead of relying on this +; feature. Also note, this feature has been deprecated as of PHP 5.3.0 and is +; scheduled for removal in PHP 6. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/magic-quotes-gpc +magic_quotes_gpc = Off + +; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc. +; http://php.net/magic-quotes-runtime +magic_quotes_runtime = Off + +; Use Sybase-style magic quotes (escape ' with '' instead of \'). +; http://php.net/magic-quotes-sybase +magic_quotes_sybase = Off + +; Automatically add files before PHP document. +; http://php.net/auto-prepend-file +auto_prepend_file = + +; Automatically add files after PHP document. +; http://php.net/auto-append-file +auto_append_file = + +; By default, PHP will output a character encoding using +; the Content-type: header. To disable sending of the charset, simply +; set it to be empty. +; +; PHP's built-in default is text/html +; http://php.net/default-mimetype +default_mimetype = "text/html" + +; PHP's default character set is set to empty. +; http://php.net/default-charset +;default_charset = "iso-8859-1" + +; Always populate the $HTTP_RAW_POST_DATA variable. PHP's default behavior is +; to disable this feature. +; http://php.net/always-populate-raw-post-data +;always_populate_raw_post_data = On + +;;;;;;;;;;;;;;;;;;;;;;;;; +; Paths and Directories ; +;;;;;;;;;;;;;;;;;;;;;;;;; + +; UNIX: "/path1:/path2" +;include_path = ".:/php/includes" +; +; Windows: "\path1;\path2" +;include_path = ".;c:\php\includes" +; +; PHP's default setting for include_path is ".;/path/to/php/pear" +; http://php.net/include-path + +; The root of the PHP pages, used only if nonempty. +; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root +; if you are running php as a CGI under any web server (other than IIS) +; see documentation for security issues. The alternate is to use the +; cgi.force_redirect configuration below +; http://php.net/doc-root +doc_root = + +; The directory under which PHP opens the script using /~username used only +; if nonempty. +; http://php.net/user-dir +user_dir = + +; Directory in which the loadable extensions (modules) reside. +; http://php.net/extension-dir +; extension_dir = "./" +; On windows: +; extension_dir = "ext" + +; Whether or not to enable the dl() function. The dl() function does NOT work +; properly in multithreaded servers, such as IIS or Zeus, and is automatically +; disabled on them. +; http://php.net/enable-dl +enable_dl = Off + +; cgi.force_redirect is necessary to provide security running PHP as a CGI under +; most web servers. Left undefined, PHP turns this on by default. You can +; turn it off here AT YOUR OWN RISK +; **You CAN safely turn this off for IIS, in fact, you MUST.** +; http://php.net/cgi.force-redirect +;cgi.force_redirect = 1 + +; if cgi.nph is enabled it will force cgi to always sent Status: 200 with +; every request. PHP's default behavior is to disable this feature. +;cgi.nph = 1 + +; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape +; (iPlanet) web servers, you MAY need to set an environment variable name that PHP +; will look for to know it is OK to continue execution. Setting this variable MAY +; cause security issues, KNOW WHAT YOU ARE DOING FIRST. +; http://php.net/cgi.redirect-status-env +;cgi.redirect_status_env = ; + +; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's +; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok +; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting +; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting +; of zero causes PHP to behave as before. Default is 1. You should fix your scripts +; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. +; http://php.net/cgi.fix-pathinfo +;cgi.fix_pathinfo=1 + +; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate +; security tokens of the calling client. This allows IIS to define the +; security context that the request runs under. mod_fastcgi under Apache +; does not currently support this feature (03/17/2002) +; Set to 1 if running under IIS. Default is zero. +; http://php.net/fastcgi.impersonate +;fastcgi.impersonate = 1; + +; Disable logging through FastCGI connection. PHP's default behavior is to enable +; this feature. +;fastcgi.logging = 0 + +; cgi.rfc2616_headers configuration option tells PHP what type of headers to +; use when sending HTTP response code. If it's set 0 PHP sends Status: header that +; is supported by Apache. When this option is set to 1 PHP will send +; RFC2616 compliant header. +; Default is zero. +; http://php.net/cgi.rfc2616-headers +;cgi.rfc2616_headers = 0 + +;;;;;;;;;;;;;;;; +; File Uploads ; +;;;;;;;;;;;;;;;; + +; Whether to allow HTTP file uploads. +; http://php.net/file-uploads +file_uploads = On + +; Temporary directory for HTTP uploaded files (will use system default if not +; specified). +; http://php.net/upload-tmp-dir +;upload_tmp_dir = + +; Maximum allowed size for uploaded files. +; http://php.net/upload-max-filesize +upload_max_filesize = 2M + +; Maximum number of files that can be uploaded via a single request +max_file_uploads = 20 + +;;;;;;;;;;;;;;;;;; +; Fopen wrappers ; +;;;;;;;;;;;;;;;;;; + +; Whether to allow the treatment of URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-fopen +allow_url_fopen = On + +; Whether to allow include/require to open URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-include +allow_url_include = Off + +; Define the anonymous ftp password (your email address). PHP's default setting +; for this is empty. +; http://php.net/from +;from="john@doe.com" + +; Define the User-Agent string. PHP's default setting for this is empty. +; http://php.net/user-agent +;user_agent="PHP" + +; Default timeout for socket based streams (seconds) +; http://php.net/default-socket-timeout +default_socket_timeout = 60 + +; If your scripts have to deal with files from Macintosh systems, +; or you are running on a Mac and need to deal with files from +; unix or win32 systems, setting this flag will cause PHP to +; automatically detect the EOL character in those files so that +; fgets() and file() will work regardless of the source of the file. +; http://php.net/auto-detect-line-endings +;auto_detect_line_endings = Off + +;;;;;;;;;;;;;;;;;;;;;; +; Dynamic Extensions ; +;;;;;;;;;;;;;;;;;;;;;; + +; If you wish to have an extension loaded automatically, use the following +; syntax: +; +; extension=modulename.extension +; +; For example, on Windows: +; +; extension=msql.dll +; +; ... or under UNIX: +; +; extension=msql.so +; +; ... or with a path: +; +; extension=/path/to/extension/msql.so +; +; If you only provide the name of the extension, PHP will look for it in its +; default extension directory. +; +; Windows Extensions +; Note that ODBC support is built in, so no dll is needed for it. +; Note that many DLL files are located in the extensions/ (PHP 4) ext/ (PHP 5) +; extension folders as well as the separate PECL DLL download (PHP 5). +; Be sure to appropriately set the extension_dir directive. +; +;extension=php_bz2.dll +;extension=php_curl.dll +;extension=php_fileinfo.dll +;extension=php_gd2.dll +;extension=php_gettext.dll +;extension=php_gmp.dll +;extension=php_intl.dll +;extension=php_imap.dll +;extension=php_interbase.dll +;extension=php_ldap.dll +;extension=php_mbstring.dll +;extension=php_exif.dll ; Must be after mbstring as it depends on it +;extension=php_mysql.dll +;extension=php_mysqli.dll +;extension=php_oci8.dll ; Use with Oracle 10gR2 Instant Client +;extension=php_oci8_11g.dll ; Use with Oracle 11g Instant Client +;extension=php_openssl.dll +;extension=php_pdo_firebird.dll +;extension=php_pdo_mssql.dll +;extension=php_pdo_mysql.dll +;extension=php_pdo_oci.dll +;extension=php_pdo_odbc.dll +;extension=php_pdo_pgsql.dll +;extension=php_pdo_sqlite.dll +;extension=php_pgsql.dll +;extension=php_pspell.dll +;extension=php_shmop.dll + +; The MIBS data available in the PHP distribution must be installed. +; See http://www.php.net/manual/en/snmp.installation.php +;extension=php_snmp.dll + +;extension=php_soap.dll +;extension=php_sockets.dll +;extension=php_sqlite.dll +;extension=php_sqlite3.dll +;extension=php_sybase_ct.dll +;extension=php_tidy.dll +;extension=php_xmlrpc.dll +;extension=php_xsl.dll +;extension=php_zip.dll + +;;;;;;;;;;;;;;;;;;; +; Module Settings ; +;;;;;;;;;;;;;;;;;;; + +[Date] +; Defines the default timezone used by the date functions +; http://php.net/date.timezone +date.timezone = UTC + +; http://php.net/date.default-latitude +;date.default_latitude = 31.7667 + +; http://php.net/date.default-longitude +;date.default_longitude = 35.2333 + +; http://php.net/date.sunrise-zenith +;date.sunrise_zenith = 90.583333 + +; http://php.net/date.sunset-zenith +;date.sunset_zenith = 90.583333 + +[filter] +; http://php.net/filter.default +;filter.default = unsafe_raw + +; http://php.net/filter.default-flags +;filter.default_flags = + +[iconv] +;iconv.input_encoding = ISO-8859-1 +;iconv.internal_encoding = ISO-8859-1 +;iconv.output_encoding = ISO-8859-1 + +[intl] +;intl.default_locale = +; This directive allows you to produce PHP errors when some error +; happens within intl functions. The value is the level of the error produced. +; Default is 0, which does not produce any errors. +;intl.error_level = E_WARNING + +[sqlite] +; http://php.net/sqlite.assoc-case +;sqlite.assoc_case = 0 + +[sqlite3] +;sqlite3.extension_dir = + +[Pcre] +;PCRE library backtracking limit. +; http://php.net/pcre.backtrack-limit +;pcre.backtrack_limit=100000 + +;PCRE library recursion limit. +;Please note that if you set this value to a high number you may consume all +;the available process stack and eventually crash PHP (due to reaching the +;stack size limit imposed by the Operating System). +; http://php.net/pcre.recursion-limit +;pcre.recursion_limit=100000 + +[Pdo] +; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" +; http://php.net/pdo-odbc.connection-pooling +;pdo_odbc.connection_pooling=strict + +;pdo_odbc.db2_instance_name + +[Pdo_mysql] +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/pdo_mysql.cache_size +pdo_mysql.cache_size = 2000 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/pdo_mysql.default-socket +pdo_mysql.default_socket= + +[Phar] +; http://php.net/phar.readonly +;phar.readonly = On + +; http://php.net/phar.require-hash +;phar.require_hash = On + +;phar.cache_list = + +[Syslog] +; Whether or not to define the various syslog variables (e.g. $LOG_PID, +; $LOG_CRON, etc.). Turning it off is a good idea performance-wise. In +; runtime, you can define these variables by calling define_syslog_variables(). +; http://php.net/define-syslog-variables +define_syslog_variables = Off + +[mail function] +; For Win32 only. +; http://php.net/smtp +SMTP = localhost +; http://php.net/smtp-port +smtp_port = 25 + +; For Win32 only. +; http://php.net/sendmail-from +;sendmail_from = me@example.com + +; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). +; http://php.net/sendmail-path +;sendmail_path = + +; Force the addition of the specified parameters to be passed as extra parameters +; to the sendmail binary. These parameters will always replace the value of +; the 5th parameter to mail(), even in safe mode. +;mail.force_extra_parameters = + +; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename +mail.add_x_header = On + +; The path to a log file that will log all mail() calls. Log entries include +; the full path of the script, line number, To address and headers. +;mail.log = + +[SQL] +; http://php.net/sql.safe-mode +sql.safe_mode = Off + +[ODBC] +; http://php.net/odbc.default-db +;odbc.default_db = Not yet implemented + +; http://php.net/odbc.default-user +;odbc.default_user = Not yet implemented + +; http://php.net/odbc.default-pw +;odbc.default_pw = Not yet implemented + +; Controls the ODBC cursor model. +; Default: SQL_CURSOR_STATIC (default). +;odbc.default_cursortype + +; Allow or prevent persistent links. +; http://php.net/odbc.allow-persistent +odbc.allow_persistent = On + +; Check that a connection is still valid before reuse. +; http://php.net/odbc.check-persistent +odbc.check_persistent = On + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/odbc.max-persistent +odbc.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/odbc.max-links +odbc.max_links = -1 + +; Handling of LONG fields. Returns number of bytes to variables. 0 means +; passthru. +; http://php.net/odbc.defaultlrl +odbc.defaultlrl = 4096 + +; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. +; See the documentation on odbc_binmode and odbc_longreadlen for an explanation +; of odbc.defaultlrl and odbc.defaultbinmode +; http://php.net/odbc.defaultbinmode +odbc.defaultbinmode = 1 + +;birdstep.max_links = -1 + +[Interbase] +; Allow or prevent persistent links. +ibase.allow_persistent = 1 + +; Maximum number of persistent links. -1 means no limit. +ibase.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +ibase.max_links = -1 + +; Default database name for ibase_connect(). +;ibase.default_db = + +; Default username for ibase_connect(). +;ibase.default_user = + +; Default password for ibase_connect(). +;ibase.default_password = + +; Default charset for ibase_connect(). +;ibase.default_charset = + +; Default timestamp format. +ibase.timestampformat = "%Y-%m-%d %H:%M:%S" + +; Default date format. +ibase.dateformat = "%Y-%m-%d" + +; Default time format. +ibase.timeformat = "%H:%M:%S" + +[MySQL] +; Allow accessing, from PHP's perspective, local files with LOAD DATA statements +; http://php.net/mysql.allow_local_infile +mysql.allow_local_infile = On + +; Allow or prevent persistent links. +; http://php.net/mysql.allow-persistent +mysql.allow_persistent = On + +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/mysql.cache_size +mysql.cache_size = 2000 + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/mysql.max-persistent +mysql.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/mysql.max-links +mysql.max_links = -1 + +; Default port number for mysql_connect(). If unset, mysql_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +; http://php.net/mysql.default-port +mysql.default_port = + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/mysql.default-socket +mysql.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysql.default-host +mysql.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysql.default-user +mysql.default_user = + +; Default password for mysql_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +; http://php.net/mysql.default-password +mysql.default_password = + +; Maximum time (in seconds) for connect timeout. -1 means no limit +; http://php.net/mysql.connect-timeout +mysql.connect_timeout = 60 + +; Trace mode. When trace_mode is active (=On), warnings for table/index scans and +; SQL-Errors will be displayed. +; http://php.net/mysql.trace-mode +mysql.trace_mode = Off + +[MySQLi] + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/mysqli.max-persistent +mysqli.max_persistent = -1 + +; Allow accessing, from PHP's perspective, local files with LOAD DATA statements +; http://php.net/mysqli.allow_local_infile +;mysqli.allow_local_infile = On + +; Allow or prevent persistent links. +; http://php.net/mysqli.allow-persistent +mysqli.allow_persistent = On + +; Maximum number of links. -1 means no limit. +; http://php.net/mysqli.max-links +mysqli.max_links = -1 + +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/mysqli.cache_size +mysqli.cache_size = 2000 + +; Default port number for mysqli_connect(). If unset, mysqli_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +; http://php.net/mysqli.default-port +mysqli.default_port = 3306 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/mysqli.default-socket +mysqli.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-host +mysqli.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-user +mysqli.default_user = + +; Default password for mysqli_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +; http://php.net/mysqli.default-pw +mysqli.default_pw = + +; Allow or prevent reconnect +mysqli.reconnect = Off + +[mysqlnd] +; Enable / Disable collection of general statstics by mysqlnd which can be +; used to tune and monitor MySQL operations. +; http://php.net/mysqlnd.collect_statistics +mysqlnd.collect_statistics = On + +; Enable / Disable collection of memory usage statstics by mysqlnd which can be +; used to tune and monitor MySQL operations. +; http://php.net/mysqlnd.collect_memory_statistics +mysqlnd.collect_memory_statistics = Off + +; Size of a pre-allocated buffer used when sending commands to MySQL in bytes. +; http://php.net/mysqlnd.net_cmd_buffer_size +;mysqlnd.net_cmd_buffer_size = 2048 + +; Size of a pre-allocated buffer used for reading data sent by the server in +; bytes. +; http://php.net/mysqlnd.net_read_buffer_size +;mysqlnd.net_read_buffer_size = 32768 + +[OCI8] + +; Connection: Enables privileged connections using external +; credentials (OCI_SYSOPER, OCI_SYSDBA) +; http://php.net/oci8.privileged-connect +;oci8.privileged_connect = Off + +; Connection: The maximum number of persistent OCI8 connections per +; process. Using -1 means no limit. +; http://php.net/oci8.max-persistent +;oci8.max_persistent = -1 + +; Connection: The maximum number of seconds a process is allowed to +; maintain an idle persistent connection. Using -1 means idle +; persistent connections will be maintained forever. +; http://php.net/oci8.persistent-timeout +;oci8.persistent_timeout = -1 + +; Connection: The number of seconds that must pass before issuing a +; ping during oci_pconnect() to check the connection validity. When +; set to 0, each oci_pconnect() will cause a ping. Using -1 disables +; pings completely. +; http://php.net/oci8.ping-interval +;oci8.ping_interval = 60 + +; Connection: Set this to a user chosen connection class to be used +; for all pooled server requests with Oracle 11g Database Resident +; Connection Pooling (DRCP). To use DRCP, this value should be set to +; the same string for all web servers running the same application, +; the database pool must be configured, and the connection string must +; specify to use a pooled server. +;oci8.connection_class = + +; High Availability: Using On lets PHP receive Fast Application +; Notification (FAN) events generated when a database node fails. The +; database must also be configured to post FAN events. +;oci8.events = Off + +; Tuning: This option enables statement caching, and specifies how +; many statements to cache. Using 0 disables statement caching. +; http://php.net/oci8.statement-cache-size +;oci8.statement_cache_size = 20 + +; Tuning: Enables statement prefetching and sets the default number of +; rows that will be fetched automatically after statement execution. +; http://php.net/oci8.default-prefetch +;oci8.default_prefetch = 100 + +; Compatibility. Using On means oci_close() will not close +; oci_connect() and oci_new_connect() connections. +; http://php.net/oci8.old-oci-close-semantics +;oci8.old_oci_close_semantics = Off + +[PostgresSQL] +; Allow or prevent persistent links. +; http://php.net/pgsql.allow-persistent +pgsql.allow_persistent = On + +; Detect broken persistent links always with pg_pconnect(). +; Auto reset feature requires a little overheads. +; http://php.net/pgsql.auto-reset-persistent +pgsql.auto_reset_persistent = Off + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/pgsql.max-persistent +pgsql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +; http://php.net/pgsql.max-links +pgsql.max_links = -1 + +; Ignore PostgreSQL backends Notice message or not. +; Notice message logging require a little overheads. +; http://php.net/pgsql.ignore-notice +pgsql.ignore_notice = 0 + +; Log PostgreSQL backends Notice message or not. +; Unless pgsql.ignore_notice=0, module cannot log notice message. +; http://php.net/pgsql.log-notice +pgsql.log_notice = 0 + +[Sybase-CT] +; Allow or prevent persistent links. +; http://php.net/sybct.allow-persistent +sybct.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/sybct.max-persistent +sybct.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/sybct.max-links +sybct.max_links = -1 + +; Minimum server message severity to display. +; http://php.net/sybct.min-server-severity +sybct.min_server_severity = 10 + +; Minimum client message severity to display. +; http://php.net/sybct.min-client-severity +sybct.min_client_severity = 10 + +; Set per-context timeout +; http://php.net/sybct.timeout +;sybct.timeout= + +;sybct.packet_size + +; The maximum time in seconds to wait for a connection attempt to succeed before returning failure. +; Default: one minute +;sybct.login_timeout= + +; The name of the host you claim to be connecting from, for display by sp_who. +; Default: none +;sybct.hostname= + +; Allows you to define how often deadlocks are to be retried. -1 means "forever". +; Default: 0 +;sybct.deadlock_retry_count= + +[bcmath] +; Number of decimal digits for all bcmath functions. +; http://php.net/bcmath.scale +bcmath.scale = 0 + +[browscap] +; http://php.net/browscap +;browscap = extra/browscap.ini + +[Session] +; Handler used to store/retrieve data. +; http://php.net/session.save-handler +session.save_handler = files + +; Argument passed to save_handler. In the case of files, this is the path +; where data files are stored. Note: Windows users have to change this +; variable in order to use PHP's session functions. +; +; The path can be defined as: +; +; session.save_path = "N;/path" +; +; where N is an integer. Instead of storing all the session files in +; /path, what this will do is use subdirectories N-levels deep, and +; store the session data in those directories. This is useful if you +; or your OS have problems with lots of files in one directory, and is +; a more efficient layout for servers that handle lots of sessions. +; +; NOTE 1: PHP will not create this directory structure automatically. +; You can use the script in the ext/session dir for that purpose. +; NOTE 2: See the section on garbage collection below if you choose to +; use subdirectories for session storage +; +; The file storage module creates files using mode 600 by default. +; You can change that by using +; +; session.save_path = "N;MODE;/path" +; +; where MODE is the octal representation of the mode. Note that this +; does not overwrite the process's umask. +; http://php.net/session.save-path +;session.save_path = "/tmp" + +; Whether to use cookies. +; http://php.net/session.use-cookies +session.use_cookies = 1 + +; http://php.net/session.cookie-secure +;session.cookie_secure = + +; This option forces PHP to fetch and use a cookie for storing and maintaining +; the session id. We encourage this operation as it's very helpful in combatting +; session hijacking when not specifying and managing your own session id. It is +; not the end all be all of session hijacking defense, but it's a good start. +; http://php.net/session.use-only-cookies +session.use_only_cookies = 1 + +; Name of the session (used as cookie name). +; http://php.net/session.name +session.name = PHPSESSID + +; Initialize session on request startup. +; http://php.net/session.auto-start +session.auto_start = 0 + +; Lifetime in seconds of cookie or, if 0, until browser is restarted. +; http://php.net/session.cookie-lifetime +session.cookie_lifetime = 0 + +; The path for which the cookie is valid. +; http://php.net/session.cookie-path +session.cookie_path = / + +; The domain for which the cookie is valid. +; http://php.net/session.cookie-domain +session.cookie_domain = + +; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript. +; http://php.net/session.cookie-httponly +session.cookie_httponly = + +; Handler used to serialize data. php is the standard serializer of PHP. +; http://php.net/session.serialize-handler +session.serialize_handler = php + +; Defines the probability that the 'garbage collection' process is started +; on every session initialization. The probability is calculated by using +; gc_probability/gc_divisor. Where session.gc_probability is the numerator +; and gc_divisor is the denominator in the equation. Setting this value to 1 +; when the session.gc_divisor value is 100 will give you approximately a 1% chance +; the gc will run on any give request. +; Default Value: 1 +; Development Value: 1 +; Production Value: 1 +; http://php.net/session.gc-probability +session.gc_probability = 1 + +; Defines the probability that the 'garbage collection' process is started on every +; session initialization. The probability is calculated by using the following equation: +; gc_probability/gc_divisor. Where session.gc_probability is the numerator and +; session.gc_divisor is the denominator in the equation. Setting this value to 1 +; when the session.gc_divisor value is 100 will give you approximately a 1% chance +; the gc will run on any give request. Increasing this value to 1000 will give you +; a 0.1% chance the gc will run on any give request. For high volume production servers, +; this is a more efficient approach. +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 +; http://php.net/session.gc-divisor +session.gc_divisor = 1000 + +; After this number of seconds, stored data will be seen as 'garbage' and +; cleaned up by the garbage collection process. +; http://php.net/session.gc-maxlifetime +session.gc_maxlifetime = 1440 + +; NOTE: If you are using the subdirectory option for storing session files +; (see session.save_path above), then garbage collection does *not* +; happen automatically. You will need to do your own garbage +; collection through a shell script, cron entry, or some other method. +; For example, the following script would is the equivalent of +; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): +; find /path/to/sessions -cmin +24 | xargs rm + +; PHP 4.2 and less have an undocumented feature/bug that allows you to +; to initialize a session variable in the global scope, even when register_globals +; is disabled. PHP 4.3 and later will warn you, if this feature is used. +; You can disable the feature and the warning separately. At this time, +; the warning is only displayed, if bug_compat_42 is enabled. This feature +; introduces some serious security problems if not handled correctly. It's +; recommended that you do not use this feature on production servers. But you +; should enable this on development servers and enable the warning as well. If you +; do not enable the feature on development servers, you won't be warned when it's +; used and debugging errors caused by this can be difficult to track down. +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/session.bug-compat-42 +session.bug_compat_42 = Off + +; This setting controls whether or not you are warned by PHP when initializing a +; session value into the global space. session.bug_compat_42 must be enabled before +; these warnings can be issued by PHP. See the directive above for more information. +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/session.bug-compat-warn +session.bug_compat_warn = Off + +; Check HTTP Referer to invalidate externally stored URLs containing ids. +; HTTP_REFERER has to contain this substring for the session to be +; considered as valid. +; http://php.net/session.referer-check +session.referer_check = + +; How many bytes to read from the file. +; http://php.net/session.entropy-length +session.entropy_length = 0 + +; Specified here to create the session id. +; http://php.net/session.entropy-file +; On systems that don't have /dev/urandom /dev/arandom can be used +; On windows, setting the entropy_length setting will activate the +; Windows random source (using the CryptoAPI) +;session.entropy_file = /dev/urandom + +; Set to {nocache,private,public,} to determine HTTP caching aspects +; or leave this empty to avoid sending anti-caching headers. +; http://php.net/session.cache-limiter +session.cache_limiter = nocache + +; Document expires after n minutes. +; http://php.net/session.cache-expire +session.cache_expire = 180 + +; trans sid support is disabled by default. +; Use of trans sid may risk your users security. +; Use this option with caution. +; - User may send URL contains active session ID +; to other person via. email/irc/etc. +; - URL that contains active session ID may be stored +; in publically accessible computer. +; - User may access your site with the same session ID +; always using URL stored in browser's history or bookmarks. +; http://php.net/session.use-trans-sid +session.use_trans_sid = 0 + +; Select a hash function for use in generating session ids. +; Possible Values +; 0 (MD5 128 bits) +; 1 (SHA-1 160 bits) +; This option may also be set to the name of any hash function supported by +; the hash extension. A list of available hashes is returned by the hash_algos() +; function. +; http://php.net/session.hash-function +session.hash_function = 0 + +; Define how many bits are stored in each character when converting +; the binary hash data to something readable. +; Possible values: +; 4 (4 bits: 0-9, a-f) +; 5 (5 bits: 0-9, a-v) +; 6 (6 bits: 0-9, a-z, A-Z, "-", ",") +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 +; http://php.net/session.hash-bits-per-character +session.hash_bits_per_character = 5 + +; The URL rewriter will look for URLs in a defined set of HTML tags. +; form/fieldset are special; if you include them here, the rewriter will +; add a hidden field with the info which is otherwise appended +; to URLs. If you want XHTML conformity, remove the form entry. +; Note that all valid entries require a "=", even if no value follows. +; Default Value: "a=href,area=href,frame=src,form=,fieldset=" +; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; http://php.net/url-rewriter.tags +url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry" + +[MSSQL] +; Allow or prevent persistent links. +mssql.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +mssql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +mssql.max_links = -1 + +; Minimum error severity to display. +mssql.min_error_severity = 10 + +; Minimum message severity to display. +mssql.min_message_severity = 10 + +; Compatibility mode with old versions of PHP 3.0. +mssql.compatability_mode = Off + +; Connect timeout +;mssql.connect_timeout = 5 + +; Query timeout +;mssql.timeout = 60 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textlimit = 4096 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textsize = 4096 + +; Limits the number of records in each batch. 0 = all records in one batch. +;mssql.batchsize = 0 + +; Specify how datetime and datetim4 columns are returned +; On => Returns data converted to SQL server settings +; Off => Returns values as YYYY-MM-DD hh:mm:ss +;mssql.datetimeconvert = On + +; Use NT authentication when connecting to the server +mssql.secure_connection = Off + +; Specify max number of processes. -1 = library default +; msdlib defaults to 25 +; FreeTDS defaults to 4096 +;mssql.max_procs = -1 + +; Specify client character set. +; If empty or not set the client charset from freetds.comf is used +; This is only used when compiled with FreeTDS +;mssql.charset = "ISO-8859-1" + +[Assertion] +; Assert(expr); active by default. +; http://php.net/assert.active +;assert.active = On + +; Issue a PHP warning for each failed assertion. +; http://php.net/assert.warning +;assert.warning = On + +; Don't bail out by default. +; http://php.net/assert.bail +;assert.bail = Off + +; User-function to be called if an assertion fails. +; http://php.net/assert.callback +;assert.callback = 0 + +; Eval the expression with current error_reporting(). Set to true if you want +; error_reporting(0) around the eval(). +; http://php.net/assert.quiet-eval +;assert.quiet_eval = 0 + +[COM] +; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs +; http://php.net/com.typelib-file +;com.typelib_file = + +; allow Distributed-COM calls +; http://php.net/com.allow-dcom +;com.allow_dcom = true + +; autoregister constants of a components typlib on com_load() +; http://php.net/com.autoregister-typelib +;com.autoregister_typelib = true + +; register constants casesensitive +; http://php.net/com.autoregister-casesensitive +;com.autoregister_casesensitive = false + +; show warnings on duplicate constant registrations +; http://php.net/com.autoregister-verbose +;com.autoregister_verbose = true + +; The default character set code-page to use when passing strings to and from COM objects. +; Default: system ANSI code page +;com.code_page= + +[mbstring] +; language for internal character representation. +; http://php.net/mbstring.language +;mbstring.language = Japanese + +; internal/script encoding. +; Some encoding cannot work as internal encoding. +; (e.g. SJIS, BIG5, ISO-2022-*) +; http://php.net/mbstring.internal-encoding +;mbstring.internal_encoding = EUC-JP + +; http input encoding. +; http://php.net/mbstring.http-input +;mbstring.http_input = auto + +; http output encoding. mb_output_handler must be +; registered as output buffer to function +; http://php.net/mbstring.http-output +;mbstring.http_output = SJIS + +; enable automatic encoding translation according to +; mbstring.internal_encoding setting. Input chars are +; converted to internal encoding by setting this to On. +; Note: Do _not_ use automatic encoding translation for +; portable libs/applications. +; http://php.net/mbstring.encoding-translation +;mbstring.encoding_translation = Off + +; automatic encoding detection order. +; auto means +; http://php.net/mbstring.detect-order +;mbstring.detect_order = auto + +; substitute_character used when character cannot be converted +; one from another +; http://php.net/mbstring.substitute-character +;mbstring.substitute_character = none; + +; overload(replace) single byte functions by mbstring functions. +; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), +; etc. Possible values are 0,1,2,4 or combination of them. +; For example, 7 for overload everything. +; 0: No overload +; 1: Overload mail() function +; 2: Overload str*() functions +; 4: Overload ereg*() functions +; http://php.net/mbstring.func-overload +;mbstring.func_overload = 0 + +; enable strict encoding detection. +;mbstring.strict_detection = Off + +; This directive specifies the regex pattern of content types for which mb_output_handler() +; is activated. +; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) +;mbstring.http_output_conv_mimetype= + +; Allows to set script encoding. Only affects if PHP is compiled with --enable-zend-multibyte +; Default: "" +;mbstring.script_encoding= + +[gd] +; Tell the jpeg decode to ignore warnings and try to create +; a gd image. The warning will then be displayed as notices +; disabled by default +; http://php.net/gd.jpeg-ignore-warning +;gd.jpeg_ignore_warning = 0 + +[exif] +; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. +; With mbstring support this will automatically be converted into the encoding +; given by corresponding encode setting. When empty mbstring.internal_encoding +; is used. For the decode settings you can distinguish between motorola and +; intel byte order. A decode setting cannot be empty. +; http://php.net/exif.encode-unicode +;exif.encode_unicode = ISO-8859-15 + +; http://php.net/exif.decode-unicode-motorola +;exif.decode_unicode_motorola = UCS-2BE + +; http://php.net/exif.decode-unicode-intel +;exif.decode_unicode_intel = UCS-2LE + +; http://php.net/exif.encode-jis +;exif.encode_jis = + +; http://php.net/exif.decode-jis-motorola +;exif.decode_jis_motorola = JIS + +; http://php.net/exif.decode-jis-intel +;exif.decode_jis_intel = JIS + +[Tidy] +; The path to a default tidy configuration file to use when using tidy +; http://php.net/tidy.default-config +;tidy.default_config = /usr/local/lib/php/default.tcfg + +; Should tidy clean and repair output automatically? +; WARNING: Do not use this option if you are generating non-html content +; such as dynamic images +; http://php.net/tidy.clean-output +tidy.clean_output = Off + +[soap] +; Enables or disables WSDL caching feature. +; http://php.net/soap.wsdl-cache-enabled +soap.wsdl_cache_enabled=1 + +; Sets the directory name where SOAP extension will put cache files. +; http://php.net/soap.wsdl-cache-dir +soap.wsdl_cache_dir="/tmp" + +; (time to live) Sets the number of second while cached file will be used +; instead of original one. +; http://php.net/soap.wsdl-cache-ttl +soap.wsdl_cache_ttl=86400 + +; Sets the size of the cache limit. (Max. number of WSDL files to cache) +soap.wsdl_cache_limit = 5 + +[sysvshm] +; A default size of the shared memory segment +;sysvshm.init_mem = 10000 + +[ldap] +; Sets the maximum number of open links or -1 for unlimited. +ldap.max_links = -1 + +[mcrypt] +; For more information about mcrypt settings see http://php.net/mcrypt-module-open + +; Directory where to load mcrypt algorithms +; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) +;mcrypt.algorithms_dir= + +; Directory where to load mcrypt modes +; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) +;mcrypt.modes_dir= + +[dba] +;dba.default_handler= + +; Local Variables: +; tab-width: 4 +; End: diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_docker/README.md b/vendor/heroku/heroku-buildpack-php/support/build/_docker/README.md new file mode 100644 index 0000000..7394447 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_docker/README.md @@ -0,0 +1,31 @@ +# Building Platform Packages using Docker + +## Building the Image + +**After every change to your formulae, perform the following** from the root of the Git repository (not from `support/build/_docker/`): + + $ docker build --tag heroku-php-build-cedar-14 --file $(pwd)/support/build/_docker/cedar-14.Dockerfile . + +## Configuration + +File `env.default` contains a list of required env vars, some with default values. You can modify it with the values you desire, or pass them to `docker run` using `--env`. + +Out of the box, you'll likely want to change `S3_BUCKET` and `S3_PREFIX` to match your info. Instead of setting `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` in that file, it is recommended to pass them to `docker run` through the environment, or explicitly using `--env`, in order to prevent accidental commits of credentials. + +## Using the Image + +From the root of the Git repository (not from `support/build/_docker/`): + + docker run --rm --tty --interactive --env-file=support/build/_docker/env.default heroku-php-build-cedar-14 /bin/bash + +That runs with values from `env.default`; if you need to pass e.g. `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` because they are not already in your environment, do either: + + AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... docker run --rm --tty --interactive --env-file=support/build/_docker/env.default heroku-php-build-cedar-14 /bin/bash + +or + + docker run --rm --tty --interactive --env-file=support/build/_docker/env.default -e AWS_ACCESS_KEY_ID=... -e AWS_SECRET_ACCESS_KEY=... heroku-php-build-cedar-14 /bin/bash + +You then have a shell where you can run `bob build`, `deploy.sh` and so forth. + +The `support/build/_util/` directory is on `$PATH` in the image. diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_docker/cedar-14.Dockerfile b/vendor/heroku/heroku-buildpack-php/support/build/_docker/cedar-14.Dockerfile new file mode 100644 index 0000000..9ea9e44 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_docker/cedar-14.Dockerfile @@ -0,0 +1,13 @@ +FROM heroku/cedar:14 + +WORKDIR /app +ENV WORKSPACE_DIR=/app/support/build +ENV PATH=/app/support/build/_util:$PATH + +RUN apt-get update && apt-get install -y python-pip + +COPY requirements.txt /app/requirements.txt + +RUN pip install -r /app/requirements.txt + +COPY . /app diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_docker/env.default b/vendor/heroku/heroku-buildpack-php/support/build/_docker/env.default new file mode 100644 index 0000000..f796351 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_docker/env.default @@ -0,0 +1,8 @@ +AWS_ACCESS_KEY_ID +AWS_SECRET_ACCESS_KEY + +S3_BUCKET=lang-php +S3_PREFIX=dist-cedar-14-develop/ +S3_REGION=s3 + +STACK=cedar-14 diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_docker/heroku-16.Dockerfile b/vendor/heroku/heroku-buildpack-php/support/build/_docker/heroku-16.Dockerfile new file mode 100644 index 0000000..806bbd0 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_docker/heroku-16.Dockerfile @@ -0,0 +1,13 @@ +FROM heroku/heroku:16-build + +WORKDIR /app +ENV WORKSPACE_DIR=/app/support/build +ENV PATH=/app/support/build/_util:$PATH + +RUN apt-get update && apt-get install -y python-pip + +COPY requirements.txt /app/requirements.txt + +RUN pip install -r /app/requirements.txt + +COPY . /app diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_util/deploy.sh b/vendor/heroku/heroku-buildpack-php/support/build/_util/deploy.sh new file mode 100755 index 0000000..0acbd18 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_util/deploy.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +# fail hard +set -o pipefail +# fail harder +set -eu + +publish=false + +# process flags +optstring=":-:" +while getopts "$optstring" opt; do + case $opt in + -) + case "$OPTARG" in + publish) + publish=true + break + ;; + *) + OPTIND=1 + break + ;; + esac + esac +done +# clear processed "publish" argument +shift $((OPTIND-1)) + +if [[ $# -lt 1 ]]; then + echo "Usage: $(basename $0) [--publish] FORMULA-VERSION [--overwrite]" >&2 + echo " If --publish is given, mkrepo.sh will be invoked after a successful deploy to" >&2 + echo " re-generate the repo. CAUTION: this will cause all manifests in the bucket to" >&2 + echo " be included in the repo, including potentially currently unpublished ones." >&2 + echo " All additional arguments, including --overwrite, are passed through to 'bob'." >&2 + exit 2 +fi + +if [[ -z "${AWS_ACCESS_KEY_ID:-}" || -z "${AWS_SECRET_ACCESS_KEY:-}" ]]; then + echo '$AWS_ACCESS_KEY_ID or $AWS_SECRET_ACCESS_KEY not set!' >&2 + exit 2 +fi + +# a helper (print_or_export_manifest_cmd) called in the script invoked by Bob will write to this if set +export MANIFEST_CMD=$(mktemp -t "manifest.XXXXX") +trap 'rm -rf $MANIFEST_CMD;' EXIT + +# make sure we start cleanly +rm -rf /app/.heroku/php + +# pass through args (so users can pass --overwrite etc) +# but modify any path by stripping $WORKSPACE_DIR from the front, if it's there +# so that one can also pass in the full path to the formula relative to the root, and not just relative to $WORKSPACE_DIR +# that allows for simpler mass build loops using wildcards without having to worry about the relative location of other references such as an --env-file, like: +# for f in support/build/php-{5,7}.* support/build/extensions/no-debug-non-zts-201*/{redis,blackfire,imagick}-*; do docker run --rm --tty --interactive --env-file=../dockerenv.cedar-14 heroku-php-builder-cedar-14 deploy.sh $f; done +args=() +for var in "$@"; do + expanded="$(pwd)/$var" + if [[ -f $expanded ]]; then + var="${expanded#$WORKSPACE_DIR/}" + fi + args+=("$var") +done + +bob deploy "${args[@]}" + +# invoke manifest upload +echo "" +echo "Uploading manifest..." +. $MANIFEST_CMD + +if $publish; then + echo "Updating repository..." + $(dirname $BASH_SOURCE)/mkrepo.sh --upload "$S3_BUCKET" "${S3_PREFIX}" +fi diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_util/include/manifest.py b/vendor/heroku/heroku-buildpack-php/support/build/_util/include/manifest.py new file mode 100644 index 0000000..c2a1770 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_util/include/manifest.py @@ -0,0 +1,23 @@ +import os, sys, json, re, datetime + +require = json.loads(sys.argv[5]) if len(sys.argv) > 5 else {} +stack=re.match("^([^-]+)(?:-([0-9]+))?$", os.getenv("STACK", "cedar-14")) +require["heroku-sys/"+stack.group(1)] = "^{}.0.0".format(stack.group(2) or "1") +require["heroku/installer-plugin"] = "^1.2.0" + +manifest = { + "type": sys.argv[1], + "name": sys.argv[2], + "version": sys.argv[3], + "dist": { + "type": "heroku-sys-tar", + "url": "https://"+os.getenv("S3_BUCKET")+"."+os.getenv("S3_REGION", "s3")+".amazonaws.com/"+os.getenv("S3_PREFIX")+sys.argv[4] + }, + "require": require, + "conflict": json.loads(sys.argv[6]) if len(sys.argv) > 6 else {}, + "replace": json.loads(sys.argv[7]) if len(sys.argv) > 7 else {}, + "extra": json.loads(sys.argv[8]) if len(sys.argv) > 8 else {}, + "time": datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") +} + +json.dump(manifest, sys.stdout, sort_keys=True) diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_util/include/manifest.sh b/vendor/heroku/heroku-buildpack-php/support/build/_util/include/manifest.sh new file mode 100755 index 0000000..a7f1ddc --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_util/include/manifest.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +print_or_export_manifest_cmd() { + if [[ "${MANIFEST_CMD:-}" ]]; then + echo "$1" > $MANIFEST_CMD + else + echo "-----> Done. Run '$1' to upload manifest." + fi +} + +generate_manifest_cmd() { + echo "s3cmd --ssl${AWS_ACCESS_KEY_ID+" --access_key=\$AWS_ACCESS_KEY_ID"}${AWS_SECRET_ACCESS_KEY+" --secret_key=\$AWS_SECRET_ACCESS_KEY"} --acl-public -m application/json put $(pwd)/${1} s3://${S3_BUCKET}/${S3_PREFIX}${1}" +} diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_util/mkrepo.sh b/vendor/heroku/heroku-buildpack-php/support/build/_util/mkrepo.sh new file mode 100755 index 0000000..1fae7b4 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_util/mkrepo.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash + +# fail hard +set -o pipefail +# fail harder +set -eu + +function s3cmd_get_progress() { + len=0 + while read line; do + if [[ "$len" -gt 0 ]]; then + # repeat a backspace $len times + # need to use seq; {1..$len} doesn't work + printf '%0.s\b' $(seq 1 $len) + fi + echo -n "$line" + len=${#line} + done < <(grep --line-buffered -o -E '\[[0-9]+ of [0-9]+\]') # filter only the "[1 of 99]" bits from 's3cmd get' output +} + +upload=false + +# process flags +optstring=":-:" +while getopts "$optstring" opt; do + case $opt in + -) + case "$OPTARG" in + upload) + upload=true + ;; + *) + echo "Invalid option: --$OPTARG" >&2 + exit 2 + ;; + esac + esac +done +# clear processed arguments +shift $((OPTIND-1)) + +if [[ $# == "1" ]]; then + echo "Usage: $(basename $0) [--upload] [S3_BUCKET S3_PREFIX [MANIFEST...]]" >&2 + echo " S3_BUCKET: S3 bucket name for packages.json upload; default: '\$S3_BUCKET'." >&2 + echo " S3_PREFIX: S3 prefix, e.g. '' or 'dist-stable/'; default: '\${S3_PREFIX}'." >&2 + echo " If MANIFEST arguments are given, those are used to build the repo; otherwise," >&2 + echo " all manifests from given or default S3_BUCKET+S3_PREFIX are downloaded." >&2 + echo " A --upload flag triggers immediate upload, otherwise instructions are printed." >&2 + echo " If --upload, or if stdout is a terminal, packages.json will be written to cwd." >&2 + echo " If no --upload, and if stdout is a pipe, repo JSON will be echo'd to stdout." >&2 + exit 2 +fi + +here=$(cd $(dirname $0); pwd) + +if [[ $# != "0" ]]; then + S3_BUCKET=$1; shift + S3_PREFIX=$1; shift +fi + +if [[ $# == "0" ]]; then + manifests_tmp=$(mktemp -d -t "dst-repo.XXXXX") + trap 'rm -rf $manifests_tmp;' EXIT + echo -n "-----> Fetching manifests... " >&2 + ( + cd $manifests_tmp + s3cmd --ssl --progress get s3://${S3_BUCKET}/${S3_PREFIX}*.composer.json 2>&1 | tee download.log | s3cmd_get_progress >&2 || { echo -e "failed! Error:\n$(cat download.log)" >&2; exit 1; } + rm download.log + ) + echo "" >&2 + manifests=$manifests_tmp/*.composer.json +else + manifests="$@" +fi + +echo "-----> Generating packages.json..." >&2 +redir=false +if $upload || [[ -t 1 ]]; then + redir=true + # if stdout is a terminal or if we're uploading; we write a "packages.json" instead of echoing + # this is so other programs can pipe our output and capture the generated repo from stdout + # also back up stdout so we restore it to the right thing (tty or pipe) later + exec 3>&1 1>packages.json +fi + +# sort so that packages with the same name and version (e.g. ext-memcached 2.2.0) show up with their hhvm or php requirement in descending order - otherwise a Composer limitation means that a simple "ext-memcached: * + php: ^5.5.17" request would install 5.5.latest and not 5.6.latest, as it finds the 5.5.* requirement extension first and sticks to that instead of 5.6. For packages with identical names and versions (but different e.g. requirements), Composer basically treats them as equal and picks as a winner whatever it finds first. The requirements have to be written like "x.y.*" for this to work of course. +python -c 'import sys, json; from distutils import version; json.dump({"packages": [ sorted([json.load(open(item)) for item in sys.argv[1:] if json.load(open(item)).get("type", "") != "heroku-sys-package"], key=lambda package: version.LooseVersion(package.get("require", {}).get("heroku-sys/hhvm", package.get("require", {}).get("heroku-sys/php", "0.0.0"))), reverse=True) ] }, sys.stdout, sort_keys=True)' $manifests + +# restore stdout +# note that 'exec >$(tty)' does not work as FD 1 may have been a pipe originally and not a tty +if $redir; then + exec 1>&3 3>&- +fi + +cmd="s3cmd --ssl${AWS_ACCESS_KEY_ID+" --access_key=\$AWS_ACCESS_KEY_ID"}${AWS_SECRET_ACCESS_KEY+" --secret_key=\$AWS_SECRET_ACCESS_KEY"} --acl-public -m application/json put packages.json s3://${S3_BUCKET}/${S3_PREFIX}packages.json" +if $upload; then + echo "-----> Uploading packages.json..." >&2 + eval "$cmd 1>&2" + echo "-----> Done." >&2 +elif [[ -t 1 ]]; then + echo "-----> Done. Run '$cmd' to upload repository." >&2 +fi diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_util/remove.sh b/vendor/heroku/heroku-buildpack-php/support/build/_util/remove.sh new file mode 100755 index 0000000..004e291 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_util/remove.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env bash + +# fail hard +set -o pipefail +# fail harder +set -eu + +publish=true + +# process flags +optstring=":-:" +while getopts "$optstring" opt; do + case $opt in + -) + case "$OPTARG" in + no-publish) + publish=false + ;; + *) + echo "Invalid option: --$OPTARG" >&2 + exit 2 + ;; + esac + esac +done +# clear processed arguments +shift $((OPTIND-1)) + +if [[ $# -lt "1" ]]; then + echo "Usage: $(basename $0) [--no-publish] MANIFEST..." >&2 + echo " MANIFEST: name of manifest file, e.g. 'ext-event-2.0.0_php-5.6.composer.json'" >&2 + echo " If --no-publish is given, mkrepo.sh will NOT be invoked after removal to" >&2 + echo " re-generate the repo." >&2 + echo " CAUTION: re-generating the repo will cause all manifests in the bucket" >&2 + echo " to be included in the repo, including potentially currently unpublished ones." >&2 + echo " CAUTION: using --no-publish means the repo will point to non-existing packages" >&2 + echo " until 'mkrepo.sh --upload' is run!" >&2 + echo " Bucket name and prefix will be read from '\$S3_BUCKET' and '\$S3_PREFIX'." >&2 + exit 2 +fi + +S3_PREFIX=${S3_PREFIX:-} + +here=$(cd $(dirname $0); pwd) + +manifests=("$@") + +indices="${!manifests[@]}" +for index in $indices; do + manifests[$index]="s3://${S3_BUCKET}/${S3_PREFIX}${manifests[$index]%.composer.json}.composer.json" +done + +manifests_tmp=$(mktemp -d -t "dst-repo.XXXXX") +trap 'rm -rf $manifests_tmp;' EXIT +echo "-----> Fetching manifests..." >&2 +( + cd $manifests_tmp + s3cmd --ssl get "${manifests[@]}" 1>&2 +) + +echo " +WARNING: POTENTIALLY DESTRUCTIVE ACTION! + +The following packages will be REMOVED + from s3://${S3_BUCKET}/${S3_PREFIX}: +$(IFS=$'\n'; echo "${manifests[*]:-(none)}" | xargs -n1 basename | sed -e 's/^/ - /' -e 's/.composer.json$//') +" >&2 + +if $publish; then + echo "NOTICE: You have selected to publish the repo after removal of packages." >&2 + echo "This means the repo will be re-generated based on the current bucket contents!" >&2 + regenmsg="& regenerate packages.json" +else + regenmsg="without updating the repo" + echo "WARNING: You have selected to NOT publish the repo after removal of packages." >&2 + echo "This means the repo will point to non-existing packages until mkrepo.sh is run!" >&2 +fi +echo "" >&2 + +read -p "Are you sure you want to remove the packages $regenmsg? [yN] " proceed + +[[ ! $proceed =~ [yY](es)* ]] && exit + +echo "" >&2 + +remove_files=() +for manifest in "${manifests[@]}"; do + echo "Removing $(basename $manifest ".composer.json"):" >&2 + if filename=$(cat $manifests_tmp/$(basename $manifest) | python <(cat <<-'PYTHON' # beware of single quotes in body + import sys, json, re; + manifest=json.load(sys.stdin) + url=manifest.get("dist",{}).get("url","").partition("https://"+sys.argv[1]+"."+sys.argv[2]+".amazonaws.com/"+sys.argv[3]) + if url[0]: + # dist URL does not match https://${dst_bucket}.${dst_region}.amazonaws.com/${dst_prefix} + print(url[0]) + sys.exit(1) + else: + print(url[2]) + PYTHON + ) $S3_BUCKET ${S3_REGION:-s3} ${S3_PREFIX}) + then + echo " - queued '$filename' for removal." >&2 + remove_files+=("$filename") + else + # the dist URL points somewhere else, so we are not touching that + echo " - WARNING: not removing '$filename' (in manifest 'dist.url')!" >&2 + fi + echo -n " - removing manifest file '$(basename $manifest)'... " >&2 + out=$(s3cmd rm ${AWS_ACCESS_KEY_ID+"--access_key=$AWS_ACCESS_KEY_ID"} ${AWS_SECRET_ACCESS_KEY+"--secret_key=$AWS_SECRET_ACCESS_KEY"} --ssl "$manifest" 2>&1) || { echo -e "failed! Error:\n$out" >&2; exit 1; } + rm $manifests_tmp/$(basename $manifest) + echo "done." >&2 +done + +echo "" >&2 + +if $publish; then + echo -n "Generating and uploading packages.json... " >&2 + out=$(cd $manifests_tmp; $here/mkrepo.sh --upload 2>&1) || { echo -e "failed! Error:\n$out" >&2; exit 1; } + cat >&2 <<-EOF + done! + $(echo "$out" | grep -E '^Public URL' | sed 's/^Public URL of the object is: http:/Public URL of the repository is: https:/') + + EOF +fi + +if [[ "${#remove_files[@]}" != "0" ]]; then + echo "Removing files queued for deletion from bucket:" >&2 + for filename in "${remove_files[@]}"; do + echo -n " - removing '$filename'... " >&2 + out=$(s3cmd rm ${AWS_ACCESS_KEY_ID+"--access_key=$AWS_ACCESS_KEY_ID"} ${AWS_SECRET_ACCESS_KEY+"--secret_key=$AWS_SECRET_ACCESS_KEY"} --ssl s3://${S3_BUCKET}/${S3_PREFIX}${filename} 2>&1) && echo "done." >&2 || echo -e "failed! Error:\n$out" >&2 + done + echo "" >&2 +fi + +echo "Removal complete. +" >&2 + +if ! $publish; then + cat >&2 <<-EOF + WARNING: repo has not been re-generated. It may currently be in a broken state. + There may be packages still listed in the repo that have just been removed. + Run 'mkrepo.sh --upload' at once to return repository into a consistent state. + + EOF +fi diff --git a/vendor/heroku/heroku-buildpack-php/support/build/_util/sync.sh b/vendor/heroku/heroku-buildpack-php/support/build/_util/sync.sh new file mode 100755 index 0000000..c26ac5d --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/_util/sync.sh @@ -0,0 +1,287 @@ +#!/usr/bin/env bash + +set -eu +set -o pipefail + +function s3cmd_get_progress() { + len=0 + while read line; do + if [[ "$len" -gt 0 ]]; then + # repeat a backspace $len times + # need to use seq; {1..$len} doesn't work + printf '%0.s\b' $(seq 1 $len) + fi + echo -n "$line" + len=${#line} + done < <(grep --line-buffered -o -E '\[[0-9]+ of [0-9]+\]') # filter only the "[1 of 99]" bits from 's3cmd get' output +} + +remove=true + +# process flags +optstring=":-:" +while getopts "$optstring" opt; do + case $opt in + -) + case "$OPTARG" in + no-remove) + remove=false + ;; + *) + echo "Invalid option: --$OPTARG" >&2 + exit 2 + ;; + esac + esac +done +# clear processed arguments +shift $((OPTIND-1)) + +if [[ $# -lt "2" || $# -gt "6" ]]; then + echo "Usage: $(basename $0) [--no-remove] DEST_BUCKET DEST_PREFIX [DEST_REGION [SOURCE_BUCKET SOURCE_PREFIX [SOURCE_REGION]]]" >&2 + echo " DEST_BUCKET: destination S3 bucket name." >&2 + echo " DEST_REGION: destination bucket region, e.g. us-west-1; default: 's3'." >&2 + echo " DEST_PREFIX: destination prefix, e.g. '' or 'dist-stable/'." >&2 + echo " SOURCE_BUCKET: source S3 bucket name; default: '\$S3_BUCKET'." >&2 + echo " SOURCE_REGION: source bucket region; default: '\$S3_REGION' or 's3'." >&2 + echo " SOURCE_PREFIX: source prefix; default: '\${S3_PREFIX}'." >&2 + echo " --no-remove: no removal of destination packages that are not in source bucket." >&2 + exit 2 +fi + +dst_bucket=$1; shift +dst_prefix=$1; shift +if [[ $# -gt 2 ]]; then + # region name given + dst_region=$1; shift +else + dst_region="s3" +fi +echo "$@" +src_bucket=${1:-$S3_BUCKET}; shift || true +src_prefix=${1:-$S3_PREFIX}; shift || true +if [[ $# == "1" ]]; then + # region name given + src_region=$1; shift +else + src_region=${S3_REGION:-"s3"} +fi + +src_tmp=$(mktemp -d -t "src-repo.XXXXX") +dst_tmp=$(mktemp -d -t "dst-repo.XXXXX") +here=$(cd $(dirname $0); pwd) + +# clean up at the end +trap 'rm -rf $src_tmp $dst_tmp;' EXIT + +echo -n "Fetching source's manifests from s3://${src_bucket}/${src_prefix}... " >&2 +( + cd $src_tmp + out=$(s3cmd --ssl get s3://${src_bucket}/${src_prefix}packages.json 2>&1) || { echo -e "No packages.json in source repo:\n$out" >&2; exit 1; } + s3cmd --ssl --progress get s3://${src_bucket}/${src_prefix}*.composer.json 2>&1 | tee download.log | s3cmd_get_progress >&2 || { echo -e "failed! Error:\n$(cat download.log)" >&2; exit 1; } + ls *.composer.json 2>/dev/null 1>&2 || { echo "failed; no manifests found!" >&2; exit 1; } + rm download.log +) +echo "" >&2 + +# this mkrepo.sh call won't actually download, but use the given *.composer.json, and echo a generated packages.json +# we use this to compare to the downloaded packages.json +$here/mkrepo.sh $src_bucket $src_prefix ${src_tmp}/*.composer.json 2>/dev/null | python -c 'import sys, json; sys.exit(abs(cmp(json.load(open(sys.argv[1])), json.load(sys.stdin))))' ${src_tmp}/packages.json || { + echo "WARNING: packages.json from source does not match its list of manifests!" >&2 + echo " You should run 'mkrepo.sh' to update, or ask the bucket maintainers to do so." >&2 + read -p "Would you like to abort this operation? [Yn] " proceed + [[ ! $proceed =~ [nN]o* ]] && exit 1 # yes is the default so doing yes | sync.sh won't do something stupid +} + +echo -n "Fetching destination's manifests from s3://${dst_bucket}/${dst_prefix}... " >&2 +( + cd $dst_tmp + s3cmd --ssl --progress get s3://${dst_bucket}/${dst_prefix}*.composer.json 2>&1 | tee download.log | s3cmd_get_progress >&2 || { echo -e "failed! Error:\n$(cat download.log)" >&2; exit 1; } + rm download.log +) +echo "" >&2 + +comm=$(comm <(cd $src_tmp; ls -1 *.composer.json) <(cd $dst_tmp; ls -1 *.composer.json 2> /dev/null)) # comm produces three columns of output: entries only in left file, entries only in right file, entries in both +add_manifests=$(echo "$comm" | grep '^\S' || true) # no tabs means output in col 1 = files only in src +remove_manifests=$(echo "$comm" | grep '^\s\S' | cut -c2- || true) # one tab means output in col 2 = files only in dst +common=$(echo "$comm" | grep '^\s\s' | cut -c3- || true) # two tabs means output in col 3 = files in both +update_manifests=() +ignore_manifests=() +for filename in $common; do + result=0 + python <(cat <<-'PYTHON' # beware of single quotes in body + from __future__ import print_function + import sys, json, os, datetime + # for python 2+3 compat + def stderrprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + src_manifest = json.load(open(sys.argv[1])) + dst_manifest = json.load(open(sys.argv[2])) + # remove URLs so they don't interfere with comparison + src_manifest.get("dist", {}).pop("url", None) + dst_manifest.get("dist", {}).pop("url", None) + # same for times, but we'll look at them + try: + src_time = datetime.datetime.strptime(src_manifest.pop("time"), "%Y-%m-%d %H:%M:%S") # UTC + except KeyError, ValueError: + src_time = datetime.datetime.utcfromtimestamp(os.path.getmtime(sys.argv[1])) + stderrprint("WARNING: source manifest {} has invalid time entry, using mtime: {}".format(os.path.basename(sys.argv[1]), src_time.isoformat())) + try: + dst_time = datetime.datetime.strptime(dst_manifest.pop("time"), "%Y-%m-%d %H:%M:%S") # UTC + except KeyError, ValueError: + dst_time = datetime.datetime.utcfromtimestamp(os.path.getmtime(sys.argv[2])) + stderrprint("WARNING: destination manifest {} has invalid time entry, using mtime: {}".format(os.path.basename(sys.argv[2]), dst_time.isoformat())) + # a newer source time means we will copy + if src_time > dst_time: + sys.exit(0) + else: + # 1 = content identical, src_time = dst_time (up to date) + # 3 = content different, src_time = dst_time (weird) + # 5 = content identical, src_time < dst_time (probably needs sync the other way) + # 7 = content different, src_time < dst_time (probably needs sync the other way) + ret = 1 + ret = ret | abs(cmp(src_manifest, dst_manifest))<<1 + ret = ret | (src_time < dst_time)<<2 + sys.exit(ret) + PYTHON + ) $src_tmp/$filename $dst_tmp/$filename || result=$? + if [[ $result -eq 0 ]]; then + update_manifests+=($filename) + elif [[ $result != "1" ]]; then + case $result in + 3) + ignore_manifests+=("$filename (contents differ, time fields identical!?)") + ;; + 5) + ignore_manifests+=("$filename (contents match, destination manifest newer)") + ;; + 7) + ignore_manifests+=("$filename (contents differ, destination manifest newer)") + ;; + esac + fi +done + +echo " +WARNING: POTENTIALLY DESTRUCTIVE ACTION! + +The following packages will be IGNORED: +$(IFS=$'\n'; echo "${ignore_manifests[*]:-(none)}" | sed -e 's/^/ - /' -e 's/.composer.json//') + +The following packages will be ADDED + from s3://${src_bucket}/${src_prefix} + to s3://${dst_bucket}/${dst_prefix}: +$(echo "${add_manifests:-(none)}" | sed -e 's/^/ - /' -e 's/.composer.json$//') + +The following packages will be UPDATED (source manifest is newer) + from s3://${src_bucket}/${src_prefix} + to s3://${dst_bucket}/${dst_prefix}: +$(IFS=$'\n'; echo "${update_manifests[*]:-(none)}" | sed -e 's/^/ - /' -e 's/.composer.json$//') + +The following packages will $($remove || echo -n "NOT ")be REMOVED + from s3://${dst_bucket}/${dst_prefix}$($remove && echo -n ":")$($remove || echo -ne "\n because '--no-remove' was given:") +$(echo "${remove_manifests:-(none)}" | sed -e 's/^/ - /' -e 's/.composer.json$//') +" >&2 + +# clear remove_manifests if --no-remove given +$remove || remove_manifests= + +if [[ ! "$add_manifests" && ! "$remove_manifests" && "${#update_manifests[@]}" -eq 0 ]]; then + echo "Nothing to do. Aborting." >&2 + exit +fi + +read -p "Are you sure you want to sync to destination & regenerate packages.json? [yN] " proceed + +[[ ! $proceed =~ [yY](es)* ]] && exit + +echo "" >&2 + +copied_files=() +for manifest in $add_manifests ${update_manifests[@]:-}; do + echo "Copying ${manifest%.composer.json}:" >&2 + if filename=$(cat ${src_tmp}/${manifest} | python <(cat <<-'PYTHON' # beware of single quotes in body + import sys, json; + manifest=json.load(sys.stdin) + url=manifest.get("dist",{}).get("url","").partition("https://"+sys.argv[1]+"."+sys.argv[2]+".amazonaws.com/"+sys.argv[3]) + if url[0]: + # dist URL does not match https://${src_bucket}.${src_region}.amazonaws.com/${src_prefix} + print(url[0]) + sys.exit(1) + else: + # rewrite dist URL in manifest to destination bucket + manifest["dist"]["url"] = "https://"+sys.argv[4]+"."+sys.argv[5]+".amazonaws.com/"+sys.argv[6]+url[2] + json.dump(manifest, open(sys.argv[7], "w"), sort_keys=True) + print(url[2]) + PYTHON + ) $src_bucket $src_region $src_prefix $dst_bucket $dst_region $dst_prefix ${dst_tmp}/${manifest}) + then + # the dist URL in the source's manifest points to the source bucket, so we copy the file to the dest bucket + echo -n " - copying '$filename'... " >&2 + out=$(s3cmd ${AWS_ACCESS_KEY_ID+"--access_key=$AWS_ACCESS_KEY_ID"} ${AWS_SECRET_ACCESS_KEY+"--secret_key=$AWS_SECRET_ACCESS_KEY"} --ssl --acl-public cp s3://${src_bucket}/${src_prefix}${filename} s3://${dst_bucket}/${dst_prefix}${filename} 2>&1) || { echo -e "failed! Error:\n$out" >&2; exit 1; } + copied_files+=("$filename") + echo "done." >&2 + else + # the dist URL points somewhere else, so we are not touching that + echo " - WARNING: not copying '$filename' (in manifest 'dist.url')!" >&2 + # just copy over the manifest (in the above branch, the Python script in the if expression already took care of that) + cp ${src_tmp}/${manifest} ${dst_tmp}/${manifest} + fi + echo -n " - copying manifest file '$manifest'... " >&2 + out=$(s3cmd ${AWS_ACCESS_KEY_ID+"--access_key=$AWS_ACCESS_KEY_ID"} ${AWS_SECRET_ACCESS_KEY+"--secret_key=$AWS_SECRET_ACCESS_KEY"} --ssl --acl-public -m application/json put ${dst_tmp}/${manifest} s3://${dst_bucket}/${dst_prefix}${manifest} 2>&1) || { echo -e "failed! Error:\n$out" >&2; exit 1; } + echo "done." >&2 +done + +remove_files=() +for manifest in $remove_manifests; do + echo "Removing ${manifest%.composer.json}:" >&2 + if filename=$(cat ${dst_tmp}/${manifest} | python <(cat <<-'PYTHON' # beware of single quotes in body + import sys, json; + manifest=json.load(sys.stdin) + url=manifest.get("dist",{}).get("url","").partition("https://"+sys.argv[1]+"."+sys.argv[2]+".amazonaws.com/"+sys.argv[3]) + if url[0]: + # dist URL does not match https://${dst_bucket}.${dst_region}.amazonaws.com/${dst_prefix} + print(url[0]) + sys.exit(1) + else: + print(url[2]) + PYTHON + ) $dst_bucket $dst_region $dst_prefix) + then + # the dist URL in the destination manifest points to the destination bucket, so we remove that file at the end of the script... + if [[ " ${copied_files[@]:-} " =~ " $filename " ]]; then + # ...unless it was copied earlier (may happen if a new/updated manifest points to the same file name that this to-be-removed one is using) + echo " - NOTICE: keeping newly copied '$filename'!" >&2 + else + echo " - queued '$filename' for removal." >&2 + remove_files+=("$filename") + fi + else + # the dist URL points somewhere else, so we are not touching that + echo " - WARNING: not removing '$filename' (in manifest 'dist.url')!" >&2 + fi + echo -n " - removing manifest file '$manifest'... " >&2 + out=$(s3cmd rm ${AWS_ACCESS_KEY_ID+"--access_key=$AWS_ACCESS_KEY_ID"} ${AWS_SECRET_ACCESS_KEY+"--secret_key=$AWS_SECRET_ACCESS_KEY"} --ssl s3://${dst_bucket}/${dst_prefix}${manifest} 2>&1) || { echo -e "failed! Error:\n$out" >&2; exit 1; } + rm ${dst_tmp}/${manifest} + echo "done." >&2 +done + +echo "" >&2 + +echo -n "Generating and uploading packages.json... " >&2 +out=$(cd $dst_tmp; $here/mkrepo.sh --upload $dst_bucket $dst_prefix *.composer.json 2>&1) || { echo -e "failed! Error:\n$out" >&2; exit 1; } +echo "done! +$(echo "$out" | grep -E '^Public URL' | sed 's/^Public URL of the object is: http:/Public URL of the repository is: https:/') +" >&2 + +if [[ "${#remove_files[@]}" != "0" ]]; then + echo "Removing files queued for deletion from destination:" >&2 + for filename in "${remove_files[@]}"; do + echo -n " - removing '$filename'... " >&2 + out=$(s3cmd rm ${AWS_ACCESS_KEY_ID+"--access_key=$AWS_ACCESS_KEY_ID"} ${AWS_SECRET_ACCESS_KEY+"--secret_key=$AWS_SECRET_ACCESS_KEY"} --ssl s3://${dst_bucket}/${dst_prefix}${filename} 2>&1) && echo "done." >&2 || echo -e "failed! Error:\n$out" >&2 + done + echo "" >&2 +fi + +echo "Sync complete. +" >&2 diff --git a/vendor/heroku/heroku-buildpack-php/support/build/apache b/vendor/heroku/heroku-buildpack-php/support/build/apache new file mode 100755 index 0000000..251036e --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/apache @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +OUT_PREFIX=$1 + +source $(dirname $BASH_SOURCE)/_util/include/manifest.sh + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula#"${dep_name}-"} +dep_package=${dep_name}-${dep_version} +dep_dirname=httpd-${dep_version} +dep_archive_name=${dep_dirname}.tar.gz +depdeps_archive_name=${dep_dirname}-deps.tar.gz +dep_url=https://archive.apache.org/dist/httpd/${dep_archive_name} +depdeps_url=https://archive.apache.org/dist/httpd/${depdeps_archive_name} +dep_manifest=${dep_package}.composer.json + +echo "-----> Building ${dep_package}..." + +curl -L ${dep_url} | tar xz +# both of these untar to $dep_dirname +curl -L ${depdeps_url} | tar xz + +pushd ${dep_dirname} +./configure \ + --enable-layout=GNU \ + --prefix=${OUT_PREFIX} \ + --disable-static \ + --with-included-apr \ + --with-pcre \ + --with-z \ + --with-ssl \ + --with-mpm=event \ + --enable-mods-shared=all \ + --enable-proxy \ + --enable-proxy-fcgi \ + --enable-rewrite \ + --enable-deflate +make -s -j 9 +make install -s +find ${OUT_PREFIX} -type f \( -executable -o -name '*.a' \) -exec sh -c "file -i '{}' | grep -Eq 'application/x-(archive|executable|sharedlib); charset=binary'" \; -print | xargs strip --strip-unneeded +popd + +rm -rf ${OUT_PREFIX}/man ${OUT_PREFIX}/share/apache2/manual + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{\"export\":\"bin/export.apache2.sh\",\"profile\":\"bin/profile.apache2.sh\"}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +mkdir -p ${OUT_PREFIX}/etc/apache2 +cp $(dirname $BASH_SOURCE)/_conf/apache2/httpd.conf ${OUT_PREFIX}/etc/apache2/httpd.conf + +mkdir -p ${OUT_PREFIX}/bin +# this gets sourced after package install, so that the buildpack and following buildpacks can invoke +cat > ${OUT_PREFIX}/bin/export.apache2.sh <<'EOF' +export PATH="/app/.heroku/php/bin:/app/.heroku/php/sbin:$PATH" +EOF +# this gets sourced on dyno boot +cat > ${OUT_PREFIX}/bin/profile.apache2.sh <<'EOF' +export PATH="$HOME/.heroku/php/bin:$HOME/.heroku/php/sbin:$PATH" +EOF + +python $(dirname $BASH_SOURCE)/_util/include/manifest.py "heroku-sys-webserver" "heroku-sys/${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/apache-2.4.20 b/vendor/heroku/heroku-buildpack-php/support/build/apache-2.4.20 new file mode 100755 index 0000000..bb636ea --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/apache-2.4.20 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/apache diff --git a/vendor/heroku/heroku-buildpack-php/support/build/composer b/vendor/heroku/heroku-buildpack-php/support/build/composer new file mode 100755 index 0000000..bf7faa8 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/composer @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/_util/include/manifest.sh + +OUT_PREFIX=$1 + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula#"${dep_name}-"} +dep_package=pkg-${dep_name}-${dep_version} +dep_manifest=${dep_package}.composer.json + +echo "-----> Bundling Composer (${dep_version})..." + +export PATH=${OUT_PREFIX}/bin:$PATH + +EXPECTED_SIGNATURE=$(wget -q -O - https://composer.github.io/installer.sig) +php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" +ACTUAL_SIGNATURE=$(php -r "echo hash_file('SHA384', 'composer-setup.php');") +if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]; then + >&2 echo 'ERROR: Invalid installer signature' + rm composer-setup.php + exit 1 +fi + +php composer-setup.php --version=${dep_version} + +# php is in there, so clear it first +rm -rf ${OUT_PREFIX}/* +mkdir -p ${OUT_PREFIX}/bin + +mv composer.phar ${OUT_PREFIX}/bin/composer + +python $(dirname $BASH_SOURCE)/_util/include/manifest.py "heroku-sys-package" "heroku-sys/pkg-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/composer-1.3.2 b/vendor/heroku/heroku-buildpack-php/support/build/composer-1.3.2 new file mode 100755 index 0000000..94786ce --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/composer-1.3.2 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-min-7.0.16 + +source $(dirname $0)/composer diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/apcu b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/apcu new file mode 100755 index 0000000..6f9d58f --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/apcu @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +dep_name=$(basename $BASH_SOURCE) + +ZEND_MODULE_API_VERSION=$(basename $(dirname $0)) +ZEND_MODULE_API_VERSION=${ZEND_MODULE_API_VERSION#no-debug-non-zts-} + +case ${ZEND_MODULE_API_VERSION} in + 20121212 | 20131226) + MANIFEST_REPLACE='{"heroku-sys/ext-apc":"self.version"}' + ;; +esac + +source $(dirname $BASH_SOURCE)/../pecl diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/apcu-4.0.11 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/apcu-4.0.11 new file mode 100755 index 0000000..6ca0887 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/apcu-4.0.11 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38 + +source $(dirname $0)/apcu diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/blackfire b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/blackfire new file mode 100755 index 0000000..53ddcbf --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/blackfire @@ -0,0 +1,133 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php + +OUT_PREFIX=$1 + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../../_util/include/manifest.sh + +ZEND_MODULE_API_VERSION=$(basename $(dirname $0)) +ZEND_MODULE_API_VERSION=${ZEND_MODULE_API_VERSION#no-debug-non-zts-} + +case ${ZEND_MODULE_API_VERSION} in + 20121212) + series=5.5 + ;; + 20131226) + series=5.6 + ;; + 20151012) + series=7.0 + ;; + 20160303) + series=7.1 + ;; + *) + echo "Unsupported PHP/Zend Module API version: ${ZEND_MODULE_API_VERSION}" + exit 1 + ;; +esac + +ext_dir=${OUT_PREFIX}/lib/php/extensions/no-debug-non-zts-${ZEND_MODULE_API_VERSION} +bin_dir=${OUT_PREFIX}/bin + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +if [[ "$dep_formula" != "$dep_name" ]]; then + probe_version=${dep_formula##*"/${dep_name}-"} + + echo "Using explicit version ${probe_version}" +else + probe_version=`curl -I -A "Heroku" -L -s https://blackfire.io/api/v1/releases/probe/php/linux/amd64/${series/\./} | grep 'X-Blackfire-Release-Version: ' | sed "s%X-Blackfire-Release-Version: %%" | sed s%.$%%` + cat <<-EOF + + !!! WARNING !!! + You're building the generic version of this extension. + API returned version ${probe_version}; it will be built in five seconds. + If you used --overwrite (and no deploy.sh --publish), then this will replace + the existing version of the package under a wrong version number IMMEDIATELY, + even without re-generating the repository, since the archive name is identical: + the repo and new manifest both point to ${dep_name}.tar.gz, but the new manifest + information will not be exposed in the repo until you run mkrepo.sh. + + EOF + sleep 5 +fi +dep_version=${probe_version} +dep_package=ext-${dep_name}-${dep_version} +if [[ "$dep_formula" != "$dep_name" ]]; then + dep_manifest=${dep_package}_php-$series.composer.json +else + dep_manifest=ext-${dep_name}_php-$series.composer.json +fi + +echo "-----> Packaging ${dep_package}..." + +curl -L -o probe.tar.gz "https://packages.blackfire.io/binaries/blackfire-php/${probe_version}/blackfire-php-linux_amd64-php-${series/\./}.tar.gz" + +mkdir -p ${ext_dir} +tar -zxf probe.tar.gz +cp blackfire-${ZEND_MODULE_API_VERSION}.so ${ext_dir}/blackfire.so +rm probe.tar.gz blackfire-${ZEND_MODULE_API_VERSION}.so blackfire-${ZEND_MODULE_API_VERSION}.sha + +agent_version=`curl -A "Heroku" -o agent.tar.gz -D - -L -s https://blackfire.io/api/v1/releases/agent/linux/amd64 | grep 'X-Blackfire-Release-Version: ' | sed "s%X-Blackfire-Release-Version: %%" | sed s%.$%%` +echo "-----> Packaging bin/blackfire-agent ${agent_version}..." + +mkdir -p ${OUT_PREFIX}/var/blackfire/run +mkdir -p ${OUT_PREFIX}/etc/blackfire +echo -e "[blackfire]\nserver-id=f1abf3a8-3f85-4743-99b2-97f066c099b9\nserver-token=5ecbc6486e9db6b780a0c0a9ef1e244709e632996fe9105cb9075ab2826944d5" > ${OUT_PREFIX}/etc/blackfire/agent.ini +mkdir -p ${bin_dir} +tar -zxf agent.tar.gz +chmod +x agent +cp agent ${bin_dir}/blackfire-agent +rm agent.tar.gz agent agent.sha1 + +echo "-----> Packaging bin/blackfire ${agent_version}..." +curl https://packages.blackfire.io/binaries/blackfire-agent/${agent_version}/blackfire-cli-linux_amd64 > ${bin_dir}/blackfire +chmod +x ${bin_dir}/blackfire + +find ${OUT_PREFIX} -type f \( -executable -o -name '*.a' \) -exec sh -c "file -i '{}' | grep -Eq 'application/x-(archive|executable|sharedlib); charset=binary'" \; -print | xargs strip --strip-unneeded + +# gets sourced on dyno boot +cat > ${OUT_PREFIX}/bin/profile.blackfire.sh <<'EOF' +if [[ -n "$BLACKFIRE_SERVER_TOKEN" && -n "$BLACKFIRE_SERVER_ID" ]]; then + if [[ -f "/app/.heroku/php/bin/blackfire-agent" ]]; then + touch /app/.heroku/php/var/blackfire/run/agent.sock + /app/.heroku/php/bin/blackfire-agent -config=/app/.heroku/php/etc/blackfire/agent.ini -socket="unix:///app/.heroku/php/var/blackfire/run/agent.sock" & + else + echo >&2 "WARNING: Add-on 'blackfire' detected, but PHP extension not yet installed. Push an update to the application to finish installation of the add-on; an empty change ('git commit --allow-empty') is sufficient." + fi +fi +EOF +mkdir -p ${OUT_PREFIX}/etc/php/conf.d +cat > ${OUT_PREFIX}/etc/php/conf.d/blackfire.ini-dist <<'EOF' +extension = blackfire.so + +blackfire.server_token = ${BLACKFIRE_SERVER_TOKEN} +blackfire.server_id = ${BLACKFIRE_SERVER_ID} +blackfire.agent_socket = "unix:///app/.heroku/php/var/blackfire/run/agent.sock" +EOF + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\"}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{\"config\":\"etc/php/conf.d/blackfire.ini-dist\",\"profile\":\"bin/profile.blackfire.sh\"}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +python $(dirname $BASH_SOURCE)/../../_util/include/manifest.py "heroku-sys-php-extension" "heroku-sys/ext-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" + +if [[ "$dep_formula" == "$dep_name" ]]; then + cat <<-EOF + + !!! WARNING !!! If you just deployed using --overwrite and without --publish: + the new manifest points to the updated tarball ${dep_name}.tar.gz; + this tarball will now already be picked up by the existing repository under a + wrong version number. Regenerate repository with 'mkrepo.sh --upload' at once! + + EOF +fi diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/blackfire-1.14.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/blackfire-1.14.3 new file mode 100755 index 0000000..e093375 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/blackfire-1.14.3 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/blackfire diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra new file mode 100755 index 0000000..62e45d0 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../../_util/include/manifest.sh + +OUT_PREFIX=$1 + +ZEND_MODULE_API_VERSION=$(basename $(dirname $0)) +ZEND_MODULE_API_VERSION=${ZEND_MODULE_API_VERSION#no-debug-non-zts-} + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=ext-${dep_name}-${dep_version} +case ${ZEND_MODULE_API_VERSION} in + 20121212) + series=5.5 + ;; + 20131226) + series=5.6 + ;; + 20151012) + series=7.0 + ;; + 20160303) + series=7.1 + ;; +esac +dep_manifest=${dep_package}_php-$series.composer.json + +echo "-----> Merging dependencies..." + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\"}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +python $(dirname $BASH_SOURCE)/../../_util/include/manifest.py "heroku-sys-php-extension" "heroku-sys/ext-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-1.2.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-1.2.2 new file mode 100755 index 0000000..3629604 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-1.2.2 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20121212/cassandra-bare-1.2.2, libraries/libcassandra-2.4.2 + +source $(dirname $0)/cassandra diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-bare b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-bare new file mode 100755 index 0000000..d7da45f --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-bare @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../../_util/include/manifest.sh + +OUT_PREFIX=$1 + +export PATH=${OUT_PREFIX}/bin:${PATH} + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=pkg-ext-${dep_name}-${dep_version} +dep_dirname=cassandra-${dep_version} +dep_archive_name=${dep_dirname}.tgz +dep_url=https://pecl.php.net/get/${dep_archive_name} +series=$(php-config --version | cut -d. -f1,2) # get "5.5", "5.6", "7.0" etc for the php requirement in the manifest +dep_manifest=${dep_package}_php-$series.composer.json + +echo "-----> Building ${dep_package} (from PECL)..." + +# we need libgmp-dev +needed=( libgmp-dev ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + apt-get update -qq || { echo "Failed to 'apt-get update'. You must build this formula using Docker."; exit 1; } + apt-get install -q -y $missing +fi + +curl -L ${dep_url} | tar xz + +pushd ${dep_dirname} +phpize +./configure \ + --prefix=${OUT_PREFIX} \ + --with-cassandra=${OUT_PREFIX} +make -s -j 9 +# php was a build dep, and it's in $OUT_PREFIX. nuke that, then make install so all we're left with is the extension +rm -rf ${OUT_PREFIX}/* +make install -s +strip --strip-unneeded ${OUT_PREFIX}/lib/php/extensions/*/*.so +popd + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\"}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +python $(dirname $BASH_SOURCE)/../../_util/include/manifest.py "heroku-sys-php-package" "heroku-sys/ext-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-bare-1.2.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-bare-1.2.2 new file mode 100755 index 0000000..b7e968d --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/cassandra-bare-1.2.2 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38, libraries/libcassandra-2.4.2 + +source $(dirname $0)/cassandra-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/ev b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/ev new file mode 100755 index 0000000..58fb390 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/ev @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +dep_name=$(basename $BASH_SOURCE) + +source $(dirname $BASH_SOURCE)/../pecl diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/ev-1.0.4 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/ev-1.0.4 new file mode 100755 index 0000000..723183a --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/ev-1.0.4 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38 + +source $(dirname $0)/ev diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/event b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/event new file mode 100755 index 0000000..58fb390 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/event @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +dep_name=$(basename $BASH_SOURCE) + +source $(dirname $BASH_SOURCE)/../pecl diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/event-2.2.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/event-2.2.1 new file mode 100755 index 0000000..8d00bf4 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/event-2.2.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38 + +source $(dirname $0)/event diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/imagick b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/imagick new file mode 100755 index 0000000..58fb390 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/imagick @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +dep_name=$(basename $BASH_SOURCE) + +source $(dirname $BASH_SOURCE)/../pecl diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/imagick-3.4.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/imagick-3.4.3 new file mode 100755 index 0000000..41d19e8 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/imagick-3.4.3 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38 + +source $(dirname $0)/imagick diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached new file mode 100755 index 0000000..630b42b --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../../_util/include/manifest.sh + +OUT_PREFIX=$1 + +ZEND_MODULE_API_VERSION=$(basename $(dirname $0)) +ZEND_MODULE_API_VERSION=${ZEND_MODULE_API_VERSION#no-debug-non-zts-} + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=ext-${dep_name}-${dep_version} +case ${ZEND_MODULE_API_VERSION} in + 20121212) + series=5.5 + ;; + 20131226) + series=5.6 + ;; + 20151012) + series=7.0 + ;; + 20160303) + series=7.1 + ;; +esac +dep_manifest=${dep_package}_php-$series.composer.json + +echo "-----> Merging dependencies..." + +mkdir -p ${OUT_PREFIX}/etc/php/conf.d +cat > ${OUT_PREFIX}/etc/php/conf.d/memcached.ini-dist <<'EOF' +extension = memcached.so +memcached.use_sasl = 1 +EOF + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\"}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{\"config\":\"etc/php/conf.d/memcached.ini-dist\"}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +python $(dirname $BASH_SOURCE)/../../_util/include/manifest.py "heroku-sys-php-extension" "heroku-sys/ext-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-2.2.0 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-2.2.0 new file mode 100755 index 0000000..4aa0601 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-2.2.0 @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20121212/memcached-bare-2.2.0, libraries/libmemcached-1.0.18 + +# That's it - we're combining the dep build and the extension build here + +source $(dirname $0)/memcached diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-bare b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-bare new file mode 100755 index 0000000..56034f8 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-bare @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../../_util/include/manifest.sh + +OUT_PREFIX=$1 + +export PATH=${OUT_PREFIX}/bin:${PATH} + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=pkg-ext-${dep_name}-${dep_version} +dep_dirname=memcached-${dep_version} +dep_archive_name=${dep_dirname}.tgz +dep_url=https://pecl.php.net/get/${dep_archive_name} +series=$(php-config --version | cut -d. -f1,2) # get "5.5", "5.6", "7.0" etc for the php requirement in the manifest +dep_manifest=${dep_package}_php-$series.composer.json + +echo "-----> Building ${dep_package}..." + +# can't build without this +needed=( libsasl2-2 ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + echo "Error! Missing libraries: $missing" + exit 1 +fi + +# let's see if libmemcached is there, if not then we have to use the vendored one +needed=( libmemcached11 ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + echo "Using vendored libmemcached..." + # use vendored libmcrypt + with_libmemcached_dir="--with-libmemcached-dir=${OUT_PREFIX}" +else + echo "Using system libmemcached..." + # use system libmemcached + with_libmemcached_dir= + # but do we need headers? + needed=( libmemcached-dev ) + missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) + if [[ "$missing" ]]; then + apt-get update -qq || { echo "Failed to 'apt-get update'. You must build this formula using Docker."; exit 1; } + apt-get install -q -y $missing + fi +fi + +# we need libsasl2-dev for ext-memcached +needed=( libsasl2-dev ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + apt-get update -qq || { echo "Failed to 'apt-get update'. You must build this formula using Docker."; exit 1; } + apt-get install -q -y $missing +fi + +curl -L ${dep_url} | tar xz + +pushd ${dep_dirname} +phpize +./configure \ + --prefix=${OUT_PREFIX} \ + ${with_libmemcached_dir} +make -s -j 9 +# php was a build dep, and it's in $OUT_PREFIX. nuke that, then make install so all we're left with is the extension +rm -rf ${OUT_PREFIX}/* +make install -s +strip --strip-unneeded ${OUT_PREFIX}/lib/php/extensions/*/*.so +popd + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\"}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +python $(dirname $BASH_SOURCE)/../../_util/include/manifest.py "heroku-sys-package" "heroku-sys/pkg-ext-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-bare-2.2.0 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-bare-2.2.0 new file mode 100755 index 0000000..48de658 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/memcached-bare-2.2.0 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38, libraries/libmemcached-1.0.18 + +source $(dirname $0)/memcached-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongo b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongo new file mode 100755 index 0000000..58fb390 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongo @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +dep_name=$(basename $BASH_SOURCE) + +source $(dirname $BASH_SOURCE)/../pecl diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongo-1.6.14 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongo-1.6.14 new file mode 100755 index 0000000..9316497 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongo-1.6.14 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38 + +source $(dirname $0)/mongo diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongodb b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongodb new file mode 100755 index 0000000..58fb390 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongodb @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +dep_name=$(basename $BASH_SOURCE) + +source $(dirname $BASH_SOURCE)/../pecl diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongodb-1.2.5 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongodb-1.2.5 new file mode 100755 index 0000000..6d7e8f6 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/mongodb-1.2.5 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38 + +source $(dirname $0)/mongodb diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/newrelic b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/newrelic new file mode 100755 index 0000000..2038d02 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/newrelic @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../../_util/include/manifest.sh + +OUT_PREFIX=$1 + +ZEND_MODULE_API_VERSION=$(basename $(dirname $0)) +ZEND_MODULE_API_VERSION=${ZEND_MODULE_API_VERSION#no-debug-non-zts-} + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=ext-${dep_name}-${dep_version} +dep_dirname=newrelic-php5-${dep_version}-linux +dep_archive_name=${dep_dirname}.tar.gz +dep_url=https://download.newrelic.com/php_agent/archive/${dep_version}/${dep_archive_name} +case ${ZEND_MODULE_API_VERSION} in + 20121212) + series=5.5 + ;; + 20131226) + series=5.6 + ;; + 20151012) + series=7.0 + ;; + 20160303) + series=7.1 + ;; +esac +dep_manifest=${dep_package}_php-$series.composer.json + +echo "-----> Packaging ${dep_package}..." + +curl -L ${dep_url} | tar xz + +pushd ${dep_dirname} +ext_dir=${OUT_PREFIX}/lib/php/extensions/no-debug-non-zts-${ZEND_MODULE_API_VERSION} +bin_dir=${OUT_PREFIX}/bin +mkdir -p ${ext_dir} +mkdir -p ${bin_dir} +cp agent/x64/newrelic-${ZEND_MODULE_API_VERSION}.so ${ext_dir}/newrelic.so +cp daemon/newrelic-daemon.x64 ${bin_dir}/newrelic-daemon +find ${OUT_PREFIX} -type f \( -executable -o -name '*.a' \) -exec sh -c "file -i '{}' | grep -Eq 'application/x-(archive|executable|sharedlib); charset=binary'" \; -print | xargs strip --strip-unneeded +popd + +mkdir -p ${OUT_PREFIX}/bin +# gets sourced on dyno boot +cat > ${OUT_PREFIX}/bin/profile.newrelic.sh <<'EOF' +if [[ -n "$NEW_RELIC_LICENSE_KEY" ]]; then + if [[ -f "/app/.heroku/php/bin/newrelic-daemon" ]]; then + export NEW_RELIC_APP_NAME=${NEW_RELIC_APP_NAME:-${HEROKU_APP_NAME:-"PHP Application on Heroku"}} + export NEW_RELIC_LOG_LEVEL=${NEW_RELIC_LOG_LEVEL:-"warning"} + + # The daemon is a started in foreground mode so it will not daemonize + # (i.e. disassociate from the controlling TTY and disappear into the + # background). + # + # Perpetually tail and redirect the daemon log file to stderr so that it + # may be observed via 'heroku logs'. + touch /tmp/heroku.ext-newrelic.newrelic-daemon.${PORT}.log + tail -qF -n 0 /tmp/heroku.ext-newrelic.newrelic-daemon.${PORT}.log 1>&2 & + + # daemon start + /app/.heroku/php/bin/newrelic-daemon --foreground --logfile "/tmp/heroku.ext-newrelic.newrelic-daemon.${PORT}.log" --loglevel "${NEW_RELIC_LOG_LEVEL}" --pidfile "/tmp/newrelic-daemon.pid" & + + # give it a moment to connect + sleep 2 + else + echo >&2 "WARNING: Add-on 'newrelic' detected, but PHP extension not yet installed. Push an update to the application to finish installation of the add-on; an empty change ('git commit --allow-empty') is sufficient." + fi +fi +EOF +mkdir -p ${OUT_PREFIX}/etc/php/conf.d +cat > ${OUT_PREFIX}/etc/php/conf.d/newrelic.ini-dist <<'EOF' +extension = newrelic.so + +newrelic.daemon.location = /app/.heroku/php/bin/newrelic-daemon + +newrelic.loglevel = ${NEW_RELIC_LOG_LEVEL} +newrelic.daemon.loglevel = ${NEW_RELIC_LOG_LEVEL} + +newrelic.license = ${NEW_RELIC_LICENSE_KEY} +newrelic.appname = ${NEW_RELIC_APP_NAME} +newrelic.logfile = stderr ; the stdout default messes up boots as we capture output for crash detection + +; The daemon gets spawned by the PHP agent and is configured with the same values +; +; There is code in bin/compile to create .profile.d/newrelic.sh. That script +; starts the daemon and runs a perpetual tail command which will redirect daemon +; logs to stderr so that it may be observed via 'heroku logs'. +newrelic.daemon.logfile = /tmp/heroku.ext-newrelic.newrelic-daemon.${PORT}.log + +; or else: +; 2015-05-18 13:00:43.144 (28 28) warning: unable to find suitable pidfile location, using none +newrelic.daemon.pidfile = /tmp/newrelic-daemon.pid +EOF + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\"}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{\"config\":\"etc/php/conf.d/newrelic.ini-dist\",\"profile\":\"bin/profile.newrelic.sh\"}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +python $(dirname $BASH_SOURCE)/../../_util/include/manifest.py "heroku-sys-php-extension" "heroku-sys/ext-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/newrelic-6.9.0.182 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/newrelic-6.9.0.182 new file mode 100755 index 0000000..04e8b30 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/newrelic-6.9.0.182 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/newrelic diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/oauth b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/oauth new file mode 100755 index 0000000..58fb390 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/oauth @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +dep_name=$(basename $BASH_SOURCE) + +source $(dirname $BASH_SOURCE)/../pecl diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/oauth-1.2.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/oauth-1.2.3 new file mode 100755 index 0000000..58ec38f --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/oauth-1.2.3 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38 + +source $(dirname $0)/oauth diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon new file mode 100755 index 0000000..417493d --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../../_util/include/manifest.sh + +OUT_PREFIX=$1 + +export PATH=${OUT_PREFIX}/bin:${PATH} + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=ext-${dep_name}-${dep_version} +if [[ "$dep_version" == 2.* ]]; then + dep_dirname=cphalcon-${dep_name}-v${dep_version} + dep_archive_name=${dep_name}-v${dep_version}.tar.gz +else + dep_dirname=cphalcon-${dep_version} + dep_archive_name=v${dep_version}.tar.gz +fi +dep_url=https://github.com/phalcon/cphalcon/archive/${dep_archive_name} +series=$(php-config --version | cut -d. -f1,2) # get "5.5", "5.6", "7.0" etc for the php requirement in the manifest +dep_manifest=${dep_package}_php-$series.composer.json + +echo "-----> Building ${dep_package}..." + +curl -L ${dep_url} | tar xz + +if [[ "$dep_version" == 2.* ]]; then + workdir=64bits +else + workdir=php${series:0:1}/64bits +fi +pushd ${dep_dirname} +pushd build +pushd ${workdir} +export CC="gcc" +export CFLAGS="-O2 -fvisibility=hidden" +export CPPFLAGS="-DPHALCON_RELEASE" +phpize +./configure --prefix=${OUT_PREFIX} --enable-phalcon +make -s -j9 +# php was a build dep, and it's in $OUT_PREFIX. nuke that, then make install so all we're left with is the extension +rm -rf ${OUT_PREFIX}/* +make install -s +popd +popd +strip --strip-unneeded ${OUT_PREFIX}/lib/php/extensions/*/*.so +popd + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\"}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +python $(dirname $BASH_SOURCE)/../../_util/include/manifest.py "heroku-sys-php-extension" "heroku-sys/ext-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon-2.0.13 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon-2.0.13 new file mode 100755 index 0000000..397c478 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon-2.0.13 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38 + +source $(dirname $0)/phalcon diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon-3.0.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon-3.0.3 new file mode 100755 index 0000000..397c478 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/phalcon-3.0.3 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38 + +source $(dirname $0)/phalcon diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/pq b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/pq new file mode 100755 index 0000000..c804b2c --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/pq @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +dep_name=$(basename $BASH_SOURCE) + +OUT_PREFIX=$1 +export PATH=${OUT_PREFIX}/bin:${PATH} + +# raphf needs to be loaded at build time +echo 'extension=raphf.so' > ${OUT_PREFIX}/etc/php/conf.d/raphf.ini + +# we need to declare the right version of raphf as required +dep_formula=${0#$WORKSPACE_DIR/} +dep_version=${dep_formula##*"/${dep_name}-"} +series=$(php-config --version | cut -d. -f1,2) # get "5.5", "5.6", "7.0" etc for the php requirement in the manifest +case "$dep_version" in + 1.*) + MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\",\"heroku-sys/ext-raphf\":\"^1.1.0\",\"heroku-sys/ext-json\":\"*\",\"heroku-sys/ext-spl\":\"*\"}"}" + ;; + *) + MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\",\"heroku-sys/ext-raphf\":\">=2.0.0\",\"heroku-sys/ext-json\":\"*\",\"heroku-sys/ext-spl\":\"*\"}"}" + ;; +esac + +source $(dirname $BASH_SOURCE)/../pecl diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/pq-1.1.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/pq-1.1.1 new file mode 100755 index 0000000..5cf133f --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/pq-1.1.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38, extensions/no-debug-non-zts-20121212/raphf-1.1.2 + +source $(dirname $0)/pq diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/raphf b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/raphf new file mode 100755 index 0000000..58fb390 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/raphf @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +dep_name=$(basename $BASH_SOURCE) + +source $(dirname $BASH_SOURCE)/../pecl diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/raphf-1.1.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/raphf-1.1.2 new file mode 100755 index 0000000..35c4aba --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/raphf-1.1.2 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38 + +source $(dirname $0)/raphf diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka new file mode 100755 index 0000000..62e45d0 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../../_util/include/manifest.sh + +OUT_PREFIX=$1 + +ZEND_MODULE_API_VERSION=$(basename $(dirname $0)) +ZEND_MODULE_API_VERSION=${ZEND_MODULE_API_VERSION#no-debug-non-zts-} + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=ext-${dep_name}-${dep_version} +case ${ZEND_MODULE_API_VERSION} in + 20121212) + series=5.5 + ;; + 20131226) + series=5.6 + ;; + 20151012) + series=7.0 + ;; + 20160303) + series=7.1 + ;; +esac +dep_manifest=${dep_package}_php-$series.composer.json + +echo "-----> Merging dependencies..." + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\"}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +python $(dirname $BASH_SOURCE)/../../_util/include/manifest.py "heroku-sys-php-extension" "heroku-sys/ext-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-3.0.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-3.0.1 new file mode 100755 index 0000000..99c200d --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-3.0.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20121212/rdkafka-bare-3.0.1, libraries/librdkafka-0.9.3 + +source $(dirname $0)/rdkafka diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-bare b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-bare new file mode 100755 index 0000000..64320f3 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-bare @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../../_util/include/manifest.sh + +OUT_PREFIX=$1 + +export PATH=${OUT_PREFIX}/bin:${PATH} + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=pkg-ext-${dep_name}-${dep_version} +dep_dirname=rdkafka-${dep_version} +dep_archive_name=${dep_dirname}.tgz +dep_url=https://pecl.php.net/get/${dep_archive_name} +series=$(php-config --version | cut -d. -f1,2) # get "5.5", "5.6", "7.0" etc for the php requirement in the manifest +dep_manifest=${dep_package}_php-$series.composer.json + +echo "-----> Building ${dep_package} (from PECL)..." + +curl -L ${dep_url} | tar xz + +pushd ${dep_dirname} +phpize +./configure \ + --prefix=${OUT_PREFIX} \ + --with-rdkafka=${OUT_PREFIX} +make -s -j 9 +# php was a build dep, and it's in $OUT_PREFIX. nuke that, then make install so all we're left with is the extension +rm -rf ${OUT_PREFIX}/* +make install -s +strip --strip-unneeded ${OUT_PREFIX}/lib/php/extensions/*/*.so +popd + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\"}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +python $(dirname $BASH_SOURCE)/../../_util/include/manifest.py "heroku-sys-php-package" "heroku-sys/ext-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-bare-3.0.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-bare-3.0.1 new file mode 100755 index 0000000..7f2a9ba --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/rdkafka-bare-3.0.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38, libraries/librdkafka-0.9.3 + +source $(dirname $0)/rdkafka-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/redis b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/redis new file mode 100755 index 0000000..58fb390 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/redis @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +dep_name=$(basename $BASH_SOURCE) + +source $(dirname $BASH_SOURCE)/../pecl diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/redis-3.1.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/redis-3.1.1 new file mode 100755 index 0000000..5148c25 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20121212/redis-3.1.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.5.38 + +source $(dirname $0)/redis diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/amqp b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/amqp new file mode 100755 index 0000000..ce331ed --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/amqp @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# let's see if librabbitmq is there +needed=( librabbitmq4 ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + echo "Need $missing"; exit 1; +fi + +# but do we need headers? +needed=( librabbitmq-dev ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + apt-get update -qq || { echo "Failed to 'apt-get update'. You must build this formula using Docker."; exit 1; } + apt-get install -q -y $missing +fi + +dep_name=$(basename $BASH_SOURCE) + +source $(dirname $BASH_SOURCE)/../pecl diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/amqp-1.8.0 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/amqp-1.8.0 new file mode 100755 index 0000000..9e3989e --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/amqp-1.8.0 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + +source $(dirname $0)/amqp diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/apcu-4.0.11 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/apcu-4.0.11 new file mode 100755 index 0000000..e3fac52 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/apcu-4.0.11 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + + +source $(dirname $0)/../no-debug-non-zts-20121212/apcu diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/blackfire b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/blackfire new file mode 100755 index 0000000..153289a --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/blackfire @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/../no-debug-non-zts-20121212/blackfire diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/blackfire-1.14.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/blackfire-1.14.3 new file mode 100755 index 0000000..e093375 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/blackfire-1.14.3 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/blackfire diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/cassandra-1.2.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/cassandra-1.2.2 new file mode 100755 index 0000000..e89ab76 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/cassandra-1.2.2 @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20131226/cassandra-bare-1.2.2, libraries/libcassandra-2.4.2 + +# That's it - we're combining the dep build and the extension build here + +source $(dirname $0)/../no-debug-non-zts-20121212/cassandra diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/cassandra-bare-1.2.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/cassandra-bare-1.2.2 new file mode 100755 index 0000000..47319c7 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/cassandra-bare-1.2.2 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30, libraries/libcassandra-2.4.2 + +source $(dirname $0)/../no-debug-non-zts-20121212/cassandra-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/ev-1.0.4 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/ev-1.0.4 new file mode 100755 index 0000000..3653cdb --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/ev-1.0.4 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + + +source $(dirname $0)/../no-debug-non-zts-20121212/ev diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/event-2.2.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/event-2.2.1 new file mode 100755 index 0000000..ee81f43 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/event-2.2.1 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + + +source $(dirname $0)/../no-debug-non-zts-20121212/event diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/imagick-3.4.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/imagick-3.4.3 new file mode 100755 index 0000000..a8a1d7f --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/imagick-3.4.3 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + + +source $(dirname $0)/../no-debug-non-zts-20121212/imagick diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/memcached-2.2.0 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/memcached-2.2.0 new file mode 100755 index 0000000..4a5d753 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/memcached-2.2.0 @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20131226/memcached-bare-2.2.0, libraries/libmemcached-1.0.18 + +# That's it - we're combining the dep build and the extension build here + +source $(dirname $0)/../no-debug-non-zts-20121212/memcached diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/memcached-bare-2.2.0 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/memcached-bare-2.2.0 new file mode 100755 index 0000000..fe23aa5 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/memcached-bare-2.2.0 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30, libraries/libmemcached-1.0.18 + +source $(dirname $0)/../no-debug-non-zts-20121212/memcached-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/mongo-1.6.14 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/mongo-1.6.14 new file mode 100755 index 0000000..9428b64 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/mongo-1.6.14 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + + +source $(dirname $0)/../no-debug-non-zts-20121212/mongo diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/mongodb-1.2.5 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/mongodb-1.2.5 new file mode 100755 index 0000000..59b93dc --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/mongodb-1.2.5 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + + +source $(dirname $0)/../no-debug-non-zts-20121212/mongodb diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/newrelic-6.9.0.182 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/newrelic-6.9.0.182 new file mode 100755 index 0000000..42faa75 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/newrelic-6.9.0.182 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/../no-debug-non-zts-20121212/newrelic diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/oauth-1.2.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/oauth-1.2.3 new file mode 100755 index 0000000..86fa52e --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/oauth-1.2.3 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + + +source $(dirname $0)/../no-debug-non-zts-20121212/oauth diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/phalcon-2.0.13 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/phalcon-2.0.13 new file mode 100755 index 0000000..f48e52a --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/phalcon-2.0.13 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + + +source $(dirname $0)/../no-debug-non-zts-20121212/phalcon diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/phalcon-3.0.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/phalcon-3.0.3 new file mode 100755 index 0000000..f48e52a --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/phalcon-3.0.3 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + + +source $(dirname $0)/../no-debug-non-zts-20121212/phalcon diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/pq-1.1.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/pq-1.1.1 new file mode 100755 index 0000000..0dabfb2 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/pq-1.1.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30, extensions/no-debug-non-zts-20131226/raphf-1.1.2 + +source $(dirname $0)/../no-debug-non-zts-20121212/pq diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/raphf-1.1.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/raphf-1.1.2 new file mode 100755 index 0000000..eaf3933 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/raphf-1.1.2 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + + +source $(dirname $0)/../no-debug-non-zts-20121212/raphf diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/rdkafka-3.0.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/rdkafka-3.0.1 new file mode 100755 index 0000000..f0c5706 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/rdkafka-3.0.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20131226/rdkafka-bare-3.0.1, libraries/librdkafka-0.9.3 + +source $(dirname $0)/../no-debug-non-zts-20121212/rdkafka diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/rdkafka-bare-3.0.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/rdkafka-bare-3.0.1 new file mode 100755 index 0000000..1bb96cc --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/rdkafka-bare-3.0.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30, libraries/librdkafka-0.9.3 + +source $(dirname $0)/../no-debug-non-zts-20121212/rdkafka-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/redis-3.1.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/redis-3.1.1 new file mode 100755 index 0000000..500aa0e --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20131226/redis-3.1.1 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-5.6.30 + + +source $(dirname $0)/../no-debug-non-zts-20121212/redis diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/amqp-1.8.0 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/amqp-1.8.0 new file mode 100755 index 0000000..6325f13 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/amqp-1.8.0 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16 + +source $(dirname $0)/../no-debug-non-zts-20131226/amqp diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/apcu b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/apcu new file mode 100755 index 0000000..87d8ace --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/apcu @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../../_util/include/manifest.sh + +OUT_PREFIX=$1 + +export PATH=${OUT_PREFIX}/bin:${PATH} + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=ext-${dep_name}-${dep_version} +dep_dirname=${dep_name}-${dep_version} +dep_archive_name=${dep_dirname}.tgz +dep_url=https://pecl.php.net/get/${dep_archive_name} +series=$(php-config --version | cut -d. -f1,2) # get "5.5", "5.6", "7.0" etc for the php requirement in the manifest +dep_manifest=${dep_package}_php-$series.composer.json + +echo "-----> Building ${dep_package} (from PECL)..." + +curl -L ${dep_url} | tar xz + +pushd ${dep_dirname} +phpize +./configure \ + --prefix=${OUT_PREFIX} \ + ${CONFIGURE_EXTRA:-} +make -s -j 9 +make install -s +popd + +dep2_name=apcu_bc +dep2_version=1.0.3 +dep2_dirname=${dep2_name}-${dep2_version} +dep2_archive_name=${dep2_dirname}.tgz +dep2_url=https://pecl.php.net/get/${dep2_archive_name} + +echo "-----> Building ${dep2_name}-${dep2_version} (from PECL)..." + +curl -L ${dep2_url} | tar xz + +pushd ${dep2_dirname} +phpize +./configure \ + --prefix=${OUT_PREFIX} +make -s -j 9 +# php was a build dep, and it's in $OUT_PREFIX. nuke that, then make install so all we're left with is the extension +rm -rf ${OUT_PREFIX}/* +make install -s +popd + +pushd ${dep_dirname} +# install again, we removed it earlier +make install -s +popd + +# cleanup +strip --strip-unneeded ${OUT_PREFIX}/lib/php/extensions/*/*.so + +mkdir -p ${OUT_PREFIX}/etc/php/conf.d +cat > ${OUT_PREFIX}/etc/php/conf.d/apcu-apc.ini-dist <<'EOF' +extension=apcu.so +extension=apc.so +EOF + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\"}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{\"config\":\"etc/php/conf.d/apcu-apc.ini-dist\"}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{\"heroku-sys/ext-apc\":\"self.version\"}"}" # despite version 1.0.3 or whatever, apcu_bc identifies itself using the apcu version number + +python $(dirname $BASH_SOURCE)/../../_util/include/manifest.py "heroku-sys-php-extension" "heroku-sys/ext-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/apcu-5.1.8 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/apcu-5.1.8 new file mode 100755 index 0000000..f57e007 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/apcu-5.1.8 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16 + +source $(dirname $0)/apcu diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/blackfire b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/blackfire new file mode 100755 index 0000000..153289a --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/blackfire @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/../no-debug-non-zts-20121212/blackfire diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/blackfire-1.14.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/blackfire-1.14.3 new file mode 100755 index 0000000..e093375 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/blackfire-1.14.3 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/blackfire diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/cassandra-1.2.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/cassandra-1.2.2 new file mode 100755 index 0000000..3ee5d4d --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/cassandra-1.2.2 @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20151012/cassandra-bare-1.2.2, libraries/libcassandra-2.4.2 + +# That's it - we're combining the dep build and the extension build here + +source $(dirname $0)/../no-debug-non-zts-20121212/cassandra diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/cassandra-bare-1.2.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/cassandra-bare-1.2.2 new file mode 100755 index 0000000..3ac47e1 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/cassandra-bare-1.2.2 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16, libraries/libcassandra-2.4.2 + +source $(dirname $0)/../no-debug-non-zts-20121212/cassandra-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/ev-1.0.4 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/ev-1.0.4 new file mode 100755 index 0000000..70f5eb0 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/ev-1.0.4 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16 + +source $(dirname $0)/../no-debug-non-zts-20121212/ev diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/event-2.2.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/event-2.2.1 new file mode 100755 index 0000000..5e47ea3 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/event-2.2.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16 + +source $(dirname $0)/../no-debug-non-zts-20121212/event diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/imagick-3.4.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/imagick-3.4.3 new file mode 100755 index 0000000..b0f2316 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/imagick-3.4.3 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16 + +source $(dirname $0)/../no-debug-non-zts-20121212/imagick diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/memcached-3.0.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/memcached-3.0.3 new file mode 100755 index 0000000..28bf3fc --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/memcached-3.0.3 @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20151012/memcached-bare-3.0.3, libraries/libmemcached-1.0.18 + +# That's it - we're combining the dep build and the extension build here + +source $(dirname $0)/../no-debug-non-zts-20121212/memcached diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/memcached-bare-3.0.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/memcached-bare-3.0.3 new file mode 100755 index 0000000..acff49b --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/memcached-bare-3.0.3 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16, libraries/libmemcached-1.0.18 + +source $(dirname $0)/../no-debug-non-zts-20121212/memcached-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/mongodb-1.2.5 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/mongodb-1.2.5 new file mode 100755 index 0000000..ead9d2d --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/mongodb-1.2.5 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16 + +source $(dirname $0)/../no-debug-non-zts-20121212/mongodb diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/newrelic-6.9.0.182 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/newrelic-6.9.0.182 new file mode 100755 index 0000000..42faa75 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/newrelic-6.9.0.182 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/../no-debug-non-zts-20121212/newrelic diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/oauth-2.0.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/oauth-2.0.2 new file mode 100755 index 0000000..ef56061 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/oauth-2.0.2 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16 + +source $(dirname $0)/../no-debug-non-zts-20121212/oauth diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/phalcon-3.0.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/phalcon-3.0.3 new file mode 100755 index 0000000..df79335 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/phalcon-3.0.3 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16 + +source $(dirname $0)/../no-debug-non-zts-20121212/phalcon diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/pq-2.1.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/pq-2.1.1 new file mode 100755 index 0000000..f6cb6be --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/pq-2.1.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16, extensions/no-debug-non-zts-20151012/raphf-2.0.0 + +source $(dirname $0)/../no-debug-non-zts-20121212/pq diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/raphf-2.0.0 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/raphf-2.0.0 new file mode 100755 index 0000000..69a505d --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/raphf-2.0.0 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16 + +source $(dirname $0)/../no-debug-non-zts-20121212/raphf diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/rdkafka-3.0.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/rdkafka-3.0.1 new file mode 100755 index 0000000..a62b7b5 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/rdkafka-3.0.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20151012/rdkafka-bare-3.0.1, libraries/librdkafka-0.9.3 + +source $(dirname $0)/../no-debug-non-zts-20121212/rdkafka diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/rdkafka-bare-3.0.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/rdkafka-bare-3.0.1 new file mode 100755 index 0000000..d42104c --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/rdkafka-bare-3.0.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16, libraries/librdkafka-0.9.3 + +source $(dirname $0)/../no-debug-non-zts-20121212/rdkafka-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/redis-3.1.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/redis-3.1.1 new file mode 100755 index 0000000..b0eacee --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20151012/redis-3.1.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.0.16 + +source $(dirname $0)/../no-debug-non-zts-20121212/redis diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/amqp-1.8.0 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/amqp-1.8.0 new file mode 100755 index 0000000..c829f4c --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/amqp-1.8.0 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2 + +source $(dirname $0)/../no-debug-non-zts-20131226/amqp diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/apcu-5.1.8 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/apcu-5.1.8 new file mode 100755 index 0000000..7091ed3 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/apcu-5.1.8 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2 + +source $(dirname $0)/../no-debug-non-zts-20151012/apcu diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/blackfire b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/blackfire new file mode 100755 index 0000000..153289a --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/blackfire @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/../no-debug-non-zts-20121212/blackfire diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/blackfire-1.14.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/blackfire-1.14.3 new file mode 100755 index 0000000..e093375 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/blackfire-1.14.3 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/blackfire diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/cassandra-1.2.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/cassandra-1.2.2 new file mode 100755 index 0000000..032a878 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/cassandra-1.2.2 @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20160303/cassandra-bare-1.2.2, libraries/libcassandra-2.4.2 + +# That's it - we're combining the dep build and the extension build here + +source $(dirname $0)/../no-debug-non-zts-20121212/cassandra diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/cassandra-bare-1.2.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/cassandra-bare-1.2.2 new file mode 100755 index 0000000..48699af --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/cassandra-bare-1.2.2 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2, libraries/libcassandra-2.4.2 + +source $(dirname $0)/../no-debug-non-zts-20121212/cassandra-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/ev-1.0.4 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/ev-1.0.4 new file mode 100755 index 0000000..965ebd1 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/ev-1.0.4 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2 + +source $(dirname $0)/../no-debug-non-zts-20121212/ev diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/event-2.2.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/event-2.2.1 new file mode 100755 index 0000000..d2dae01 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/event-2.2.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2 + +source $(dirname $0)/../no-debug-non-zts-20121212/event diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/imagick-3.4.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/imagick-3.4.3 new file mode 100755 index 0000000..9ef824d --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/imagick-3.4.3 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2 + +source $(dirname $0)/../no-debug-non-zts-20121212/imagick diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/memcached-3.0.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/memcached-3.0.3 new file mode 100755 index 0000000..e63d496 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/memcached-3.0.3 @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20160303/memcached-bare-3.0.3, libraries/libmemcached-1.0.18 + +# That's it - we're combining the dep build and the extension build here + +source $(dirname $0)/../no-debug-non-zts-20121212/memcached diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/memcached-bare-3.0.3 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/memcached-bare-3.0.3 new file mode 100755 index 0000000..6e899aa --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/memcached-bare-3.0.3 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2, libraries/libmemcached-1.0.18 + +source $(dirname $0)/../no-debug-non-zts-20121212/memcached-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/mongodb-1.2.5 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/mongodb-1.2.5 new file mode 100755 index 0000000..a3eee25 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/mongodb-1.2.5 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2 + +source $(dirname $0)/../no-debug-non-zts-20121212/mongodb diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/newrelic-6.9.0.182 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/newrelic-6.9.0.182 new file mode 100755 index 0000000..42faa75 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/newrelic-6.9.0.182 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/../no-debug-non-zts-20121212/newrelic diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/oauth-2.0.2 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/oauth-2.0.2 new file mode 100755 index 0000000..b14f774 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/oauth-2.0.2 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2 + +source $(dirname $0)/../no-debug-non-zts-20121212/oauth diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/pq-2.1.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/pq-2.1.1 new file mode 100755 index 0000000..78127e8 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/pq-2.1.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2, extensions/no-debug-non-zts-20160303/raphf-2.0.0 + +source $(dirname $0)/../no-debug-non-zts-20121212/pq diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/raphf-2.0.0 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/raphf-2.0.0 new file mode 100755 index 0000000..9e02c47 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/raphf-2.0.0 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2 + +source $(dirname $0)/../no-debug-non-zts-20121212/raphf diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/rdkafka-3.0.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/rdkafka-3.0.1 new file mode 100755 index 0000000..a62b7b5 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/rdkafka-3.0.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: extensions/no-debug-non-zts-20151012/rdkafka-bare-3.0.1, libraries/librdkafka-0.9.3 + +source $(dirname $0)/../no-debug-non-zts-20121212/rdkafka diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/rdkafka-bare-3.0.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/rdkafka-bare-3.0.1 new file mode 100755 index 0000000..325293c --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/rdkafka-bare-3.0.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2, libraries/librdkafka-0.9.3 + +source $(dirname $0)/../no-debug-non-zts-20121212/rdkafka-bare diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/redis-3.1.1 b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/redis-3.1.1 new file mode 100755 index 0000000..fc8e49c --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/no-debug-non-zts-20160303/redis-3.1.1 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: php-7.1.2 + +source $(dirname $0)/../no-debug-non-zts-20121212/redis diff --git a/vendor/heroku/heroku-buildpack-php/support/build/extensions/pecl b/vendor/heroku/heroku-buildpack-php/support/build/extensions/pecl new file mode 100755 index 0000000..e1365a2 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/extensions/pecl @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../_util/include/manifest.sh + +OUT_PREFIX=$1 + +export PATH=${OUT_PREFIX}/bin:${PATH} + +dep_formula=${0#$WORKSPACE_DIR/} +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=ext-${dep_name}-${dep_version} +dep_dirname=${dep_name}-${dep_version} +dep_archive_name=${dep_dirname}.tgz +dep_url=https://pecl.php.net/get/${dep_archive_name} +series=$(php-config --version | cut -d. -f1,2) # get "5.5", "5.6", "7.0" etc for the php requirement in the manifest +dep_manifest=${dep_package}_php-$series.composer.json + +echo "-----> Building ${dep_package} (from PECL)..." + +curl -L ${dep_url} | tar xz + +pushd ${dep_dirname} +phpize +./configure \ + --prefix=${OUT_PREFIX} \ + ${CONFIGURE_EXTRA:-} +make -s -j 9 +# php was a build dep, and it's in $OUT_PREFIX. nuke that, then make install so all we're left with is the extension +rm -rf ${OUT_PREFIX}/* +make install -s +strip --strip-unneeded ${OUT_PREFIX}/lib/php/extensions/*/*.so +popd + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{\"heroku-sys/php\":\"${series}.*\"}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +python $(dirname $BASH_SOURCE)/../_util/include/manifest.py "heroku-sys-php-extension" "heroku-sys/ext-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/hhvm b/vendor/heroku/heroku-buildpack-php/support/build/hhvm new file mode 100755 index 0000000..55e0675 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/hhvm @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/_util/include/manifest.sh + +OUT_PREFIX=$1 + +STACK=${STACK:-"cedar"} + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula#"${dep_name}-"} +dep_package=${dep_name}-${dep_version} +dep_dirname=hhvm_${dep_version} +if [[ $STACK == "cedar" ]]; then + dep_archive_name=${dep_dirname}~lucid_amd64.deb +else + dep_archive_name=${dep_dirname}~trusty_amd64.deb +fi +dep_url=http://dl.hhvm.com/ubuntu/pool/main/h/hhvm/${dep_archive_name} +dep_manifest=${dep_package}.composer.json + +echo "-----> Building ${dep_package}..." + +mkdir -p $OUT_PREFIX + +if [[ $STACK == "cedar" ]]; then + deps="${dep_url} +http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu/pool/main/b/binutils/binutils_2.22-4ubuntu1~10.04.1_amd64.deb +http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu/pool/main/g/gcc-4.8/libstdc++6_4.8.1-2ubuntu1~10.04.1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/universe/t/tbb/libtbb2_2.2+r009-1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/universe/libo/libonig/libonig2_5.9.1-1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/universe/libm/libmcrypt/libmcrypt4_2.5.8-3.1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/universe/u/uw-imap/libc-client2007e_2007e~dfsg-3.1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/e/elfutils/libelf1_0.143-1_amd64.deb" +else + deps="${dep_url} +http://mirrors.kernel.org/ubuntu/pool/main/b/boost1.54/libboost-filesystem1.54.0_1.54.0-4ubuntu3.1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/b/boost1.54/libboost-program-options1.54.0_1.54.0-4ubuntu3.1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/b/boost1.54/libboost-regex1.54.0_1.54.0-4ubuntu3.1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/b/boost1.54/libboost-system1.54.0_1.54.0-4ubuntu3.1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/b/boost1.54/libboost-thread1.54.0_1.54.0-4ubuntu3.1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/universe/u/uw-imap/libc-client2007e_2007f~dfsg-4_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/e/elfutils/libelf1_0.160-0ubuntu3_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/g/gflags/libgflags2_2.0-2.1build1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/g/google-glog/libgoogle-glog0_0.3.3-2build1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/i/icu/libicu52_52.1-8_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/universe/j/jemalloc/libjemalloc1_3.6.0-9ubuntu1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/universe/libm/libmcrypt/libmcrypt4_2.5.8-3.3_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/libm/libmemcached/libmemcached10_1.0.8-1ubuntu2_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/universe/libo/libonig/libonig2_5.9.6-1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/g/gcc-4.9/libstdc%2b%2b6_4.9.2-10ubuntu13_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/universe/t/tbb/libtbb2_4.3~20150316-0ubuntu1_amd64.deb +http://mirrors.kernel.org/ubuntu/pool/main/libu/libunwind/libunwind8_1.1-3.2_amd64.deb" +fi + +for dep in $deps; do + depb=$(basename $dep) + echo " - $depb" + curl -LO $dep + dpkg -x $depb ${OUT_PREFIX} +done +strip --strip-unneeded ${OUT_PREFIX}/usr/bin/* + +export LD_LIBRARY_PATH=/app/.heroku/php/usr/lib/x86_64-linux-gnu:/app/.heroku/php/usr/lib/hhvm:/app/.heroku/php/usr/lib +export PATH=/app/.heroku/php/usr/bin:$PATH +echo "-----> Generating manifest..." +curl -sS https://getcomposer.org/installer | hhvm --php + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/php\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{\"export\":\"bin/export.hhvm.sh\",\"profile\":\"bin/profile.hhvm.sh\"}"}" +MANIFEST_REPLACE=$(hhvm --php composer.phar show --platform | grep -E '^(ext-\S+|php-64bit\b|php\b)' | tr -s " " | cut -d " " -f1,2 | sed -e "s/ $dep_version\$/ self.version/" -e 's/^/heroku-sys\//' | python -c 'import sys, json; json.dump(dict(item.split() for item in sys.stdin), sys.stdout)') + +# remove temporary composer download +rm composer.phar + +mkdir -p ${OUT_PREFIX}/bin +# this gets sourced after package install, so that the buildpack and following buildpacks can invoke +cat > ${OUT_PREFIX}/bin/export.hhvm.sh <<'EOF' +export LD_LIBRARY_PATH=$HOME/.heroku/php/usr/lib/x86_64-linux-gnu:$HOME/.heroku/php/usr/lib/hhvm:$HOME/.heroku/php/usr/lib +export PATH="$PATH:/app/.heroku/php/usr/bin" +EOF +# this gets sourced on dyno boot +cat > ${OUT_PREFIX}/bin/profile.hhvm.sh <<'EOF' +export PATH="$PATH:$HOME/.heroku/php/usr/bin" +hhvm() { LD_LIBRARY_PATH=$HOME/.heroku/php/usr/lib/x86_64-linux-gnu:$HOME/.heroku/php/usr/lib/hhvm:$HOME/.heroku/php/usr/lib $(which hhvm) "$@"; } +export -f hhvm +composer() { hhvm $(which composer) "$@"; } +export -f composer +EOF + +python $(dirname $BASH_SOURCE)/_util/include/manifest.py "heroku-sys-hhvm" "heroku-sys/${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/hhvm-3.5.1 b/vendor/heroku/heroku-buildpack-php/support/build/hhvm-3.5.1 new file mode 100755 index 0000000..3a74791 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/hhvm-3.5.1 @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# Depends: +# binutils +# libasn1-8-heimdal +# libboost-filesystem1.54.0 +# libboost-program-options1.54.0 +# libboost-regex1.54.0 +# libboost-system1.54.0 +# libboost-system1.54.0 +# libboost-thread1.54.0 +# libbz2-1.0 +# libc-client2007e +# libc6 +# libcap2 +# libcomerr2 +# libcurl3 (>= 7.28.0) +# libedit2 +# libelf1 +# libevent-2.0-5 +# libexpat1 +# libfontconfig1 +# libfreetype6 +# libgcc1 +# libgcrypt11 +# libgd3 +# libgmp10 +# libgnutls26 +# libgoogle-glog0 (>= 0.3.1) +# libgpg-error0 +# libgssapi-krb5-2 +# libgssapi3-heimdal +# libhcrypto4-heimdal +# libheimbase1-heimdal +# libheimntlm0-heimdal +# libhx509-5-heimdal +# libicu52 +# libidn11 +# libjemalloc1 (>= 3.0.0) +# libjpeg-turbo8 +# libk5crypto3 +# libkeyutils1 +# libkrb5-26-heimdal +# libkrb5-3 +# libkrb5support0 +# libldap-2.4-2 +# libmagickwand5 +# libmcrypt4 +# libmemcached10 +# libmysqlclient18 +# libonig2 +# libp11-kit0 +# libpam0g +# libpcre3 +# libpng12-0 +# libroken18-heimdal +# librtmp0 +# libsasl2-2 +# libsqlite3-0 +# libssl1.0.0 +# libstdc++6 +# libtasn1-6 +# libtbb2 +# libtinfo5 +# libwind0-heimdal +# libx11-6 +# libxau6 +# libxcb1 +# libxdmcp6 +# libxml2 +# libxpm4 +# libxslt1.1 +# zlib1g + +source $(dirname $0)/hhvm diff --git a/vendor/heroku/heroku-buildpack-php/support/build/libraries/libc-client b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libc-client new file mode 100755 index 0000000..3b874c1 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libc-client @@ -0,0 +1,46 @@ +#!/bin/bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../_util/include/manifest.sh + +OUT_PREFIX=$1 + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=pkg-${dep_name}-${dep_version} +dep_dirname=imap-${dep_version} +dep_archive_name=${dep_dirname}.tar.gz +dep_url=ftp://ftp.cac.washington.edu/imap/${dep_archive_name} +dep_manifest=${dep_package}.composer.json + +echo "-----> Building ${dep_package}..." + +# we need that for IMAP +needed=( libpam0g-dev ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + apt-get update -qq || { echo "Failed to 'apt-get update'. You must build this formula using Docker."; exit 1; } + apt-get install -q -y $missing +fi + +curl -L ${dep_url} | tar xz + +pushd ${dep_dirname} +touch ip6 # so we do not get prompted +make ldb EXTRACFLAGS=-fPIC # need PIC so relocations work in the shared imap.so ext later +mkdir -p ${OUT_PREFIX}/opt/${dep_dirname}/include ${OUT_PREFIX}/opt/${dep_dirname}/lib +cp c-client/*.h ${OUT_PREFIX}/opt/${dep_dirname}/include +cp c-client/*.c ${OUT_PREFIX}/opt/${dep_dirname}/lib +cp c-client/*.a ${OUT_PREFIX}/opt/${dep_dirname}/lib +strip --strip-unneeded ${OUT_PREFIX}/opt/${dep_dirname}/lib/*.a +popd + +python $(dirname $BASH_SOURCE)/../_util/include/manifest.py "heroku-sys-package" "heroku-sys/pkg-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/libraries/libc-client-2007f b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libc-client-2007f new file mode 100755 index 0000000..e81fadd --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libc-client-2007f @@ -0,0 +1,4 @@ +#!/bin/bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/libc-client diff --git a/vendor/heroku/heroku-buildpack-php/support/build/libraries/libcassandra b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libcassandra new file mode 100755 index 0000000..93744ed --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libcassandra @@ -0,0 +1,43 @@ +#!/bin/bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../_util/include/manifest.sh + +OUT_PREFIX=$1 + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=pkg-${dep_name}-${dep_version} +dep_dirname=cpp-driver-${dep_version} +dep_archive_name=${dep_version}.tar.gz +dep_url=https://github.com/datastax/cpp-driver/archive/${dep_version}.tar.gz +dep_manifest=${dep_package}.composer.json + +# we need libgmp-dev and cmake +needed=( libgmp-dev cmake ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + apt-get update -qq || { echo "Failed to 'apt-get update'. You must build this formula using Docker."; exit 1; } + apt-get install -q -y $missing +fi + +echo "-----> Building ${dep_package}..." + +curl -L ${dep_url} | tar xz +pushd ${dep_dirname} +cmake -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_INSTALL_PREFIX:PATH=${OUT_PREFIX} -DCMAKE_BUILD_TYPE=RELEASE -DCASS_USE_ZLIB=ON -DCMAKE_INSTALL_LIBDIR:PATH=lib . +make -s -j9 +make install -s +rm ${OUT_PREFIX}/lib/libcassandra_static.a +strip --strip-unneeded ${OUT_PREFIX}/lib/libcassandra*.so* +popd + +python $(dirname $BASH_SOURCE)/../_util/include/manifest.py "heroku-sys-package" "heroku-sys/pkg-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/libraries/libcassandra-2.4.2 b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libcassandra-2.4.2 new file mode 100755 index 0000000..78a8d18 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libcassandra-2.4.2 @@ -0,0 +1,4 @@ +#!/bin/bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/libcassandra diff --git a/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmcrypt b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmcrypt new file mode 100755 index 0000000..4c35f18 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmcrypt @@ -0,0 +1,44 @@ +#!/bin/bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../_util/include/manifest.sh + +OUT_PREFIX=$1 + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=pkg-${dep_name}-${dep_version} +dep_dirname=${dep_name}-${dep_version} +dep_archive_name=${dep_dirname}.tar.gz +dep_url=https://downloads.sourceforge.net/project/mcrypt/Libmcrypt/${dep_version}/${dep_archive_name} +dep_manifest=${dep_package}.composer.json + +# skip build if already present +needed=( libmcrypt4 ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) + +if [[ "$missing" ]]; then + echo "-----> Building ${dep_package}..." + + curl -L ${dep_url} | tar xz + + pushd ${dep_dirname} + ./configure --disable-posix-threads --prefix=${OUT_PREFIX} + make -s -j 9 + make install-strip -s + popd + + rm -rf ${OUT_PREFIX}/man +else + echo "-----> System ${dep_name} available, creating empty package..." +fi + +python $(dirname $BASH_SOURCE)/../_util/include/manifest.py "heroku-sys-package" "heroku-sys/pkg-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmcrypt-2.5.8 b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmcrypt-2.5.8 new file mode 100755 index 0000000..4f23e8f --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmcrypt-2.5.8 @@ -0,0 +1,4 @@ +#!/bin/bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/libmcrypt diff --git a/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmemcached b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmemcached new file mode 100755 index 0000000..6d161b2 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmemcached @@ -0,0 +1,57 @@ +#!/bin/bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../_util/include/manifest.sh + +OUT_PREFIX=$1 + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=pkg-${dep_name}-${dep_version} +dep_dirname=${dep_name}-${dep_version} +dep_archive_name=${dep_dirname}.tar.gz +dep_url=https://launchpad.net/libmemcached/1.0/${dep_version}/+download/${dep_archive_name} +dep_manifest=${dep_package}.composer.json + +# can't build without this +needed=( libsasl2-2 ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + echo "Error! Missing libraries: $missing" + exit 1 +fi + +# skip build if already present +needed=( libmemcached11 ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + # we need libsasl2-dev + needed=( libsasl2-dev ) + missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) + if [[ "$missing" ]]; then + apt-get update -qq || { echo "Failed to 'apt-get update'. You must build this formula using Docker."; exit 1; } + apt-get install -q -y $missing + fi + echo "-----> Building ${dep_package}..." + + curl -L ${dep_url} | tar xz + pushd ${dep_dirname} + ./configure --prefix=${OUT_PREFIX} --without-memcached --disable-static + make -s -j 9 + make install-strip -s + popd + + rm -rf ${OUT_PREFIX}/share/man +else + echo "-----> System ${dep_name} available, creating empty package..." +fi + +python $(dirname $BASH_SOURCE)/../_util/include/manifest.py "heroku-sys-package" "heroku-sys/pkg-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmemcached-1.0.18 b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmemcached-1.0.18 new file mode 100755 index 0000000..4495a90 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/libraries/libmemcached-1.0.18 @@ -0,0 +1,4 @@ +#!/bin/bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/libmemcached diff --git a/vendor/heroku/heroku-buildpack-php/support/build/libraries/librdkafka b/vendor/heroku/heroku-buildpack-php/support/build/libraries/librdkafka new file mode 100755 index 0000000..007eaf5 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/libraries/librdkafka @@ -0,0 +1,42 @@ +#!/bin/bash + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/../_util/include/manifest.sh + +OUT_PREFIX=$1 + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula##*"/${dep_name}-"} +dep_package=pkg-${dep_name}-${dep_version} +dep_dirname=librdkafka-${dep_version} +dep_archive_name=v${dep_version}.tar.gz +dep_url=https://github.com/edenhill/librdkafka/archive/${dep_archive_name} +dep_manifest=${dep_package}.composer.json + +# we need libsasl2-dev +needed=( libsasl2-dev ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + apt-get update -qq || { echo "Failed to 'apt-get update'. You must build this formula using Docker."; exit 1; } + apt-get install -q -y $missing +fi + +echo "-----> Building ${dep_package}..." + +curl -L ${dep_url} | tar xz +pushd ${dep_dirname} +./configure --prefix=${OUT_PREFIX} +make -s -j9 +make install -s +rm ${OUT_PREFIX}/lib/*.a +find ${OUT_PREFIX} -type f \( -executable -o -name '*.a' \) -exec sh -c "file -i '{}' | grep -Eq 'application/x-(archive|executable|sharedlib); charset=binary'" \; -print | xargs strip --strip-unneeded +popd + +python $(dirname $BASH_SOURCE)/../_util/include/manifest.py "heroku-sys-package" "heroku-sys/pkg-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/libraries/librdkafka-0.9.3 b/vendor/heroku/heroku-buildpack-php/support/build/libraries/librdkafka-0.9.3 new file mode 100755 index 0000000..89ee181 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/libraries/librdkafka-0.9.3 @@ -0,0 +1,4 @@ +#!/bin/bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/librdkafka diff --git a/vendor/heroku/heroku-buildpack-php/support/build/nginx b/vendor/heroku/heroku-buildpack-php/support/build/nginx new file mode 100755 index 0000000..0e152c3 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/nginx @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +OUT_PREFIX=$1 + +source $(dirname $BASH_SOURCE)/_util/include/manifest.sh + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula#"${dep_name}-"} +dep_package=${dep_name}-${dep_version} +dep_dirname=nginx-${dep_version} +dep_archive_name=${dep_dirname}.tar.gz +dep_url=https://nginx.org/download/${dep_archive_name} +dep_manifest=${dep_package}.composer.json + +echo "-----> Building ${dep_package}..." + +curl -L ${dep_url} | tar xz + +pushd ${dep_dirname} +ETC=${OUT_PREFIX}/etc +VAR=${OUT_PREFIX}/var +./configure \ + --prefix=${OUT_PREFIX} \ + --conf-path=${ETC}/nginx/nginx.conf \ + --pid-path=${VAR}/run/nginx.pid \ + --lock-path=${VAR}/run/nginx.lock \ + --http-client-body-temp-path=${VAR}/run/nginx/client_body_temp \ + --http-proxy-temp-path=${VAR}/run/nginx/proxy_temp \ + --http-fastcgi-temp-path=${VAR}/run/nginx/fastcgi_temp \ + --http-uwsgi-temp-path=${VAR}/run/nginx/uwsgi_temp \ + --http-scgi-temp-path=${VAR}/run/nginx/scgi_temp \ + --http-log-path=${VAR}/log/nginx/access.log \ + --error-log-path=${VAR}/log/nginx/error.log \ + --with-http_realip_module +make -s -j 9 +make install -s +find ${OUT_PREFIX} -type f \( -executable -o -name '*.a' \) -exec sh -c "file -i '{}' | grep -Eq 'application/x-(archive|executable|sharedlib); charset=binary'" \; -print | xargs strip --strip-unneeded +popd + +# this doesn't get created +mkdir -p ${VAR}/run/nginx + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"{\"export\":\"bin/export.nginx.sh\",\"profile\":\"bin/profile.nginx.sh\"}"}" +MANIFEST_REPLACE="${MANIFEST_REPLACE:-"{}"}" + +mkdir -p ${OUT_PREFIX}/etc/nginx +cp $(dirname $BASH_SOURCE)/_conf/nginx/nginx.conf ${OUT_PREFIX}/etc/nginx/nginx.conf + +mkdir -p ${OUT_PREFIX}/bin +# this gets sourced after package install, so that the buildpack and following buildpacks can invoke +cat > ${OUT_PREFIX}/bin/export.nginx.sh <<'EOF' +export PATH="/app/.heroku/php/bin:/app/.heroku/php/sbin:$PATH" +EOF +# this gets sourced on dyno boot +cat > ${OUT_PREFIX}/bin/profile.nginx.sh <<'EOF' +export PATH="$HOME/.heroku/php/bin:$HOME/.heroku/php/sbin:$PATH" +EOF + +python $(dirname $BASH_SOURCE)/_util/include/manifest.py "heroku-sys-webserver" "heroku-sys/${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/nginx-1.8.1 b/vendor/heroku/heroku-buildpack-php/support/build/nginx-1.8.1 new file mode 100755 index 0000000..b696276 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/nginx-1.8.1 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/nginx diff --git a/vendor/heroku/heroku-buildpack-php/support/build/php b/vendor/heroku/heroku-buildpack-php/support/build/php new file mode 100755 index 0000000..5cbd4ea --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/php @@ -0,0 +1,199 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/_util/include/manifest.sh + +OUT_PREFIX=$1 + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula#"${dep_name}-"} +dep_package=${dep_name}-${dep_version} +dep_dirname=php-${dep_version} +dep_archive_name=${dep_dirname}.tar.gz +if [[ $dep_version == *alpha* ]] || [[ $dep_version == *beta* ]] || [[ $dep_version == *RC* ]]; then + if [[ $dep_version == 5.5.* ]]; then + dep_url=https://downloads.php.net/~jpauli/${dep_archive_name} + elif [[ $dep_version == 5.6.* ]]; then + dep_url=https://downloads.php.net/~tyrael/${dep_archive_name} + elif [[ $dep_version == 7.0.* ]]; then + dep_url=https://downloads.php.net/~ab/${dep_archive_name} + elif [[ $dep_version == 7.1.* ]]; then + dep_url=https://downloads.php.net/~krakjoe/${dep_archive_name} + fi +else + dep_url=https://php.net/get/${dep_archive_name}/from/this/mirror +fi +dep_manifest=${dep_package}.composer.json + +echo "-----> Building ${dep_package}..." + +curl -L ${dep_url} | tar xz + +pushd ${dep_dirname} + +libicu="libicu55" +if [[ $STACK == "cedar-14" ]]; then + libicu="libicu52" +fi +# we need libgmp for GMP, libpam0g for IMAP, libicu for intl, libsasl2/krb/ldap for LDAP +needed=( libgmp10 libpam0g $libicu libsasl2-2 libkrb5-3 libldap-2.4-2 ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + echo "Error! Missing libraries: $missing" + exit 1 +fi +# we need libgmp-dev for GMP, libpam0g-dev for IMAP, libicu-dev for intl, libsasl2/krb5/ldap2-dev for LDAP +needed=( libgmp-dev libpam0g-dev libicu-dev libsasl2-dev libkrb5-dev libldap2-dev ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + apt-get update -qq || { echo "Failed to 'apt-get update'. You must build this formula using Docker."; exit 1; } + apt-get install -q -y $missing +fi + +# look for GMP libs in /usr/lib/x86_64-linux-gnu and not /usr/lib +sed -i 's/$GMP_DIR\/$PHP_LIBDIR/$GMP_DIR\/$PHP_LIBDIR\/x86_64-linux-gnu/' configure +# symlink in gmp.h +ln -s /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h + +# look for LDAP and SASL libs in /usr/lib/x86_64-linux-gnu and not /usr/lib +sed -i 's/LDAP_LIBDIR=$i\/$PHP_LIBDIR/LDAP_LIBDIR=$i\/$PHP_LIBDIR\/x86_64-linux-gnu/' configure +sed -i 's/LDAP_SASL_LIBDIR=$LDAP_SASL_DIR\/$PHP_LIBDIR/LDAP_SASL_LIBDIR=$LDAP_SASL_DIR\/$PHP_LIBDIR\/x86_64-linux-gnu/' configure + +# let's see if mcrypt is there, if not then we have to use the vendored one +needed=( libmcrypt4 ) +missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) +if [[ "$missing" ]]; then + echo "Using vendored libmcrypt..." + # use vendored libmcrypt + mcrypt_prefix="${OUT_PREFIX}" +else + echo "Using system libmcrypt..." + # use system libmcrypt + mcrypt_prefix= + # but do we need headers? + needed=( libmcrypt-dev ) + missing=$(comm -1 -3 <(dpkg-query -W -f '${package}\n' | sort) <(IFS=$'\n'; echo "${needed[*]}" | sort)) + if [[ "$missing" ]]; then + apt-get update -qq || { echo "Failed to 'apt-get update'. You must build this formula using Docker."; exit 1; } + apt-get install -q -y $missing + fi +fi + +configureopts= +if [[ $dep_version == 7.* ]]; then + configureopts="\ +--with-mcrypt=shared${mcrypt_prefix:+","}${mcrypt_prefix} \ +--enable-opcache-file\ +" +else + configureopts="\ +--with-mcrypt${mcrypt_prefix:+"="}${mcrypt_prefix} \ +--with-mysql=shared \ +" +fi + +export PATH=${OUT_PREFIX}/bin:$PATH +# cannot be built shared: date, ereg, opcache (always), pcre, reflection, sockets (?), spl, standard, +# sqlite3 and pdo_sqlite are on by default but we're building them shared on purpose +./configure \ + --prefix=${OUT_PREFIX} \ + --with-config-file-path=/app/.heroku/php/etc/php \ + --with-config-file-scan-dir=/app/.heroku/php/etc/php/conf.d \ + --disable-phpdbg \ + --enable-fpm \ + --with-bz2 \ + --with-curl \ + --with-pdo-mysql \ + --with-mysqli \ + --with-openssl \ + --with-kerberos \ + --with-pgsql \ + --with-pdo-pgsql \ + --with-readline \ + --enable-sockets \ + --enable-zip \ + --with-zlib \ + --enable-bcmath=shared \ + --enable-calendar=shared \ + --enable-exif=shared \ + --enable-ftp=shared \ + --with-gd=shared \ + --enable-gd-native-ttf \ + --with-freetype-dir=/usr \ + --with-jpeg-dir=/usr \ + --with-png-dir=/usr \ + --with-gettext=shared \ + --with-gmp=shared \ + --with-imap=shared,${OUT_PREFIX}/opt/imap-2007f \ + --with-imap-ssl \ + --enable-intl=shared \ + --with-ldap=shared \ + --with-ldap-sasl \ + --enable-mbstring=shared \ + --enable-pcntl=shared \ + --enable-shmop=shared \ + --enable-soap=shared \ + --with-sqlite3=shared \ + --with-pdo-sqlite=shared \ + --with-xmlrpc=shared \ + --with-xsl=shared \ + $configureopts +make -s -j 9 +make install -s +rm -rf ${OUT_PREFIX}/opt/imap-2007f # c-client.a got linked statically +find ${OUT_PREFIX} -type f \( -executable -o -name '*.a' \) -exec sh -c "file -i '{}' | grep -Eq 'application/x-(archive|executable|sharedlib); charset=binary'" \; -print | xargs strip --strip-unneeded +popd + +rm -rf ${OUT_PREFIX}/php/man ${OUT_PREFIX}/lib/php/extensions/*/*.a + +echo "-----> Preparing PECL..." +${OUT_PREFIX}/bin/pecl channel-update pecl.php.net + +echo "-----> Generating manifest..." +curl -sS https://getcomposer.org/installer | php +# enable all extensions +mkdir -p ${OUT_PREFIX}/etc/php/conf.d +shared=() +for f in ${OUT_PREFIX}/lib/php/extensions/*/*.so; do + if [[ $(basename $f) == "opcache.so" ]]; then + # opcache needs to be loaded using zend_extension + echo -n "zend_" >> ${OUT_PREFIX}/etc/php/php.ini + else + # do not record opcache.so as shared; always on via php.ini + shared+=("heroku-sys/ext-$(basename $f .so)") + fi + echo "extension=$(basename $f)" >> ${OUT_PREFIX}/etc/php/php.ini +done + +extra=$(echo "${shared[@]}" | python -c 'import sys, json; json.dump({"shared": dict([item.split(":") if ":" in item else (item, True) for item in sys.stdin.read().split()]), "export": "bin/export.php.sh", "profile": "bin/profile.php.sh"}, sys.stdout)') + +MANIFEST_REQUIRE="${MANIFEST_REQUIRE:-"{}"}" +MANIFEST_CONFLICT="${MANIFEST_CONFLICT:-"{\"heroku-sys/hhvm\":\"*\"}"}" +MANIFEST_EXTRA="${MANIFEST_EXTRA:-"$extra"}" +MANIFEST_REPLACE=$(php composer.phar show --platform | grep -E '^(ext-\S+|php-64bit\b|hhvm\b)' | tr -s " " | cut -d " " -f1,2 | sed -e "s/ $dep_version\$/ self.version/" -e 's/^/heroku-sys\//' | python -c 'import sys, json; json.dump(dict(item.split() for item in sys.stdin), sys.stdout)') + +# remove temporary ini file that enables all extensions, and the composer download +rm ${OUT_PREFIX}/etc/php/php.ini composer.phar + +cp $(dirname $BASH_SOURCE)/_conf/php/php.ini ${OUT_PREFIX}/etc/php/ +cp $(dirname $BASH_SOURCE)/_conf/php/conf.d/*.ini ${OUT_PREFIX}/etc/php/conf.d/ +cp $(dirname $BASH_SOURCE)/../../conf/php/php-fpm.conf ${OUT_PREFIX}/etc/php/ + +# this gets sourced after package install, so that the buildpack and following buildpacks can invoke +cat > ${OUT_PREFIX}/bin/export.php.sh <<'EOF' +export PATH="/app/.heroku/php/bin:/app/.heroku/php/sbin:$PATH" +EOF +# this gets sourced on dyno boot +cat > ${OUT_PREFIX}/bin/profile.php.sh <<'EOF' +export PATH="$HOME/.heroku/php/bin:$HOME/.heroku/php/sbin:$PATH" +EOF + +python $(dirname $BASH_SOURCE)/_util/include/manifest.py "heroku-sys-php" "heroku-sys/${dep_name}" "$dep_version" "${dep_formula}.tar.gz" "$MANIFEST_REQUIRE" "$MANIFEST_CONFLICT" "$MANIFEST_REPLACE" "$MANIFEST_EXTRA" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/php-5.5.38 b/vendor/heroku/heroku-buildpack-php/support/build/php-5.5.38 new file mode 100755 index 0000000..919e4a9 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/php-5.5.38 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: libraries/libmcrypt-2.5.8, libraries/libc-client-2007f + +source $(dirname $0)/php diff --git a/vendor/heroku/heroku-buildpack-php/support/build/php-5.6.30 b/vendor/heroku/heroku-buildpack-php/support/build/php-5.6.30 new file mode 100755 index 0000000..919e4a9 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/php-5.6.30 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: libraries/libmcrypt-2.5.8, libraries/libc-client-2007f + +source $(dirname $0)/php diff --git a/vendor/heroku/heroku-buildpack-php/support/build/php-7.0.16 b/vendor/heroku/heroku-buildpack-php/support/build/php-7.0.16 new file mode 100755 index 0000000..919e4a9 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/php-7.0.16 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: libraries/libmcrypt-2.5.8, libraries/libc-client-2007f + +source $(dirname $0)/php diff --git a/vendor/heroku/heroku-buildpack-php/support/build/php-7.1.2 b/vendor/heroku/heroku-buildpack-php/support/build/php-7.1.2 new file mode 100755 index 0000000..919e4a9 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/php-7.1.2 @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ +# Build Deps: libraries/libmcrypt-2.5.8, libraries/libc-client-2007f + +source $(dirname $0)/php diff --git a/vendor/heroku/heroku-buildpack-php/support/build/php-min b/vendor/heroku/heroku-buildpack-php/support/build/php-min new file mode 100755 index 0000000..b31456d --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/php-min @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php-min/ + +# fail hard +set -o pipefail +# fail harder +set -eu + +source $(dirname $BASH_SOURCE)/_util/include/manifest.sh + +OUT_PREFIX=$1 + +dep_formula=${0#$WORKSPACE_DIR/} +dep_name=$(basename $BASH_SOURCE) +dep_version=${dep_formula#"${dep_name}-"} +dep_package=pkg-${dep_name}-${dep_version} +dep_dirname=php-${dep_version} +dep_archive_name=${dep_dirname}.tar.gz +dep_url=https://php.net/get/${dep_archive_name}/from/this/mirror +dep_manifest=${dep_package}.composer.json + +echo "-----> Building minimal PHP ${dep_version}..." + +curl -L ${dep_url} | tar xz + +pushd ${dep_dirname} + +export PATH=${OUT_PREFIX}/bin:$PATH +# cannot be built shared: date, ereg, opcache (always), pcre, reflection, sockets (?), spl, standard, +# sqlite3 and pdo_sqlite are on by default but we're building them shared on purpose +./configure \ + --prefix=${OUT_PREFIX} \ + --with-config-file-path=/app/.heroku/php-min/etc/php \ + --with-config-file-scan-dir=/app/.heroku/php-min/etc/php/conf.d \ + --enable-static \ + --disable-phpdbg \ + --disable-cgi \ + --enable-cli\ + --with-bz2 \ + --disable-dom \ + --disable-libxml \ + --with-openssl \ + --without-pear \ + --disable-pdo \ + --without-pdo-sqlite \ + --with-readline \ + --disable-session \ + --disable-simplexml \ + --without-sqlite3 \ + --enable-sockets \ + --disable-xml \ + --disable-xmlreader \ + --disable-xmlwriter \ + --enable-zip \ + --with-zlib +make -s -j 9 + +mkdir -p ${OUT_PREFIX}/bin +cp sapi/cli/php ${OUT_PREFIX}/bin/php +popd + +echo "-----> Stripping..." +strip ${OUT_PREFIX}/bin/php + +python $(dirname $BASH_SOURCE)/_util/include/manifest.py "heroku-sys-package" "heroku-sys/pkg-${dep_name}" "$dep_version" "${dep_formula}.tar.gz" > $dep_manifest + +print_or_export_manifest_cmd "$(generate_manifest_cmd "$dep_manifest")" diff --git a/vendor/heroku/heroku-buildpack-php/support/build/php-min-7.0.16 b/vendor/heroku/heroku-buildpack-php/support/build/php-min-7.0.16 new file mode 100755 index 0000000..ae248ca --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/build/php-min-7.0.16 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/php/ + +source $(dirname $0)/php-min diff --git a/vendor/heroku/heroku-buildpack-php/support/installer/composer.json b/vendor/heroku/heroku-buildpack-php/support/installer/composer.json new file mode 100644 index 0000000..6dbe089 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/installer/composer.json @@ -0,0 +1,16 @@ +{ + "type": "composer-plugin", + "name": "heroku/installer-plugin", + "version": "1.2.1", + "autoload": { + "psr-4": { + "Heroku\\Buildpack\\PHP\\": "src/" + } + }, + "extra": { + "class": "Heroku\\Buildpack\\PHP\\ComposerInstallerPlugin" + }, + "require": { + "composer-plugin-api": "^1.0.0" + } +} diff --git a/vendor/heroku/heroku-buildpack-php/support/installer/src/ComposerInstaller.php b/vendor/heroku/heroku-buildpack-php/support/installer/src/ComposerInstaller.php new file mode 100644 index 0000000..2facf84 --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/installer/src/ComposerInstaller.php @@ -0,0 +1,33 @@ +getInstallPath($package); + $this->downloadManager->download($package, $downloadPath); + } +} diff --git a/vendor/heroku/heroku-buildpack-php/support/installer/src/ComposerInstallerPlugin.php b/vendor/heroku/heroku-buildpack-php/support/installer/src/ComposerInstallerPlugin.php new file mode 100644 index 0000000..bdde82e --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/installer/src/ComposerInstallerPlugin.php @@ -0,0 +1,201 @@ +composer = $composer; + $this->io = $io; + + // check if there already are scripts in .profile.d, or INI files (because we got invoked before), then calculate new starting point for file names + foreach([ + 'profileCounter' => (getenv('profile_dir_path')?:'/dev/null').'/[0-9][0-9][0-9]-*.sh', + 'configCounter' => self::CONF_D_PATHNAME.'/[0-9][0-9][0-9]-*.ini' + ] as $var => $glob) { + if($matches = glob($glob)) { + $this->$var = ceil(max(array_merge([$this->$var], array_map(function($e) { return explode('-', pathinfo($e, PATHINFO_FILENAME), 2)[0]; }, $matches)))/10)+1; + } + } + + $composer->getDownloadManager()->setDownloader( + 'heroku-sys-tar', + new Downloader( + $io, + $composer->getConfig(), + $composer->getEventDispatcher() + // $cache + ) + ); + $composer->getInstallationManager()->addInstaller(new ComposerInstaller($io, $composer)); + } + + public static function getSubscribedEvents() + { + return [PackageEvents::POST_PACKAGE_INSTALL => 'onPostPackageInstall']; + } + + public function onPostPackageInstall(PackageEvent $event) + { + if(!in_array($event->getOperation()->getPackage()->getType(), ['heroku-sys-php', 'heroku-sys-hhvm', 'heroku-sys-php-extension', 'heroku-sys-hhvm-extension', 'heroku-sys-webserver'])) return; + + $this->initAllPlatformRequirements($event->getOperations()); + + try { + $this->configurePackage($event->getOperation()->getPackage()); + $this->enableReplaces($event->getOperation()->getPackage()); + $this->writeProfile($event->getOperation()->getPackage()); + $this->writeExport($event->getOperation()->getPackage()); + } catch(\Exception $e) { + $this->io->writeError(sprintf('Failed to activate package %s', $event->getOperation()->getPackage()->getName())); + $this->io->writeError(''); + throw $e; + } + } + + protected function initAllPlatformRequirements(array $operations) + { + if($this->allPlatformRequirements !== null) return; + + $this->allPlatformRequirements = []; + foreach($operations as $operation) { + foreach($operation->getPackage()->getRequires() as $require) { + if(strpos($require->getTarget(), 'heroku-sys/') === 0) { + $this->allPlatformRequirements[$require->getTarget()] = $require->getSource(); + } + } + } + } + + protected function configurePackage(PackageInterface $package) + { + if(in_array($package->getType(), ['heroku-sys-php-extension', 'heroku-sys-hhvm-extension'])) { + $this->enableExtension($package->getPrettyName(), $package); + } + } + + protected function enableReplaces(PackageInterface $package) + { + // we may "replace" any of the packages (e.g. ext-mbstring is bundled with PHP) that have been required + // figure out which those are so we can decide if they need enabling (because they're built shared) + $enable = array_intersect_key($package->getReplaces(), $this->allPlatformRequirements); + + foreach(array_keys($enable) as $extension) { + $this->enableExtension($extension, $package); + } + } + + protected function enableExtension($prettyName, PackageInterface $parent) + { + // for comparison etc + $packageName = strtolower($prettyName); + // strip "heroku-sys/ext-" + $extName = substr($packageName, 15); + + // check if it's an extension + if(strpos($packageName, 'heroku-sys/ext-') !== 0) return; + + $extra = $parent->getExtra(); + + if($parent->getName() == $packageName) { + // we're enabling the parent package itself + $config = isset($extra['config']) ? $extra['config'] : true; + } else { + // we're enabling another extension that this package provides + $shared = isset($extra['shared']) ? array_change_key_case($extra['shared'], CASE_LOWER) : []; + if(!isset($shared[$packageName])) { + // that ext is on by default or whatever + return; + } + + $this->io->writeError(sprintf(' - Enabling %s (bundled with %s)', $prettyName, $parent->getPrettyName())); + $this->io->writeError(''); + + $config = $shared[$packageName]; + } + + $ini = sprintf('%s/%03u-%%s.ini', self::CONF_D_PATHNAME, $this->configCounter++*10); + @mkdir(dirname($ini), 0777, true); + + if($config === true || (is_string($config) && substr($config, -3) === '.so' && is_readable($config))) { + // just enable that ext (arg is true, or the .so filename) + file_put_contents(sprintf($ini, "ext-$extName"), sprintf("extension=%s\n", $config === true ? "$extName.so" : $config)); + } elseif(is_string($config) && is_readable($config)) { + // ini file, maybe with special contents like extra config or different .so name (think "zend-opcache" vs "opcache.so") + // FIXME: consider ignoring/overriding the numeric prefix and re-using the original file name for "replace"d extensions, which may deliberately be different to ensure a certain loading order? + // example: some rare extensions (e.g. recode: http://php.net/manual/en/recode.installation.php) need to be loaded in a specific order (https://www.pingle.org/2006/10/18/php-crashes-extensions) + // this can only happen if several extensions, built as shared, are included in a package and will be activated (so typically just PHP with its shared exts); for real dependencies (ext-apc needs ext-apcu, ext-foobar needs ext-mysql), Composer already does that ordering for us + rename($config, sprintf($ini, "ext-$extName")); + } elseif (!$config) { + return; + } else { + throw new \RuntimeException('Package declares invalid or missing "config" in "extra"'); + } + } + + protected function writeExport(PackageInterface $package) + { + if(!($fn = getenv('export_file_path'))) return; + + $extra = $package->getExtra(); + if(!isset($extra['export']) || !$extra['export']) return; + + if(is_string($extra['export']) && is_readable($extra['export'])) { + // a file from the package used to export vars for the next buildpack, e.g. $PATH + $export = file_get_contents($extra['export']); + @unlink($extra['export']); + } elseif(is_array($extra['export'])) { + // a hash of vars for the next buildpack, e.g. "PATH": "$HOME/.heroku/php/bin:$PATH" + $export = implode("\n", array_map(function($v, $k) { return sprintf('export %s="%s"', $k, $v); }, $extra['export'], array_keys($extra['export']))); + } else { + throw new \RuntimeException('Package declares invalid or missing "export" in "extra"'); + } + + file_put_contents($fn, "\n$export\n", FILE_APPEND); + } + + protected function writeProfile(PackageInterface $package) + { + if(!getenv('profile_dir_path')) return; + + $profile = $package->getExtra(); + if(!isset($profile['profile']) || !$profile['profile']) return; + $profile = $profile['profile']; + + $fn = sprintf("%s/%03u-%s.sh", getenv('profile_dir_path'), $this->profileCounter++*10, str_replace('heroku-sys/', '', $package->getName())); + @mkdir(dirname($fn), 0777, true); + + if(is_string($profile) && is_readable($profile)) { + // move profile file to ~/.profile.d/ + rename($profile, $fn); + } elseif(is_array($profile)) { + // a hash of vars for startup, e.g. "PATH": "$HOME/.heroku/php/bin:$PATH" + file_put_contents( + $fn, + implode("\n", array_map(function($v, $k) { return sprintf('export %s="%s"', $k, $v); }, $profile, array_keys($profile))) + ); + } else { + throw new \RuntimeException('Package declares invalid or missing "profile" in "extra"'); + } + } +} diff --git a/vendor/heroku/heroku-buildpack-php/support/installer/src/Downloader.php b/vendor/heroku/heroku-buildpack-php/support/installer/src/Downloader.php new file mode 100644 index 0000000..210008a --- /dev/null +++ b/vendor/heroku/heroku-buildpack-php/support/installer/src/Downloader.php @@ -0,0 +1,98 @@ +process = $process ?: new ProcessExecutor($io); + + parent::__construct($io, $config, $eventDispatcher, $cache); + } + + // extract using cmdline tar, which merges with existing files and folders + protected function extract($file, $path) + { + // we must use cmdline tar, as PharData::extract() messes up symlinks + $command = 'tar -xzf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path); + + if (0 === $this->process->execute($command, $ignoredOutput)) { + return; + } + + throw new \RuntimeException("Failed to execute '$command'\n\n" . $this->process->getErrorOutput()); + } + + // ArchiveDownloader unpacks to a temp dir, then replaces the destination + // we can't do that, since we need our contents to be merged into the probably existing folder structure + public function download(PackageInterface $package, $path) + { + $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8); + $this->filesystem->ensureDirectoryExists($temporaryDir); + + // START: from FileDownloader::download() + + if (!$package->getDistUrl()) { + throw new \InvalidArgumentException('The given package is missing url information'); + } + + $this->io->writeError(" - Installing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")"); + + $urls = $package->getDistUrls(); + while ($url = array_shift($urls)) { + try { + $fileName = $this->doDownload($package, $temporaryDir, $url); + } catch (\Exception $e) { + if ($this->io->isDebug()) { + $this->io->writeError(''); + $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage()); + } elseif (count($urls)) { + $this->io->writeError(''); + $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')'); + } + + if (!count($urls)) { + throw $e; + } + } + } + + // END: from FileDownloader::download() + + // START: from ArchiveDownloader::download() + + $this->io->writeError(' Extracting archive', true, IOInterface::VERBOSE); + + try { + $this->extract($fileName, $path); + } catch (\Exception $e) { + // remove cache if the file was corrupted + parent::clearLastCacheWrite($package); + throw $e; + } + + $this->filesystem->unlink($fileName); + + if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) { + $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/'); + } + if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) { + $this->filesystem->removeDirectory($this->config->get('vendor-dir')); + } + + $this->io->writeError(''); + + // END: from ArchiveDownloader::download() + } +} diff --git a/webroot/_htaccess b/webroot/_htaccess new file mode 100644 index 0000000..cd3c3e2 --- /dev/null +++ b/webroot/_htaccess @@ -0,0 +1,33 @@ + + RewriteEngine on + RewriteBase / + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + + RewriteRule ^(.*)$ index.php [QSA,L] + + + + AddOutputFilterByType DEFLATE text/plain text/html text/xml text/css text/javascript + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE application/rss+xml + AddOutputFilterByType DEFLATE application/javascript application/x-javascript + + + + ExpiresActive on + ExpiresDefault "access plus 5 minutes" + ExpiresByType image/ico "access plus 1 year" + ExpiresByType image/jpg "access plus 1 month" + ExpiresByType image/jpeg "access plus 1 month" + ExpiresByType image/gif "access plus 1 month" + ExpiresByType image/png "access plus 1 month" + ExpiresByType application/x-shockwave-flash "access plus 1 month" + ExpiresByType text/javascript "access plus 2 days" + ExpiresByType text/css "access plus 2 days" + ExpiresByType text/xml "access plus 0 seconds" + ExpiresByType application/xml "access plus 0 seconds" + ExpiresByType application/json "access plus 0 seconds" + ExpiresByType text/cache-manifest "access plus 0 seconds" + \ No newline at end of file diff --git a/webroot/assets/css/.gitkeep b/webroot/assets/css/.gitkeep new file mode 100644 index 0000000..1ec6b8a --- /dev/null +++ b/webroot/assets/css/.gitkeep @@ -0,0 +1 @@ +EMPTY \ No newline at end of file diff --git a/webroot/assets/css/custom/.gitkeep b/webroot/assets/css/custom/.gitkeep new file mode 100644 index 0000000..1ec6b8a --- /dev/null +++ b/webroot/assets/css/custom/.gitkeep @@ -0,0 +1 @@ +EMPTY \ No newline at end of file diff --git a/webroot/assets/icons/.gitkeep b/webroot/assets/icons/.gitkeep new file mode 100644 index 0000000..1ec6b8a --- /dev/null +++ b/webroot/assets/icons/.gitkeep @@ -0,0 +1 @@ +EMPTY \ No newline at end of file diff --git a/webroot/assets/images/.gitkeep b/webroot/assets/images/.gitkeep new file mode 100644 index 0000000..1ec6b8a --- /dev/null +++ b/webroot/assets/images/.gitkeep @@ -0,0 +1 @@ +EMPTY \ No newline at end of file diff --git a/webroot/assets/js/.gitkeep b/webroot/assets/js/.gitkeep new file mode 100644 index 0000000..1ec6b8a --- /dev/null +++ b/webroot/assets/js/.gitkeep @@ -0,0 +1 @@ +EMPTY \ No newline at end of file diff --git a/webroot/assets/js/custom/.gitkeep b/webroot/assets/js/custom/.gitkeep new file mode 100644 index 0000000..1ec6b8a --- /dev/null +++ b/webroot/assets/js/custom/.gitkeep @@ -0,0 +1 @@ +EMPTY \ No newline at end of file diff --git a/webroot/assets/vendor/.gitkeep b/webroot/assets/vendor/.gitkeep new file mode 100644 index 0000000..1ec6b8a --- /dev/null +++ b/webroot/assets/vendor/.gitkeep @@ -0,0 +1 @@ +EMPTY \ No newline at end of file diff --git a/webroot/index.php b/webroot/index.php new file mode 100644 index 0000000..bed87c9 --- /dev/null +++ b/webroot/index.php @@ -0,0 +1,26 @@ +config('../config/settings.ini'); +$f3->config('../config/routes.ini'); +// $f3->set('CACHE',TRUE); +// new Session(); + +### CONFIG / ENVIRONMENT +$host = $_SERVER['HTTP_HOST']; +if(strpos($host, 'local.') !== false) { + $f3->config('../config/config.local.ini'); +} else { + if (strpos($host, 'dev.') !== false) { + $f3->config('../config/config.dev.ini'); + } else if (strpos($host, 'testing') !== false) { + $f3->config('../config/config.testing.ini'); + } else if (strpos($host, 'staging') !== false) { + $f3->config('../config/config.staging.ini'); + } else { + $f3->config('../config/config.production.ini'); + } +} + +################################################################################ + +$f3->run(); diff --git a/webroot/info.php b/webroot/info.php new file mode 100644 index 0000000..c9f5eeb --- /dev/null +++ b/webroot/info.php @@ -0,0 +1 @@ + \ No newline at end of file