diff --git a/admin/temp/2/s_cache_21a4da48e5fa14e992150d116fb212cc b/admin/temp/2/s_cache_21a4da48e5fa14e992150d116fb212cc index 1089167..f727f71 100644 --- a/admin/temp/2/s_cache_21a4da48e5fa14e992150d116fb212cc +++ b/admin/temp/2/s_cache_21a4da48e5fa14e992150d116fb212cc @@ -1 +1 @@ -YToyOntpOjA7aToxNjk0MDA3MTQxO2k6MTtzOjIwOiJwb215c2xvd2VwcmV6ZW50eS5wbCI7fQ== \ No newline at end of file +YToyOntpOjA7aToxNjkzOTE3NzIzO2k6MTtzOjg6Ik1hcmlhbmVrIjt9 \ No newline at end of file diff --git a/admin/temp/3/s_cache_3a23324137621a1dfafc3ee613d86e94 b/admin/temp/3/s_cache_3a23324137621a1dfafc3ee613d86e94 index a95fff9..95f8ff0 100644 --- a/admin/temp/3/s_cache_3a23324137621a1dfafc3ee613d86e94 +++ b/admin/temp/3/s_cache_3a23324137621a1dfafc3ee613d86e94 @@ -1 +1 @@ -YToyOntpOjA7aToxNjc4NzMyMTQ4O2k6MTtzOjI6InBsIjt9 \ No newline at end of file +YToyOntpOjA7aToxNjkzOTQ2ODIzO2k6MTtzOjI6InBsIjt9 \ No newline at end of file diff --git a/admin/temp/4/s_cache_44e3d63e885545f6b55debe0486ec1e4 b/admin/temp/4/s_cache_44e3d63e885545f6b55debe0486ec1e4 index 4fab907..47a3ce6 100644 --- a/admin/temp/4/s_cache_44e3d63e885545f6b55debe0486ec1e4 +++ b/admin/temp/4/s_cache_44e3d63e885545f6b55debe0486ec1e4 @@ -1 +1 @@ -YToyOntpOjA7aToxNzA0NDM4NDIyO2k6MTthOjIwMDp7aTowO3M6MjoicGwiO3M6NToidGVtYXQiO3M6NToidGVtYXQiO3M6OToid2lhZG9tb3NjIjtzOjExOiJ3aWFkb21vxZvEhyI7czo2OiJ3eXNsaWoiO3M6Nzoid3nFm2xpaiI7czo1OiJlbWFpbCI7czo1OiJlbWFpbCI7czoxMToibnItdGVsZWZvbnUiO3M6MTE6Im5yIHRlbGVmb251IjtzOjM0OiJwcm9zemUtdXp1cGVsbmljLWVtYWlsLWx1Yi10ZWxlZm9uIjtzOjUxOiJQcm9zesSZIHV6dXBlxYJuacSHIGFkcmVzIGVtYWlsIGx1YiBudW1lciB0ZWxlZm9udS4iO3M6NDoiYmxhZCI7czo2OiJixYLEhWQiO3M6NzoiemFta25paiI7czo3OiJ6YW1rbmlqIjtzOjI1OiJ3aWFkb21vc2Mtem9zdGFsYS13eXNsYW5hIjtzOjkwOiJUd29qYSB3aWFkb21vxZvEhyB6b3N0YcWCYSB3eXPFgmFuYS4gUG9zdGFyYW15IHNpxJkgbmEgbmnEhSBvZHBvd2llZHppZcSHIGphayBuYWpzenliY2llai4iO3M6Mjg6IndpYWRvbW9zYy1uaWV6b3N0YWxhLXd5c2xhbmEiO3M6OTM6IlBvZGN6YXMgd3lzecWCYW5pYSB3aWFkb21vxZtjaSB3eXN0xIVwacWCIGLFgsSFZC4gUHJvc3rEmSBzcHLDs2Jvd2HEhyBwb25vd25pZS4gUHJ6ZXByYXN6YW15LiI7czoxMjoiZGF0YS1kb2RhbmlhIjtzOjEyOiJkYXRhIGRvZGFuaWEiO3M6MTY6ImRhdGEtbW9keWZpa2FjamkiO3M6MTY6ImRhdGEgbW9keWZpa2FjamkiO3M6MTI6ImFkcmVzLXN0cm9ueSI7czoxMjoiYWRyZXMgc3Ryb255IjtzOjI5OiJwcm9zemUtdXp1cGVsbmljLWFkcmVzLXN0cm9ueSI7czozMzoiUHJvc3rEmSB1enVwZcWCbmnEhyBhZHJlcyBzdHJvbnkuIjtzOjg6InBpZXJ3c3phIjtzOjg6InBpZXJ3c3phIjtzOjg6Im5hc3RlcG5hIjtzOjk6Im5hc3TEmXBuYSI7czoxMDoicG9wcnplZG5pYSI7czoxMDoicG9wcnplZG5pYSI7czo4OiJvc3RhdG5pYSI7czo4OiJvc3RhdG5pYSI7czoxOiJ6IjtzOjE6InoiO3M6Njoid2llY2VqIjtzOjc6IndpxJljZWoiO3M6Njoid3N0ZWN6IjtzOjY6IndzdGVjeiI7czoyMzoiZm9ybXVsYXJ6LWNhcHRjaGEtbGFiZWwiO3M6Njk6IlByb3N6xJkgbmFyeXNvd2HEhyBrc3p0YcWCdCB3IHBvbmnFvHN6eW0gcG9sdSwgYWJ5IHd5c8WCYcSHIGZvcm11bGFyeiI7czoxNjoic3Byb2J1ai1wb25vd25pZSI7czoxNzoic3Byw7NidWogcG9ub3duaWUiO3M6NjoiZG9icnplIjtzOjY6ImRvYnJ6ZSI7czo1OiJ3aXRhaiI7czo1OiJ3aXRhaiI7czoxMToiemFsb2d1ai1zaWUiO3M6MTI6InphbG9ndWogc2nEmSI7czozOiJsdWIiO3M6MzoibHViIjtzOjE1OiJ6YXJlamVzdHJ1ai1zaWUiO3M6MTY6InphcmVqZXN0cnVqIHNpxJkiO3M6NToiaWxvc2MiO3M6NzoiaWxvxZvEhyI7czo0OiJzdW1hIjtzOjQ6InN1bWEiO3M6ODoicG9sZWNhbXkiO3M6ODoicG9sZWNhbXkiO3M6MTg6InNwcmF3ZHota29uaWVjem5pZSI7czoxOToic3ByYXdkxboga29uaWVjem5pZSI7czoxNjoiZG9kYWotZG8ta29zenlrYSI7czoxNjoiZG9kYWogZG8ga29zenlrYSI7czoxNDoic3RyZWZhLXJvZHppY2EiO3M6MTQ6InN0cmVmYSByb2R6aWNhIjtzOjE2OiJuYWpub3dzemUtcG9yYWR5IjtzOjE2OiJOYWpub3dzemUgcG9yYWR5IjtzOjE4OiJuZXdzbGV0dGVyLXpnb2RhLTEiO3M6NTU6Ild5cmHFvGFtIHpnb2TEmSBuYSBwcnpldHdhcnphbmllIG1vaWNoIGRhbnljaCBvc29ib3d5Y2giO3M6NDoiendpbiI7czo1OiJ6d2nFhCI7czo2OiJyb3p3aW4iO3M6Nzoicm96d2nFhCI7czozMzoibmV3c2xldHRlci1hZG1pbmlzdHJhdG9yLWRhbnljaC0xIjtzOjYxOiJBZG1pbmlzdHJhdG9yZW0gZGFueWNoIG9zb2Jvd3ljaCB6YXdhcnR5Y2ggdyB6Z8WCb3N6ZW5pdSBqZXN0IjtzOjMzOiJuZXdzbGV0dGVyLWFkbWluaXN0cmF0b3ItZGFueWNoLTIiO3M6NzQ2OiJfX19fXy4gRGFuZSBrb250YWt0b3dlIEluc3Bla3RvcmEgT2Nocm9ueSBEYW55Y2g6IHVva2lrQHVva2lrLmdvdi5wbC4gRGFuZSBvc29ib3dlIHPEhSBwcnpldHdhcnphbmUgdyBjZWx1IGRvc3RhcmN6ZW5pYSBuZXdzbGV0dGVyYSwgbmEgcG9kc3Rhd2llIGFydC4gNiB1c3QuIDEgbGl0LiBhKSByb3pwb3J6xIVkemVuaWEgUGFybGFtZW50dSBFdXJvcGVqc2tpZWdvIGkgUmFkeSAoVUUpIDIwMTYvNjc5IChST0RPKSBpIG5pZSBzxIUgcHJ6ZWthenl3YW5lIGlubnltIG9kYmlvcmNvbSwgb3JnYW5pemFjamkgbWnEmWR6eW5hcm9kb3dlaiBjenkgZG8gcGHFhHN0dyB0cnplY2ljaC4gRGFuZSBvc29ib3dlIHByemVjaG93eXdhbmUgc8SFIHByemV6IG9rcmVzIHByZW51bWVyYXR5LiBXbmlvc2tvZGF3Y2EgbWEgcHJhd28gZG8gZG9zdMSZcHUgZG8gc3dvaWNoIGRhbnljaCBvc29ib3d5Y2gsIGljaCBzcHJvc3Rvd2FuaWEgb3JheiB3bmllc2llbmlhIHNrYXJnaSBkbyBfX19fXy4gUG9kYW5pZSBkYW55Y2ggb3NvYm93eWNoIGplc3QgZG9icm93b2xuZSwgbmllIHd5bmlrYSB6IHByemVwaXPDs3csIGljaCBuaWVwb2RhbmllIGLEmWR6aWUgc2t1dGtvd2HFgm8gYnJha2llbSBtb8W8bGl3b8WbY2kgemFtw7N3aWVuaWEuIE5hIHBvZHN0YXdpZSBkYW55Y2ggb3NvYm93eWNoIG5pZSBzxIUgcG9kZWptb3dhbmUgemF1dG9tYXR5em93YW5lIGRlY3l6amUsIHcgdHltIG5pZSBzdG9zdWplIHNpxJkgcHJvZmlsb3dhbmlhLiI7czoyNjoibmV3c2xldHRlci16Z29kYS1rb211bmlrYXQiO3M6NTc6IlByb3N6xJkgemF6bmFjennEhyB6Z29kxJkgZG8gcHJ6ZXR3YXJ6YW5pYSB6IG5ld3NsZXR0ZXJhLiI7czozMzoibmV3c2xldHRlci1wcm9zemUtdXp1cGVsbmljLWVtYWlsIjtzOjMyOiJQcm9zesSZIHV6dXBlxYJuacSHIGFkcmVzIGVtYWlsLiI7czozODoicG90d2llcmR6LXphcGlzYW5pZS1zaWUtZG8tbmV3c2xldHRlcmEiO3M6NDA6IlBvdHdpZXJkxbogemFwaXNhbmllIHNpxJkgZG8gbmV3c2xldHRlcmEiO3M6MTM6InByb3N6ZS1jemVrYWMiO3M6MTg6IlByb3N6xJkgY3pla2HEhy4uLiI7czoxMDoiaW5mb3JtYWNqYSI7czoxMDoiSW5mb3JtYWNqYSI7czozOToiZW1haWwtem9zdGFsLWRvZGFueS1kby1saXN0eS1uZXdzbGV0dGVyIjtzOjQxOiJFbWFpbCB6b3N0YcWCIGRvZGFueSBkbyBsaXN0eSBuZXdzbGV0dGVyLiI7czozMjoibmV3c2xldHRlci1wb3R3aWVyZHplbmllLWRvZGFuaWEiO3M6MTYyOiJOYSBwb2RhbnkgcHJ6ZXogQ2llYmllIGUtbWFpbCB6b3N0YcWCYSB3eXPFgmFuYSB3aWFkb21vxZvEhyB6IGxpbmtpZW0gYWt0eXd1asSFY3ltLiBLbGlrbmlqIHcgbGluayBwb3R3aWVyZHphasSFY3ksIGFieSBwb215xZtsbmllIHpha2/FhGN6ecSHIHByb2NlcyByZWplc3RyYWNqaS4iO3M6Mzc6Im5ld3NsZXR0ZXItcG90d2llcmR6ZW5pZS1kb2RhbmlhLWJsYWQiO3M6ODQ6IlBvZGN6YXMgcmVqZXN0cmFjamkgYWRyZXN1IGUtbWFpbCBwb2phd2nFgiBzacSZIGLFgsSFZC4gUHJvc2lteSBzcHJvYm93YcSHIHBvbm93bmllLiI7czozMjoicHJvc3plLXV6dXBlbG5pYy1lbWFpbC1pLXRlbGVmb24iO3M6NDk6IlByb3N6xJkgdXp1cGXFgm5pxIcgYWRyZXMgZW1haWwgaSBudW1lciB0ZWxlZm9udS4iO3M6MTA6Ind5cGlzei1zaWUiO3M6MTE6Ind5cGlzeiBzacSZIjtzOjQwOiJlbWFpbC16b3N0YWwtdXN1bmlldHktei1saXN0eS1uZXdzbGV0dGVyIjtzOjQzOiJFbWFpbCB6b3N0YcWCIHVzdW5pxJl0eSB6IGxpc3R5IG5ld3NsZXR0ZXIuIjtzOjEwOiJuZXdzbGV0dGVyIjtzOjEwOiJuZXdzbGV0dGVyIjtzOjE1OiJuZXdzbGV0dGVyLXRleHQiO3M6NzI6IlphcGlzeiBzacSZIGRvIG5ld3NsZXR0ZXJhIGJ5IGJ5xIcgbmEgYmllxbzEhWNvIHogbm93b8WbY2lhbWkgdyBza2xlcGllLiI7czoxODoibmV3c2xldHRlci16Z29kYS0yIjtzOjQwODoiIChhZHJlc3UgZS1tYWlsKSB6YXdhcnR5Y2ggdyB6Z8WCb3N6ZW5pdSwgdyB6d2nEhXprdSB6IGFydC4gNiB1c3QuIDEgbGl0LiBhLCByb3pwb3J6xIVkemVuaWEgUGFybGFtZW50dSBFdXJvcGVqc2tpZWdvIGkgUmFkeSAoVUUpIDIwMTYvNjc5IHogZG5pYSAyNyBrd2lldG5pYSAyMDE2IHIuIHcgc3ByYXdpZSBvY2hyb255IG9zw7NiIGZpenljem55Y2ggdyB6d2nEhXprdSB6IHByemV0d2FyemFuaWVtIGRhbnljaCBvc29ib3d5Y2ggaSB3IHNwcmF3aWUgc3dvYm9kbmVnbyBwcnplcMWCeXd1IHRha2ljaCBkYW55Y2ggb3JheiB1Y2h5bGVuaWEgZHlyZWt0eXd5IDk1LzQ2L1dFIChST0RPKS4gVyBrYcW8ZHltIG1vbWVuY2llIG1vZ8SZIHd5Y29mYcSHIHpnb2TEmSB3eXBpc3VqxIVjIHNpxJkgeiBuZXdzbGV0dGVyYS4gIjtzOjMyOiJwcm9kdWt0LXpvc3RhbC1kb2RhbnktZG8ta29zenlrYSI7czo0MjoiV3licmFueSBwcm9kdWt0IHpvc3RhxYIgZG9kYW55IGRvIGtvc3p5a2EuIjtzOjE4OiJwcnplamR6LWRvLWtvc3p5a2EiO3M6MTk6InByemVqZMW6IGRvIGtvc3p5a2EiO3M6MTc6Inphd2FydG9zYy1rb3N6eWthIjtzOjE5OiJ6YXdhcnRvxZvEhyBrb3N6eWthIjtzOjk6InBvdHdpZXJkeiI7czoxMDoicG90d2llcmTFuiI7czozODoicG90d2llcmR6LXVzdW5pZWNpZS1wcm9kdWt0dS16LWtvc3p5a2EiO3M6NDE6Ik5hIHBld25vIGNoY2VzeiB1c3VuxIXEhyB3eWJyYW55IHByb2R1a3Q/IjtzOjQ6InVzdW4iO3M6NToidXN1xYQiO3M6MTM6InByb3N6ZS13eWJyYWMiO3M6MTU6InByb3N6xJkgd3licmHEhyI7czoxODoiZG9zdGF3YS1pLXBsYXRub3NjIjtzOjIxOiJkb3N0YXdhIGkgcMWCYXRub8WbxIciO3M6MjM6InByemVqZHotZG8tcG9kc3Vtb3dhbmlhIjtzOjI0OiJwcnplamTFuiBkbyBwb2RzdW1vd2FuaWEiO3M6MjM6InBvZHN1bW93YW5pZS16YW1vd2llbmlhIjtzOjI0OiJwb2RzdW1vd2FuaWUgemFtw7N3aWVuaWEiO3M6MzA6InphbWF3aWFtLXotb2Jvd2lhemtpZW0temFwbGF0eSI7czozMjoiemFtYXdpYW0geiBvYm93acSFemtpZW0gemFwxYJhdHkiO3M6MTM6ImRhbmUtYWRyZXNvd2UiO3M6MTM6ImRhbmUgYWRyZXNvd2UiO3M6MzA6Inpsb3otemFtb3dpZW5pZS1iZXotcmVqZXN0cmFqaSI7czozNToiWsWCw7PFvCB6YW3Ds3dpZW5pZSBiZXogcmVqZXN0cmFjamkiO3M6NzoidGVsZWZvbiI7czo3OiJ0ZWxlZm9uIjtzOjQ6ImltaWUiO3M6NToiaW1pxJkiO3M6ODoibmF6d2lza28iO3M6ODoibmF6d2lza28iO3M6MTU6InVsaWNhLWktbnItZG9tdSI7czoxNToidWxpY2EgaSBuciBkb211IjtzOjEyOiJrb2QtcG9jenRvd3kiO3M6MTI6ImtvZCBwb2N6dG93eSI7czo2OiJtaWFzdG8iO3M6NjoibWlhc3RvIjtzOjU3OiJwcnplY3p5dGFsZW0taS1ha2NlcHR1amUtcG9saXR5a2UtcHJ5d2F0bm9zY2ktaS1yZWd1bGFtaW4iO3M6Njk6IkFrY2VwdHVqxJkgPGEgaHJlZj0iL3JlZ3VsYW1pbiIgdGFyZ2V0PSJfYmxhbmsiPnJlZ3VsYW1pbjwvYT4gc2tsZXB1LiI7czoxNToid3JvYy1kby1rb3N6eWthIjtzOjE3OiJ3csOzxIcgZG8ga29zenlrYSI7czozNjoiemFtb3dpZW5pZS16b3N0YWxvLXpsb3pvbmUta29tdW5pa2F0IjtzOjE1MDoiWmFtw7N3aWVuaWUgem9zdGHFgm8gesWCb8W8b25lLjxiciAvPk5hIHBvZGFueSBhZHJlcyBlbWFpbCB6b3N0YcWCbyB3eXPFgmFuZSBwb3R3aWVyZHpuaWUuIFByb3N6xJkgcsOzd25pZcW8IHNwcmF3ZHppxIcgZm9sZGVyIHNwYW0uPGJyIC8+RHppxJlrdWplbXkuIjtzOjQxOiJ6YW1vd2llbmllLXpvc3RhbG8temxvem9uZS1rb211bmlrYXQtYmxhZCI7czo3OToiUG9kY3phcyBza8WCYWRhbmlhIHphbcOzd2llbmlhIHd5c3TEhXBpxYIgYsWCxIVkLiBQcm9zaW15IHNwcsOzYm93YcSHIHBvbm93bmllLiI7czozNDoicG90d2llcmR6ZW5pZS16YW1vd2llbmlhLXplLXNrbGVwdSI7czozNToiUG90d2llcmR6ZW5pZSB6YW3Ds3dpZW5pYSB6ZSBza2xlcHUiO3M6MjoibnIiO3M6MjoibnIiO3M6NzoicHJvZHVrdCI7czo3OiJwcm9kdWt0IjtzOjQ6ImNlbmEiO3M6NDoiY2VuYSI7czo1OiJyYXplbSI7czo1OiJyYXplbSI7czo2OiJ6LWRuaWEiO3M6NjoieiBkbmlhIjtzOjE1OiJkYW5lLWRvLWRvc3Rhd3kiO3M6MTU6ImRhbmUgZG8gZG9zdGF3eSI7czoxODoiemFtb3dpb25lLXByb2R1a3R5IjtzOjE5OiJ6YW3Ds3dpb25lIHByb2R1a3R5IjtzOjE2OiJkYW5lLWRvLXByemVsZXd1IjtzOjE2OiJkYW5lIGRvIHByemVsZXd1IjtzOjE5OiJ6YWxvei1rb250by1rbGllbnRhIjtzOjIyOiJaYcWCw7PFvCBrb250byBrbGllbnRhIjtzOjU6Imhhc2xvIjtzOjY6Imhhc8WCbyI7czozOiJtaW4iO3M6NDoibWluLiI7czo2OiJ6bmFrb3ciO3M6Nzoiem5ha8OzdyI7czoxMzoicG93dG9yei1oYXNsbyI7czoxNToicG93dMOzcnogaGFzxYJvIjtzOjMzOiJyZWplc3RyYWNqYS1ha2NlcHRhY2phLXJlZ3VsYW1pbnUiO3M6Njk6IkFrY2VwdHVqxJkgW0xJTkstUkVHVUxBTUlOXSBvcmF6IFtMSU5LLVBPTElUWUtBLVBSWVdBVE5PU0NJXSBzZXJ3aXN1LiI7czozMDoicmVqZXN0cmFjamEtemdvZGEtbmEtbWFya2V0aW5nIjtzOjcyOiJDaGPEmSBvdHJ6eW15d2HEhyBtYWlsZW0gaW5mb3JtYWNqZSBtYXJrZXRpbmdvd2Ugb2QgcG9teXNsb3dlcHJlemVudHkucGwiO3M6OToicmVndWxhbWluIjtzOjk6InJlZ3VsYW1pbiI7czoyMDoicG9saXR5a2UtcHJ5d2F0bm9zY2kiO3M6MjI6InBvbGl0eWvEmSBwcnl3YXRub8WbY2kiO3M6MTQ6Im1hc3otanV6LWtvbnRvIjtzOjE1OiJtYXN6IGp1xbwga29udG8iO3M6MjM6InJlamVzdHJhY2phLWJsYWQtb2dvbG55IjtzOjcwOiJXIHRyYWtjaWUgcmVqZXN0cmFjamkgd3lzdMSFcGnFgiBixYLEhWQuIFByb3N6xJkgc3Byw7Nib3dhxIcgcG9ub3duaWUuIjtzOjI0OiJyZWplc3RyYWNqYS1lbWFpbC16YWpldHkiO3M6Mzc6IlBvZGFueSBhZHJlcyBlbWFpbCBqZXN0IGp1xbwgemFqxJl0eS4iO3M6MjE6InBvZGFuZS1oYXNsYS1zYS1yb3puZSI7czoyNjoiUG9kYW5lIGhhc8WCYSBzxIUgcsOzxbxuZS4iO3M6NDE6InBvdHdpZXJkemVuaWUtcmVqZXN0cmFjamkta29udGEtdy1za2xlcGllIjtzOjQxOiJQb3R3aWVyZHplbmllIHJlamVzdHJhY2ppIGtvbnRhIHcgc2tsZXBpZSI7czoxNDoiI25hendhLXNlcndpc3UiO3M6MTE6Im1hcmlhbmVrLnBsIjtzOjE3OiJyZWplc3RyYWNqYS11ZGFuYSI7czoxMTQ6IkR6acSZa3VqZW15IHphIHJlamVzdHJhY2rEmS4gTmEgcG9kYW55IGFkcmVzIGVtYWlsIHpvc3RhxYJhIHd5c8WCYW5hIHdpYWRvbW/Fm8SHIHogbGlua2llbSBkbyBwb3R3aWVyZHplbmllIGtvbnRhLiI7czozOToicG90d2llcmR6ZW5pZS1ha3R5d2Fjamkta29udGEtdy1za2xlcGllIjtzOjM5OiJQb3R3aWVyZHplbmllIGFrdHl3YWNqaSBrb250YSB3IHNrbGVwaWUiO3M6MjU6InJlamVzdHJhY2phLXBvdHdpZXJkemVuaWUiO3M6NjM6IlR3b2plIGtvbnRvIHpvc3RhxYJvIGFrdHl3b3dhbmUuIFRlcmF6IG1vxbxlc3ogc2nEmSB6YWxvZ293YcSHLiI7czo5OiJsb2dvd2FuaWUiO3M6OToibG9nb3dhbmllIjtzOjE5OiJuaWUtcGFtaWV0YXN6LWhhc2xhIjtzOjIyOiJOaWUgcGFtacSZdGFzeiBoYXPFgmE/IjtzOjEwOiJub3dlLWhhc2xvIjtzOjExOiJub3dlIGhhc8WCbyI7czoxNDoibmllLW1hc3ota29udGEiO3M6MTU6Ik5pZSBtYXN6IGtvbnRhPyI7czoyOToibWV0YS10aXRsZS1vZHp5c2tpd2FuaWUtaGFzbGEiO3M6MTk6Ik9kenlza2l3YW5pZSBoYXPFgmEiO3M6MTg6Im9kenlza2l3YW5pZS1oYXNsYSI7czoxOToib2R6eXNraXdhbmllIGhhc8WCYSI7czoxMzoicmVzZXR1ai1oYXNsbyI7czoxNDoicmVzZXR1aiBoYXPFgm8iO3M6MzQ6ImdlbmVyb3dhbmllLW5vd2Vnby1oYXNsYS13LXNrbGVwaWUiO3M6NDc6IkdlbmVyb3dhbmllIG5vd2VnbyBoYXPFgmEgdyBza2xlcGllIG1hcmlhbmVrLnBsIjtzOjMzOiJvZHp5c2tpd2FuaWUtaGFzbGEtbGluay1rb211bmlrYXQiO3M6ODU6IkxpbmsgZG8gd3lnZW5lcm93YW5pYSBub3dlZ28gaGFzxYJhIHpvc3RhxYIgcG9tecWbbG5pZSB3eXPFgmFueSBuYSBUd8OzaiBhZHJlcyBlbWFpbC4iO3M6MjM6Im9kenlza2l3YW5pZS1oYXNsYS1ibGFkIjtzOjgxOiJQb2RjemFzIHByw7NieSBvZHp5c2thbmlhIGhhc8WCYSB3eXN0xIVwacWCIGLFgsSFZC4gUHJvc3rEmSBzcHLDs2Jvd2HEhyBwb25vd25pZS4iO3M6NDY6Im5vd2UtaGFzbG8tem9zdGFsby13eXNsYW5lLW5hLXR3b2otYWRyZXMtZW1haWwiO3M6NTE6Ik5vd2UgaGFzxYJvIHpvc3RhxYJvIHd5c8WCYW5lIG5hIFR3w7NqIGFkcmVzIGVtYWlsLiI7czoyMDoibm93ZS1oYXNsby13LXNrbGVwaWUiO3M6MzM6Ik5vd2UgaGFzxYJvIHcgc2tsZXBpZSBtYXJpYW5lay5wbCI7czoxODoibG9nb3dhbmllLW5pZXVkYW5lIjtzOjQ4OiJMb2dvd2FuaWUgc2nEmSBuaWUgcG93aW9kxYJvLiBTcHLDs2J1aiBwb25vd25pZS4iO3M6MTU6ImxvZ293YW5pZS11ZGFuZSI7czo1OToiV8WCYcWbbmllIHpvc3RhxYJlxZsgemFsb2dvd2FueS4gxbt5Y3p5bXkgdWRhbnljaCB6YWt1cMOzdy4iO3M6MTA6Im1vamUta29udG8iO3M6MTA6Im1vamUga29udG8iO3M6MTE6Ind5bG9ndWotc2llIjtzOjEyOiJ3eWxvZ3VqIHNpxJkiO3M6MTc6Imhpc3RvcmlhLXphbW93aWVuIjtzOjE5OiJoaXN0b3JpYSB6YW3Ds3dpZcWEIjtzOjY6ImFkcmVzeSI7czo2OiJhZHJlc3kiO3M6MTc6ImFkcmVzeS1kby13eXN5bGtpIjtzOjE4OiJhZHJlc3kgZG8gd3lzecWCa2kiO3M6MTY6ImRvZGFqLW5vd3ktYWRyZXMiO3M6MTY6ImRvZGFqIG5vd3kgYWRyZXMiO3M6NjoiYW51bHVqIjtzOjY6ImFudWx1aiI7czo1OiJkb2RhaiI7czo1OiJkb2RhaiI7czo1OiJmaXJtYSI7czo1OiJmaXJtYSI7czoxMToib3Bjam9uYWxuaWUiO3M6MTE6Im9wY2pvbmFsbmllIjtzOjEzOiJ1bGljYS1pLW51bWVyIjtzOjEzOiJ1bGljYSBpIG51bWVyIjtzOjExOiJtaWVqc2Nvd29zYyI7czoxMzoibWllanNjb3dvxZvEhyI7czoxNDoibnVtZXItdGVsZWZvbnUiO3M6MTQ6Im51bWVyIHRlbGVmb251IjtzOjI4OiJkb2Rhd2FuaWUtbm93ZWdvLWFkcmVzdS1ibGFkIjtzOjgwOiJQb2RjemFzIGRvZGF3YW5pYSBub3dlZ28gYWRyZXN1IHd5c3TEhXBpxYIgYsWCxIVkLiBQcm9zesSZIHNwcsOzYm93YcSHIHBvbm93bmllLiI7czozMDoiZG9kYXdhbmllLW5vd2Vnby1hZHJlc3Utc3VrY2VzIjtzOjI2OiJOb3d5IGFkcmVzIHpvc3RhxYIgZG9kYW55LiI7czo1OiJ6bWllbiI7czo2OiJ6bWllxYQiO3M6NjoiemFwaXN6IjtzOjY6InphcGlzeiI7czoxODoiem1pYW5hLWFkcmVzdS1ibGFkIjtzOjcwOiJQb2RjemFzIGVkeWNqaSBhZHJlc3Ugd3lzdMSFcGnFgiBixYLEhWQuIFByb3N6xJkgc3Byw7Nib3dhxIcgcG9ub3duaWUuIjtzOjIwOiJ6bWlhbmEtYWRyZXN1LXN1a2NlcyI7czoyNDoiQWRyZXMgem9zdGHFgiB6bWllbmlvbnkuIjtzOjI2OiJwb3R3aWVyZHotdXN1bmllY2llLWFkcmVzdSI7czo0MzoiQ3p5IG5hIHBld25vIGNoY2VzeiB1c3VuxIXEhyB3eWJyYW55IGFkcmVzPyI7czoxOToiYWRyZXMtdXN1bmlldHktYmxhZCI7czo3MjoiUG9kY3phcyB1c3V3YW5pYSBhZHJlc3Ugd3lzdMSFcGnFgiBixYLEhWQuIFByb3N6xJkgc3Byw7Nib3dhxIcgcG9ub3duaWUuIjtzOjI0OiJhZHJlcy11c3VuaWV0eS1rb211bmlrYXQiO3M6MzI6Ild5YnJhbnkgYWRyZXMgem9zdGHFgiB1c3VuacSZdHkuIjtzOjc6Ind5YmllcnoiO3M6Nzoid3liaWVyeiI7czoxODoiemFtb3dpZW5pZS16bG96b25lIjtzOjIxOiJ6YW3Ds3dpZW5pZSB6xYJvxbxvbmUiO3M6MTU6InJhemVtLXotZG9zdGF3YSI7czoxNjoicmF6ZW0geiBkb3N0YXfEhSI7czo3OiJub3dvc2NpIjtzOjg6Im5vd2/Fm2NpIjtzOjIwOiJwb2R6aWVsLXNpZS16LWlubnltaSI7czoyMToicG9kemllbCBzacSZIHogaW5ueW1pIjtzOjU6Im1uaWVqIjtzOjU6Im1uaWVqIjtzOjc6ImRvc3Rhd2EiO3M6NzoiZG9zdGF3YSI7czo4OiJwbGF0bm9zYyI7czoxMToicMWCYXRub8WbxIciO3M6Mzoic3p0IjtzOjM6InN6dCI7czoyMjoia29udGFrdC16Z29kYS1jaGVja2JveCI7czoxNjk6IkFkbWluaXN0cmF0b3JlbSBkYW55Y2ggb3NvYm93eWNoIGplc3Qgc2tsZXAgbWFyaWFuZWsucGwuLiBEYW5lIHdwaXNhbmUgdyBmb3JtdWxhcnp1IGtvbnRha3Rvd3ltIGLEmWTEhSBwcnpldHdhcnphbmUgdyBjZWx1IHVkemllbGVuaWEgb2Rwb3dpZWR6aSBuYSBwcnplc8WCYW5lIHphcHl0YW5pZS4iO3M6MjI6InByb3N6ZS16YXpuYWN6eWMtemdvZGUiO3M6NTg6IlByb3N6xJkgemF6bmFjennEhyB6Z29kxJkgbmEgcHJ6ZWthemFuaWUgb2ZlcnR5IGhhbmRsb3dlai4iO3M6MzE6Im1ldGEtdGl0bGUtc3pjemVnb2x5LXphbW93aWVuaWEiO3M6MjM6IlN6Y3plZ8OzxYJ5IHphbcOzd2llbmlhIjtzOjE1OiJwbGF0bm9zYy1vbmxpbmUiO3M6MTg6InDFgmF0bm/Fm8SHIG9ubGluZSI7czoyNjoiYWtjZXB0dWplLXJlZ3VsYW1pbi1za2xlcHUiO3M6Njk6IkFrY2VwdHVqxJkgPGEgaHJlZj0iL3JlZ3VsYW1pbiIgdGFyZ2V0PSJfYmxhbmsiPnJlZ3VsYW1pbjwvYT4gc2tsZXB1LiI7czoxMzoiemFwbGFjLW9ubGluZSI7czoxNToiemFwxYJhxIcgb25saW5lIjtzOjIwOiJzemN6ZWdvbHktemFtb3dpZW5pYSI7czoyMzoic3pjemVnw7PFgnkgemFtw7N3aWVuaWEiO3M6MTk6InphbW93aWVuaWUtb3BsYWNvbmUiO3M6MjE6InphbcOzd2llbmllIG9wxYJhY29uZSI7czoxODoicGxhdG5vc2Mtb2RyenVjb25hIjtzOjIxOiJwxYJhdG5vxZvEhyBvZHJ6dWNvbmEiO3M6Mjc6InBsYXRub3NjLXNwcmF3ZHphbmEtcmVjem5pZSI7czozMToicMWCYXRub8WbxIcgc3ByYXdkemFuYSByxJljem5pZSI7czo5OiJzemN6ZWdvbHkiO3M6MTE6InN6Y3plZ8OzxYJ5IjtzOjI3OiJ6YW1vd2llbmllLXpvc3RhbG8tb3BsYWNvbmUiO3M6MzE6IlphbcOzd2llbmllIHpvc3RhxYJvIG9wxYJhY29uZS4iO3M6MjY6InBsYXRub3NjLXpvc3RhbGEtb2RyenVjb25hIjtzOjMxOiJQxYJhdG5vxZvEhyB6b3N0YcWCYSBvZHJ6dWNvbmEuIjtzOjM0OiJ6YW1vd2llbmllLXpvc3RhbG8tb3BsYWNvbmUtcmVjem5lIjtzOjc4OiJQxYJhdG5vxZvEhyB6b3N0YcWCYSB6YWFrY2VwdG93YW5hLCBhbGUgbXVzaSBqZXN6Y3plIGJ5xIcgc3ByYXdkem9uYSByxJljem5pZS4iO3M6NDoib3BpcyI7czo0OiJvcGlzIjtzOjE3OiJ3cm9jLWRvLWthdGVnb3JpaSI7czoxOToid3LDs8SHIGRvIGthdGVnb3JpaSI7czoyMDoibWV0YS10aXRsZS1sb2dvd2FuaWUiO3M6OToiTG9nb3dhbmllIjtzOjIyOiJtZXRhLXRpdGxlLXJlamVzdHJhY2phIjtzOjExOiJSZWplc3RyYWNqYSI7czoyODoibWV0YS10aXRsZS1oaXN0b3JpYS16YW1vd2llbiI7czoxOToiSGlzdG9yaWEgemFtw7N3aWXFhCI7czoyNDoibWV0YS10aXRsZS1saXN0YS1hZHJlc293IjtzOjE0OiJMaXN0YSBhZHJlc8OzdyI7czoyNDoibWV0YS10aXRsZS1lZHljamEtYWRyZXN1IjtzOjEzOiJFZHljamEgYWRyZXN1IjtzOjIxOiJwb2thei11a3J5ai1rYXRlZ29yaWUiO3M6MjQ6Iihwb2thxbwvdWtyeWoga2F0ZWdvcmllKSI7czoxODoicHJvZHVrdHktcG93aWF6YW5lIjtzOjE5OiJwcm9kdWt0eSBwb3dpxIV6YW5lIjtzOjM0OiJsb2dvd2FuaWUtYmxhZC1uaWVwcmF3aWRsb3dlLWhhc2xvIjtzOjM0OiJQb2RhbmUgaGFzxYJvIGplc3QgbmllcHJhd2lkxYJvd2UuIjtzOjE5OiJkb2JpZXJ6LWRvLWtvbXBsZXR1IjtzOjE5OiJkb2JpZXJ6IGRvIGtvbXBsZXR1IjtzOjE2OiJrb250eW51dWotemFrdXB5IjtzOjE2OiJrb250eW51dWogemFrdXB5IjtzOjY6Im5vd29zYyI7czo4OiJub3dvxZvEhyI7czoxNzoicG9sZWNhbmUtcHJvZHVrdHkiO3M6MTc6IlBvbGVjYW5lIHByb2R1a3R5IjtzOjIzOiJwcm9kdWt0LWN6YXMtcmVhbGl6YWNqaSI7czo1OToiQ3phcyByZWFsaXphY2ppIHphbcOzd2llbmlhIHd5bm9zaSBvZCAxIGRvIDMgZG5pIHJvYm9jenljaC4iO3M6NToidXdhZ2EiO3M6NToidXdhZ2EiO3M6MzM6InphbW93aWVuaWUtcHJ6eWpldGUtZG8tcmVhbGl6YWNqaSI7czozNToiemFtw7N3aWVuaWUgcHJ6eWrEmXRlIGRvIHJlYWxpemFjamkiO3M6MTg6InphbW93aWVuaWUtd3lzbGFuZSI7czoyMDoiemFtw7N3aWVuaWUgd3lzxYJhbmUiO3M6MjM6InphbW93aWVuaWUtenJlYWxpem93YW5lIjtzOjI0OiJ6YW3Ds3dpZW5pZSB6cmVhbGl6b3dhbmUiO3M6MzA6InphbW93aWVuaWUtbnItem9zdGFsby1vcGxhY29uZSI7czozODoiWmFtw7N3aWVuaWUgW05VTUVSXSB6b3N0YcWCbyBvcMWCYWNvbmUiO3M6NDQ6InphbW93aWVuaWUtbnItem9zdGFsby1wcnp5amV0ZS1kby1yZWFsaXphY2ppIjtzOjUyOiJaYW3Ds3dpZW5pZSBbTlVNRVJdIHpvc3RhxYJvIHByenlqxJl0ZSBkbyByZWFsaXphY2ppIjtzOjI5OiJ6YW1vd2llbmllLW5yLXpvc3RhbG8td3lzbGFuZSI7czozNzoiWmFtw7N3aWVuaWUgW05VTUVSXSB6b3N0YcWCbyB3eXPFgmFuZSI7czozNDoiemFtb3dpZW5pZS1uci16b3N0YWxvLXpyZWFsaXpvd2FuZSI7czo0MToiWmFtw7N3aWVuaWUgW05VTUVSXSB6b3N0YcWCbyB6cmVhbGl6b3dhbmUiO3M6MTA6ImRvLWtvc3p5a2EiO3M6MTA6ImRvIGtvc3p5a2EiO3M6MzM6Ind5bmlraS13eXN6dWtpd2FuaWEtZGxhLXphcHl0YW5pYSI7czozMzoiV3luaWtpIHd5c3p1a2l3YW5pYSBkbGEgemFweXRhbmlhIjtzOjExOiJzcGlzLXRyZXNjaSI7czoxMjoic3BpcyB0cmXFm2NpIjtzOjEzOiJ6b2JhY3otd2llY2VqIjtzOjE0OiJab2JhY3ogd2nEmWNlaiI7czoxMzoib3Bpcy1wcm9kdWt0dSI7czoxMzoiT3BpcyBwcm9kdWt0dSI7czoxOToicG9wdWxhcm5lLWthdGVnb3JpZSI7czoxOToiUG9wdWxhcm5lIGthdGVnb3JpZSI7czoxMzoiY3plZ28tc3p1a2FzeiI7czoxMzoiQ3plZ28gc3p1a2FzeiI7czoyMToid3Bpc3otc3p1a2FueS1wcm9kdWt0IjtzOjIxOiJXcGlzeiBzenVrYW55IHByb2R1a3QiO3M6MjQ6Im5pZS16bmFsZXppb25vLXByb2R1a3RvdyI7czozNDoiTmllIHpuYWxlemlvbm8gxbxhZG55Y2ggcHJvZHVrdMOzdyI7czo0MDoicHJvZHVrdC1taWVqc2NlLW5hLXdpYWRvbW9zYy1wbGFjZWhvbGRlciI7czozODoiVHV0YWogbW/FvGVzeiBwb2RhxIcgbnAuIGltacSZIGR6aWVja2EiO3M6Njoib3BpbmllIjtzOjY6Im9waW5pZSI7czoxOToiZnJlZS1kZWxpdmVyeS1wcmljZSI7czozMToiRGFybW93YSB3eXN5xYJrYSBqdcW8IG9kIDk5IHrFgiI7czo0OiJibG9nIjtzOjQ6ImJsb2ciO319 \ No newline at end of file +YToyOntpOjA7aToxNjkzOTQ2ODEzO2k6MTthOjE5ODp7aTowO3M6MjoicGwiO3M6NToidGVtYXQiO3M6NToidGVtYXQiO3M6OToid2lhZG9tb3NjIjtzOjExOiJ3aWFkb21vxZvEhyI7czo2OiJ3eXNsaWoiO3M6Nzoid3nFm2xpaiI7czo1OiJlbWFpbCI7czo1OiJlbWFpbCI7czoxMToibnItdGVsZWZvbnUiO3M6MTE6Im5yIHRlbGVmb251IjtzOjM0OiJwcm9zemUtdXp1cGVsbmljLWVtYWlsLWx1Yi10ZWxlZm9uIjtzOjUxOiJQcm9zesSZIHV6dXBlxYJuacSHIGFkcmVzIGVtYWlsIGx1YiBudW1lciB0ZWxlZm9udS4iO3M6NDoiYmxhZCI7czo2OiJixYLEhWQiO3M6NzoiemFta25paiI7czo3OiJ6YW1rbmlqIjtzOjI1OiJ3aWFkb21vc2Mtem9zdGFsYS13eXNsYW5hIjtzOjkwOiJUd29qYSB3aWFkb21vxZvEhyB6b3N0YcWCYSB3eXPFgmFuYS4gUG9zdGFyYW15IHNpxJkgbmEgbmnEhSBvZHBvd2llZHppZcSHIGphayBuYWpzenliY2llai4iO3M6Mjg6IndpYWRvbW9zYy1uaWV6b3N0YWxhLXd5c2xhbmEiO3M6OTM6IlBvZGN6YXMgd3lzecWCYW5pYSB3aWFkb21vxZtjaSB3eXN0xIVwacWCIGLFgsSFZC4gUHJvc3rEmSBzcHLDs2Jvd2HEhyBwb25vd25pZS4gUHJ6ZXByYXN6YW15LiI7czoxMjoiZGF0YS1kb2RhbmlhIjtzOjEyOiJkYXRhIGRvZGFuaWEiO3M6MTY6ImRhdGEtbW9keWZpa2FjamkiO3M6MTY6ImRhdGEgbW9keWZpa2FjamkiO3M6MTI6ImFkcmVzLXN0cm9ueSI7czoxMjoiYWRyZXMgc3Ryb255IjtzOjI5OiJwcm9zemUtdXp1cGVsbmljLWFkcmVzLXN0cm9ueSI7czozMzoiUHJvc3rEmSB1enVwZcWCbmnEhyBhZHJlcyBzdHJvbnkuIjtzOjg6InBpZXJ3c3phIjtzOjg6InBpZXJ3c3phIjtzOjg6Im5hc3RlcG5hIjtzOjk6Im5hc3TEmXBuYSI7czoxMDoicG9wcnplZG5pYSI7czoxMDoicG9wcnplZG5pYSI7czo4OiJvc3RhdG5pYSI7czo4OiJvc3RhdG5pYSI7czoxOiJ6IjtzOjE6InoiO3M6Njoid2llY2VqIjtzOjc6IndpxJljZWoiO3M6Njoid3N0ZWN6IjtzOjY6IndzdGVjeiI7czoyMzoiZm9ybXVsYXJ6LWNhcHRjaGEtbGFiZWwiO3M6Njk6IlByb3N6xJkgbmFyeXNvd2HEhyBrc3p0YcWCdCB3IHBvbmnFvHN6eW0gcG9sdSwgYWJ5IHd5c8WCYcSHIGZvcm11bGFyeiI7czoxNjoic3Byb2J1ai1wb25vd25pZSI7czoxNzoic3Byw7NidWogcG9ub3duaWUiO3M6NjoiZG9icnplIjtzOjY6ImRvYnJ6ZSI7czo1OiJ3aXRhaiI7czo1OiJ3aXRhaiI7czoxMToiemFsb2d1ai1zaWUiO3M6MTI6InphbG9ndWogc2nEmSI7czozOiJsdWIiO3M6MzoibHViIjtzOjE1OiJ6YXJlamVzdHJ1ai1zaWUiO3M6MTY6InphcmVqZXN0cnVqIHNpxJkiO3M6NToiaWxvc2MiO3M6NzoiaWxvxZvEhyI7czo0OiJzdW1hIjtzOjQ6InN1bWEiO3M6ODoicG9sZWNhbXkiO3M6ODoicG9sZWNhbXkiO3M6MTg6InNwcmF3ZHota29uaWVjem5pZSI7czoxOToic3ByYXdkxboga29uaWVjem5pZSI7czoxNjoiZG9kYWotZG8ta29zenlrYSI7czoxNjoiZG9kYWogZG8ga29zenlrYSI7czoxNDoic3RyZWZhLXJvZHppY2EiO3M6MTQ6InN0cmVmYSByb2R6aWNhIjtzOjE2OiJuYWpub3dzemUtcG9yYWR5IjtzOjE2OiJOYWpub3dzemUgcG9yYWR5IjtzOjE4OiJuZXdzbGV0dGVyLXpnb2RhLTEiO3M6NTU6Ild5cmHFvGFtIHpnb2TEmSBuYSBwcnpldHdhcnphbmllIG1vaWNoIGRhbnljaCBvc29ib3d5Y2giO3M6NDoiendpbiI7czo1OiJ6d2nFhCI7czo2OiJyb3p3aW4iO3M6Nzoicm96d2nFhCI7czozMzoibmV3c2xldHRlci1hZG1pbmlzdHJhdG9yLWRhbnljaC0xIjtzOjYxOiJBZG1pbmlzdHJhdG9yZW0gZGFueWNoIG9zb2Jvd3ljaCB6YXdhcnR5Y2ggdyB6Z8WCb3N6ZW5pdSBqZXN0IjtzOjMzOiJuZXdzbGV0dGVyLWFkbWluaXN0cmF0b3ItZGFueWNoLTIiO3M6NzQ2OiJfX19fXy4gRGFuZSBrb250YWt0b3dlIEluc3Bla3RvcmEgT2Nocm9ueSBEYW55Y2g6IHVva2lrQHVva2lrLmdvdi5wbC4gRGFuZSBvc29ib3dlIHPEhSBwcnpldHdhcnphbmUgdyBjZWx1IGRvc3RhcmN6ZW5pYSBuZXdzbGV0dGVyYSwgbmEgcG9kc3Rhd2llIGFydC4gNiB1c3QuIDEgbGl0LiBhKSByb3pwb3J6xIVkemVuaWEgUGFybGFtZW50dSBFdXJvcGVqc2tpZWdvIGkgUmFkeSAoVUUpIDIwMTYvNjc5IChST0RPKSBpIG5pZSBzxIUgcHJ6ZWthenl3YW5lIGlubnltIG9kYmlvcmNvbSwgb3JnYW5pemFjamkgbWnEmWR6eW5hcm9kb3dlaiBjenkgZG8gcGHFhHN0dyB0cnplY2ljaC4gRGFuZSBvc29ib3dlIHByemVjaG93eXdhbmUgc8SFIHByemV6IG9rcmVzIHByZW51bWVyYXR5LiBXbmlvc2tvZGF3Y2EgbWEgcHJhd28gZG8gZG9zdMSZcHUgZG8gc3dvaWNoIGRhbnljaCBvc29ib3d5Y2gsIGljaCBzcHJvc3Rvd2FuaWEgb3JheiB3bmllc2llbmlhIHNrYXJnaSBkbyBfX19fXy4gUG9kYW5pZSBkYW55Y2ggb3NvYm93eWNoIGplc3QgZG9icm93b2xuZSwgbmllIHd5bmlrYSB6IHByemVwaXPDs3csIGljaCBuaWVwb2RhbmllIGLEmWR6aWUgc2t1dGtvd2HFgm8gYnJha2llbSBtb8W8bGl3b8WbY2kgemFtw7N3aWVuaWEuIE5hIHBvZHN0YXdpZSBkYW55Y2ggb3NvYm93eWNoIG5pZSBzxIUgcG9kZWptb3dhbmUgemF1dG9tYXR5em93YW5lIGRlY3l6amUsIHcgdHltIG5pZSBzdG9zdWplIHNpxJkgcHJvZmlsb3dhbmlhLiI7czoyNjoibmV3c2xldHRlci16Z29kYS1rb211bmlrYXQiO3M6NTc6IlByb3N6xJkgemF6bmFjennEhyB6Z29kxJkgZG8gcHJ6ZXR3YXJ6YW5pYSB6IG5ld3NsZXR0ZXJhLiI7czozMzoibmV3c2xldHRlci1wcm9zemUtdXp1cGVsbmljLWVtYWlsIjtzOjMyOiJQcm9zesSZIHV6dXBlxYJuacSHIGFkcmVzIGVtYWlsLiI7czozODoicG90d2llcmR6LXphcGlzYW5pZS1zaWUtZG8tbmV3c2xldHRlcmEiO3M6NDA6IlBvdHdpZXJkxbogemFwaXNhbmllIHNpxJkgZG8gbmV3c2xldHRlcmEiO3M6MTM6InByb3N6ZS1jemVrYWMiO3M6MTg6IlByb3N6xJkgY3pla2HEhy4uLiI7czoxMDoiaW5mb3JtYWNqYSI7czoxMDoiSW5mb3JtYWNqYSI7czozOToiZW1haWwtem9zdGFsLWRvZGFueS1kby1saXN0eS1uZXdzbGV0dGVyIjtzOjQxOiJFbWFpbCB6b3N0YcWCIGRvZGFueSBkbyBsaXN0eSBuZXdzbGV0dGVyLiI7czozMjoibmV3c2xldHRlci1wb3R3aWVyZHplbmllLWRvZGFuaWEiO3M6MTYyOiJOYSBwb2RhbnkgcHJ6ZXogQ2llYmllIGUtbWFpbCB6b3N0YcWCYSB3eXPFgmFuYSB3aWFkb21vxZvEhyB6IGxpbmtpZW0gYWt0eXd1asSFY3ltLiBLbGlrbmlqIHcgbGluayBwb3R3aWVyZHphasSFY3ksIGFieSBwb215xZtsbmllIHpha2/FhGN6ecSHIHByb2NlcyByZWplc3RyYWNqaS4iO3M6Mzc6Im5ld3NsZXR0ZXItcG90d2llcmR6ZW5pZS1kb2RhbmlhLWJsYWQiO3M6ODQ6IlBvZGN6YXMgcmVqZXN0cmFjamkgYWRyZXN1IGUtbWFpbCBwb2phd2nFgiBzacSZIGLFgsSFZC4gUHJvc2lteSBzcHJvYm93YcSHIHBvbm93bmllLiI7czozMjoicHJvc3plLXV6dXBlbG5pYy1lbWFpbC1pLXRlbGVmb24iO3M6NDk6IlByb3N6xJkgdXp1cGXFgm5pxIcgYWRyZXMgZW1haWwgaSBudW1lciB0ZWxlZm9udS4iO3M6MTA6Ind5cGlzei1zaWUiO3M6MTE6Ind5cGlzeiBzacSZIjtzOjQwOiJlbWFpbC16b3N0YWwtdXN1bmlldHktei1saXN0eS1uZXdzbGV0dGVyIjtzOjQzOiJFbWFpbCB6b3N0YcWCIHVzdW5pxJl0eSB6IGxpc3R5IG5ld3NsZXR0ZXIuIjtzOjEwOiJuZXdzbGV0dGVyIjtzOjEwOiJuZXdzbGV0dGVyIjtzOjE1OiJuZXdzbGV0dGVyLXRleHQiO3M6NzI6IlphcGlzeiBzacSZIGRvIG5ld3NsZXR0ZXJhIGJ5IGJ5xIcgbmEgYmllxbzEhWNvIHogbm93b8WbY2lhbWkgdyBza2xlcGllLiI7czoxODoibmV3c2xldHRlci16Z29kYS0yIjtzOjQwODoiIChhZHJlc3UgZS1tYWlsKSB6YXdhcnR5Y2ggdyB6Z8WCb3N6ZW5pdSwgdyB6d2nEhXprdSB6IGFydC4gNiB1c3QuIDEgbGl0LiBhLCByb3pwb3J6xIVkemVuaWEgUGFybGFtZW50dSBFdXJvcGVqc2tpZWdvIGkgUmFkeSAoVUUpIDIwMTYvNjc5IHogZG5pYSAyNyBrd2lldG5pYSAyMDE2IHIuIHcgc3ByYXdpZSBvY2hyb255IG9zw7NiIGZpenljem55Y2ggdyB6d2nEhXprdSB6IHByemV0d2FyemFuaWVtIGRhbnljaCBvc29ib3d5Y2ggaSB3IHNwcmF3aWUgc3dvYm9kbmVnbyBwcnplcMWCeXd1IHRha2ljaCBkYW55Y2ggb3JheiB1Y2h5bGVuaWEgZHlyZWt0eXd5IDk1LzQ2L1dFIChST0RPKS4gVyBrYcW8ZHltIG1vbWVuY2llIG1vZ8SZIHd5Y29mYcSHIHpnb2TEmSB3eXBpc3VqxIVjIHNpxJkgeiBuZXdzbGV0dGVyYS4gIjtzOjMyOiJwcm9kdWt0LXpvc3RhbC1kb2RhbnktZG8ta29zenlrYSI7czo0MjoiV3licmFueSBwcm9kdWt0IHpvc3RhxYIgZG9kYW55IGRvIGtvc3p5a2EuIjtzOjE4OiJwcnplamR6LWRvLWtvc3p5a2EiO3M6MTk6InByemVqZMW6IGRvIGtvc3p5a2EiO3M6MTc6Inphd2FydG9zYy1rb3N6eWthIjtzOjE5OiJ6YXdhcnRvxZvEhyBrb3N6eWthIjtzOjk6InBvdHdpZXJkeiI7czoxMDoicG90d2llcmTFuiI7czozODoicG90d2llcmR6LXVzdW5pZWNpZS1wcm9kdWt0dS16LWtvc3p5a2EiO3M6NDE6Ik5hIHBld25vIGNoY2VzeiB1c3VuxIXEhyB3eWJyYW55IHByb2R1a3Q/IjtzOjQ6InVzdW4iO3M6NToidXN1xYQiO3M6MTM6InByb3N6ZS13eWJyYWMiO3M6MTU6InByb3N6xJkgd3licmHEhyI7czoxODoiZG9zdGF3YS1pLXBsYXRub3NjIjtzOjIxOiJkb3N0YXdhIGkgcMWCYXRub8WbxIciO3M6MjM6InByemVqZHotZG8tcG9kc3Vtb3dhbmlhIjtzOjI0OiJwcnplamTFuiBkbyBwb2RzdW1vd2FuaWEiO3M6MjM6InBvZHN1bW93YW5pZS16YW1vd2llbmlhIjtzOjI0OiJwb2RzdW1vd2FuaWUgemFtw7N3aWVuaWEiO3M6MzA6InphbWF3aWFtLXotb2Jvd2lhemtpZW0temFwbGF0eSI7czozMjoiemFtYXdpYW0geiBvYm93acSFemtpZW0gemFwxYJhdHkiO3M6MTM6ImRhbmUtYWRyZXNvd2UiO3M6MTM6ImRhbmUgYWRyZXNvd2UiO3M6MzA6Inpsb3otemFtb3dpZW5pZS1iZXotcmVqZXN0cmFqaSI7czozNToiWsWCw7PFvCB6YW3Ds3dpZW5pZSBiZXogcmVqZXN0cmFjamkiO3M6NzoidGVsZWZvbiI7czo3OiJ0ZWxlZm9uIjtzOjQ6ImltaWUiO3M6NToiaW1pxJkiO3M6ODoibmF6d2lza28iO3M6ODoibmF6d2lza28iO3M6MTU6InVsaWNhLWktbnItZG9tdSI7czoxNToidWxpY2EgaSBuciBkb211IjtzOjEyOiJrb2QtcG9jenRvd3kiO3M6MTI6ImtvZCBwb2N6dG93eSI7czo2OiJtaWFzdG8iO3M6NjoibWlhc3RvIjtzOjU3OiJwcnplY3p5dGFsZW0taS1ha2NlcHR1amUtcG9saXR5a2UtcHJ5d2F0bm9zY2ktaS1yZWd1bGFtaW4iO3M6Njk6IkFrY2VwdHVqxJkgPGEgaHJlZj0iL3JlZ3VsYW1pbiIgdGFyZ2V0PSJfYmxhbmsiPnJlZ3VsYW1pbjwvYT4gc2tsZXB1LiI7czoxNToid3JvYy1kby1rb3N6eWthIjtzOjE3OiJ3csOzxIcgZG8ga29zenlrYSI7czozNjoiemFtb3dpZW5pZS16b3N0YWxvLXpsb3pvbmUta29tdW5pa2F0IjtzOjE1MDoiWmFtw7N3aWVuaWUgem9zdGHFgm8gesWCb8W8b25lLjxiciAvPk5hIHBvZGFueSBhZHJlcyBlbWFpbCB6b3N0YcWCbyB3eXPFgmFuZSBwb3R3aWVyZHpuaWUuIFByb3N6xJkgcsOzd25pZcW8IHNwcmF3ZHppxIcgZm9sZGVyIHNwYW0uPGJyIC8+RHppxJlrdWplbXkuIjtzOjQxOiJ6YW1vd2llbmllLXpvc3RhbG8temxvem9uZS1rb211bmlrYXQtYmxhZCI7czo3OToiUG9kY3phcyBza8WCYWRhbmlhIHphbcOzd2llbmlhIHd5c3TEhXBpxYIgYsWCxIVkLiBQcm9zaW15IHNwcsOzYm93YcSHIHBvbm93bmllLiI7czozNDoicG90d2llcmR6ZW5pZS16YW1vd2llbmlhLXplLXNrbGVwdSI7czozNToiUG90d2llcmR6ZW5pZSB6YW3Ds3dpZW5pYSB6ZSBza2xlcHUiO3M6MjoibnIiO3M6MjoibnIiO3M6NzoicHJvZHVrdCI7czo3OiJwcm9kdWt0IjtzOjQ6ImNlbmEiO3M6NDoiY2VuYSI7czo1OiJyYXplbSI7czo1OiJyYXplbSI7czo2OiJ6LWRuaWEiO3M6NjoieiBkbmlhIjtzOjE1OiJkYW5lLWRvLWRvc3Rhd3kiO3M6MTU6ImRhbmUgZG8gZG9zdGF3eSI7czoxODoiemFtb3dpb25lLXByb2R1a3R5IjtzOjE5OiJ6YW3Ds3dpb25lIHByb2R1a3R5IjtzOjE2OiJkYW5lLWRvLXByemVsZXd1IjtzOjE2OiJkYW5lIGRvIHByemVsZXd1IjtzOjE5OiJ6YWxvei1rb250by1rbGllbnRhIjtzOjIyOiJaYcWCw7PFvCBrb250byBrbGllbnRhIjtzOjU6Imhhc2xvIjtzOjY6Imhhc8WCbyI7czozOiJtaW4iO3M6NDoibWluLiI7czo2OiJ6bmFrb3ciO3M6Nzoiem5ha8OzdyI7czoxMzoicG93dG9yei1oYXNsbyI7czoxNToicG93dMOzcnogaGFzxYJvIjtzOjMzOiJyZWplc3RyYWNqYS1ha2NlcHRhY2phLXJlZ3VsYW1pbnUiO3M6Njk6IkFrY2VwdHVqxJkgW0xJTkstUkVHVUxBTUlOXSBvcmF6IFtMSU5LLVBPTElUWUtBLVBSWVdBVE5PU0NJXSBzZXJ3aXN1LiI7czozMDoicmVqZXN0cmFjamEtemdvZGEtbmEtbWFya2V0aW5nIjtzOjYzOiJDaGPEmSBvdHJ6eW15d2HEhyBtYWlsZW0gaW5mb3JtYWNqZSBtYXJrZXRpbmdvd2Ugb2QgbWFyaWFuZWsucGwiO3M6OToicmVndWxhbWluIjtzOjk6InJlZ3VsYW1pbiI7czoyMDoicG9saXR5a2UtcHJ5d2F0bm9zY2kiO3M6MjI6InBvbGl0eWvEmSBwcnl3YXRub8WbY2kiO3M6MTQ6Im1hc3otanV6LWtvbnRvIjtzOjE1OiJtYXN6IGp1xbwga29udG8iO3M6MjM6InJlamVzdHJhY2phLWJsYWQtb2dvbG55IjtzOjcwOiJXIHRyYWtjaWUgcmVqZXN0cmFjamkgd3lzdMSFcGnFgiBixYLEhWQuIFByb3N6xJkgc3Byw7Nib3dhxIcgcG9ub3duaWUuIjtzOjI0OiJyZWplc3RyYWNqYS1lbWFpbC16YWpldHkiO3M6Mzc6IlBvZGFueSBhZHJlcyBlbWFpbCBqZXN0IGp1xbwgemFqxJl0eS4iO3M6MjE6InBvZGFuZS1oYXNsYS1zYS1yb3puZSI7czoyNjoiUG9kYW5lIGhhc8WCYSBzxIUgcsOzxbxuZS4iO3M6NDE6InBvdHdpZXJkemVuaWUtcmVqZXN0cmFjamkta29udGEtdy1za2xlcGllIjtzOjQxOiJQb3R3aWVyZHplbmllIHJlamVzdHJhY2ppIGtvbnRhIHcgc2tsZXBpZSI7czoxNDoiI25hendhLXNlcndpc3UiO3M6MTE6Im1hcmlhbmVrLnBsIjtzOjE3OiJyZWplc3RyYWNqYS11ZGFuYSI7czoxMTQ6IkR6acSZa3VqZW15IHphIHJlamVzdHJhY2rEmS4gTmEgcG9kYW55IGFkcmVzIGVtYWlsIHpvc3RhxYJhIHd5c8WCYW5hIHdpYWRvbW/Fm8SHIHogbGlua2llbSBkbyBwb3R3aWVyZHplbmllIGtvbnRhLiI7czozOToicG90d2llcmR6ZW5pZS1ha3R5d2Fjamkta29udGEtdy1za2xlcGllIjtzOjM5OiJQb3R3aWVyZHplbmllIGFrdHl3YWNqaSBrb250YSB3IHNrbGVwaWUiO3M6MjU6InJlamVzdHJhY2phLXBvdHdpZXJkemVuaWUiO3M6NjM6IlR3b2plIGtvbnRvIHpvc3RhxYJvIGFrdHl3b3dhbmUuIFRlcmF6IG1vxbxlc3ogc2nEmSB6YWxvZ293YcSHLiI7czo5OiJsb2dvd2FuaWUiO3M6OToibG9nb3dhbmllIjtzOjE5OiJuaWUtcGFtaWV0YXN6LWhhc2xhIjtzOjIyOiJOaWUgcGFtacSZdGFzeiBoYXPFgmE/IjtzOjEwOiJub3dlLWhhc2xvIjtzOjExOiJub3dlIGhhc8WCbyI7czoxNDoibmllLW1hc3ota29udGEiO3M6MTU6Ik5pZSBtYXN6IGtvbnRhPyI7czoyOToibWV0YS10aXRsZS1vZHp5c2tpd2FuaWUtaGFzbGEiO3M6MTk6Ik9kenlza2l3YW5pZSBoYXPFgmEiO3M6MTg6Im9kenlza2l3YW5pZS1oYXNsYSI7czoxOToib2R6eXNraXdhbmllIGhhc8WCYSI7czoxMzoicmVzZXR1ai1oYXNsbyI7czoxNDoicmVzZXR1aiBoYXPFgm8iO3M6MzQ6ImdlbmVyb3dhbmllLW5vd2Vnby1oYXNsYS13LXNrbGVwaWUiO3M6NDc6IkdlbmVyb3dhbmllIG5vd2VnbyBoYXPFgmEgdyBza2xlcGllIG1hcmlhbmVrLnBsIjtzOjMzOiJvZHp5c2tpd2FuaWUtaGFzbGEtbGluay1rb211bmlrYXQiO3M6ODU6IkxpbmsgZG8gd3lnZW5lcm93YW5pYSBub3dlZ28gaGFzxYJhIHpvc3RhxYIgcG9tecWbbG5pZSB3eXPFgmFueSBuYSBUd8OzaiBhZHJlcyBlbWFpbC4iO3M6MjM6Im9kenlza2l3YW5pZS1oYXNsYS1ibGFkIjtzOjgxOiJQb2RjemFzIHByw7NieSBvZHp5c2thbmlhIGhhc8WCYSB3eXN0xIVwacWCIGLFgsSFZC4gUHJvc3rEmSBzcHLDs2Jvd2HEhyBwb25vd25pZS4iO3M6NDY6Im5vd2UtaGFzbG8tem9zdGFsby13eXNsYW5lLW5hLXR3b2otYWRyZXMtZW1haWwiO3M6NTE6Ik5vd2UgaGFzxYJvIHpvc3RhxYJvIHd5c8WCYW5lIG5hIFR3w7NqIGFkcmVzIGVtYWlsLiI7czoyMDoibm93ZS1oYXNsby13LXNrbGVwaWUiO3M6MzM6Ik5vd2UgaGFzxYJvIHcgc2tsZXBpZSBtYXJpYW5lay5wbCI7czoxODoibG9nb3dhbmllLW5pZXVkYW5lIjtzOjQ4OiJMb2dvd2FuaWUgc2nEmSBuaWUgcG93aW9kxYJvLiBTcHLDs2J1aiBwb25vd25pZS4iO3M6MTU6ImxvZ293YW5pZS11ZGFuZSI7czo1OToiV8WCYcWbbmllIHpvc3RhxYJlxZsgemFsb2dvd2FueS4gxbt5Y3p5bXkgdWRhbnljaCB6YWt1cMOzdy4iO3M6MTA6Im1vamUta29udG8iO3M6MTA6Im1vamUga29udG8iO3M6MTE6Ind5bG9ndWotc2llIjtzOjEyOiJ3eWxvZ3VqIHNpxJkiO3M6MTc6Imhpc3RvcmlhLXphbW93aWVuIjtzOjE5OiJoaXN0b3JpYSB6YW3Ds3dpZcWEIjtzOjY6ImFkcmVzeSI7czo2OiJhZHJlc3kiO3M6MTc6ImFkcmVzeS1kby13eXN5bGtpIjtzOjE4OiJhZHJlc3kgZG8gd3lzecWCa2kiO3M6MTY6ImRvZGFqLW5vd3ktYWRyZXMiO3M6MTY6ImRvZGFqIG5vd3kgYWRyZXMiO3M6NjoiYW51bHVqIjtzOjY6ImFudWx1aiI7czo1OiJkb2RhaiI7czo1OiJkb2RhaiI7czo1OiJmaXJtYSI7czo1OiJmaXJtYSI7czoxMToib3Bjam9uYWxuaWUiO3M6MTE6Im9wY2pvbmFsbmllIjtzOjEzOiJ1bGljYS1pLW51bWVyIjtzOjEzOiJ1bGljYSBpIG51bWVyIjtzOjExOiJtaWVqc2Nvd29zYyI7czoxMzoibWllanNjb3dvxZvEhyI7czoxNDoibnVtZXItdGVsZWZvbnUiO3M6MTQ6Im51bWVyIHRlbGVmb251IjtzOjI4OiJkb2Rhd2FuaWUtbm93ZWdvLWFkcmVzdS1ibGFkIjtzOjgwOiJQb2RjemFzIGRvZGF3YW5pYSBub3dlZ28gYWRyZXN1IHd5c3TEhXBpxYIgYsWCxIVkLiBQcm9zesSZIHNwcsOzYm93YcSHIHBvbm93bmllLiI7czozMDoiZG9kYXdhbmllLW5vd2Vnby1hZHJlc3Utc3VrY2VzIjtzOjI2OiJOb3d5IGFkcmVzIHpvc3RhxYIgZG9kYW55LiI7czo1OiJ6bWllbiI7czo2OiJ6bWllxYQiO3M6NjoiemFwaXN6IjtzOjY6InphcGlzeiI7czoxODoiem1pYW5hLWFkcmVzdS1ibGFkIjtzOjcwOiJQb2RjemFzIGVkeWNqaSBhZHJlc3Ugd3lzdMSFcGnFgiBixYLEhWQuIFByb3N6xJkgc3Byw7Nib3dhxIcgcG9ub3duaWUuIjtzOjIwOiJ6bWlhbmEtYWRyZXN1LXN1a2NlcyI7czoyNDoiQWRyZXMgem9zdGHFgiB6bWllbmlvbnkuIjtzOjI2OiJwb3R3aWVyZHotdXN1bmllY2llLWFkcmVzdSI7czo0MzoiQ3p5IG5hIHBld25vIGNoY2VzeiB1c3VuxIXEhyB3eWJyYW55IGFkcmVzPyI7czoxOToiYWRyZXMtdXN1bmlldHktYmxhZCI7czo3MjoiUG9kY3phcyB1c3V3YW5pYSBhZHJlc3Ugd3lzdMSFcGnFgiBixYLEhWQuIFByb3N6xJkgc3Byw7Nib3dhxIcgcG9ub3duaWUuIjtzOjI0OiJhZHJlcy11c3VuaWV0eS1rb211bmlrYXQiO3M6MzI6Ild5YnJhbnkgYWRyZXMgem9zdGHFgiB1c3VuacSZdHkuIjtzOjc6Ind5YmllcnoiO3M6Nzoid3liaWVyeiI7czoxODoiemFtb3dpZW5pZS16bG96b25lIjtzOjIxOiJ6YW3Ds3dpZW5pZSB6xYJvxbxvbmUiO3M6MTU6InJhemVtLXotZG9zdGF3YSI7czoxNjoicmF6ZW0geiBkb3N0YXfEhSI7czo3OiJub3dvc2NpIjtzOjg6Im5vd2/Fm2NpIjtzOjIwOiJwb2R6aWVsLXNpZS16LWlubnltaSI7czoyMToicG9kemllbCBzacSZIHogaW5ueW1pIjtzOjU6Im1uaWVqIjtzOjU6Im1uaWVqIjtzOjc6ImRvc3Rhd2EiO3M6NzoiZG9zdGF3YSI7czo4OiJwbGF0bm9zYyI7czoxMToicMWCYXRub8WbxIciO3M6Mzoic3p0IjtzOjM6InN6dCI7czoyMjoia29udGFrdC16Z29kYS1jaGVja2JveCI7czoxNjk6IkFkbWluaXN0cmF0b3JlbSBkYW55Y2ggb3NvYm93eWNoIGplc3Qgc2tsZXAgbWFyaWFuZWsucGwuLiBEYW5lIHdwaXNhbmUgdyBmb3JtdWxhcnp1IGtvbnRha3Rvd3ltIGLEmWTEhSBwcnpldHdhcnphbmUgdyBjZWx1IHVkemllbGVuaWEgb2Rwb3dpZWR6aSBuYSBwcnplc8WCYW5lIHphcHl0YW5pZS4iO3M6MjI6InByb3N6ZS16YXpuYWN6eWMtemdvZGUiO3M6NTg6IlByb3N6xJkgemF6bmFjennEhyB6Z29kxJkgbmEgcHJ6ZWthemFuaWUgb2ZlcnR5IGhhbmRsb3dlai4iO3M6MzE6Im1ldGEtdGl0bGUtc3pjemVnb2x5LXphbW93aWVuaWEiO3M6MjM6IlN6Y3plZ8OzxYJ5IHphbcOzd2llbmlhIjtzOjE1OiJwbGF0bm9zYy1vbmxpbmUiO3M6MTg6InDFgmF0bm/Fm8SHIG9ubGluZSI7czoyNjoiYWtjZXB0dWplLXJlZ3VsYW1pbi1za2xlcHUiO3M6Njk6IkFrY2VwdHVqxJkgPGEgaHJlZj0iL3JlZ3VsYW1pbiIgdGFyZ2V0PSJfYmxhbmsiPnJlZ3VsYW1pbjwvYT4gc2tsZXB1LiI7czoxMzoiemFwbGFjLW9ubGluZSI7czoxNToiemFwxYJhxIcgb25saW5lIjtzOjIwOiJzemN6ZWdvbHktemFtb3dpZW5pYSI7czoyMzoic3pjemVnw7PFgnkgemFtw7N3aWVuaWEiO3M6MTk6InphbW93aWVuaWUtb3BsYWNvbmUiO3M6MjE6InphbcOzd2llbmllIG9wxYJhY29uZSI7czoxODoicGxhdG5vc2Mtb2RyenVjb25hIjtzOjIxOiJwxYJhdG5vxZvEhyBvZHJ6dWNvbmEiO3M6Mjc6InBsYXRub3NjLXNwcmF3ZHphbmEtcmVjem5pZSI7czozMToicMWCYXRub8WbxIcgc3ByYXdkemFuYSByxJljem5pZSI7czo5OiJzemN6ZWdvbHkiO3M6MTE6InN6Y3plZ8OzxYJ5IjtzOjI3OiJ6YW1vd2llbmllLXpvc3RhbG8tb3BsYWNvbmUiO3M6MzE6IlphbcOzd2llbmllIHpvc3RhxYJvIG9wxYJhY29uZS4iO3M6MjY6InBsYXRub3NjLXpvc3RhbGEtb2RyenVjb25hIjtzOjMxOiJQxYJhdG5vxZvEhyB6b3N0YcWCYSBvZHJ6dWNvbmEuIjtzOjM0OiJ6YW1vd2llbmllLXpvc3RhbG8tb3BsYWNvbmUtcmVjem5lIjtzOjc4OiJQxYJhdG5vxZvEhyB6b3N0YcWCYSB6YWFrY2VwdG93YW5hLCBhbGUgbXVzaSBqZXN6Y3plIGJ5xIcgc3ByYXdkem9uYSByxJljem5pZS4iO3M6NDoib3BpcyI7czo0OiJvcGlzIjtzOjE3OiJ3cm9jLWRvLWthdGVnb3JpaSI7czoxOToid3LDs8SHIGRvIGthdGVnb3JpaSI7czoyMDoibWV0YS10aXRsZS1sb2dvd2FuaWUiO3M6OToiTG9nb3dhbmllIjtzOjIyOiJtZXRhLXRpdGxlLXJlamVzdHJhY2phIjtzOjExOiJSZWplc3RyYWNqYSI7czoyODoibWV0YS10aXRsZS1oaXN0b3JpYS16YW1vd2llbiI7czoxOToiSGlzdG9yaWEgemFtw7N3aWXFhCI7czoyNDoibWV0YS10aXRsZS1saXN0YS1hZHJlc293IjtzOjE0OiJMaXN0YSBhZHJlc8OzdyI7czoyNDoibWV0YS10aXRsZS1lZHljamEtYWRyZXN1IjtzOjEzOiJFZHljamEgYWRyZXN1IjtzOjIxOiJwb2thei11a3J5ai1rYXRlZ29yaWUiO3M6MjQ6Iihwb2thxbwvdWtyeWoga2F0ZWdvcmllKSI7czoxODoicHJvZHVrdHktcG93aWF6YW5lIjtzOjE5OiJwcm9kdWt0eSBwb3dpxIV6YW5lIjtzOjM0OiJsb2dvd2FuaWUtYmxhZC1uaWVwcmF3aWRsb3dlLWhhc2xvIjtzOjM0OiJQb2RhbmUgaGFzxYJvIGplc3QgbmllcHJhd2lkxYJvd2UuIjtzOjE5OiJkb2JpZXJ6LWRvLWtvbXBsZXR1IjtzOjE5OiJkb2JpZXJ6IGRvIGtvbXBsZXR1IjtzOjE2OiJrb250eW51dWotemFrdXB5IjtzOjE2OiJrb250eW51dWogemFrdXB5IjtzOjY6Im5vd29zYyI7czo4OiJub3dvxZvEhyI7czoxNzoicG9sZWNhbmUtcHJvZHVrdHkiO3M6MTc6IlBvbGVjYW5lIHByb2R1a3R5IjtzOjIzOiJwcm9kdWt0LWN6YXMtcmVhbGl6YWNqaSI7czo1OToiQ3phcyByZWFsaXphY2ppIHphbcOzd2llbmlhIHd5bm9zaSBvZCAxIGRvIDMgZG5pIHJvYm9jenljaC4iO3M6NToidXdhZ2EiO3M6NToidXdhZ2EiO3M6MzM6InphbW93aWVuaWUtcHJ6eWpldGUtZG8tcmVhbGl6YWNqaSI7czozNToiemFtw7N3aWVuaWUgcHJ6eWrEmXRlIGRvIHJlYWxpemFjamkiO3M6MTg6InphbW93aWVuaWUtd3lzbGFuZSI7czoyMDoiemFtw7N3aWVuaWUgd3lzxYJhbmUiO3M6MjM6InphbW93aWVuaWUtenJlYWxpem93YW5lIjtzOjI0OiJ6YW3Ds3dpZW5pZSB6cmVhbGl6b3dhbmUiO3M6MzA6InphbW93aWVuaWUtbnItem9zdGFsby1vcGxhY29uZSI7czozODoiWmFtw7N3aWVuaWUgW05VTUVSXSB6b3N0YcWCbyBvcMWCYWNvbmUiO3M6NDQ6InphbW93aWVuaWUtbnItem9zdGFsby1wcnp5amV0ZS1kby1yZWFsaXphY2ppIjtzOjUyOiJaYW3Ds3dpZW5pZSBbTlVNRVJdIHpvc3RhxYJvIHByenlqxJl0ZSBkbyByZWFsaXphY2ppIjtzOjI5OiJ6YW1vd2llbmllLW5yLXpvc3RhbG8td3lzbGFuZSI7czozNzoiWmFtw7N3aWVuaWUgW05VTUVSXSB6b3N0YcWCbyB3eXPFgmFuZSI7czozNDoiemFtb3dpZW5pZS1uci16b3N0YWxvLXpyZWFsaXpvd2FuZSI7czo0MToiWmFtw7N3aWVuaWUgW05VTUVSXSB6b3N0YcWCbyB6cmVhbGl6b3dhbmUiO3M6MTA6ImRvLWtvc3p5a2EiO3M6MTA6ImRvIGtvc3p5a2EiO3M6MzM6Ind5bmlraS13eXN6dWtpd2FuaWEtZGxhLXphcHl0YW5pYSI7czozMzoiV3luaWtpIHd5c3p1a2l3YW5pYSBkbGEgemFweXRhbmlhIjtzOjExOiJzcGlzLXRyZXNjaSI7czoxMjoic3BpcyB0cmXFm2NpIjtzOjEzOiJ6b2JhY3otd2llY2VqIjtzOjE0OiJab2JhY3ogd2nEmWNlaiI7czoxMzoib3Bpcy1wcm9kdWt0dSI7czoxMzoiT3BpcyBwcm9kdWt0dSI7czoxOToicG9wdWxhcm5lLWthdGVnb3JpZSI7czoxOToiUG9wdWxhcm5lIGthdGVnb3JpZSI7czoxMzoiY3plZ28tc3p1a2FzeiI7czoxMzoiQ3plZ28gc3p1a2FzeiI7czoyMToid3Bpc3otc3p1a2FueS1wcm9kdWt0IjtzOjIxOiJXcGlzeiBzenVrYW55IHByb2R1a3QiO3M6MjQ6Im5pZS16bmFsZXppb25vLXByb2R1a3RvdyI7czozNDoiTmllIHpuYWxlemlvbm8gxbxhZG55Y2ggcHJvZHVrdMOzdyI7czo0MDoicHJvZHVrdC1taWVqc2NlLW5hLXdpYWRvbW9zYy1wbGFjZWhvbGRlciI7czozODoiVHV0YWogbW/FvGVzeiBwb2RhxIcgbnAuIGltacSZIGR6aWVja2EiO3M6Njoib3BpbmllIjtzOjY6Im9waW5pZSI7fX0= \ No newline at end of file diff --git a/admin/temp/4/s_cache_4b916ae533b4ded88ddc3edfe99de1be b/admin/temp/4/s_cache_4b916ae533b4ded88ddc3edfe99de1be index e8907b1..f062108 100644 --- a/admin/temp/4/s_cache_4b916ae533b4ded88ddc3edfe99de1be +++ b/admin/temp/4/s_cache_4b916ae533b4ded88ddc3edfe99de1be @@ -1 +1 @@ -YToyOntpOjA7aToxNzI1MTk4NDExO2k6MTthOjM5OntzOjk6ImZpcm1fbmFtZSI7czoyMDoicG9teXNsb3dlcHJlemVudHkucGwiO3M6MTE6ImZpcm1fYWRyZXNzIjtzOjA6IiI7czoxNToiYWRkaXRpb25hbF9pbmZvIjtzOjI1OToiPHA+PHN0cm9uZz5NYXN6IHB5dGFuaWE/IFphZHp3b8WEIGRvIG5hcy48L3N0cm9uZz48L3A+DQoNCjxwPnRlbC4gPGEgaHJlZj0idGVsOi8vNTMwNzU1Nzc0Ij41MzAgNzU1IDc3NDwvYT48YnIgLz4NCmVtYWlsOiZuYnNwOzxhIGhyZWY9Im1haWx0bzpza2xlcEBwb215c2xvd2VwcmV6ZW50eS5wbCI+c2tsZXBAcG9teXNsb3dlcHJlemVudHkucGw8L2E+PGJyIC8+DQp1bC4gS3Jha293c2thIDE1Ni8xMDQsIDM1LTUwNiBSemVzeiZvYWN1dGU7dzwvcD4NCiI7czoxMjoiY29udGFjdF9mb3JtIjtzOjE6IjEiO3M6MTM6ImNvbnRhY3RfZW1haWwiO3M6MjY6InNrbGVwQHBvbXlzbG93ZXByZXplbnR5LnBsIjtzOjEwOiJlbWFpbF9ob3N0IjtzOjI1OiJtYWlsLnBvbXlzbG93ZXByZXplbnR5LnBsIjtzOjEwOiJlbWFpbF9wb3J0IjtzOjI6IjI1IjtzOjExOiJlbWFpbF9sb2dpbiI7czoyNjoic2tsZXBAcG9teXNsb3dlcHJlemVudHkucGwiO3M6MTQ6ImVtYWlsX3Bhc3N3b3JkIjtzOjk6IkxlZ2lhMTkxNiI7czoxMToiZ29vZ2xlX21hcHMiO3M6MDoiIjtzOjEzOiJmYWNlYm9va19saW5rIjtzOjA6IiI7czoxNDoic3RhdGlzdGljX2NvZGUiO3M6MDoiIjtzOjg6Imh0YWNjZXNzIjtzOjA6IiI7czo2OiJyb2JvdHMiO3M6MDoiIjtzOjIyOiJzaG9wX2JhbmtfYWNjb3VudF9pbmZvIjtzOjIyODoiPHA+UHJvamVjdC1Qcm88YnIgLz4NCk5lc3RCYW5rJm5ic3A7PHN0cm9uZz4yMiAyNTMwIDAwMDggMjA1MSAxMDUwIDY3NjMgMDAwMTwvc3Ryb25nPjwvcD4NCg0KPHA+S3dvdGE6IDxzdHJvbmc+W0tXT1RBXTwvc3Ryb25nPjxiciAvPg0KVyB0eXR1bGUgcHJvc3rEmSB3cGlzYcSHIG51bWVyIHphbSZvYWN1dGU7d2llbmlhOiZuYnNwOzxzdHJvbmc+W05SLVpBTU9XSUVOSUFdPC9zdHJvbmc+PC9wPg0KIjtzOjY6InVwZGF0ZSI7czoxOiIxIjtzOjE0OiJib290X2FuaW1hdGlvbiI7czowOiIiO3M6MTc6Im5ld3NsZXR0ZXJfaGVhZGVyIjtzOjE1MDoiPGRpdiBzdHlsZT0iYm9yZGVyLWJvdHRvbTo1cHggc29saWQgI2I3MTc0ZDsgcGFkZGluZzoyMHB4OyB0ZXh0LWFsaWduOmNlbnRlciI+PGltZyBhbHQ9IiIgc3JjPSIvbGF5b3V0L2ltYWdlcy9sb2dvLnN2ZyIgc3R5bGU9IndpZHRoOjIwOHB4IiAvPjwvZGl2Pg0KIjtzOjE3OiJuZXdzbGV0dGVyX2Zvb3RlciI7czo3NDg6IjxkaXYgc3R5bGU9ImJvcmRlci10b3A6NXB4IHNvbGlkICNiNzE3NGQ7IHBhZGRpbmc6MjBweCAyMHB4IDAgMjBweCI+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjpjZW50ZXIiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTJweCI+PGVtPlBvemRyYXdpYW15LDxiciAvPg0KWmVzcCZvYWN1dGU7xYIgcG9teXNsb3dlcHJlemVudHkucGw8YnIgLz4NCjxhIGhyZWY9Imh0dHBzOi8vcG9teXNsb3dlcHJlemVudHkucGwiPnBvbXlzbG93ZXByZXplbnR5LnBsPC9hPjwvZW0+PC9zcGFuPjwvcD4NCg0KPHAgc3R5bGU9InRleHQtYWxpZ246Y2VudGVyIj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjExcHgiPjxzcGFuIHN0eWxlPSJjb2xvcjojOTVhNWE2Ij5XaWFkb21vxZvEhyB6b3N0YcWCYSB3eWdlbmVyb3dhbmEgYXV0b21hdHljem5pZSwgcHJvc2lteSBuYSBuacSFIG5pZSBvZHBvd2lhZGHEhy4gJm5ic3A7QWJ5IHNrb250YWt0b3dhxIcgc2nEmSB6IHNlcndpc2VtIDxhIGhyZWY9Imh0dHBzOi8vcG9teXNsb3dlcHJlemVudHkucGwiPnBvbXlzbG93ZXByZXplbnR5LnBsPC9hPiwgcHJvc2lteSBvIHByemVzxYJhbmllIGUtbWFpbGEgbmEgYWRyZXMmbmJzcDs8L3NwYW4+PGEgaHJlZj0ibWFpbHRvOnNrbGVwQHBvbXlzbG93ZXByZXplbnR5LnBsIiB0YXJnZXQ9Il9ibGFuayI+PHNwYW4gc3R5bGU9ImNvbG9yOiM5NWE1YTYiPnNrbGVwQHBvbXlzbG93ZXByZXplbnR5LnBsPC9zcGFuPjwvYT48L3NwYW4+PC9wPg0KPC9kaXY+DQoiO3M6MTA6ImhvdHBheV9hcGkiO3M6MDoiIjtzOjU6ImRldmVsIjtzOjE6IjAiO3M6Mzoic3NsIjtzOjE6IjAiO3M6MTQ6Imh0YWNjZXNzX2NhY2hlIjtzOjE6IjEiO3M6MTM6ImZyZWVfZGVsaXZlcnkiO3M6NToiOTkuMDAiO3M6MTg6InByemVsZXd5MjRfc2FuZGJveCI7czoxOiIwIjtzOjIyOiJwcnplbGV3eTI0X21lcmNoYW50X2lkIjtzOjA6IiI7czoxODoicHJ6ZWxld3kyNF9jcmNfa2V5IjtzOjA6IiI7czoxMDoidXBkYXRlX2tleSI7czozMjoiZmZmYTY4M2VhZWMxNTZkZDA0Y2IwMzdmZTQ4MzJkNjkiO3M6NzoidHBheV9pZCI7czo2OiIxMTM1NzUiO3M6MTI6InRwYXlfc2FuZGJveCI7czoxOiIwIjtzOjE4OiJ0cGF5X3NlY3VyaXR5X2NvZGUiO3M6MTk6Ik4+QiNpRiokTEg1QnwzKFp6eSQiO3M6NjoicGlrc2VsIjtzOjA6IiI7czoxMzoiZ2VuZXJhdGVfd2VicCI7czoxOiIxIjtzOjEyOiJsYXp5X2xvYWRpbmciO3M6MToiMSI7czoxMjoiZWtvbWlfc3VydmV5IjtzOjA6IiI7czoyMToiZ29vZ2xlX3RhZ19tYW5hZ2VyX2lkIjtzOjEyOiJHVE0tTUdHMjgyQlEiO3M6MTQ6ImluZmluaXRlc2Nyb2xsIjtzOjE6IjAiO3M6MjU6IndhcmVob3VzZV9tZXNzYWdlX3plcm9fcGwiO3M6MTU6Ild5c3nFgmFteSB3IDQ4ISI7czoyODoid2FyZWhvdXNlX21lc3NhZ2Vfbm9uemVyb19wbCI7czoxNToiV3lzecWCYW15IHcgNDghIjt9fQ== \ No newline at end of file +YToyOntpOjA7aToxNzI0MjYzMTIxO2k6MTthOjM5OntzOjk6ImZpcm1fbmFtZSI7czo4OiJNYXJpYW5layI7czoxMToiZmlybV9hZHJlc3MiO3M6MDoiIjtzOjE1OiJhZGRpdGlvbmFsX2luZm8iO3M6MjQxOiI8cD48c3Ryb25nPk1hc3ogcHl0YW5pYT8gWmFkendvxYQgZG8gbmFzLjwvc3Ryb25nPjwvcD4NCg0KPHA+dGVsLiA8YSBocmVmPSJ0ZWw6Ly81MzA3NTU3NzQiPjUzMCA3NTUgNzc0PC9hPjxiciAvPg0KZW1haWw6Jm5ic3A7PGEgaHJlZj0ibWFpbHRvOnNrbGVwQG1hcmlhbmVrLnBsIj5za2xlcEBtYXJpYW5lay5wbDwvYT48YnIgLz4NCnVsLiBLcmFrb3dza2EgMTU2LzEwNCwgMzUtNTA2IFJ6ZXN6Jm9hY3V0ZTt3PC9wPg0KIjtzOjEyOiJjb250YWN0X2Zvcm0iO3M6MToiMSI7czoxMzoiY29udGFjdF9lbWFpbCI7czoxNzoic2tsZXBAbWFyaWFuZWsucGwiO3M6MTA6ImVtYWlsX2hvc3QiO3M6MTY6Im1haWwubWFyaWFuZWsucGwiO3M6MTA6ImVtYWlsX3BvcnQiO3M6MjoiMjUiO3M6MTE6ImVtYWlsX2xvZ2luIjtzOjE3OiJza2xlcEBtYXJpYW5lay5wbCI7czoxNDoiZW1haWxfcGFzc3dvcmQiO3M6OToiTGVnaWExOTE2IjtzOjExOiJnb29nbGVfbWFwcyI7czowOiIiO3M6MTM6ImZhY2Vib29rX2xpbmsiO3M6MDoiIjtzOjE0OiJzdGF0aXN0aWNfY29kZSI7czowOiIiO3M6ODoiaHRhY2Nlc3MiO3M6MDoiIjtzOjY6InJvYm90cyI7czowOiIiO3M6MjI6InNob3BfYmFua19hY2NvdW50X2luZm8iO3M6MjI4OiI8cD5Qcm9qZWN0LVBybzxiciAvPg0KTmVzdEJhbmsmbmJzcDs8c3Ryb25nPjIyIDI1MzAgMDAwOCAyMDUxIDEwNTAgNjc2MyAwMDAxPC9zdHJvbmc+PC9wPg0KDQo8cD5Ld290YTogPHN0cm9uZz5bS1dPVEFdPC9zdHJvbmc+PGJyIC8+DQpXIHR5dHVsZSBwcm9zesSZIHdwaXNhxIcgbnVtZXIgemFtJm9hY3V0ZTt3aWVuaWE6Jm5ic3A7PHN0cm9uZz5bTlItWkFNT1dJRU5JQV08L3N0cm9uZz48L3A+DQoiO3M6NjoidXBkYXRlIjtzOjE6IjEiO3M6MTQ6ImJvb3RfYW5pbWF0aW9uIjtzOjA6IiI7czoxNzoibmV3c2xldHRlcl9oZWFkZXIiO3M6MTYzOiI8ZGl2IHN0eWxlPSJib3JkZXItYm90dG9tOjVweCBzb2xpZCAjNzdjZGQxOyBwYWRkaW5nOjIwcHg7IHRleHQtYWxpZ246Y2VudGVyIj48aW1nIGFsdD0iIiBzcmM9Ii9sYXlvdXQvaW1hZ2VzL2xvZ28ucG5nIiBzdHlsZT0iaGVpZ2h0OjUwcHg7IHdpZHRoOjIwOHB4IiAvPjwvZGl2Pg0KIjtzOjE3OiJuZXdzbGV0dGVyX2Zvb3RlciI7czo2OTM6IjxkaXYgc3R5bGU9ImJvcmRlci10b3A6NXB4IHNvbGlkICM3N2NkZDE7IHBhZGRpbmc6MjBweCAyMHB4IDAgMjBweCI+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjpjZW50ZXIiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTJweCI+PGVtPlBvemRyYXdpYW15LDxiciAvPg0KWmVzcG9sIE1BUklBTkVLLlBMPGJyIC8+DQo8YSBocmVmPSJodHRwczovL3d3dy5tYXJpYW5lay5wbCI+d3d3Lm1hcmlhbmVrLnBsPC9hPjwvZW0+PC9zcGFuPjwvcD4NCg0KPHAgc3R5bGU9InRleHQtYWxpZ246Y2VudGVyIj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjExcHgiPjxzcGFuIHN0eWxlPSJjb2xvcjojOTVhNWE2Ij5XaWFkb21vxZvEhyB6b3N0YcWCYSB3eWdlbmVyb3dhbmEgYXV0b21hdHljem5pZSwgcHJvc2lteSBuYSBuacSFIG5pZSBvZHBvd2lhZGHEhy4gJm5ic3A7QWJ5IHNrb250YWt0b3dhxIcgc2nEmSB6IHNlcndpc2VtIDxhIGhyZWY9Imh0dHBzOi8vd3d3Lm1hcmlhbmVrLnBsIj5NQVJJQU5FSy5QTDwvYT4sIHByb3NpbXkgbyBwcnplc8WCYW5pZSBlLW1haWxhIG5hIGFkcmVzJm5ic3A7PC9zcGFuPjxhIGhyZWY9Im1haWx0bzprb250YWt0QG1hcmlhbmVrLnBsIiB0YXJnZXQ9Il9ibGFuayI+PHNwYW4gc3R5bGU9ImNvbG9yOiM5NWE1YTYiPmtvbnRha3RAbWFyaWFuZWsucGw8L3NwYW4+PC9hPjwvc3Bhbj48L3A+DQo8L2Rpdj4NCiI7czoxMDoiaG90cGF5X2FwaSI7czo1OToiUkZSTmFHUk9ibXBuVEUxbWNtUlVNME5OZFRsTlJqWndSeTg0U1dsaFFXRTJhWHA1UzFKRVYwOHdjejAiO3M6NToiZGV2ZWwiO3M6MToiMCI7czozOiJzc2wiO3M6MToiMCI7czoxNDoiaHRhY2Nlc3NfY2FjaGUiO3M6MToiMSI7czoxMzoiZnJlZV9kZWxpdmVyeSI7czo1OiI5OS4wMCI7czoxODoicHJ6ZWxld3kyNF9zYW5kYm94IjtzOjE6IjAiO3M6MjI6InByemVsZXd5MjRfbWVyY2hhbnRfaWQiO3M6NjoiMTU2MTAxIjtzOjE4OiJwcnplbGV3eTI0X2NyY19rZXkiO3M6MTY6ImQ4NWFkOWRlOGNiYTBlMDEiO3M6MTA6InVwZGF0ZV9rZXkiO3M6MzI6ImZmZmE2ODNlYWVjMTU2ZGQwNGNiMDM3ZmU0ODMyZDY5IjtzOjc6InRwYXlfaWQiO3M6NToiNzQ2OTgiO3M6MTI6InRwYXlfc2FuZGJveCI7czoxOiIwIjtzOjE4OiJ0cGF5X3NlY3VyaXR5X2NvZGUiO3M6MTc6IilER01xPmt6eEApIzcwdmFyIjtzOjY6InBpa3NlbCI7czoxNjoiMjU2Nzk5OTIwMzMxNDI3NyI7czoxMzoiZ2VuZXJhdGVfd2VicCI7czoxOiIxIjtzOjEyOiJsYXp5X2xvYWRpbmciO3M6MToiMSI7czoxMjoiZWtvbWlfc3VydmV5IjtzOjA6IiI7czoyMToiZ29vZ2xlX3RhZ19tYW5hZ2VyX2lkIjtzOjEyOiJHVE0tUE03WjNMUjgiO3M6MTQ6ImluZmluaXRlc2Nyb2xsIjtzOjE6IjAiO3M6MjU6IndhcmVob3VzZV9tZXNzYWdlX3plcm9fcGwiO3M6MTY6IiFXeXN5xYJrYSBkbyAyNGgiO3M6Mjg6IndhcmVob3VzZV9tZXNzYWdlX25vbnplcm9fcGwiO3M6MTc6IiEhV3lzecWCa2EgZG8gMjRoIjt9fQ== \ No newline at end of file diff --git a/admin/templates/shop-product/products-list.php b/admin/templates/shop-product/products-list.php index bc9566f..3e44dbc 100644 --- a/admin/templates/shop-product/products-list.php +++ b/admin/templates/shop-product/products-list.php @@ -110,7 +110,7 @@ typeAnimated: true, animation: 'opacity', columnClass: 'col-12 col-lg-8', - theme: 'supervan', + theme: 'material', icon: 'fa fa-exclamation-triangle', buttons: { confirm: { diff --git a/autoload/.DS_Store b/autoload/.DS_Store deleted file mode 100644 index 3239922..0000000 Binary files a/autoload/.DS_Store and /dev/null differ diff --git a/autoload/admin/factory/class.ShopProduct.php b/autoload/admin/factory/class.ShopProduct.php index 90d5e09..c2e8c4a 100644 --- a/autoload/admin/factory/class.ShopProduct.php +++ b/autoload/admin/factory/class.ShopProduct.php @@ -622,53 +622,6 @@ class ShopProduct return $result; } - public static function permutation_quantity($id_product, $permutation) - { - global $mdb; - - return $mdb -> get('pp_shop_products_stock', 'quantity', ['AND' => ['id_product' => $id_product, 'permutation' => $permutation]]); - } - - public static function stock_save($id_product, $permutations_quantity) - { - global $mdb; - - $mdb -> delete( 'pp_shop_products_stock', [ 'id_product' => $id_product ] ); - - if ( is_array( $permutations_quantity ) ) foreach ($permutations_quantity as $key => $val) - { - $permutations[] = $mdb -> get('pp_shop_products_stock', 'id', ['AND' => ['id_product' => $id_product, 'permutation' => $key]]); - $mdb -> delete('pp_shop_products_stock', ['AND' => ['id_product' => $id_product, 'id[!]' => $permutations]]); - } - - if (\is_array($permutations_quantity)) - { - foreach ($permutations_quantity as $key => $val) - { - if ($id = $mdb -> get('pp_shop_products_stock', 'id', ['AND' => ['id_product' => $id_product, 'permutation' => $key]])) - { - $mdb -> update('pp_shop_products_stock', [ - 'quantity' => $val, - ], [ - 'id' => $id, - ]); - \S::delete_dir('../temp/'); - } - else - { - $mdb -> insert('pp_shop_products_stock', [ - 'id_product' => $id_product, - 'permutation' => $key, - 'quantity' => $val, - ]); - \S::delete_dir('../temp/'); - } - } - } - - return true; - } - // product_unarchive static public function product_unarchive( int $product_id ) { @@ -1050,12 +1003,6 @@ class ShopProduct \admin\factory\ShopProduct::update_product_combinations_prices( $product_id, $price_brutto, $vat, $price_brutto_promo ); - //stan magazynowy - if ( $mdb -> count( 'pp_shop_products_stock', [ 'id_product' => $product_id ] ) ) - $mdb -> update( 'pp_shop_products_stock', [ 'quantity' => $quantity ], [ 'id_product' => $product_id ] ); - else - $mdb -> insert( 'pp_shop_products_stock', [ 'id_product' => $product_id, 'quantity' => $quantity ] ); - foreach ( $name as $key => $val ) { if ( $translation_id = $mdb -> get( 'pp_shop_products_langs', 'id', [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => $key ] ] ) ) diff --git a/autoload/class.Article.php b/autoload/class.Article.php index 170c848..3998a06 100644 --- a/autoload/class.Article.php +++ b/autoload/class.Article.php @@ -39,8 +39,6 @@ class Article implements \ArrayAccess $this -> images = $mdb -> select( 'pp_articles_images', '*', [ 'article_id' => (int)$article_id, 'ORDER' => [ 'o' => 'ASC', 'id' => 'ASC' ] ] ); $this -> files = $mdb -> select( 'pp_articles_files', '*', [ 'article_id' => (int)$article_id ] ); $this -> pages = $mdb -> select( 'pp_articles_pages', 'page_id', [ 'article_id' => (int)$article_id ] ); - $this -> tags = $mdb -> select( 'pp_tags', [ '[><]pp_articles_tags' => [ 'id' => 'tag_id' ] ], 'name', [ 'article_id' => (int)$article_id ] ); - $results = $mdb -> select( 'pp_articles_additional_params', [ '[><]pp_articles_additional_values' => [ 'id' => 'param_id' ] ], [ 'name', 'value', 'language_id' ], [ 'article_id' => (int)$article_id ] ); if ( is_array( $results ) ) foreach ( $results as $row ) { if ( !$row['language_id'] ) @@ -51,7 +49,7 @@ class Article implements \ArrayAccess $this -> params = $params; } - public function get_from_cache( $article_id, $lang_id ) + static public function get_from_cache( $article_id, $lang_id ) { $cacheHandler = new \CacheHandler(); $cacheKey = "\Article::get_from_cache:$article_id:$lang_id"; diff --git a/autoload/class.Image.php b/autoload/class.Image.php index d767133..0065afa 100644 --- a/autoload/class.Image.php +++ b/autoload/class.Image.php @@ -1,64 +1,82 @@ file = $file; + if ($file !== null) { + $this->file = $file; - if ( is_file( $file ) ) - $this->setImageFile($file); - else - $this->setImageString($file); - } + if (is_file($file)) { + $this->setImageFile($file); + } else { + $this->setImageString($file); + } + } } /** * Set image resource from file * * @param string $file Path to image file - * @return ImageManipulator for a fluent interface + * @return self * @throws InvalidArgumentException */ - public function setImageFile($file) + public function setImageFile(string $file): self { if (!(is_readable($file) && is_file($file))) { throw new InvalidArgumentException("Image file $file is not readable"); } - if (is_resource($this->image)) { + if (isset($this->image) && $this->image instanceof \GdImage) { imagedestroy($this->image); } - list ( $this -> width, $this -> height, $type ) = getimagesize($file); + [$width, $height, $type] = getimagesize($file); + + if ($width === false || $height === false) { + throw new InvalidArgumentException("Unable to get image size for $file"); + } + + error_log("Loaded image size from file: width: $width, height: $height, type: $type"); switch ($type) { - case IMAGETYPE_GIF : - $this->image = imagecreatefromgif($file); - break; - case IMAGETYPE_JPEG : - $this->image = imagecreatefromjpeg($file); - break; - case IMAGETYPE_PNG : - $this->image = imagecreatefrompng($file); - break; + case IMAGETYPE_GIF: + $this->image = imagecreatefromgif($file); + break; + case IMAGETYPE_JPEG: + $this->image = imagecreatefromjpeg($file); + break; + case IMAGETYPE_PNG: + $this->image = imagecreatefrompng($file); + break; case IMAGETYPE_WEBP: - $this -> image = imagecreatefromwebp($file); - break; - default : - throw new InvalidArgumentException("Image type $type not supported"); + $this->image = imagecreatefromwebp($file); + break; + default: + throw new InvalidArgumentException("Image type $type not supported"); + } + + if (!$this->image instanceof \GdImage) { + throw new InvalidArgumentException("Failed to create image from $file"); + } + + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + + error_log("Set image dimensions: width: {$this->width}, height: {$this->height}"); + + if ($this->width === 0 || $this->height === 0) { + throw new InvalidArgumentException("Image dimensions are invalid (width: $this->width, height: $this->height)"); } return $this; @@ -67,21 +85,31 @@ class ImageManipulator /** * Set image resource from string data * - * @param string $data - * @return ImageManipulator for a fluent interface + * @param string $data Image data as string + * @return self * @throws RuntimeException */ - public function setImageString($data) + public function setImageString(string $data): self { - if (is_resource($this->image)) { + if (isset($this->image) && $this->image instanceof \GdImage) { imagedestroy($this->image); } - if (!$this->image = imagecreatefromstring($data)) { + $image = imagecreatefromstring($data); + if (!$image instanceof \GdImage) { throw new RuntimeException('Cannot create image from data string'); } + + $this->image = $image; $this->width = imagesx($this->image); $this->height = imagesy($this->image); + + error_log("Set image dimensions from string: width: {$this->width}, height: {$this->height}"); + + if ($this->width === 0 || $this->height === 0) { + throw new RuntimeException("Image dimensions are invalid (width: $this->width, height: $this->height)"); + } + return $this; } @@ -91,54 +119,57 @@ class ImageManipulator * @param int $width New width * @param int $height New height * @param bool $constrainProportions Constrain current image proportions when resizing - * @return ImageManipulator for a fluent interface + * @return self * @throws RuntimeException */ - public function resample( $width, $height, $constrainProportions = true ) + public function resample(int $width, int $height, bool $constrainProportions = true): self { - if (!is_resource($this->image)) { - throw new RuntimeException('No image set'); + if (!isset($this->image) || !$this->image instanceof \GdImage) { + throw new RuntimeException('No image set'); } - if ( $constrainProportions ) - { - if ( $height >= $width ) - { - $width = round($height / $this->height * $this->width); - } - else - { - $height = round($width / $this->width * $this->height); - } + if ($constrainProportions) { + if ($this->height === 0) { + throw new RuntimeException('Image height is zero, cannot calculate aspect ratio'); + } + + $aspectRatio = $this->width / $this->height; + + // Ustaw domyślną wysokość, jeśli podana jest równa zero + if ($height === 0) { + $height = (int) round($width / $aspectRatio); + } + + if ($width / $height > $aspectRatio) { + $width = (int) round($height * $aspectRatio); + } else { + $height = (int) round($width / $aspectRatio); + } + + if ($width <= 0 || $height <= 0) { + throw new RuntimeException('Calculated dimensions are invalid (width: ' . $width . ', height: ' . $height . ')'); + } } - $temp = imagecreatetruecolor($width, $height); - - - $transparent_index = imagecolortransparent( $this -> image ); - imagealphablending($temp, false); - imagesavealpha($temp,true); - $transparent = imagecolorallocatealpha($temp, 255, 255, 255, 127); - imagefilledrectangle($temp, 0, 0, $this->width, $this->height, $transparent); - imagecopyresampled($temp, $this->image, 0, 0, 0, 0, $width, $height, $this->width, $this->height); - - return $this->_replace($temp); + // reszta kodu metody + return $this; } + /** * Enlarge canvas * - * @param int $width Canvas width - * @param int $height Canvas height - * @param array $rgb RGB colour values - * @param int $xpos X-Position of image in new canvas, null for centre - * @param int $ypos Y-Position of image in new canvas, null for centre - * @return ImageManipulator for a fluent interface + * @param int $width Canvas width + * @param int $height Canvas height + * @param array $rgb RGB colour values [R, G, B] + * @param int|null $xpos X-Position of image in new canvas, null for centre + * @param int|null $ypos Y-Position of image in new canvas, null for centre + * @return self * @throws RuntimeException */ - public function enlargeCanvas($width, $height, array $rgb = array(), $xpos = null, $ypos = null) + public function enlargeCanvas(int $width, int $height, array $rgb = [], ?int $xpos = null, ?int $ypos = null): self { - if (!is_resource($this->image)) { + if (!isset($this->image) || !$this->image instanceof \GdImage) { throw new RuntimeException('No image set'); } @@ -146,52 +177,108 @@ class ImageManipulator $height = max($height, $this->height); $temp = imagecreatetruecolor($width, $height); - if (count($rgb) == 3) { - $bg = imagecolorallocate($temp, $rgb[0], $rgb[1], $rgb[2]); + if (!$temp instanceof \GdImage) { + throw new RuntimeException('Failed to create a new image for enlarging canvas'); + } + + // Fill background if RGB provided + if (count($rgb) === 3) { + [$r, $g, $b] = $rgb; + $bg = imagecolorallocate($temp, $r, $g, $b); imagefill($temp, 0, 0, $bg); + } else { + // Preserve transparency + imagealphablending($temp, false); + imagesavealpha($temp, true); + $transparent = imagecolorallocatealpha($temp, 255, 255, 255, 127); + imagefilledrectangle($temp, 0, 0, $width, $height, $transparent); } - if (null === $xpos) { - $xpos = round(($width - $this->width) / 2); + // Calculate positions + if ($xpos === null) { + $xpos = (int) round(($width - $this->width) / 2); } - if (null === $ypos) { - $ypos = round(($height - $this->height) / 2); + if ($ypos === null) { + $ypos = (int) round(($height - $this->height) / 2); + } + + // Logowanie przed kopiowaniem obrazu na nowe płótno + error_log("Enlarging canvas: xpos: $xpos, ypos: $ypos"); + + if (!imagecopy( + $temp, + $this->image, + $xpos, + $ypos, + 0, + 0, + $this->width, + $this->height + )) { + throw new RuntimeException('Failed to copy image onto enlarged canvas'); } - imagecopy($temp, $this->image, (int) $xpos, (int) $ypos, 0, 0, $this->width, $this->height); return $this->_replace($temp); } /** * Crop image * - * @param int|array $x1 Top left x-coordinate of crop box or array of coordinates + * @param int|array $x1 Top left x-coordinate of crop box or array of coordinates [x1, y1, x2, y2] * @param int $y1 Top left y-coordinate of crop box * @param int $x2 Bottom right x-coordinate of crop box * @param int $y2 Bottom right y-coordinate of crop box - * @return ImageManipulator for a fluent interface + * @return self * @throws RuntimeException */ - public function crop($x1, $y1 = 0, $x2 = 0, $y2 = 0) + public function crop($x1, int $y1 = 0, int $x2 = 0, int $y2 = 0): self { - if (!is_resource($this->image)) { + if (!isset($this->image) || !$this->image instanceof \GdImage) { throw new RuntimeException('No image set'); } - if (is_array($x1) && 4 == count($x1)) { - list($x1, $y1, $x2, $y2) = $x1; + + if (is_array($x1) && count($x1) === 4) { + [$x1, $y1, $x2, $y2] = $x1; } - $x1 = max($x1, 0); + $x1 = max((int)$x1, 0); $y1 = max($y1, 0); - $x2 = min($x2, $this->width); $y2 = min($y2, $this->height); - $width = $x2 - $x1; - $height = $y2 - $y1; + $cropWidth = $x2 - $x1; + $cropHeight = $y2 - $y1; - $temp = imagecreatetruecolor($width, $height); - imagecopy($temp, $this->image, 0, 0, $x1, $y1, $width, $height); + // Logowanie wymiarów do przycięcia + error_log("Cropping image: x1: $x1, y1: $y1, x2: $x2, y2: $y2, cropWidth: $cropWidth, cropHeight: $cropHeight"); + + if ($cropWidth <= 0 || $cropHeight <= 0) { + throw new RuntimeException('Invalid crop dimensions'); + } + + $temp = imagecreatetruecolor($cropWidth, $cropHeight); + if (!$temp instanceof \GdImage) { + throw new RuntimeException('Failed to create a new image for cropping'); + } + + // Preserve transparency + imagealphablending($temp, false); + imagesavealpha($temp, true); + $transparent = imagecolorallocatealpha($temp, 255, 255, 255, 127); + imagefilledrectangle($temp, 0, 0, $cropWidth, $cropHeight, $transparent); + + if (!imagecopy( + $temp, + $this->image, + 0, + 0, + $x1, + $y1, + $cropWidth, + $cropHeight + )) { + throw new RuntimeException('Failed to crop image'); + } return $this->_replace($temp); } @@ -199,82 +286,119 @@ class ImageManipulator /** * Replace current image resource with a new one * - * @param resource $res New image resource - * @return ImageManipulator for a fluent interface + * @param \GdImage $res New image resource + * @return self * @throws UnexpectedValueException */ - protected function _replace($res) + protected function _replace(\GdImage $res): self { - if (!is_resource($res)) { - throw new UnexpectedValueException('Invalid resource'); + if (!$res instanceof \GdImage) { + throw new UnexpectedValueException('Invalid image resource'); } - if (is_resource($this->image)) { + + if (isset($this->image) && $this->image instanceof \GdImage) { imagedestroy($this->image); } + $this->image = $res; $this->width = imagesx($res); $this->height = imagesy($res); + + error_log("Replaced image dimensions: width: {$this->width}, height: {$this->height}"); + + if ($this->width === 0 || $this->height === 0) { + throw new UnexpectedValueException("Replaced image has invalid dimensions (width: $this->width, height: $this->height)"); + } + return $this; } /** * Save current image to file * - * @param string $fileName + * @param string $fileName Path to save the image + * @param int|null $type Image type (IMAGETYPE_*) or null to auto-detect from file extension * @return void * @throws RuntimeException */ - public function save($fileName, $type = IMAGETYPE_JPEG) + public function save(string $fileName, ?int $type = null): void { $dir = dirname($fileName); if (!is_dir($dir)) { - if (!mkdir($dir, 0755, true)) { + if (!mkdir($dir, 0755, true) && !is_dir($dir)) { throw new RuntimeException('Error creating directory ' . $dir); } } + // Auto-detect type from file extension if not provided + if ($type === null) { + $extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION)); + switch ($extension) { + case 'gif': + $type = IMAGETYPE_GIF; + break; + case 'jpeg': + case 'jpg': + $type = IMAGETYPE_JPEG; + break; + case 'png': + $type = IMAGETYPE_PNG; + break; + case 'webp': + $type = IMAGETYPE_WEBP; + break; + default: + $type = IMAGETYPE_JPEG; + } + } + + error_log("Saving image to $fileName with type $type"); + try { switch ($type) { case IMAGETYPE_WEBP: - if ( !imagewebp( $this -> image, $fileName ) ) - throw new RuntimeException; - break; - case IMAGETYPE_GIF : - if ( !imagegif( $this -> image, $fileName ) ) - throw new RuntimeException; - break; - case 'image/png': - if (!imagepng($this->image, $fileName)) { - throw new RuntimeException; + if (!imagewebp($this->image, $fileName)) { + throw new RuntimeException('Failed to save image as WEBP'); } break; - case IMAGETYPE_JPEG : - default : + case IMAGETYPE_GIF: + if (!imagegif($this->image, $fileName)) { + throw new RuntimeException('Failed to save image as GIF'); + } + break; + case IMAGETYPE_PNG: + if (!imagepng($this->image, $fileName)) { + throw new RuntimeException('Failed to save image as PNG'); + } + break; + case IMAGETYPE_JPEG: + default: if (!imagejpeg($this->image, $fileName, 95)) { - throw new RuntimeException; + throw new RuntimeException('Failed to save image as JPEG'); } } - } catch (Exception $ex) { - throw new RuntimeException('Error saving image file to ' . $fileName); + error_log("Image saved successfully to $fileName"); + } catch (\Exception $ex) { + throw new RuntimeException('Error saving image file to ' . $fileName . ': ' . $ex->getMessage()); } } /** * Returns the GD image resource * - * @return resource + * @return \GdImage */ - public function getResource() + public function getResource(): \GdImage { return $this->image; } /** - * Get current image resource width + * Get current image width * * @return int */ - public function getWidth() + public function getWidth(): int { return $this->width; } @@ -284,8 +408,18 @@ class ImageManipulator * * @return int */ - public function getHeight() + public function getHeight(): int { return $this->height; } -} \ No newline at end of file + + /** + * Destructor to clean up the image resource + */ + public function __destruct() + { + if (isset($this->image) && $this->image instanceof \GdImage) { + imagedestroy($this->image); + } + } +} diff --git a/autoload/class.S.php b/autoload/class.S.php index 6d14e85..4495c14 100644 --- a/autoload/class.S.php +++ b/autoload/class.S.php @@ -170,7 +170,7 @@ class S public static function get_domain( $url ) { $parseUrl = parse_url( trim( $url ) ); - return trim( $parseUrl[host] ? str_replace( 'www.', '', $parseUrl[host] ) : str_replace( 'www.', '', array_shift( explode( '/', $parseUrl[path], 2 ) ) ) ); + return trim( $parseUrl['host'] ? str_replace( 'www.', '', $parseUrl['host'] ) : str_replace( 'www.', '', array_shift( explode( '/', $parseUrl['path'], 2 ) ) ) ); } static public function pre_dump( $value ) @@ -237,7 +237,7 @@ class S { $result = array(); - while ( list($key, $values) = each( $input ) ) + foreach ($array as $key => $value) { if ( empty( $values ) ) continue; diff --git a/autoload/front/.DS_Store b/autoload/front/.DS_Store deleted file mode 100644 index 7285fd1..0000000 Binary files a/autoload/front/.DS_Store and /dev/null differ diff --git a/autoload/front/controls/class.ShopBasket.php b/autoload/front/controls/class.ShopBasket.php index 93696cf..d7a6f42 100644 --- a/autoload/front/controls/class.ShopBasket.php +++ b/autoload/front/controls/class.ShopBasket.php @@ -202,8 +202,12 @@ class ShopBasket $values['wp'] = \front\factory\ShopProduct::product_wp( $values[ 'product-id' ] ); + $attributes_implode = ''; // generuj unikalny kod produktu dodanego do koszyka - $product_code = md5( $values['product-id'] . implode( '|', $attributes ) . $values['product-message'] . json_encode( $custom_fields ) ); + if ( is_array( $attributes ) ) + $attributes_implode = implode( '|', $attributes ); + + $product_code = md5( $values['product-id'] . $attributes_implode . $values['product-message'] . json_encode( $custom_fields ) ); if ( isset( $basket[ $product_code ] ) ) $basket[ $product_code ][ 'quantity' ] += $values[ 'quantity' ]; diff --git a/autoload/front/controls/class.ShopOrder.php b/autoload/front/controls/class.ShopOrder.php index c7de541..170b66a 100644 --- a/autoload/front/controls/class.ShopOrder.php +++ b/autoload/front/controls/class.ShopOrder.php @@ -18,6 +18,8 @@ class ShopOrder { global $mdb; + file_put_contents( 'tpay.txt', print_r( $_POST, true ) . print_r( $_GET, true ), FILE_APPEND ); + if ( \S::get( 'tr_status' ) == 'TRUE' and \S::get( 'tr_crc' ) ) { $order = new \shop\Order( 0, \S::get( 'tr_crc' ) ); diff --git a/autoload/front/factory/class.Layouts.php b/autoload/front/factory/class.Layouts.php index 3b396ad..c23d930 100644 --- a/autoload/front/factory/class.Layouts.php +++ b/autoload/front/factory/class.Layouts.php @@ -65,18 +65,18 @@ class Layouts if ( !$objectData ) { - $layout = $mdb -> get( 'pp_layouts', '*', [ '[><]pp_layouts_categories' => [ 'id' => 'layout_id' ] ], [ 'category_id' => (int)$category_id ] ); + $layout = $mdb -> query( "SELECT pp_layouts.* FROM pp_layouts JOIN pp_layouts_categories ON pp_layouts.id = pp_layouts_categories.layout_id WHERE pp_layouts_categories.category_id = " . (int)$category_id ) -> fetchAll( \PDO::FETCH_ASSOC ); if ( !$layout ) $layout = $mdb -> get( 'pp_layouts', '*', [ 'categories_default' => 1 ] ); - $cacheHandler -> set( $cacheKey, $layout ); + $cacheHandler -> set( $cacheKey, $layout[0] ); } else { return unserialize( $objectData ); } - return $layout; + return $layout[0]; } static public function active_layout( $page_id ) diff --git a/autoload/front/factory/class.ShopProduct.php b/autoload/front/factory/class.ShopProduct.php index 070032f..3453a3d 100644 --- a/autoload/front/factory/class.ShopProduct.php +++ b/autoload/front/factory/class.ShopProduct.php @@ -248,11 +248,6 @@ class ShopProduct if ( is_array( $results ) ) foreach ( $results as $row ) { - $row[ 'require' ] = $mdb -> get( 'pp_shop_attributes', - 'required', - [ 'id' => $row[ 'attribute_id' ] ] - ); - $row[ 'type' ] = $mdb -> get( 'pp_shop_attributes', 'type', [ 'id' => $row[ 'attribute_id' ] ] @@ -301,9 +296,9 @@ class ShopProduct $product[ 'products_related' ] = $mdb -> select( 'pp_shop_products_related', 'product_related_id', [ 'product_id' => (int)$product_id ] ); - $products_sets_1 = $mdb -> select( 'pp_shop_products_sets', 'product_sets_id', [ 'product_id' => (int)$product_id ] ); - $products_sets_2 = $mdb -> select( 'pp_shop_products_sets', 'product_id', [ 'product_sets_id' => (int)$product_id ] ); - $products_sets = array_unique( array_merge( $products_sets_1, $products_sets_2 ) ); + $set_id = $mdb -> select( 'pp_shop_product_sets_products', 'set_id', [ 'product_id' => (int)$product_id ] ); + $products_sets = $mdb -> select( 'pp_shop_product_sets_products', 'product_id', [ 'set_id' => (int)$set_id ] ); + $products_sets = array_unique( $products_sets ); $product[ 'products_sets' ] = $products_sets; @@ -338,28 +333,6 @@ class ShopProduct return $mdb -> get( 'pp_shop_products_langs', 'warehouse_message_nonzero', [ 'AND' => [ 'product_id' => $id_product, 'lang_id' => $lang_id ] ] ); } - public static function permutation_quantity( $id_product, $permutation, bool $is_multichoice ) - { - global $mdb; - - if ( !$is_multichoice ) - return $mdb -> get( 'pp_shop_products_stock', 'quantity', [ 'AND' => [ 'id_product' => $id_product, 'permutation' => 0 ] ] ); - - if ( is_array( $permutation ) ) - { - foreach ( $permutation as $key => $val ) - { - $permutation_id .= $val; - if ( $val != end( $permutation ) ) - $permutation_id .= '_'; - } - } - else - $permutation_id = $permutation; - - return $mdb -> get( 'pp_shop_products_stock', 'quantity', [ 'AND' => [ 'id_product' => $id_product, 'permutation' => $permutation_id ] ] ); - } - //TO:DO do usunięcia public static function product_both_price( $product_id ) { diff --git a/autoload/shop/class.Product.php b/autoload/shop/class.Product.php index d399870..2004ccc 100644 --- a/autoload/shop/class.Product.php +++ b/autoload/shop/class.Product.php @@ -795,7 +795,7 @@ class Product implements \ArrayAccess { $result = array(); - while ( list($key, $values) = each( $input ) ) + foreach ( $input as $key => $values ) { if ( empty( $values ) ) continue; @@ -834,7 +834,7 @@ class Product implements \ArrayAccess public function __get( $variable ) { - if ( array_key_exists( $variable, $this -> data ) ) + if ( is_array( $this -> data ) and array_key_exists( $variable, $this -> data ) ) return $this -> $variable; } diff --git a/libraries/grid/gdb.min.php b/libraries/grid/gdb.min.php index eb56f0f..f8a6c0e 100644 --- a/libraries/grid/gdb.min.php +++ b/libraries/grid/gdb.min.php @@ -3,7 +3,7 @@ * Medoo database framework * http://medoo.in * Version 0.9.7 - * + * * Copyright 2014, Angel Lai * Released under the MIT license */ @@ -33,7 +33,7 @@ class gdb protected $option = array(); - // Variable + // Variable protected $logs = array(); public function __construct($options = null) @@ -131,7 +131,7 @@ class gdb } $this->pdo = new PDO( - $dsn, + $dsn, $this->username, $this->password, $this->option @@ -148,14 +148,14 @@ class gdb } public function query($query) - { + { array_push($this->logs, $query); return $this->pdo->query($query); } public function exec($query) - { + { array_push($this->logs, $query); return $this->pdo->exec($query); @@ -199,7 +199,10 @@ class gdb } } - return implode($stack, ','); + if ( is_array( $stack ) ) + return implode( ',', $stack ); + else + return $stack; } protected function array_quote($array) @@ -318,11 +321,11 @@ class gdb } $value = '%' . $value . '%'; - + $wheres[] = $column . ' LIKE ' . $this->fn_quote($key, $value); } } - + if (in_array($operator, array('>', '>=', '<', '<='))) { if (is_numeric($value)) @@ -835,7 +838,7 @@ class gdb if (isset($data[0])) { $column = $where == null ? $join : $column; - + if (is_string($column) && $column != '*') { return $data[ 0 ][ $column ]; diff --git a/libraries/grid/grid.php b/libraries/grid/grid.php index d9624bb..f77c6e5 100644 --- a/libraries/grid/grid.php +++ b/libraries/grid/grid.php @@ -1,29 +1,29 @@ 'mysql', 'database_name' => 'db_name', 'server' => 'db_host', @@ -46,96 +46,97 @@ class grid 'password' => 'db_pass', 'port' => 'db_port' ); - + public $empty_txt = 'Brak danych w tabeli.'; - + public $multiselect = null; public $multidelete_url = null; - + public $buttons = null; - + public $actions = array( 'delete' => false, 'delete_url' => null, 'add' => false, 'add_url' => null, 'edit' => false ); - + function __construct( $table, $name = '' ) { $this -> table = $table; $this -> name = $name; $this -> dir = dirname( __FILE__ ); - + $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + if ( !empty( $_SESSION[ 'g' . $g_table . 'filters' ] ) ) $this -> filters = $_SESSION[ 'g' . $g_table . 'filters' ]; - + if ( !empty( $_SESSION[ 'g' . $g_table . 'limit' ] ) ) $this -> limit = $_SESSION[ 'g' . $g_table . 'limit' ]; - + if ( !empty( $_SESSION[ 'g' . $g_table . 'order' ] ) ) $this -> order = $_SESSION[ 'g' . $g_table . 'order' ]; - + if ( $this -> clear_cache ) { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; if ( is_array( $_SESSION ) ) foreach ( $_SESSION as $key => $val ) { - if ( $key != 'g' . $g_table and @get_class( $val ) == '__PHP_Incomplete_Class' ) - unset( $_SESSION[ $key ] ); + if ($key != 'g' . $g_table && is_object($val) && get_class($val) == '__PHP_Incomplete_Class') { + unset($_SESSION[$key]); + } } } } - + public function hide_column( $column, $hidden ) { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $db = $this -> connectToDb(); - + $results = $db -> get( 'grid_settings', 'settings', [ 'name' => $g_table ] ); $results = unserialize( $results ); - + $results['hidden_columns'][ $column ] = $hidden; - + if ( $db -> count( 'grid_settings', [ 'name' => $g_table ] ) ) $db -> update( 'grid_settings', [ 'settings' => serialize( $results ) ], [ 'name' => $g_table ] ); else $db -> insert( 'grid_settings', [ 'settings' => serialize( $results ), 'name' => $g_table ] ); } - + public function drawEdit( $id ) { $values = get_object_vars( $this ); - + $view = new gridView( $this -> dir . '/templates/' ); $view -> values = $values; $view -> element = $this -> getElement( $id ); return $view -> render( 'edit' ); } - + public function draw() - { + { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $db = $this -> connectToDb(); - + $results = $db -> get( 'grid_settings', 'settings', [ 'name' => $g_table ] ); $results = unserialize( $results ); - + $this -> hidden_columns = $results['hidden_columns']; - - - - (int)$_SESSION[ 'g' . $g_table . 'cp' ] ? $this -> cp = (int)$_SESSION[ 'g' . $g_table . 'cp' ] : $this -> cp = 1; - + + + + (int)$_SESSION[ 'g' . $g_table . 'cp' ] ? $this -> cp = (int)$_SESSION[ 'g' . $g_table . 'cp' ] : $this -> cp = 1; + $_SESSION[ 'g' . $g_table ] = $this; - + $values = get_object_vars( $this ); $values['content'] = $this -> drawResults(); - + $view = new gridView( $this -> dir . '/templates/' ); $view -> values = $values; return $view -> render( 'container' ); } - + public function connectToDb() { return new gdb( [ @@ -148,14 +149,14 @@ class grid 'charset' => 'utf8' ] ); } - + public function getCSV() { if ( is_array( $this -> src ) ) $results = $this -> getDataSrc(); else $results = $this -> getData( true ); - + if ( is_array( $this -> columns_view ) ) foreach ( $this -> columns_view as $column ) { $array_row = array(); @@ -164,7 +165,7 @@ class grid $headers[] = $column['name']; } } - + if ( is_array( $results ) ) foreach ( $results as $row ) { $array_row = array(); @@ -208,15 +209,15 @@ class grid } $array[] = $array_row; } - + $now = gmdate( "D, d M Y H:i:s" ); - + header( 'Content-Encoding: UTF-8' ); header( "Expires: Tue, 03 Jul 2001 06:00:00 GMT" ); header( "Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate" ); header( "Last-Modified: {$now} GMT" ); - // force download + // force download header( "Content-Type: application/force-download" ); header( "Content-Type: application/octet-stream" ); header( "Content-Type: application/download" ); @@ -233,11 +234,11 @@ class grid fclose( $df ); return ob_get_clean(); } - + public function printResults() { $values = get_object_vars( $this ); - + if ( is_array( $this -> src ) ) { $values['count'] = $this -> getDataCountSrc(); @@ -247,30 +248,30 @@ class grid $values['count'] = $this -> getDataCount(); $values['summary'] = $this -> getDataSummary(); } - + $this -> cp = 1; $this -> limit = $values['count']; - + if ( is_array( $this -> src ) ) $values['results'] = $this -> getDataSrc(); else $values['results'] = $this -> getData(); - + $view = new gridView( $this -> dir . '/templates/' ); $view -> values = $values; return $view -> render( 'print' ); } - + public function get_data_count_sql() - { + { $db = $this ->connectToDb(); - + $where = $this -> getWhereCondition(); $where = $db -> where_clause( $where ); - + if ( strpos( $this -> sql_count, 'WHERE' ) !== false and !empty( $where ) ) $where = str_replace( 'WHERE', 'AND', $where ); - + $this -> sql_tmp = str_replace( '[where]', $where, $this -> sql_count ); $query = $db -> query( $this -> sql_tmp ); @@ -289,14 +290,14 @@ class grid return 0; } } - + public function get_data_sql( $print = false ) { $db = $this -> connectToDb(); - + $where = $this -> getWhereCondition(); $where = $db -> where_clause( $where ); - + if ( strpos( $this -> sql, 'WHERE' ) !== false and !empty( $where ) ) $where = str_replace( 'WHERE', 'AND', $where ); @@ -304,10 +305,10 @@ class grid $this -> sql_tmp = $this -> sql . ' LIMIT ' . $this -> limit . ' OFFSET ' . ( $this -> cp - 1 ) * $this -> limit; else $this -> sql_tmp = $this -> sql; - $this -> sql_tmp = str_replace( '[where]', $where, $this -> sql_tmp ); + $this -> sql_tmp = str_replace( '[where]', $where, $this -> sql_tmp ); $this -> sql_tmp = str_replace( '[order_p1]', $this -> order['column'], $this -> sql_tmp ); $this -> sql_tmp = str_replace( '[order_p2]', $this -> order['type'], $this -> sql_tmp ); - + $query = $db -> query( $this -> sql_tmp ); if ( $query ) { @@ -324,11 +325,11 @@ class grid return null; } } - + public function drawResults() { $values = get_object_vars( $this ); - + if ( is_array( $this -> src ) ) $values['count'] = $this -> getDataCountSrc(); else if ( isset( $this -> sql ) and isset( $this -> sql_count ) ) @@ -338,51 +339,51 @@ class grid $values['count'] = $this -> getDataCount(); $values['summary'] = $this -> getDataSummary(); } - + $ls = ceil( $values['count'] / $this -> limit ); - + if ( !(int)$ls ) $ls = 1; - + if ( $this -> cp > $ls ) { $this -> cp = $ls; $values['cp'] = $ls; } - + if ( is_array( $this -> src ) ) $values['results'] = $this -> getDataSrc(); else if ( isset( $this -> sql ) and isset( $this -> sql_count ) ) $values['results'] = $this -> get_data_sql(); else $values['results'] = $this -> getData(); - + $view = new gridView( $this -> dir . '/templates/' ); $view -> values = $values; return $view -> render( 'results' ); } - + public function delete( $id ) { return $this -> connectToDb() -> delete( $this -> table, [ $this -> id => $id ] ); } - + public function getWhereCondition() - { + { $where = array(); - + $where['AND'] = $this -> where; - + if ( $this -> filters ) { foreach ( $this -> filters as $key => $val ) { if ( $val['type'] == 'like' ) $where['AND'] = array_merge( $where['AND'], [ $key . '[~]' => $val['value'] ] ); - + if ( $val['type'] == 'equal' ) $where['AND'] = array_merge( $where['AND'], [ $key => $val['value'] ] ); - + if ( $val['type'] == 'date_range' ) { $dates = explode( ' - ', $val['value'] ); @@ -391,13 +392,13 @@ class grid } } } - + if ( count( $where['AND'] ) ) return $where; else return array(); } - + public static function searchSrc( $array, $column, $value, $type = 'equal' ) { if ( is_array( $array ) ) foreach ( $array as $key => $val ) @@ -407,7 +408,7 @@ class grid if ( $val[ $column ] == $value ) $array_tmp[] = $val; } - + if ( $type == 'like' ) { if ( strpos( mb_strtolower( $val[ $column ], 'UTF-8' ), mb_strtolower( $value, 'UTF-8' ) ) !== false ) @@ -416,28 +417,28 @@ class grid } return $array_tmp; } - + public function filtrDataSrc() { $this -> src_filtered = $this -> src; - + if ( $this -> filters ) { foreach ( $this -> filters as $key => $val ) { if ( $val['type'] == 'like' ) $this -> src_filtered = $this -> searchSrc( $this -> src_filtered, $key, $val['value'], 'like' ); - + if ( $val['type'] == 'equal' ) $this -> src_filtered = $this -> searchSrc( $this -> src_filtered, $key, $val['value'], 'equal' ); } } } - + public function getDataSummary() { $where = self::getWhereCondition(); - + if ( is_array( $this -> summary ) ) foreach ( $this -> summary as $key ) { if ( $this -> join ) @@ -447,48 +448,48 @@ class grid } return $summary; } - + public function getDataCountSrc() { $this -> filtrDataSrc(); return count( $this -> src_filtered ); } - + public function getDataCount() { $where = self::getWhereCondition(); - + if ( $this -> join ) $results = $this -> connectToDb() -> count( $this -> table, $this -> join, '*', $where ); else $results = $this -> connectToDb() -> count( $this -> table, $where ); - + if ( $results ) return $results; else return false; } - + public function getDataSrc() { if ( $this -> order ) $this -> src_filtered = $this -> sortByColumn( $this -> src_filtered, $this -> order['column'], $this -> order['type'] ); - + $array_tmp = $this -> src_filtered; - + if ( is_array( $array_tmp ) ) return array_splice( $array_tmp, ( $this -> cp - 1 ) * $this -> limit, $this -> limit ); else - return false; + return false; } - + public function getData( $csv = false ) { $where = self::getWhereCondition(); - + if ( $this -> order ) $where = array_merge( $where, [ 'ORDER' => $this -> order['column'] . ' ' . $this -> order['type'] ] ); - + if ( $this -> limit and $this -> show_paging === true and !$csv ) $where = array_merge( $where, [ 'LIMIT' => [ ( $this -> cp - 1 ) * $this -> limit, $this -> limit ] ] ); @@ -496,18 +497,18 @@ class grid $results = $this -> connectToDb() -> select( $this -> table, $this -> join, $this -> columns, $where ); else $results = $this -> connectToDb() -> select( $this -> table, $this -> columns, $where ); - + if ( $results ) return $results; else return false; } - + public function getElement( $id ) { return $this -> connectToDb() -> get( $this -> table, '*', [ $this -> id => $id ] ); } - + public function saveElement( $values ) { if ( !$values[ $this -> id ] ) @@ -518,12 +519,12 @@ class grid else return $this -> connectToDb() -> update( $this -> table, $values, [ $this -> id => $values[ $this -> id ] ] ); } - - public static function sortByColumn( &$arr, $col, $sort ) + + public static function sortByColumn( &$arr, $col, $sort ) { - setlocale( LC_COLLATE, 'pl_PL.utf-8' ); + setlocale( LC_COLLATE, 'pl_PL.utf-8' ); $sort == 'ASC' ? $dir = SORT_ASC : $dir = SORT_DESC; - + $sort_col = array(); if ( is_array( $arr ) ) { @@ -534,46 +535,46 @@ class grid } return $arr; } - + public static function validateDate( $date ) { if ( date( 'Y-m-d', strtotime( $date ) ) != '1970-01-01' ) return true; } - + public function save_limit( $limit ) { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $_SESSION[ 'g' . $g_table . 'limit' ] = $limit; } - + public function save_order() { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $_SESSION[ 'g' . $g_table . 'order' ] = $this -> order; } - + public function save_filters() { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $_SESSION[ 'g' . $g_table . 'filters' ] = $this -> filters; } - + public function set_cp( $cp ) { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $_SESSION[ 'g' . $g_table . 'cp'] = $cp; $this -> cp = $cp; } - + public function getParams( $string ) { $params = array(); - + preg_match_all( '/\[[a-zA-Z0-9_]*\]/', $string, $results_tmp1 ); if ( is_array( $results_tmp1[0] ) ) foreach ( $results_tmp1[0] as $row_tmp1 ) { @@ -584,7 +585,7 @@ class grid } return $params; } - + public function convertString( $string, $row ) { $out = $string; @@ -599,11 +600,11 @@ class grid } return $out; } - + public function convertStringJS( $string ) { $out = 'var out = "' . addslashes( $string ) . '";' . chr( 13 ); - + preg_match_all( '/\[[a-zA-Z0-9_]*\]/', $string, $results_tmp1 ); if ( is_array( $results_tmp1[0] ) ) foreach ( $results_tmp1[0] as $row_tmp1 ) { diff --git a/libraries/grid/js/grid.js b/libraries/grid/js/grid.js index 386a172..997153a 100644 --- a/libraries/grid/js/grid.js +++ b/libraries/grid/js/grid.js @@ -1,7 +1,7 @@ -function g_validate_form( id ) +function g_validate_form( id ) { var submit = true; - jQuery( '#fg-' + id ).find( "input[type=text], input[type=password], select, textarea" ).each( function() + jQuery( '#fg-' + id ).find( "input[type=text], input[type=password], select, textarea" ).each( function() { var min = parseInt( jQuery( this ).attr( 'min' ) ); var equal = jQuery( this ).attr( 'equal' ); @@ -34,7 +34,7 @@ function g_validate_form( id ) else if ( fun !== undefined ) { var response = window[fun](); - + if ( response['status'] === 'error' ) { submit = false; @@ -56,7 +56,7 @@ function g_validate_form( id ) return submit; } -function number_format( number, decimals, dec_point, thousands_sep ) +function number_format( number, decimals, dec_point, thousands_sep ) { number = ( number + '' ).replace( /[^0-9+\-Ee.]/g, '' ); var n = !isFinite(+number) ? 0 : +number, @@ -102,7 +102,7 @@ function hide_error() { }, 3000 ); } -function create_message( text ) +function create_message( text ) { hide_message(); jQuery( '#content' ).prepend( '
* R::aliases( array( 'cover' => 'page' ) );
@@ -2009,8 +2019,8 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
* Unless you know what you are doing, do NOT use this method.
* This is for advanced users only!
*
- * @param string $type type of the new bean
- * @param BeanHelper $beanhelper bean helper to obtain a toolbox and a model
+ * @param string $type type of the new bean
+ * @param BeanHelper|NULL $beanhelper bean helper to obtain a toolbox and a model
*
* @return void
*/
@@ -2057,8 +2067,9 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
*
* Note that not all PHP functions work with the array interface.
*
- * @return ArrayIterator
+ * @return \ArrayIterator
*/
+ #[\ReturnTypeWillChange]
public function getIterator()
{
return new \ArrayIterator( $this->properties );
@@ -2067,7 +2078,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
/**
* Imports all values from an associative array $array. Chainable.
* This method imports the values in the first argument as bean
- * propery and value pairs. Use the second parameter to provide a
+ * property and value pairs. Use the second parameter to provide a
* selection. If a selection array is passed, only the entries
* having keys mentioned in the selection array will be imported.
* Set the third parameter to TRUE to preserve spaces in selection keys.
@@ -2123,6 +2134,21 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
return $this;
}
+ /**
+ * Same as import() but trims all values by default.
+ * Set the second parameter to apply a different function.
+ *
+ * @param array $array what you want to import
+ * @param callable $function function to apply (default is trim)
+ * @param string|array $selection selection of values
+ * @param boolean $notrim if TRUE selection keys will NOT be trimmed
+ *
+ * @return OODBBean
+ */
+ public function trimport( $array, $function='trim', $selection = FALSE, $notrim = FALSE ) {
+ return $this->import( array_map( $function, $array ), $selection, $notrim );
+ }
+
/**
* Imports an associative array directly into the
* internal property array of the bean as well as the
@@ -2300,11 +2326,11 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
* Returns the ID of the bean.
* If for some reason the ID has not been set, this method will
* return NULL. This is actually the same as accessing the
- * id property using $bean->id. The ID of a bean is it's primary
+ * id property using $bean->id. The ID of a bean is its primary
* key and should always correspond with a table column named
* 'id'.
*
- * @return string|null
+ * @return string|NULL
*/
public function getID()
{
@@ -2336,6 +2362,19 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
return;
}
+ /**
+ * Returns the bean wrapped in an Either-instance.
+ * This allows the user to extract data from the bean using a chain
+ * of methods without any NULL checks, similar to the ?? operator but also
+ * in a way that is compatible with older versions of PHP.
+ * For more details consult the documentation of the Either class.
+ *
+ * @return Either
+ */
+ public function either() {
+ return new Either( $this );
+ }
+
/**
* Adds WHERE clause conditions to ownList retrieval.
* For instance to get the pages that belong to a book you would
@@ -2566,13 +2605,14 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
$this->noLoad = FALSE;
$this->all = FALSE;
$this->via = NULL;
+ $this->castProperty = NULL;
return $this;
}
/**
* Determines whether a list is opened in exclusive mode or not.
* If a list has been opened in exclusive mode this method will return TRUE,
- * othwerwise it will return FALSE.
+ * otherwise it will return FALSE.
*
* @param string $listName name of the list to check
*
@@ -2667,7 +2707,12 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
//If exists and no list or exits and list not changed, bail out.
if ( $exists && ((!$isOwn && !$isShared ) || (!$hasSQL && !$differentAlias && !$hasAll)) ) {
+ $castProperty = $this->castProperty;
$this->clearModifiers();
+ if (!is_null($castProperty)) {
+ $object = new $castProperty( $this->properties[$property] );
+ return $object;
+ }
return $this->properties[$property];
}
@@ -2708,7 +2753,6 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
$this->properties[$property] = $beans;
$this->__info["sys.shadow.$property"] = $beans;
$this->__info['tainted'] = TRUE;
-
$this->clearModifiers();
return $this->properties[$property];
@@ -2800,8 +2844,8 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
$value = '0';
} elseif ( $value === TRUE ) {
$value = '1';
- /* for some reason there is some kind of bug in xdebug so that it doesnt count this line otherwise... */
- } elseif ( $value instanceof \DateTime ) { $value = $value->format( 'Y-m-d H:i:s' ); }
+ /* for some reason there is some kind of bug in xdebug so that it doesn't count this line otherwise... */
+ } elseif ( ( ( $value instanceof \DateTime ) or ( $value instanceof \DateTimeInterface ) ) ) { $value = $value->format( 'Y-m-d H:i:s' ); }
$this->properties[$property] = $value;
}
@@ -2938,6 +2982,29 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
return $this;
}
+ /**
+ * Captures a dynamic casting.
+ * Enables you to obtain a bean value as an object by type-hinting
+ * the desired return object using asX where X is the class you wish
+ * to use as a wrapper for the property.
+ *
+ * Usage:
+ *
+ * $dateTime = $bean->asDateTime()->date;
+ *
+ * @param string $method method (asXXX)...
+ *
+ * @return self|NULL
+ */
+ public function captureDynamicCasting( $method )
+ {
+ if ( strpos( $method, 'as' ) === 0 && ctype_upper( substr( $method, 2, 1) ) === TRUE ) {
+ $this->castProperty = substr( $method, 2 );
+ return $this;
+ }
+ return NULL;
+ }
+
/**
* Sends the call to the registered model.
* This method can also be used to override bean behaviour.
@@ -2963,7 +3030,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
public function __call( $method, $args )
{
if ( empty( $this->__info['model'] ) ) {
- return NULL;
+ return $this->captureDynamicCasting($method);
}
$overrideDontFail = FALSE;
@@ -2974,6 +3041,9 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
if ( !is_callable( array( $this->__info['model'], $method ) ) ) {
+ $self = $this->captureDynamicCasting($method);
+ if ($self) return $self;
+
if ( self::$errorHandlingFUSE === FALSE || $overrideDontFail ) {
return NULL;
}
@@ -3052,6 +3122,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
*
* @return void
*/
+ #[\ReturnTypeWillChange]
public function offsetSet( $offset, $value )
{
$this->__set( $offset, $value );
@@ -3069,6 +3140,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
*
* @return boolean
*/
+ #[\ReturnTypeWillChange]
public function offsetExists( $offset )
{
return $this->__isset( $offset );
@@ -3080,13 +3152,14 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
* Unsets a value from the array/bean.
*
* Array functions do not reveal x-own-lists and list-alias because
- * you dont want duplicate entries in foreach-loops.
+ * you don't want duplicate entries in foreach-loops.
* Also offers a slight performance improvement for array access.
*
* @param mixed $offset property
*
* @return void
*/
+ #[\ReturnTypeWillChange]
public function offsetUnset( $offset )
{
$this->__unset( $offset );
@@ -3098,13 +3171,14 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
* Returns value of a property.
*
* Array functions do not reveal x-own-lists and list-alias because
- * you dont want duplicate entries in foreach-loops.
+ * you don't want duplicate entries in foreach-loops.
* Also offers a slight performance improvement for array access.
*
* @param mixed $offset property
*
* @return mixed
*/
+ #[\ReturnTypeWillChange]
public function &offsetGet( $offset )
{
return $this->__get( $offset );
@@ -3182,7 +3256,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
*
* @param string $property property
* @param callable $function function
- * @param integer $maxDepth maximum depth for traversal
+ * @param integer|NULL $maxDepth maximum depth for traversal
*
* @return OODBBean
* @throws RedException
@@ -3245,6 +3319,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
*
* @return integer
*/
+ #[\ReturnTypeWillChange]
public function count()
{
return count( $this->properties );
@@ -3312,7 +3387,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
}
/**
- * Convience method.
+ * Convenience method.
* Unsets all properties in the internal properties array.
*
* Usage:
@@ -3395,7 +3470,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
*
* Note that this method will return TRUE if applied to a loaded list.
* Also note that this method keeps track of the bean's history regardless whether
- * it has been stored or not. Storing a bean does not undo it's history,
+ * it has been stored or not. Storing a bean does not undo its history,
* to clean the history of a bean use: clearHistory().
*
* @param string $property name of the property you want the change-status of
@@ -3760,9 +3835,9 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
* quest beans residing in the $questTarget->target properties
* of each element in the xownQuestTargetList.
*
- * @param string $list the list you wish to process
- * @param string $property the property to load
- * @param string $type the type of bean residing in this property (optional)
+ * @param string $list the list you wish to process
+ * @param string $property the property to load
+ * @param string|NULL $type the type of bean residing in this property (optional)
*
* @return array
*/
@@ -3818,15 +3893,17 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
*
*
* The example above compares the flavour label 'mocca' with
- * the flavour label attachec to the $coffee bean. This illustrates
+ * the flavour label attached to the $coffee bean. This illustrates
* how to use equals() with RedBeanPHP-style enums.
*
- * @param OODBBean $bean other bean
+ * @param OODBBean|null $bean other bean
*
* @return boolean
*/
public function equals(OODBBean $bean)
{
+ if ( is_null($bean) ) return false;
+
return (bool) (
( (string) $this->properties['id'] === (string) $bean->properties['id'] )
&& ( (string) $this->__info['type'] === (string) $bean->__info['type'] )
@@ -3850,6 +3927,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable
*
* @return array
*/
+ #[\ReturnTypeWillChange]
public function jsonSerialize()
{
$json = $this->__call( '@__jsonSerialize', array( ) );
@@ -4008,7 +4086,7 @@ interface Adapter
* @param array $bindings array of values to bind to parameters in query string
* @param boolean $noevent no event firing
*
- * @return void
+ * @return int
*/
public function exec( $sql, $bindings = array(), $noevent = FALSE );
@@ -4034,7 +4112,7 @@ interface Adapter
* @param string $sql string containing SQL code for database
* @param array $bindings array of values to bind to parameters in query string
*
- * @return array
+ * @return array|NULL
*/
public function getRow( $sql, $bindings = array() );
@@ -4060,7 +4138,7 @@ interface Adapter
* @param string $sql string containing SQL code for database
* @param array $bindings array of values to bind to parameters in query string
*
- * @return string
+ * @return string|NULL
*/
public function getCell( $sql, $bindings = array() );
@@ -4079,7 +4157,7 @@ interface Adapter
* Executes the SQL query specified in $sql and returns
* an associative array where the column names are the keys.
*
- * @param string $sql Sstring containing SQL code for databaseQL
+ * @param string $sql String containing SQL code for databaseQL
* @param array $bindings values to bind
*
* @return array
@@ -4117,7 +4195,7 @@ interface Adapter
* adapter. RedBean will only access the adapter and never to talk
* directly to the driver though.
*
- * @return mixed
+ * @return Driver
*/
public function getDatabase();
@@ -4477,7 +4555,7 @@ namespace RedBeanPHP {
* Database Cursor Interface.
* A cursor is used by Query Writers to fetch Query Result rows
* one row at a time. This is useful if you expect the result set to
- * be quite large. This interface dscribes the API of a database
+ * be quite large. This interface describes the API of a database
* cursor. There can be multiple implementations of the Cursor,
* by default RedBeanPHP offers the PDOCursor for drivers shipping
* with RedBeanPHP and the NULLCursor.
@@ -4497,7 +4575,7 @@ interface Cursor
* Should retrieve the next row of the result set.
* This method is used to iterate over the result set.
*
- * @return array
+ * @return array|NULL
*/
public function getNextItem();
@@ -4544,7 +4622,7 @@ use RedBeanPHP\Cursor as Cursor;
class PDOCursor implements Cursor
{
/**
- * @var PDOStatement
+ * @var \PDOStatement
*/
protected $res;
@@ -4556,7 +4634,7 @@ class PDOCursor implements Cursor
/**
* Constructor, creates a new instance of a PDO Database Cursor.
*
- * @param PDOStatement $res the PDO statement
+ * @param \PDOStatement $res the PDO statement
* @param string $fetchStyle fetch style constant to use
*
* @return void
@@ -4687,20 +4765,27 @@ class BeanCollection
*/
protected $type = NULL;
+ /**
+ * @var string
+ */
+ protected $mask = NULL;
+
/**
* Constructor, creates a new instance of the BeanCollection.
*
* @param string $type type of beans in this collection
* @param Repository $repository repository to use to generate bean objects
* @param Cursor $cursor cursor object to use
+ * @param string $mask meta mask to apply (optional)
*
* @return void
*/
- public function __construct( $type, Repository $repository, Cursor $cursor )
+ public function __construct( $type, Repository $repository, Cursor $cursor, $mask = '__meta' )
{
$this->type = $type;
$this->cursor = $cursor;
$this->repository = $repository;
+ $this->mask = $mask;
}
/**
@@ -4715,7 +4800,7 @@ class BeanCollection
{
$row = $this->cursor->getNextItem();
if ( $row ) {
- $beans = $this->repository->convertToBeans( $this->type, array( $row ) );
+ $beans = $this->repository->convertToBeans( $this->type, array( $row ), $this->mask );
return reset( $beans );
}
return NULL;
@@ -4849,7 +4934,7 @@ interface QueryWriter
* @param boolean $firstOfChain is it the join of a chain (or the only join)
* @param string $suffix suffix to add for aliasing tables (for joining same table multiple times)
*
- * @return string $joinSQLSnippet
+ * @return string
*/
public function writeJoin( $type, $targetType, $leftRight, $joinType, $firstOfChain, $suffix );
@@ -4879,8 +4964,8 @@ interface QueryWriter
* @note A default implementation is available in AQueryWriter
* unless a database uses very different SQL this should suffice.
*
- * @param string $sql SQL Snippet
- * @param integer $glue the GLUE type - how to glue (C_GLUE_WHERE or C_GLUE_AND)
+ * @param string $sql SQL Snippet
+ * @param integer|NULL $glue the GLUE type - how to glue (C_GLUE_WHERE or C_GLUE_AND)
*
* @return string
*/
@@ -4945,7 +5030,7 @@ interface QueryWriter
* C_DATA_TYPE_MANUAL (usually 99) which represents a user specified type. Although
* no special treatment has been associated with the latter for now.
*
- * @param string $value value
+ * @param mixed $value value
* @param boolean $alsoScanSpecialForTypes take special types into account
*
* @return integer
@@ -4995,10 +5080,10 @@ interface QueryWriter
* This methods selects the records from the database that match the specified
* type, conditions (optional) and additional SQL snippet (optional).
*
- * @param string $type name of the table you want to query
- * @param array $conditions criteria ( $column => array( $values ) )
- * @param string $addSql additional SQL snippet
- * @param array $bindings bindings for SQL snippet
+ * @param string $type name of the table you want to query
+ * @param array $conditions criteria ( $column => array( $values ) )
+ * @param string|NULL $addSql additional SQL snippet
+ * @param array $bindings bindings for SQL snippet
*
* @return array
*/
@@ -5009,10 +5094,10 @@ interface QueryWriter
* This methods selects the records from the database that match the specified
* type, conditions (optional) and additional SQL snippet (optional).
*
- * @param string $type name of the table you want to query
- * @param array $conditions criteria ( $column => array( $values ) )
- * @param string $addSQL additional SQL snippet
- * @param array $bindings bindings for SQL snippet
+ * @param string $type name of the table you want to query
+ * @param array $conditions criteria ( $column => array( $values ) )
+ * @param string|NULL $addSql additional SQL snippet
+ * @param array $bindings bindings for SQL snippet
*
* @return Cursor
*/
@@ -5033,7 +5118,7 @@ interface QueryWriter
public function queryRecordRelated( $sourceType, $destType, $linkID, $addSql = '', $bindings = array() );
/**
- * Returns the row that links $sourceType $sourcID to $destType $destID in an N-M relation.
+ * Returns the row that links $sourceType $sourceID to $destType $destID in an N-M relation.
*
* @param string $sourceType source type, the first part of the link you're looking for
* @param string $destType destination type, the second part of the link you're looking for
@@ -5048,10 +5133,10 @@ interface QueryWriter
* Counts the number of records in the database that match the
* conditions and additional SQL.
*
- * @param string $type name of the table you want to query
- * @param array $conditions criteria ( $column => array( $values ) )
- * @param string $addSQL additional SQL snippet
- * @param array $bindings bindings for SQL snippet
+ * @param string $type name of the table you want to query
+ * @param array $conditions criteria ( $column => array( $values ) )
+ * @param string|NULL $addSql additional SQL snippet
+ * @param array $bindings bindings for SQL snippet
*
* @return integer
*/
@@ -5111,12 +5196,12 @@ interface QueryWriter
* (count rows) used for countParents and countChildren functions - or you can specify a
* string yourself like 'count(distinct brand)'.
*
- * @param string $type the bean type you want to query rows for
- * @param integer $id id of the reference row
- * @param boolean $up TRUE to query parent rows, FALSE to query child rows
- * @param string $addSql optional SQL snippet to embed in the query
- * @param array $bindings parameter bindings for additional SQL snippet
- * @param mixed $select Select Snippet to use when querying (optional)
+ * @param string $type the bean type you want to query rows for
+ * @param integer $id id of the reference row
+ * @param boolean $up TRUE to query parent rows, FALSE to query child rows
+ * @param string|NULL $addSql optional SQL snippet to embed in the query
+ * @param array $bindings parameter bindings for additional SQL snippet
+ * @param bool $select Select Snippet to use when querying (optional)
*
* @return array
*/
@@ -5130,9 +5215,9 @@ interface QueryWriter
* Returns the new ID.
* This methods accepts a type and infers the corresponding table name.
*
- * @param string $type name of the table to update
- * @param array $updatevalues list of update values
- * @param integer $id optional primary key ID value
+ * @param string $type name of the table to update
+ * @param array $updatevalues list of update values
+ * @param integer|NULL $id optional primary key ID value
*
* @return integer
*/
@@ -5147,7 +5232,7 @@ interface QueryWriter
* @param string $addSql additional SQL
* @param array $bindings bindings
*
- * @return void
+ * @return int
*/
public function deleteRecord( $type, $conditions = array(), $addSql = '', $bindings = array() );
@@ -5163,7 +5248,7 @@ interface QueryWriter
public function deleteRelations( $sourceType, $destType, $sourceID );
/**
- * @see QueryWriter::addUniqueConstaint
+ * @see QueryWriter::addUniqueConstraint
*/
public function addUniqueIndex( $type, $columns );
@@ -5219,7 +5304,7 @@ interface QueryWriter
* @param string $targetType points to this type
* @param string $property field that contains the foreign key value
* @param string $targetProperty field where the fk points to
- * @param string $isDep whether target is dependent and should cascade on update/delete
+ * @param bool $isDep whether target is dependent and should cascade on update/delete
*
* @return void
*/
@@ -5405,6 +5490,16 @@ abstract class AQueryWriter
*/
public $typeno_sqltype = array();
+ /**
+ * @var array
+ */
+ public $sqltype_typeno = array();
+
+ /**
+ * @var array
+ */
+ public $encoding = array();
+
/**
* @var bool
*/
@@ -5417,8 +5512,10 @@ abstract class AQueryWriter
* For instance to add ROW_FORMAT=DYNAMIC to all MySQL tables
* upon creation:
*
+ *
* $sql = $writer->getDDLTemplate( 'createTable', '*' );
* $writer->setDDLTemplate( 'createTable', '*', $sql . ' ROW_FORMAT=DYNAMIC ' );
+ *
*
* For property-specific templates set $beanType to:
* account.username -- then the template will only be applied to SQL statements relating
@@ -5440,9 +5537,9 @@ abstract class AQueryWriter
* If no template can be found for the specified type, the template for
* '*' will be returned instead.
*
- * @param string $type ( 'createTable' | 'widenColumn' | 'addColumn' )
- * @param string $beanType ( type of bean or '*' to apply to all types )
- * @param string $property specify if you're looking for a property-specific template
+ * @param string $type ( 'createTable' | 'widenColumn' | 'addColumn' )
+ * @param string $beanType ( type of bean or '*' to apply to all types )
+ * @param string|NULL $property specify if you're looking for a property-specific template
*
* @return string
*/
@@ -5553,7 +5650,7 @@ abstract class AQueryWriter
* Globally available service method for RedBeanPHP.
* Converts a camel cased string to a snake cased string.
*
- * @param string $camel camelCased string to converty to snake case
+ * @param string $camel camelCased string to convert to snake case
*
* @return string
*/
@@ -5562,6 +5659,25 @@ abstract class AQueryWriter
return strtolower( preg_replace( '/(?<=[a-z])([A-Z])|([A-Z])(?=[a-z])/', '_$1$2', $camel ) );
}
+ /**
+ * Globally available service method for RedBeanPHP.
+ * Converts a snake cased string to a camel cased string.
+ *
+ * @param string $snake snake_cased string to convert to camelCase
+ * @param boolean $dolphin exception for Ids - (bookId -> bookID)
+ * too complicated for the human mind, only dolphins can understand this
+ *
+ * @return string
+ */
+ public static function snakeCamel( $snake, $dolphinMode = false )
+ {
+ $camel = lcfirst( str_replace(' ', '', ucwords( str_replace('_', ' ', $snake ) ) ) );
+ if ( $dolphinMode ) {
+ $camel = preg_replace( '/(\w)Id$/', '$1ID', $camel );
+ }
+ return $camel;
+ }
+
/**
* Clears renames.
*
@@ -5719,9 +5835,9 @@ abstract class AQueryWriter
* In previous versions you could only store one key-entry, I have changed this to
* improve caching efficiency (issue #400).
*
- * @param string $cacheTag cache tag (secondary key)
- * @param string $key key to store values under
- * @param array $values content to be stored
+ * @param string $cacheTag cache tag (secondary key)
+ * @param string $key key to store values under
+ * @param array|int $values rows or count to be stored
*
* @return void
*/
@@ -5853,7 +5969,7 @@ abstract class AQueryWriter
/**
* Determines whether a string can be considered JSON or not.
* This is used by writers that support JSON columns. However
- * we dont want that code duplicated over all JSON supporting
+ * we don't want that code duplicated over all JSON supporting
* Query Writers.
*
* @param string $value value to determine 'JSONness' of.
@@ -6017,7 +6133,7 @@ abstract class AQueryWriter
* Used for UUID support.
*
* @param integer $dataTypeID magic number constant assigned to this data type
- * @param string $SQLDefinition SQL column definition (i.e. INT(11))
+ * @param string $SQLDefinition SQL column definition (e.g. INT(11))
*
* @return self
*/
@@ -6147,6 +6263,10 @@ abstract class AQueryWriter
{
static $snippetCache = array();
+ if ( is_null( $sql ) ) {
+ return '';
+ }
+
if ( trim( $sql ) === '' ) {
return $sql;
}
@@ -7229,8 +7349,6 @@ class MySQL extends AQueryWriter implements QueryWriter
*/
public function scanType( $value, $flagSpecial = FALSE )
{
- $this->svalue = $value;
-
if ( is_null( $value ) ) return MySQL::C_DATATYPE_BOOL;
if ( $value === INF ) return MySQL::C_DATATYPE_TEXT7;
@@ -7329,7 +7447,7 @@ class MySQL extends AQueryWriter implements QueryWriter
ADD UNIQUE INDEX $name (" . implode( ',', $columns ) . ")";
$this->adapter->exec( $sql );
} catch ( SQLException $e ) {
- //do nothing, dont use alter table ignore, this will delete duplicate records in 3-ways!
+ //do nothing, don't use alter table ignore, this will delete duplicate records in 3-ways!
return FALSE;
}
return TRUE;
@@ -7353,7 +7471,6 @@ class MySQL extends AQueryWriter implements QueryWriter
/**
* @see QueryWriter::addFK
- * @return bool
*/
public function addFK( $type, $targetType, $property, $targetProperty, $isDependent = FALSE )
{
@@ -7429,938 +7546,6 @@ class MySQL extends AQueryWriter implements QueryWriter
}
}
-namespace RedBeanPHP\QueryWriter {
-
-use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter;
-use RedBeanPHP\QueryWriter as QueryWriter;
-use RedBeanPHP\Adapter\DBAdapter as DBAdapter;
-use RedBeanPHP\Adapter as Adapter;
-use RedBeanPHP\RedException\SQL as SQLException;
-
-/**
- * RedBeanPHP SQLiteWriter with support for SQLite types
- * This is a QueryWriter class for RedBeanPHP.
- * This QueryWriter provides support for the SQLite database platform.
- *
- * @file RedBeanPHP/QueryWriter/SQLiteT.php
- * @author Gabor de Mooij and the RedBeanPHP Community
- * @license BSD/GPLv2
- *
- * @copyright
- * (c) copyright G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
- * This source file is subject to the BSD/GPLv2 License that is bundled
- * with this source code in the file license.txt.
- */
-class SQLiteT extends AQueryWriter implements QueryWriter
-{
- /**
- * Data types
- */
- const C_DATATYPE_INTEGER = 0;
- const C_DATATYPE_NUMERIC = 1;
- const C_DATATYPE_TEXT = 2;
- const C_DATATYPE_SPECIFIED = 99;
-
- /**
- * @var DBAdapter
- */
- protected $adapter;
-
- /**
- * @var string
- */
- protected $quoteCharacter = '`';
-
- /**
- * @var array
- */
- protected $DDLTemplates = array(
- 'addColumn' => array(
- '*' => 'ALTER TABLE `%s` ADD `%s` %s'
- ),
- 'createTable' => array(
- '*' => 'CREATE TABLE %s ( id INTEGER PRIMARY KEY AUTOINCREMENT )'
- ),
- 'widenColumn' => array(
- '*' => ',`%s` %s '
- )
- );
-
- /**
- * Gets all information about a table (from a type).
- *
- * Format:
- * array(
- * name => name of the table
- * columns => array( name => datatype )
- * indexes => array() raw index information rows from PRAGMA query
- * keys => array() raw key information rows from PRAGMA query
- * )
- *
- * @param string $type type you want to get info of
- *
- * @return array
- */
- protected function getTable( $type )
- {
- $tableName = $this->esc( $type, TRUE );
- $columns = $this->getColumns( $type );
- $indexes = $this->getIndexes( $type );
- $keys = $this->getKeyMapForType( $type );
-
- $table = array(
- 'columns' => $columns,
- 'indexes' => $indexes,
- 'keys' => $keys,
- 'name' => $tableName
- );
-
- $this->tableArchive[$tableName] = $table;
-
- return $table;
- }
-
- /**
- * Puts a table. Updates the table structure.
- * In SQLite we can't change columns, drop columns, change or add foreign keys so we
- * have a table-rebuild function. You simply load your table with getTable(), modify it and
- * then store it with putTable()...
- *
- * @param array $tableMap information array
- *
- * @return void
- */
- protected function putTable( $tableMap )
- {
- $table = $tableMap['name'];
- $q = array();
- $q[] = "DROP TABLE IF EXISTS tmp_backup;";
-
- $oldColumnNames = array_keys( $this->getColumns( $table ) );
-
- foreach ( $oldColumnNames as $k => $v ) $oldColumnNames[$k] = "`$v`";
-
- $q[] = "CREATE TEMPORARY TABLE tmp_backup(" . implode( ",", $oldColumnNames ) . ");";
- $q[] = "INSERT INTO tmp_backup SELECT * FROM `$table`;";
- $q[] = "PRAGMA foreign_keys = 0 ";
- $q[] = "DROP TABLE `$table`;";
-
- $newTableDefStr = '';
- foreach ( $tableMap['columns'] as $column => $type ) {
- if ( $column != 'id' ) {
- $newTableDefStr .= sprintf( $this->getDDLTemplate( 'widenColumn', $table, $column ), $column, $type );
- }
- }
-
- $fkDef = '';
- foreach ( $tableMap['keys'] as $key ) {
- $fkDef .= ", FOREIGN KEY(`{$key['from']}`)
- REFERENCES `{$key['table']}`(`{$key['to']}`)
- ON DELETE {$key['on_delete']} ON UPDATE {$key['on_update']}";
- }
-
- $q[] = "CREATE TABLE `$table` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT $newTableDefStr $fkDef );";
-
- foreach ( $tableMap['indexes'] as $name => $index ) {
- if ( strpos( $name, 'UQ_' ) === 0 ) {
- $cols = explode( '__', substr( $name, strlen( 'UQ_' . $table ) ) );
- foreach ( $cols as $k => $v ) $cols[$k] = "`$v`";
- $q[] = "CREATE UNIQUE INDEX $name ON `$table` (" . implode( ',', $cols ) . ")";
- } else $q[] = "CREATE INDEX $name ON `$table` ({$index['name']}) ";
- }
-
- $q[] = "INSERT INTO `$table` SELECT * FROM tmp_backup;";
- $q[] = "DROP TABLE tmp_backup;";
- $q[] = "PRAGMA foreign_keys = 1 ";
-
- foreach ( $q as $sq ) $this->adapter->exec( $sq );
- }
-
- /**
- * Returns the an array describing the indexes for type $type.
- *
- * @param string $type type to describe indexes of
- *
- * @return array
- */
- protected function getIndexes( $type )
- {
- $table = $this->esc( $type, TRUE );
- $indexes = $this->adapter->get( "PRAGMA index_list('$table')" );
-
- $indexInfoList = array();
- foreach ( $indexes as $i ) {
- $indexInfoList[$i['name']] = $this->adapter->getRow( "PRAGMA index_info('{$i['name']}') " );
-
- $indexInfoList[$i['name']]['unique'] = $i['unique'];
- }
-
- return $indexInfoList;
- }
-
- /**
- * Adds a foreign key to a type.
- * Note: cant put this in try-catch because that can hide the fact
- * that database has been damaged.
- *
- * @param string $type type you want to modify table of
- * @param string $targetType target type
- * @param string $field field of the type that needs to get the fk
- * @param string $targetField field where the fk needs to point to
- * @param integer $buildopt 0 = NO ACTION, 1 = ON DELETE CASCADE
- *
- * @return boolean
- */
- protected function buildFK( $type, $targetType, $property, $targetProperty, $constraint = FALSE )
- {
- $table = $this->esc( $type, TRUE );
- $targetTable = $this->esc( $targetType, TRUE );
- $column = $this->esc( $property, TRUE );
- $targetColumn = $this->esc( $targetProperty, TRUE );
-
- $tables = $this->getTables();
- if ( !in_array( $targetTable, $tables ) ) return FALSE;
-
- if ( !is_null( $this->getForeignKeyForTypeProperty( $table, $column ) ) ) return FALSE;
- $t = $this->getTable( $table );
- $consSQL = ( $constraint ? 'CASCADE' : 'SET NULL' );
- $label = 'from_' . $column . '_to_table_' . $targetTable . '_col_' . $targetColumn;
- $t['keys'][$label] = array(
- 'table' => $targetTable,
- 'from' => $column,
- 'to' => $targetColumn,
- 'on_update' => $consSQL,
- 'on_delete' => $consSQL
- );
- $this->putTable( $t );
- return TRUE;
- }
-
- /**
- * @see AQueryWriter::getKeyMapForType
- */
- protected function getKeyMapForType( $type )
- {
- $table = $this->esc( $type, TRUE );
- $keys = $this->adapter->get( "PRAGMA foreign_key_list('$table')" );
- $keyInfoList = array();
- foreach ( $keys as $k ) {
- $label = $this->makeFKLabel( $k['from'], $k['table'], $k['to'] );
- $keyInfoList[$label] = array(
- 'name' => $label,
- 'from' => $k['from'],
- 'table' => $k['table'],
- 'to' => $k['to'],
- 'on_update' => $k['on_update'],
- 'on_delete' => $k['on_delete']
- );
- }
- return $keyInfoList;
- }
-
- /**
- * Constructor
- * Most of the time, you do not need to use this constructor,
- * since the facade takes care of constructing and wiring the
- * RedBeanPHP core objects. However if you would like to
- * assemble an OODB instance yourself, this is how it works:
- *
- * Usage:
- *
- *
- * $database = new RPDO( $dsn, $user, $pass );
- * $adapter = new DBAdapter( $database );
- * $writer = new PostgresWriter( $adapter );
- * $oodb = new OODB( $writer, FALSE );
- * $bean = $oodb->dispense( 'bean' );
- * $bean->name = 'coffeeBean';
- * $id = $oodb->store( $bean );
- * $bean = $oodb->load( 'bean', $id );
- *
- *
- * The example above creates the 3 RedBeanPHP core objects:
- * the Adapter, the Query Writer and the OODB instance and
- * wires them together. The example also demonstrates some of
- * the methods that can be used with OODB, as you see, they
- * closely resemble their facade counterparts.
- *
- * The wiring process: create an RPDO instance using your database
- * connection parameters. Create a database adapter from the RPDO
- * object and pass that to the constructor of the writer. Next,
- * create an OODB instance from the writer. Now you have an OODB
- * object.
- *
- * @param Adapter $adapter Database Adapter
- */
- public function __construct( Adapter $adapter )
- {
- $this->typeno_sqltype = array(
- SQLiteT::C_DATATYPE_INTEGER => 'INTEGER',
- SQLiteT::C_DATATYPE_NUMERIC => 'NUMERIC',
- SQLiteT::C_DATATYPE_TEXT => 'TEXT',
- );
-
- $this->sqltype_typeno = array();
-
- foreach ( $this->typeno_sqltype as $k => $v ) {
- $this->sqltype_typeno[$v] = $k;
- }
-
- $this->adapter = $adapter;
- $this->adapter->setOption( 'setInitQuery', ' PRAGMA foreign_keys = 1 ' );
- }
-
- /**
- * This method returns the datatype to be used for primary key IDS and
- * foreign keys. Returns one if the data type constants.
- *
- * @return integer $const data type to be used for IDS.
- */
- public function getTypeForID()
- {
- return self::C_DATATYPE_INTEGER;
- }
-
- /**
- * @see QueryWriter::scanType
- */
- public function scanType( $value, $flagSpecial = FALSE )
- {
- $this->svalue = $value;
-
- if ( $value === NULL ) return self::C_DATATYPE_INTEGER;
- if ( $value === INF ) return self::C_DATATYPE_TEXT;
-
- if ( $this->startsWithZeros( $value ) ) return self::C_DATATYPE_TEXT;
-
- if ( $value === TRUE || $value === FALSE ) return self::C_DATATYPE_INTEGER;
-
- if ( is_numeric( $value ) && ( intval( $value ) == $value ) && $value < 2147483648 && $value > -2147483648 ) return self::C_DATATYPE_INTEGER;
-
- if ( ( is_numeric( $value ) && $value < 2147483648 && $value > -2147483648)
- || preg_match( '/\d{4}\-\d\d\-\d\d/', $value )
- || preg_match( '/\d{4}\-\d\d\-\d\d\s\d\d:\d\d:\d\d/', $value )
- ) {
- return self::C_DATATYPE_NUMERIC;
- }
-
- return self::C_DATATYPE_TEXT;
- }
-
- /**
- * @see QueryWriter::addColumn
- */
- public function addColumn( $table, $column, $type )
- {
- $column = $this->check( $column );
- $table = $this->check( $table );
- $type = $this->typeno_sqltype[$type];
-
- $this->adapter->exec( sprintf( $this->getDDLTemplate( 'addColumn', $table, $column ), $table, $column, $type ) );
- }
-
- /**
- * @see QueryWriter::code
- */
- public function code( $typedescription, $includeSpecials = FALSE )
- {
- $r = ( ( isset( $this->sqltype_typeno[$typedescription] ) ) ? $this->sqltype_typeno[$typedescription] : 99 );
-
- return $r;
- }
-
- /**
- * @see QueryWriter::widenColumn
- */
- public function widenColumn( $type, $column, $datatype )
- {
- $t = $this->getTable( $type );
-
- $t['columns'][$column] = $this->typeno_sqltype[$datatype];
-
- $this->putTable( $t );
- }
-
- /**
- * @see QueryWriter::getTables();
- */
- public function getTables()
- {
- return $this->adapter->getCol( "SELECT name FROM sqlite_master
- WHERE type='table' AND name!='sqlite_sequence';" );
- }
-
- /**
- * @see QueryWriter::createTable
- */
- public function createTable( $type )
- {
- $table = $this->esc( $type );
-
- $sql = sprintf( $this->getDDLTemplate( 'createTable', $type ), $table );
-
- $this->adapter->exec( $sql );
- }
-
- /**
- * @see QueryWriter::getColumns
- */
- public function getColumns( $table )
- {
- $table = $this->esc( $table, TRUE );
-
- $columnsRaw = $this->adapter->get( "PRAGMA table_info('$table')" );
-
- $columns = array();
- foreach ( $columnsRaw as $r ) $columns[$r['name']] = $r['type'];
-
- return $columns;
- }
-
- /**
- * @see QueryWriter::addUniqueIndex
- */
- public function addUniqueConstraint( $type, $properties )
- {
- $tableNoQ = $this->esc( $type, TRUE );
- $name = 'UQ_' . $this->esc( $type, TRUE ) . implode( '__', $properties );
- $t = $this->getTable( $type );
- $t['indexes'][$name] = array( 'name' => $name );
- try {
- $this->putTable( $t );
- } catch( SQLException $e ) {
- return FALSE;
- }
- return TRUE;
- }
-
- /**
- * @see QueryWriter::sqlStateIn
- */
- public function sqlStateIn( $state, $list, $extraDriverDetails = array() )
- {
- $stateMap = array(
- '23000' => QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION
- );
- if ( $state == 'HY000'
- && isset($extraDriverDetails[1])
- && $extraDriverDetails[1] == 1
- && ( in_array( QueryWriter::C_SQLSTATE_NO_SUCH_TABLE, $list )
- || in_array( QueryWriter::C_SQLSTATE_NO_SUCH_COLUMN, $list )
- )) {
- return TRUE;
- }
- return in_array( ( isset( $stateMap[$state] ) ? $stateMap[$state] : '0' ), $list );
- }
-
- /**
- * Sets an SQL snippet to be used for the next queryRecord() operation.
- * SQLite has no SELECT-FOR-UPDATE and filters this.
- *
- * @param string $sql SQL snippet to use in SELECT statement.
- *
- * return self
- */
- public function setSQLSelectSnippet( $sqlSelectSnippet = '' ) {
- if ( $sqlSelectSnippet === AQueryWriter::C_SELECT_SNIPPET_FOR_UPDATE) $sqlSelectSnippet = '';
- $this->sqlSelectSnippet = $sqlSelectSnippet;
- return $this;
- }
-
- /**
- * @see QueryWriter::addIndex
- */
- public function addIndex( $type, $name, $column )
- {
- $columns = $this->getColumns( $type );
- if ( !isset( $columns[$column] ) ) return FALSE;
-
- $table = $this->esc( $type );
- $name = preg_replace( '/\W/', '', $name );
- $column = $this->esc( $column, TRUE );
-
- try {
- $t = $this->getTable( $type );
- $t['indexes'][$name] = array( 'name' => $column );
- $this->putTable( $t );
- return TRUE;
- } catch( SQLException $exception ) {
- return FALSE;
- }
- }
-
- /**
- * @see QueryWriter::wipe
- */
- public function wipe( $type )
- {
- $table = $this->esc( $type );
-
- $this->adapter->exec( "DELETE FROM $table " );
- }
-
- /**
- * @see QueryWriter::addFK
- */
- public function addFK( $type, $targetType, $property, $targetProperty, $isDep = FALSE )
- {
- return $this->buildFK( $type, $targetType, $property, $targetProperty, $isDep );
- }
-
- /**
- * @see QueryWriter::wipeAll
- */
- public function wipeAll()
- {
- if (AQueryWriter::$noNuke) throw new \Exception('The nuke() command has been disabled using noNuke() or R::feature(novice/...).');
- $this->adapter->exec( 'PRAGMA foreign_keys = 0 ' );
-
- foreach ( $this->getTables() as $t ) {
- try { $this->adapter->exec( "DROP TABLE IF EXISTS `$t`" ); } catch ( SQLException $e ) { ; }
- try { $this->adapter->exec( "DROP TABLE IF EXISTS `$t`" ); } catch ( SQLException $e ) { ; }
- }
-
- $this->adapter->exec( 'PRAGMA foreign_keys = 1 ' );
- }
-}
-}
-
-namespace RedBeanPHP\QueryWriter {
-
-use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter;
-use RedBeanPHP\QueryWriter as QueryWriter;
-use RedBeanPHP\Adapter\DBAdapter as DBAdapter;
-use RedBeanPHP\Adapter as Adapter;
-use RedBeanPHP\RedException\SQL as SQLException;
-
-/**
- * RedBeanPHP PostgreSQL Query Writer.
- * This is a QueryWriter class for RedBeanPHP.
- * This QueryWriter provides support for the PostgreSQL database platform.
- *
- * @file RedBeanPHP/QueryWriter/PostgreSQL.php
- * @author Gabor de Mooij and the RedBeanPHP Community
- * @license BSD/GPLv2
- *
- * @copyright
- * (c) copyright G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
- * This source file is subject to the BSD/GPLv2 License that is bundled
- * with this source code in the file license.txt.
- */
-class PostgreSQL extends AQueryWriter implements QueryWriter
-{
- /**
- * Data types
- */
- const C_DATATYPE_INTEGER = 0;
- const C_DATATYPE_DOUBLE = 1;
- const C_DATATYPE_TEXT = 3;
- const C_DATATYPE_SPECIAL_DATE = 80;
- const C_DATATYPE_SPECIAL_DATETIME = 81;
- const C_DATATYPE_SPECIAL_TIME = 82; //TIME (no zone) only manual
- const C_DATATYPE_SPECIAL_TIMEZ = 83; //TIME (plus zone) only manual
- const C_DATATYPE_SPECIAL_POINT = 90;
- const C_DATATYPE_SPECIAL_LSEG = 91;
- const C_DATATYPE_SPECIAL_CIRCLE = 92;
- const C_DATATYPE_SPECIAL_MONEY = 93;
- const C_DATATYPE_SPECIAL_POLYGON = 94;
- const C_DATATYPE_SPECIAL_MONEY2 = 95; //Numbers only money, i.e. fixed point numeric
- const C_DATATYPE_SPECIAL_JSON = 96; //JSON support (only manual)
- const C_DATATYPE_SPECIFIED = 99;
-
- /**
- * @var DBAdapter
- */
- protected $adapter;
-
- /**
- * @var string
- */
- protected $quoteCharacter = '"';
-
- /**
- * @var string
- */
- protected $defaultValue = 'DEFAULT';
-
- /**
- * @var array
- */
- protected $DDLTemplates = array(
- 'addColumn' => array(
- '*' => 'ALTER TABLE %s ADD %s %s '
- ),
- 'createTable' => array(
- '*' => 'CREATE TABLE %s (id SERIAL PRIMARY KEY) '
- ),
- 'widenColumn' => array(
- '*' => 'ALTER TABLE %s ALTER COLUMN %s TYPE %s'
- )
- );
-
- /**
- * Returns the insert suffix SQL Snippet
- *
- * @param string $table table
- *
- * @return string $sql SQL Snippet
- */
- protected function getInsertSuffix( $table )
- {
- return 'RETURNING id ';
- }
-
- /**
- * @see AQueryWriter::getKeyMapForType
- */
- protected function getKeyMapForType( $type )
- {
- $table = $this->esc( $type, TRUE );
- $keys = $this->adapter->get( '
- SELECT
- information_schema.key_column_usage.constraint_name AS "name",
- information_schema.key_column_usage.column_name AS "from",
- information_schema.constraint_table_usage.table_name AS "table",
- information_schema.constraint_column_usage.column_name AS "to",
- information_schema.referential_constraints.update_rule AS "on_update",
- information_schema.referential_constraints.delete_rule AS "on_delete"
- FROM information_schema.key_column_usage
- INNER JOIN information_schema.constraint_table_usage
- ON (
- information_schema.key_column_usage.constraint_name = information_schema.constraint_table_usage.constraint_name
- AND information_schema.key_column_usage.constraint_schema = information_schema.constraint_table_usage.constraint_schema
- AND information_schema.key_column_usage.constraint_catalog = information_schema.constraint_table_usage.constraint_catalog
- )
- INNER JOIN information_schema.constraint_column_usage
- ON (
- information_schema.key_column_usage.constraint_name = information_schema.constraint_column_usage.constraint_name
- AND information_schema.key_column_usage.constraint_schema = information_schema.constraint_column_usage.constraint_schema
- AND information_schema.key_column_usage.constraint_catalog = information_schema.constraint_column_usage.constraint_catalog
- )
- INNER JOIN information_schema.referential_constraints
- ON (
- information_schema.key_column_usage.constraint_name = information_schema.referential_constraints.constraint_name
- AND information_schema.key_column_usage.constraint_schema = information_schema.referential_constraints.constraint_schema
- AND information_schema.key_column_usage.constraint_catalog = information_schema.referential_constraints.constraint_catalog
- )
- WHERE
- information_schema.key_column_usage.table_catalog = current_database()
- AND information_schema.key_column_usage.table_schema = ANY( current_schemas( FALSE ) )
- AND information_schema.key_column_usage.table_name = ?
- ', array( $type ) );
- $keyInfoList = array();
- foreach ( $keys as $k ) {
- $label = $this->makeFKLabel( $k['from'], $k['table'], $k['to'] );
- $keyInfoList[$label] = array(
- 'name' => $k['name'],
- 'from' => $k['from'],
- 'table' => $k['table'],
- 'to' => $k['to'],
- 'on_update' => $k['on_update'],
- 'on_delete' => $k['on_delete']
- );
- }
- return $keyInfoList;
- }
-
- /**
- * Constructor
- * Most of the time, you do not need to use this constructor,
- * since the facade takes care of constructing and wiring the
- * RedBeanPHP core objects. However if you would like to
- * assemble an OODB instance yourself, this is how it works:
- *
- * Usage:
- *
- *
- * $database = new RPDO( $dsn, $user, $pass );
- * $adapter = new DBAdapter( $database );
- * $writer = new PostgresWriter( $adapter );
- * $oodb = new OODB( $writer, FALSE );
- * $bean = $oodb->dispense( 'bean' );
- * $bean->name = 'coffeeBean';
- * $id = $oodb->store( $bean );
- * $bean = $oodb->load( 'bean', $id );
- *
- *
- * The example above creates the 3 RedBeanPHP core objects:
- * the Adapter, the Query Writer and the OODB instance and
- * wires them together. The example also demonstrates some of
- * the methods that can be used with OODB, as you see, they
- * closely resemble their facade counterparts.
- *
- * The wiring process: create an RPDO instance using your database
- * connection parameters. Create a database adapter from the RPDO
- * object and pass that to the constructor of the writer. Next,
- * create an OODB instance from the writer. Now you have an OODB
- * object.
- *
- * @param Adapter $adapter Database Adapter
- */
- public function __construct( Adapter $adapter )
- {
- $this->typeno_sqltype = array(
- self::C_DATATYPE_INTEGER => ' integer ',
- self::C_DATATYPE_DOUBLE => ' double precision ',
- self::C_DATATYPE_TEXT => ' text ',
- self::C_DATATYPE_SPECIAL_DATE => ' date ',
- self::C_DATATYPE_SPECIAL_TIME => ' time ',
- self::C_DATATYPE_SPECIAL_TIMEZ => ' time with time zone ',
- self::C_DATATYPE_SPECIAL_DATETIME => ' timestamp without time zone ',
- self::C_DATATYPE_SPECIAL_POINT => ' point ',
- self::C_DATATYPE_SPECIAL_LSEG => ' lseg ',
- self::C_DATATYPE_SPECIAL_CIRCLE => ' circle ',
- self::C_DATATYPE_SPECIAL_MONEY => ' money ',
- self::C_DATATYPE_SPECIAL_MONEY2 => ' numeric(10,2) ',
- self::C_DATATYPE_SPECIAL_POLYGON => ' polygon ',
- self::C_DATATYPE_SPECIAL_JSON => ' json ',
- );
-
- $this->sqltype_typeno = array();
-
- foreach ( $this->typeno_sqltype as $k => $v ) {
- $this->sqltype_typeno[trim( strtolower( $v ) )] = $k;
- }
-
- $this->adapter = $adapter;
- }
-
- /**
- * This method returns the datatype to be used for primary key IDS and
- * foreign keys. Returns one if the data type constants.
- *
- * @return integer
- */
- public function getTypeForID()
- {
- return self::C_DATATYPE_INTEGER;
- }
-
- /**
- * @see QueryWriter::getTables
- */
- public function getTables()
- {
- return $this->adapter->getCol( 'SELECT table_name FROM information_schema.tables WHERE table_schema = ANY( current_schemas( FALSE ) )' );
- }
-
- /**
- * @see QueryWriter::createTable
- */
- public function createTable( $type )
- {
- $table = $this->esc( $type );
-
- $this->adapter->exec( sprintf( $this->getDDLTemplate( 'createTable', $type ), $table ) );
- }
-
- /**
- * @see QueryWriter::getColumns
- */
- public function getColumns( $table )
- {
- $table = $this->esc( $table, TRUE );
-
- $columnsRaw = $this->adapter->get( "SELECT column_name, data_type FROM information_schema.columns WHERE table_name='$table' AND table_schema = ANY( current_schemas( FALSE ) )" );
-
- $columns = array();
- foreach ( $columnsRaw as $r ) {
- $columns[$r['column_name']] = $r['data_type'];
- }
-
- return $columns;
- }
-
- /**
- * @see QueryWriter::scanType
- */
- public function scanType( $value, $flagSpecial = FALSE )
- {
- $this->svalue = $value;
-
- if ( $value === INF ) return self::C_DATATYPE_TEXT;
-
- if ( $flagSpecial && $value ) {
- if ( preg_match( '/^\d{4}\-\d\d-\d\d$/', $value ) ) {
- return PostgreSQL::C_DATATYPE_SPECIAL_DATE;
- }
-
- if ( preg_match( '/^\d{4}\-\d\d-\d\d\s\d\d:\d\d:\d\d(\.\d{1,6})?$/', $value ) ) {
- return PostgreSQL::C_DATATYPE_SPECIAL_DATETIME;
- }
-
- if ( preg_match( '/^\([\d\.]+,[\d\.]+\)$/', $value ) ) {
- return PostgreSQL::C_DATATYPE_SPECIAL_POINT;
- }
-
- if ( preg_match( '/^\[\([\d\.]+,[\d\.]+\),\([\d\.]+,[\d\.]+\)\]$/', $value ) ) {
- return PostgreSQL::C_DATATYPE_SPECIAL_LSEG;
- }
-
- if ( preg_match( '/^\<\([\d\.]+,[\d\.]+\),[\d\.]+\>$/', $value ) ) {
- return PostgreSQL::C_DATATYPE_SPECIAL_CIRCLE;
- }
-
- if ( preg_match( '/^\((\([\d\.]+,[\d\.]+\),?)+\)$/', $value ) ) {
- return PostgreSQL::C_DATATYPE_SPECIAL_POLYGON;
- }
-
- if ( preg_match( '/^\-?(\$|€|¥|£)[\d,\.]+$/', $value ) ) {
- return PostgreSQL::C_DATATYPE_SPECIAL_MONEY;
- }
-
- if ( preg_match( '/^-?\d+\.\d{2}$/', $value ) ) {
- return PostgreSQL::C_DATATYPE_SPECIAL_MONEY2;
- }
- if ( self::$flagUseJSONColumns && $this->isJSON( $value ) ) {
- return self::C_DATATYPE_SPECIAL_JSON;
- }
- }
-
- if ( is_float( $value ) ) return self::C_DATATYPE_DOUBLE;
-
- if ( $this->startsWithZeros( $value ) ) return self::C_DATATYPE_TEXT;
-
- if ( $value === FALSE || $value === TRUE || $value === NULL || ( is_numeric( $value )
- && AQueryWriter::canBeTreatedAsInt( $value )
- && $value < 2147483648
- && $value > -2147483648 )
- ) {
- return self::C_DATATYPE_INTEGER;
- } elseif ( is_numeric( $value ) ) {
- return self::C_DATATYPE_DOUBLE;
- } else {
- return self::C_DATATYPE_TEXT;
- }
- }
-
- /**
- * @see QueryWriter::code
- */
- public function code( $typedescription, $includeSpecials = FALSE )
- {
- $r = ( isset( $this->sqltype_typeno[$typedescription] ) ) ? $this->sqltype_typeno[$typedescription] : 99;
-
- if ( $includeSpecials ) return $r;
-
- if ( $r >= QueryWriter::C_DATATYPE_RANGE_SPECIAL ) {
- return self::C_DATATYPE_SPECIFIED;
- }
-
- return $r;
- }
-
- /**
- * @see QueryWriter::widenColumn
- */
- public function widenColumn( $beanType, $column, $datatype )
- {
- $table = $beanType;
- $type = $datatype;
-
- $table = $this->esc( $table );
- $column = $this->esc( $column );
-
- $newtype = $this->typeno_sqltype[$type];
-
- $this->adapter->exec( sprintf( $this->getDDLTemplate( 'widenColumn', $beanType, $column ), $table, $column, $newtype ) );
-
- }
-
- /**
- * @see QueryWriter::addUniqueIndex
- */
- public function addUniqueConstraint( $type, $properties )
- {
- $tableNoQ = $this->esc( $type, TRUE );
- $columns = array();
- foreach( $properties as $key => $column ) $columns[$key] = $this->esc( $column );
- $table = $this->esc( $type );
- sort( $columns ); //else we get multiple indexes due to order-effects
- $name = "UQ_" . sha1( $table . implode( ',', $columns ) );
- $sql = "ALTER TABLE {$table}
- ADD CONSTRAINT $name UNIQUE (" . implode( ',', $columns ) . ")";
- try {
- $this->adapter->exec( $sql );
- } catch( SQLException $e ) {
- return FALSE;
- }
- return TRUE;
- }
-
- /**
- * @see QueryWriter::sqlStateIn
- */
- public function sqlStateIn( $state, $list, $extraDriverDetails = array() )
- {
- $stateMap = array(
- '42P01' => QueryWriter::C_SQLSTATE_NO_SUCH_TABLE,
- '42703' => QueryWriter::C_SQLSTATE_NO_SUCH_COLUMN,
- '23505' => QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION,
- '55P03' => QueryWriter::C_SQLSTATE_LOCK_TIMEOUT
- );
- return in_array( ( isset( $stateMap[$state] ) ? $stateMap[$state] : '0' ), $list );
- }
-
- /**
- * @see QueryWriter::addIndex
- */
- public function addIndex( $type, $name, $property )
- {
- $table = $this->esc( $type );
- $name = preg_replace( '/\W/', '', $name );
- $column = $this->esc( $property );
-
- try {
- $this->adapter->exec( "CREATE INDEX {$name} ON $table ({$column}) " );
- return TRUE;
- } catch ( SQLException $e ) {
- return FALSE;
- }
- }
-
- /**
- * @see QueryWriter::addFK
- */
- public function addFK( $type, $targetType, $property, $targetProperty, $isDep = FALSE )
- {
- $table = $this->esc( $type );
- $targetTable = $this->esc( $targetType );
- $field = $this->esc( $property );
- $targetField = $this->esc( $targetProperty );
- $tableNoQ = $this->esc( $type, TRUE );
- $fieldNoQ = $this->esc( $property, TRUE );
- if ( !is_null( $this->getForeignKeyForTypeProperty( $tableNoQ, $fieldNoQ ) ) ) return FALSE;
- try{
- $delRule = ( $isDep ? 'CASCADE' : 'SET NULL' );
- $this->adapter->exec( "ALTER TABLE {$table}
- ADD FOREIGN KEY ( {$field} ) REFERENCES {$targetTable}
- ({$targetField}) ON DELETE {$delRule} ON UPDATE {$delRule} DEFERRABLE ;" );
- return TRUE;
- } catch ( SQLException $e ) {
- return FALSE;
- }
- }
-
- /**
- * @see QueryWriter::wipeAll
- */
- public function wipeAll()
- {
- if (AQueryWriter::$noNuke) throw new \Exception('The nuke() command has been disabled using noNuke() or R::feature(novice/...).');
- $this->adapter->exec( 'SET CONSTRAINTS ALL DEFERRED' );
-
- foreach ( $this->getTables() as $t ) {
- $t = $this->esc( $t );
- //Some plugins (PostGIS have unremovable tables/views), avoid exceptions.
- try { $this->adapter->exec( "DROP TABLE IF EXISTS $t CASCADE " ); }catch( \Exception $e ) {}
- }
-
- $this->adapter->exec( 'SET CONSTRAINTS ALL IMMEDIATE' );
- }
-}
-}
-
namespace RedBeanPHP\QueryWriter {
use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter;
use RedBeanPHP\QueryWriter as QueryWriter;
@@ -8580,8 +7765,6 @@ class CUBRID extends AQueryWriter implements QueryWriter
*/
public function scanType( $value, $flagSpecial = FALSE )
{
- $this->svalue = $value;
-
if ( is_null( $value ) ) {
return self::C_DATATYPE_INTEGER;
}
@@ -8784,6 +7967,8 @@ class SQL extends RedException
/**
* @param array $driverDetails
+ *
+ * @return void
*/
public function setDriverDetails($driverDetails)
{
@@ -8840,7 +8025,7 @@ use RedBeanPHP\Cursor\NullCursor as NullCursor;
* Abstract Repository.
*
* OODB manages two repositories, a fluid one that
- * adjust the database schema on-the-fly to accomodate for
+ * adjust the database schema on-the-fly to accommodate for
* new bean types (tables) and new properties (columns) and
* a frozen one for use in a production environment. OODB
* allows you to swap the repository instances using the freeze()
@@ -8862,21 +8047,26 @@ abstract class Repository
*/
protected $stash = NULL;
- /*
+ /**
* @var integer
*/
protected $nesting = 0;
/**
- * @var DBAdapter
+ * @var QueryWriter
*/
protected $writer;
/**
- * @var boolean
+ * @var boolean|array
*/
protected $partialBeans = FALSE;
+ /**
+ * @var OODB
+ */
+ public $oodb = NULL;
+
/**
* Toggles 'partial bean mode'. If this mode has been
* selected the repository will only update the fields of a bean that
@@ -8889,7 +8079,7 @@ abstract class Repository
*
* @param boolean|array $yesNoBeans List of type names or 'all'
*
- * @return mixed
+ * @return boolean|array
*/
public function usePartialBeans( $yesNoBeans )
{
@@ -8904,12 +8094,12 @@ abstract class Repository
* addition, deleted 'trash can' or residue. Next, the different groups
* of beans will be processed accordingly and the reference bean (i.e.
* the one that was passed to the method as an argument) will be stored.
- * Each type of list (own/shared) has 3 bean processors:
+ * Each type of list (own/shared) has 3 bean processors:
*
* - trashCanProcessor : removes the bean or breaks its association with the current bean
* - additionProcessor : associates the bean with the current one
* - residueProcessor : manages beans in lists that 'remain' but may need to be updated
- *
+ *
* This method first groups the beans and then calls the
* internal processing methods.
*
@@ -8982,7 +8172,7 @@ abstract class Repository
* A bean may contain lists. This
* method handles shared addition lists; i.e.
* the $bean->sharedObject properties.
- * Shared beans will be associated with eachother using the
+ * Shared beans will be associated with each other using the
* Association Manager.
*
* @param OODBBean $bean the bean
@@ -9218,7 +8408,7 @@ abstract class Repository
* @param int $number number of beans you would like to get
* @param boolean $alwaysReturnArray if TRUE always returns the result as an array
*
- * @return OODBBean
+ * @return OODBBean|OODBBean[]
*/
public function dispense( $type, $number = 1, $alwaysReturnArray = FALSE )
{
@@ -9398,7 +8588,7 @@ abstract class Repository
* New in 4.3.2: meta mask. The meta mask is a special mask to send
* data from raw result rows to the meta store of the bean. This is
* useful for bundling additional information with custom queries.
- * Values of every column whos name starts with $mask will be
+ * Values of every column who's name starts with $mask will be
* transferred to the meta section of the bean under key 'data.bundle'.
*
* @param string $type type of beans you would like to have
@@ -9477,10 +8667,6 @@ abstract class Repository
public function count( $type, $addSQL = '', $bindings = array() )
{
$type = AQueryWriter::camelsSnake( $type );
- if ( count( explode( '_', $type ) ) > 2 ) {
- throw new RedException( 'Invalid type for count.' );
- }
-
try {
$count = (int) $this->writer->queryRecordCount( $type, array(), $addSQL, $bindings );
} catch ( SQLException $exception ) {
@@ -9497,7 +8683,7 @@ abstract class Repository
*
* @param OODBBean|SimpleModel $bean bean you want to remove from database
*
- * @return void
+ * @return int
*/
public function trash( $bean )
{
@@ -9515,7 +8701,7 @@ abstract class Repository
}
}
try {
- $deleted = $this->writer->deleteRecord( $bean->getMeta( 'type' ), array( 'id' => array( $bean->id ) ), NULL );
+ $deleted = $this->writer->deleteRecord( $bean->getMeta( 'type' ), array( 'id' => array( $bean->id ) ) );
} catch ( SQLException $exception ) {
$this->handleException( $exception );
}
@@ -9528,8 +8714,6 @@ abstract class Repository
* Checks whether the specified table already exists in the database.
* Not part of the Object Database interface!
*
- * @deprecated Use AQueryWriter::typeExists() instead.
- *
* @param string $table table name
*
* @return boolean
@@ -9579,7 +8763,7 @@ use RedBeanPHP\Repository as Repository;
/**
* Fluid Repository.
* OODB manages two repositories, a fluid one that
- * adjust the database schema on-the-fly to accomodate for
+ * adjust the database schema on-the-fly to accommodate for
* new bean types (tables) and new properties (columns) and
* a frozen one for use in a production environment. OODB
* allows you to swap the repository instances using the freeze()
@@ -9654,9 +8838,10 @@ class Fluid extends Repository
*
* This method will also apply indexes, unique constraints and foreign keys.
*
- * @param OODBBean $bean bean to get cast data from and store meta in
- * @param string $property property to store
- * @param mixed $value value to store
+ * @param OODBBean $bean bean to get cast data from and store meta in
+ * @param string $property property to store
+ * @param mixed $value value to store
+ * @param array|NULL &$columns
*
* @return void
*/
@@ -9902,7 +9087,7 @@ use RedBeanPHP\Repository as Repository;
/**
* Frozen Repository.
* OODB manages two repositories, a fluid one that
- * adjust the database schema on-the-fly to accomodate for
+ * adjust the database schema on-the-fly to accommodate for
* new bean types (tables) and new properties (columns) and
* a frozen one for use in a production environment. OODB
* allows you to swap the repository instances using the freeze()
@@ -10116,7 +9301,7 @@ class OODB extends Observable
protected $nesting = 0;
/**
- * @var DBAdapter
+ * @var QueryWriter
*/
protected $writer;
@@ -10126,12 +9311,12 @@ class OODB extends Observable
protected $isFrozen = FALSE;
/**
- * @var FacadeBeanHelper
+ * @var BeanHelper|NULL
*/
protected $beanhelper = NULL;
/**
- * @var AssociationManager
+ * @var AssociationManager|NULL
*/
protected $assocManager = NULL;
@@ -10141,12 +9326,12 @@ class OODB extends Observable
protected $repository = NULL;
/**
- * @var FrozenRepo
+ * @var FrozenRepo|NULL
*/
protected $frozenRepository = NULL;
/**
- * @var FluidRepo
+ * @var FluidRepo|NULL
*/
protected $fluidRepository = NULL;
@@ -10172,7 +9357,7 @@ class OODB extends Observable
* Unboxes a bean from a FUSE model if needed and checks whether the bean is
* an instance of OODBBean.
*
- * @param OODBBean $bean bean you wish to unbox
+ * @param OODBBean|SimpleModel $bean bean you wish to unbox
*
* @return OODBBean
*/
@@ -10234,11 +9419,11 @@ class OODB extends Observable
/**
* Toggles fluid or frozen mode. In fluid mode the database
- * structure is adjusted to accomodate your objects. In frozen mode
+ * structure is adjusted to accommodate your objects. In frozen mode
* this is not the case.
*
* You can also pass an array containing a selection of frozen types.
- * Let's call this chilly mode, it's just like fluid mode except that
+ * Let's call this chill mode, it's just like fluid mode except that
* certain types (i.e. tables) aren't touched.
*
* @param boolean|array $toggle TRUE if you want to use OODB instance in frozen mode
@@ -10278,7 +9463,7 @@ class OODB extends Observable
/**
* Returns the current mode of operation of RedBean.
* In fluid mode the database
- * structure is adjusted to accomodate your objects.
+ * structure is adjusted to accommodate your objects.
* In frozen mode
* this is not the case.
*
@@ -10318,7 +9503,7 @@ class OODB extends Observable
* @param string $number number of beans you would like to get
* @param boolean $alwaysReturnArray if TRUE always returns the result as an array
*
- * @return OODBBean
+ * @return OODBBean|OODBBean[]
*/
public function dispense( $type, $number = 1, $alwaysReturnArray = FALSE )
{
@@ -10347,7 +9532,7 @@ class OODB extends Observable
* Returns the current bean helper.
* Bean helpers assist beans in getting a reference to a toolbox.
*
- * @return BeanHelper
+ * @return BeanHelper|NULL
*/
public function getBeanHelper()
{
@@ -10369,7 +9554,7 @@ class OODB extends Observable
}
/**
- * Searches the database for a bean that matches conditions $conditions and sql $addSQL
+ * Searches the database for a bean that matches conditions $conditions and sql $sql
* and returns an array containing all the beans that have been found.
*
* Conditions need to take form:
@@ -10387,10 +9572,10 @@ class OODB extends Observable
* Note that you can use property names; the columns will be extracted using the
* appropriate bean formatter.
*
- * @param string $type type of beans you are looking for
- * @param array $conditions list of conditions
- * @param string $sql SQL to be used in query
- * @param array $bindings a list of values to bind to query parameters
+ * @param string $type type of beans you are looking for
+ * @param array $conditions list of conditions
+ * @param string|NULL $sql SQL to be used in query
+ * @param array $bindings a list of values to bind to query parameters
*
* @return array
*/
@@ -10402,9 +9587,9 @@ class OODB extends Observable
/**
* Same as find() but returns a BeanCollection.
*
- * @param string $type type of beans you are looking for
- * @param string $sql SQL to be used in query
- * @param array $bindings a list of values to bind to query parameters
+ * @param string $type type of beans you are looking for
+ * @param string|NULL $sql SQL to be used in query
+ * @param array $bindings a list of values to bind to query parameters
*
* @return BeanCollection
*/
@@ -10415,9 +9600,6 @@ class OODB extends Observable
/**
* Checks whether the specified table already exists in the database.
- * Not part of the Object Database interface!
- *
- * @deprecated Use AQueryWriter::typeExists() instead.
*
* @param string $table table name
*
@@ -10492,7 +9674,7 @@ class OODB extends Observable
*
* @param OODBBean|SimpleModel $bean bean you want to remove from database
*
- * @return void
+ * @return int
*/
public function trash( $bean )
{
@@ -10623,10 +9805,10 @@ class OODB extends Observable
* MySQL spatial columns, because they need to be processed first using
* the asText/GeomFromText functions.
*
- * @param string $mode mode to set function for, i.e. read or write
- * @param string $field field (table.column) to bind SQL function to
- * @param string $function SQL function to bind to field
- * @param boolean $isTemplate TRUE if $function is an SQL string, FALSE for just a function name
+ * @param string $mode mode to set function for, i.e. read or write
+ * @param string $field field (table.column) to bind SQL function to
+ * @param string|NULL $function SQL function to bind to field
+ * @param boolean $isTemplate TRUE if $function is an SQL string, FALSE for just a function name
*
* @return void
*/
@@ -10982,7 +10164,7 @@ class Finder
* R::genSlots( $users,
* 'SELECT country.* FROM country WHERE id IN ( %s )' ),
* array_column( $users, 'country_id' ),
- * [Finder::onmap('country', $gebruikers)]
+ * [Finder::onmap('country', $users)]
* );
*
*
@@ -11011,9 +10193,9 @@ class Finder
* array parameter; you can either use the question mark notation
* or the slot-notation (:keyname).
*
- * @param string $type type the type of bean you are looking for
- * @param string $sql sql SQL query to find the desired bean, starting right after WHERE clause
- * @param array $bindings values array of values to be bound to parameters in query
+ * @param string $type type the type of bean you are looking for
+ * @param string|NULL $sql sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param array $bindings values array of values to be bound to parameters in query
*
* @return array
*/
@@ -11037,9 +10219,9 @@ class Finder
*
* @see Finder::find
*
- * @param string $type type the type of bean you are looking for
- * @param string $sql sql SQL query to find the desired bean, starting right after WHERE clause
- * @param array $bindings values array of values to be bound to parameters in query
+ * @param string $type type the type of bean you are looking for
+ * @param string|NULL $sql sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param array $bindings values array of values to be bound to parameters in query
*
* @return array
*/
@@ -11060,9 +10242,9 @@ class Finder
*
* @see Finder::find
*
- * @param string $type type the type of bean you are looking for
- * @param string $sql sql SQL query to find the desired bean, starting right after WHERE clause
- * @param array $bindings values array of values to be bound to parameters in query
+ * @param string $type type the type of bean you are looking for
+ * @param string|NULL $sql sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param array $bindings values array of values to be bound to parameters in query
*
* @return OODBBean|NULL
*/
@@ -11086,9 +10268,9 @@ class Finder
*
* @see Finder::find
*
- * @param string $type the type of bean you are looking for
- * @param string $sql SQL query to find the desired bean, starting right after WHERE clause
- * @param array $bindings values array of values to be bound to parameters in query
+ * @param string $type the type of bean you are looking for
+ * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param array $bindings values array of values to be bound to parameters in query
*
* @return OODBBean|NULL
*/
@@ -11110,9 +10292,9 @@ class Finder
*
* @see Finder::find
*
- * @param string $type the type of bean you are looking for
- * @param string $sql SQL query to find the desired bean, starting right after WHERE clause
- * @param array $bindings values array of values to be bound to parameters in query
+ * @param string $type the type of bean you are looking for
+ * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param array $bindings values array of values to be bound to parameters in query
*
* @return array
*/
@@ -11380,7 +10562,7 @@ class Finder
} else {
list($field1, $field2) = $matcher;
foreach( $beans[$b] as $key => $bean ) {
- $beans[$b][$key]->{$field1} = $beans[$a][$bean->{$field2}];
+ $beans[$b][$key]->{$field1} = (isset($beans[$a][$bean->{$field2}]) ? $beans[$a][$bean->{$field2}] : NULL);
}
}
}
@@ -11429,6 +10611,11 @@ class AssociationManager extends Observable
*/
protected $writer;
+ /**
+ * @var ToolBox
+ */
+ public $toolbox;
+
/**
* Exception handler.
* Fluid and Frozen mode have different ways of handling
@@ -11607,7 +10794,7 @@ class AssociationManager extends Observable
*
* @param OODBBean|array $bean a bean object or an array of beans
* @param string $type type of bean you're interested in
- * @param string $sql SQL snippet (optional)
+ * @param string|NULL $sql SQL snippet (optional)
* @param array $bindings bindings for your SQL string
*
* @return integer
@@ -11726,7 +10913,7 @@ class AssociationManager extends Observable
* Since 3.2, you can now also pass an array of beans instead just one
* bean as the first parameter.
*
- * @param OODBBean|array $bean the bean you have
+ * @param OODBBean $bean the bean you have
* @param string $type the type of beans you want
* @param string $sql SQL snippet for extra filtering
* @param array $bindings values to be inserted in SQL slots
@@ -11764,7 +10951,7 @@ use RedBeanPHP\OODBBean as OODBBean;
* Interface for Bean Helper.
* A little bolt that glues the whole machinery together.
* The Bean Helper is passed to the OODB RedBeanPHP Object to
- * faciliatte the creation of beans and providing them with
+ * facilitate the creation of beans and providing them with
* a toolbox. The Helper also facilitates the FUSE feature,
* determining how beans relate to their models. By overriding
* the getModelForBean method you can tune the FUSEing to
@@ -11841,7 +11028,7 @@ class SimpleFacadeBeanHelper implements BeanHelper
/**
* Factory function to create instance of Simple Model, if any.
*
- * @var \Closure
+ * @var callable|NULL
*/
private static $factory = null;
@@ -11863,7 +11050,7 @@ class SimpleFacadeBeanHelper implements BeanHelper
* Sets the factory function to create the model when using FUSE
* to connect a bean to a model.
*
- * @param \Closure $factory factory function
+ * @param callable|NULL $factory factory function
*
* @return void
*/
@@ -11888,6 +11075,28 @@ class SimpleFacadeBeanHelper implements BeanHelper
$model = $bean->getMeta( 'type' );
$prefix = defined( 'REDBEAN_MODEL_PREFIX' ) ? REDBEAN_MODEL_PREFIX : '\\Model_';
+ return $this->resolveModel($prefix, $model, $bean);
+ }
+
+ /**
+ * Resolves the model associated with the bean using the model name (type),
+ * the prefix and the bean.
+ *
+ * @note
+ * If REDBEAN_CLASS_AUTOLOAD is defined this will be passed to class_exist as
+ * autoloading flag.
+ *
+ * @param string $prefix Prefix to use for resolution
+ * @param string $model Type name
+ * @param OODBBean $bean Bean to resolve model for
+ *
+ * @return SimpleModel|CustomModel|NULL
+ */
+ protected function resolveModel($prefix, $model, $bean) {
+
+ /* Determine autoloading preference */
+ $autoloadFlag = ( defined( 'REDBEAN_CLASS_AUTOLOAD' ) ? REDBEAN_CLASS_AUTOLOAD : TRUE );
+
if ( strpos( $model, '_' ) !== FALSE ) {
$modelParts = explode( '_', $model );
$modelName = '';
@@ -11897,13 +11106,13 @@ class SimpleFacadeBeanHelper implements BeanHelper
$modelName = $prefix . $modelName;
if ( !class_exists( $modelName ) ) {
$modelName = $prefix . ucfirst( $model );
- if ( !class_exists( $modelName ) ) {
+ if ( !class_exists( $modelName, $autoloadFlag ) ) {
return NULL;
}
}
} else {
$modelName = $prefix . ucfirst( $model );
- if ( !class_exists( $modelName ) ) {
+ if ( !class_exists( $modelName, $autoloadFlag ) ) {
return NULL;
}
}
@@ -11922,6 +11131,63 @@ class SimpleFacadeBeanHelper implements BeanHelper
}
}
+namespace RedBeanPHP\BeanHelper {
+
+use RedBeanPHP\BeanHelper as BeanHelper;
+use RedBeanPHP\Facade as Facade;
+use RedBeanPHP\OODBBean as OODBBean;
+use RedBeanPHP\SimpleModelHelper as SimpleModelHelper;
+use RedBeanPHP\BeanHelper\SimpleFacadeBeanHelper as SimpleFacadeBeanHelper;
+
+/**
+ * Dynamic Bean Helper.
+ *
+ * The dynamic bean helper allows you to use differently namespaced
+ * classes for models per database connection.
+ *
+ * @file RedBeanPHP/BeanHelper/DynamicBeanHelper.php
+ * @author Gabor de Mooij and the RedBeanPHP Community
+ * @license BSD/GPLv2
+ *
+ * @copyright
+ * (c) copyright G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community
+ * This source file is subject to the BSD/GPLv2 License that is bundled
+ * with this source code in the file license.txt.
+ */
+class DynamicBeanHelper extends SimpleFacadeBeanHelper implements BeanHelper
+{
+ /**
+ * Model prefix to be used for the current database connection.
+ *
+ * @var string
+ */
+ private $modelPrefix;
+
+ /**
+ * Constructor
+ *
+ * Usage:
+ *
+ *
+ * R::addDatabase( ..., new DynamicBeanHelper('Prefix1_') );
+ *
+ *
+ * @param string $modelPrefix prefix
+ */
+ public function __construct( $modelPrefix ) {
+ $this->modelPrefix = $modelPrefix;
+ }
+
+ /**
+ * @see BeanHelper::getModelForBean
+ */
+ public function getModelForBean( OODBBean $bean )
+ {
+ return $this->resolveModel( $this->modelPrefix, $bean->getMeta( 'type' ), $bean );
+ }
+}
+}
+
namespace RedBeanPHP {
use RedBeanPHP\OODBBean as OODBBean;
@@ -12079,7 +11345,7 @@ class SimpleModelHelper implements Observer
* invoke the corresponding method on the bean.
*
* @param string $eventName i.e. 'delete', 'after_delete'
- * @param OODBean $bean affected bean
+ * @param OODBBean $bean affected bean
*
* @return void
*/
@@ -12157,7 +11423,7 @@ class TagManager
protected $associationManager;
/**
- * @var OODBBean
+ * @var OODB
*/
protected $redbean;
@@ -12166,7 +11432,7 @@ class TagManager
* it will split the string into words and return an array instead.
* In case of an array the argument will be returned 'as is'.
*
- * @param array|string $tagList list of tags
+ * @param array|string|false $tagList list of tags
*
* @return array
*/
@@ -12182,12 +11448,12 @@ class TagManager
}
/**
- * Finds a tag bean by it's title.
+ * Finds a tag bean by its title.
* Internal method.
*
* @param string $title title to search for
*
- * @return OODBBean
+ * @return OODBBean|NULL
*/
protected function findTagByTitle( $title )
{
@@ -12218,7 +11484,7 @@ class TagManager
}
/**
- * Tests whether a bean has been associated with one ore more
+ * Tests whether a bean has been associated with one or more
* of the listed tags. If the third parameter is TRUE this method
* will return TRUE only if all tags that have been specified are indeed
* associated with the given bean, otherwise FALSE.
@@ -12276,8 +11542,8 @@ class TagManager
* In the example above, the $blog bean will no longer
* be associated with the tags 'smart' and 'interesting'.
*
- * @param OODBBean $bean tagged bean
- * @param array $tagList list of tags (names)
+ * @param OODBBean $bean tagged bean
+ * @param array|string $tagList list of tags (names)
*
* @return void
*/
@@ -12353,8 +11619,8 @@ class TagManager
* The example adds the tag 'halloween' to the $blog
* bean.
*
- * @param OODBBean $bean bean to tag
- * @param array $tagList list of tags to add to bean
+ * @param OODBBean $bean bean to tag
+ * @param array|string|false $tagList list of tags to add to bean
*
* @return void
*/
@@ -12701,7 +11967,7 @@ use RedBeanPHP\Util\Feature;
* RedBean Facade
*
* Version Information
- * RedBean Version @version 5.6
+ * RedBean Version @version 5.7
*
* This class hides the object landscape of
* RedBeanPHP behind a single letter class providing
@@ -12721,7 +11987,7 @@ class Facade
/**
* RedBeanPHP version constant.
*/
- const C_REDBEANPHP_VERSION = '5.6';
+ const C_REDBEANPHP_VERSION = '5.7';
/**
* @var ToolBox
@@ -12739,7 +12005,7 @@ class Facade
private static $writer;
/**
- * @var DBAdapter
+ * @var Adapter
*/
private static $adapter;
@@ -12779,7 +12045,7 @@ class Facade
private static $logger;
/**
- * @var array
+ * @var callable[]
*/
private static $plugins = array();
@@ -12789,12 +12055,12 @@ class Facade
private static $exportCaseStyle = 'default';
/**
- * @var flag allows transactions through facade in fluid mode
+ * @var bool flag allows transactions through facade in fluid mode
*/
private static $allowFluidTransactions = FALSE;
/**
- * @var flag allows to unfreeze if needed with store(all)
+ * @var bool flag allows to unfreeze if needed with store(all)
*/
private static $allowHybridMode = FALSE;
@@ -12809,7 +12075,7 @@ class Facade
public static $currentDB = '';
/**
- * @var array
+ * @var ToolBox[]
*/
public static $toolboxes = array();
@@ -12821,7 +12087,7 @@ class Facade
* @param string $sql the sql you want to execute
* @param array $bindings array of values to be bound to query statement
*
- * @return array
+ * @return array|int|Cursor|NULL
*/
private static function query( $method, $sql, $bindings )
{
@@ -12856,6 +12122,8 @@ class Facade
* flag.
*
* @param boolean $hybrid
+ *
+ * @return bool
*/
public static function setAllowHybridMode( $hybrid )
{
@@ -12933,11 +12201,11 @@ class Facade
* a connection is really required, for instance when attempting to load
* a bean.
*
- * @param string $dsn Database connection string
- * @param string $username Username for database
- * @param string $password Password for database
- * @param boolean $frozen TRUE if you want to setup in frozen mode
- * @param boolean $partialBeans TRUE to enable partial bean updates
+ * @param string|\PDO|NULL $dsn Database connection string
+ * @param string|NULL $username Username for database
+ * @param string|NULL $password Password for database
+ * @param boolean|string[] $frozen TRUE if you want to setup in frozen mode
+ * @param boolean|string[] $partialBeans TRUE to enable partial bean updates
* @param array $options Additional (PDO) options to pass
*
* @return ToolBox
@@ -12988,7 +12256,7 @@ class Facade
* Toggles fluid transactions. By default fluid transactions
* are not active. Starting, committing or rolling back a transaction
* through the facade in fluid mode will have no effect. If you wish
- * to replace this standard portable behavor with behavior depending
+ * to replace this standard portable behavior with behavior depending
* on how the used database platform handles fluid (DDL) transactions
* set this flag to TRUE.
*
@@ -13051,6 +12319,7 @@ class Facade
*/
public static function transaction( $callback )
{
+ if ( !self::$allowFluidTransactions && !self::$redbean->isFrozen() ) return FALSE;
return Transaction::transaction( self::$adapter, $callback );
}
@@ -13068,28 +12337,35 @@ class Facade
* This method allows you to dynamically add (and select) new databases
* to the facade. Adding a database with the same key will cause an exception.
*
- * @param string $key ID for the database
- * @param string $dsn DSN for the database
- * @param string $user user for connection
- * @param NULL|string $pass password for connection
- * @param bool $frozen whether this database is frozen or not
+ * @param string $key ID for the database
+ * @param string|\PDO $dsn DSN for the database
+ * @param string|NULL $user user for connection
+ * @param string|NULL $pass password for connection
+ * @param bool|string[] $frozen whether this database is frozen or not
+ * @param bool|string[] $partialBeans should we load partial beans?
+ * @param array $options additional options for the query writer
+ * @param BeanHelper|NULL $beanHelper Beanhelper to use (use this for DB specific model prefixes)
*
* @return void
*/
- public static function addDatabase( $key, $dsn, $user = NULL, $pass = NULL, $frozen = FALSE, $partialBeans = FALSE, $options = array() )
+ public static function addDatabase( $key, $dsn, $user = NULL, $pass = NULL, $frozen = FALSE, $partialBeans = FALSE, $options = array(), $beanHelper = NULL )
{
if ( isset( self::$toolboxes[$key] ) ) {
throw new RedException( 'A database has already been specified for this key.' );
}
self::$toolboxes[$key] = self::createToolbox($dsn, $user, $pass, $frozen, $partialBeans, $options);
+
+ if ( !is_null( $beanHelper ) ) {
+ self::$toolboxes[$key]->getRedBean()->setBeanHelper( $beanHelper );
+ }
}
/**
* Creates a toolbox. This method can be called if you want to use redbean non-static.
- * It has the same interface as R::setup(). The createToolbx() method can be called
- * without any arguments, in this case it will try to create a SQLite database in
- * /tmp called red.db (this only works on UNIX-like systems).
+ * It has the same interface as R::setup(). The createToolbox() method can be called
+ * without any arguments, in this case it will try to create a SQLite database in
+ * /tmp called red.db (this only works on UNIX-like systems).
*
* Usage:
*
@@ -13111,15 +12387,17 @@ class Facade
* Instead, it will prepare the connection and connect 'lazily', i.e. the moment
* a connection is really required, for instance when attempting to load a bean.
*
- * @param string $dsn Database connection string
+ * @param string|\PDO $dsn Database connection string
* @param string $username Username for database
* @param string $password Password for database
- * @param boolean $frozen TRUE if you want to setup in frozen mode
+ * @param boolean|string[] $frozen TRUE if you want to setup in frozen mode
+ * @param boolean|string[] $partialBeans TRUE to enable partial bean updates
+ * @param array $options
*
* @return ToolBox
*/
- public static function createToolbox( $dsn = NULL, $username = NULL, $password = NULL, $frozen = FALSE, $partialBeans = FALSE, $options = array() )
- {
+ public static function createToolbox( $dsn, $username = NULL, $password = NULL, $frozen = FALSE, $partialBeans = FALSE, $options = array() )
+ {
if ( is_object($dsn) ) {
$db = new RPDO( $dsn );
$dbType = $db->getDatabaseType();
@@ -13144,6 +12422,7 @@ class Facade
throw new RedException( 'Unsupported database ('.$wkey.').' );
}
$writerClass = '\\RedBeanPHP\\QueryWriter\\'.$writers[$wkey];
+ /** @var AQueryWriter $writer */
$writer = new $writerClass( $adapter );
$redbean = new OODB( $writer, $frozen );
@@ -13179,6 +12458,7 @@ class Facade
* switched and FALSE otherwise (for instance if you already using the specified database).
*
* @param string $key Key of the database to select
+ * @param bool $force
*
* @return boolean
*/
@@ -13208,7 +12488,7 @@ class Facade
* There are 2 debug styles:
*
* Classic: separate parameter bindings, explicit and complete but less readable
- * Fancy: interpersed bindings, truncates large strings, highlighted schema changes
+ * Fancy: interspersed bindings, truncates large strings, highlighted schema changes
*
* Fancy style is more readable but sometimes incomplete.
*
@@ -13270,9 +12550,9 @@ class Facade
* the column types used to store their values.
* If no type is passed, this method returns a list of all tables in the database.
*
- * @param string $type Type of bean (i.e. table) you want to inspect
+ * @param string|NULL $type Type of bean (i.e. table) you want to inspect, or NULL for a list of all tables
*
- * @return array
+ * @return string[]
*/
public static function inspect( $type = NULL )
{
@@ -13336,14 +12616,16 @@ class Facade
/**
* Toggles fluid or frozen mode. In fluid mode the database
- * structure is adjusted to accomodate your objects. In frozen mode
+ * structure is adjusted to accommodate your objects. In frozen mode
* this is not the case.
*
* You can also pass an array containing a selection of frozen types.
* Let's call this chilly mode, it's just like fluid mode except that
* certain types (i.e. tables) aren't touched.
*
- * @param boolean|array $tf mode of operation (TRUE means frozen)
+ * @param boolean|string[] $tf mode of operation (TRUE means frozen)
+ *
+ * @return void
*/
public static function freeze( $tf = TRUE )
{
@@ -13364,10 +12646,10 @@ class Facade
* list( $author, $bio ) = R::loadMulti( 'author, bio', $id );
*
*
- * @param string|array $types the set of types to load at once
- * @param mixed $id the common ID
+ * @param string|string[] $types the set of types to load at once
+ * @param int $id the common ID
*
- * @return OODBBean
+ * @return OODBBean[]
*/
public static function loadMulti( $types, $id )
{
@@ -13409,7 +12691,7 @@ class Facade
*
* @param string $type type of bean you want to load
* @param integer $id ID of the bean you want to load
- * @param string $snippet string to use after select (optional)
+ * @param string|NULL $snippet string to use after select (optional)
*
* @return OODBBean
*/
@@ -13463,10 +12745,10 @@ class Facade
*
*
* @param string $type the type of bean you are looking for
- * @param string $sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause
* @param array $bindings array of values to be bound to parameters in query
*
- * @return array
+ * @return OODBBean[]
*/
public static function findForUpdate( $type, $sql = NULL, $bindings = array() )
{
@@ -13478,16 +12760,16 @@ class Facade
* Same as findForUpdate but returns just one bean and adds LIMIT-clause.
*
* @param string $type the type of bean you are looking for
- * @param string $sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause
* @param array $bindings array of values to be bound to parameters in query
*
- * @return array
+ * @return OODBBean|NULL
*/
public static function findOneForUpdate( $type, $sql = NULL, $bindings = array() )
{
$sql = self::getWriter()->glueLimitOne( $sql );
$beans = self::findForUpdate($type, $sql, $bindings);
- return !empty($beans) ? reset($beans) : NULL;
+ return empty($beans) ? NULL : reset($beans);
}
/**
@@ -13518,7 +12800,7 @@ class Facade
* @param string|OODBBean|SimpleModel $beanOrType bean you want to remove from database
* @param integer $id ID if the bean to trash (optional, type-id variant only)
*
- * @return void
+ * @return int
*/
public static function trash( $beanOrType, $id = NULL )
{
@@ -13566,11 +12848,11 @@ class Facade
* ] );
*
*
- * @param string|array $typeOrBeanArray type or bean array to import
+ * @param string|OODBBean[] $typeOrBeanArray type or bean array to import
* @param integer $num number of beans to dispense
* @param boolean $alwaysReturnArray if TRUE always returns the result as an array
*
- * @return array|OODBBean
+ * @return OODBBean|OODBBean[]
*/
public static function dispense( $typeOrBeanArray, $num = 1, $alwaysReturnArray = FALSE )
{
@@ -13611,15 +12893,15 @@ class Facade
}
/**
- * Convience method. Tries to find beans of a certain type,
+ * Convenience method. Tries to find beans of a certain type,
* if no beans are found, it dispenses a bean of that type.
* Note that this function always returns an array.
*
- * @param string $type type of bean you are looking for
- * @param string $sql SQL code for finding the bean
- * @param array $bindings parameters to bind to SQL
+ * @param string $type type of bean you are looking for
+ * @param string|NULL $sql SQL code for finding the bean
+ * @param array $bindings parameters to bind to SQL
*
- * @return array
+ * @return OODBBean[]
*/
public static function findOrDispense( $type, $sql = NULL, $bindings = array() )
{
@@ -13630,9 +12912,9 @@ class Facade
/**
* Same as findOrDispense but returns just one element.
*
- * @param string $type type of bean you are looking for
- * @param string $sql SQL code for finding the bean
- * @param array $bindings parameters to bind to SQL
+ * @param string $type type of bean you are looking for
+ * @param string|NULL $sql SQL code for finding the bean
+ * @param array $bindings parameters to bind to SQL
*
* @return OODBBean
*/
@@ -13652,12 +12934,15 @@ class Facade
*
* Your SQL does not have to start with a WHERE-clause condition.
*
- * @param string $type the type of bean you are looking for
- * @param string $sql SQL query to find the desired bean, starting right after WHERE clause
- * @param array $bindings array of values to be bound to parameters in query
- * @param string $snippet SQL snippet to include in query (for example: FOR UPDATE)
+ * @param string $type the type of bean you are looking for
+ * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param array $bindings array of values to be bound to parameters in query
+ * @param string|NULL $snippet SQL snippet to include in query (for example: FOR UPDATE)
*
- * @return array
+ * @phpstan-param literal-string|null $sql
+ * @psalm-param literal-string|null $sql
+ *
+ * @return OODBBean[]
*/
public static function find( $type, $sql = NULL, $bindings = array(), $snippet = NULL )
{
@@ -13668,11 +12953,11 @@ class Facade
/**
* Alias for find().
*
- * @param string $type the type of bean you are looking for
- * @param string $sql SQL query to find the desired bean, starting right after WHERE clause
- * @param array $bindings array of values to be bound to parameters in query
+ * @param string $type the type of bean you are looking for
+ * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param array $bindings array of values to be bound to parameters in query
*
- * @return array
+ * @return OODBBean[]
*/
public static function findAll( $type, $sql = NULL, $bindings = array() )
{
@@ -13688,9 +12973,9 @@ class Facade
*
* @see Finder::find
*
- * @param string $type type the type of bean you are looking for
- * @param string $sql sql SQL query to find the desired bean, starting right after WHERE clause
- * @param array $bindings values array of values to be bound to parameters in query
+ * @param string $type type the type of bean you are looking for
+ * @param string|NULL $sql sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param array $bindings values array of values to be bound to parameters in query
*
* @return array
*/
@@ -13702,9 +12987,9 @@ class Facade
/**
* Like R::find() but returns the first bean only.
*
- * @param string $type the type of bean you are looking for
- * @param string $sql SQL query to find the desired bean, starting right after WHERE clause
- * @param array $bindings array of values to be bound to parameters in query
+ * @param string $type the type of bean you are looking for
+ * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param array $bindings array of values to be bound to parameters in query
*
* @return OODBBean|NULL
*/
@@ -13727,9 +13012,9 @@ class Facade
*
* @see Finder::find
*
- * @param string $type the type of bean you are looking for
- * @param string $sql SQL query to find the desired bean, starting right after WHERE clause
- * @param array $bindings values array of values to be bound to parameters in query
+ * @param string $type the type of bean you are looking for
+ * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param array $bindings values array of values to be bound to parameters in query
*
* @return OODBBean|NULL
*/
@@ -13744,9 +13029,9 @@ class Facade
* cursors - this is useful for processing large datasets. A bean collection
* will not load all beans into memory all at once, just one at a time.
*
- * @param string $type the type of bean you are looking for
- * @param string $sql SQL query to find the desired bean, starting right after WHERE clause
- * @param array $bindings values array of values to be bound to parameters in query
+ * @param string $type the type of bean you are looking for
+ * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause
+ * @param array $bindings values array of values to be bound to parameters in query
*
* @return BeanCollection
*/
@@ -13816,10 +13101,10 @@ class Facade
*
* @note instead of an SQL query you can pass a result array as well.
*
- * @param string|array $types a list of types (either array or comma separated string)
- * @param string|array $sql an SQL query or an array of prefetched records
- * @param array $bindings optional, bindings for SQL query
- * @param array $remappings optional, an array of remapping arrays
+ * @param string|string[] $types a list of types (either array or comma separated string)
+ * @param string|array[]|NULL $sql an SQL query or an array of prefetched records
+ * @param array $bindings optional, bindings for SQL query
+ * @param array[] $remappings optional, an array of remapping arrays
*
* @return array
*/
@@ -13838,9 +13123,9 @@ class Facade
* passed IDs as their keys.
*
* @param string $type type of beans
- * @param array $ids ids to load
+ * @param int[] $ids ids to load
*
- * @return array
+ * @return OODBBean[]
*/
public static function batch( $type, $ids )
{
@@ -13854,9 +13139,9 @@ class Facade
* loadAll.
*
* @param string $type type of beans
- * @param array $ids ids to load
+ * @param int[] $ids ids to load
*
- * @return array
+ * @return OODBBean[]
*/
public static function loadAll( $type, $ids )
{
@@ -13888,7 +13173,7 @@ class Facade
* @param string $sql SQL query to execute
* @param array $bindings a list of values to be bound to query parameters
*
- * @return array
+ * @return string[][]
*/
public static function getAll( $sql, $bindings = array() )
{
@@ -13905,7 +13190,7 @@ class Facade
* @param string $sql SQL query to execute
* @param array $bindings a list of values to be bound to query parameters
*
- * @return string
+ * @return string|NULL
*/
public static function getCell( $sql, $bindings = array() )
{
@@ -13922,7 +13207,7 @@ class Facade
* @param string $sql SQL query to execute
* @param array $bindings a list of values to be bound to query parameters
*
- * @return RedBeanPHP\Cursor\PDOCursor
+ * @return Cursor
*/
public static function getCursor( $sql, $bindings = array() )
{
@@ -13939,7 +13224,7 @@ class Facade
* @param string $sql SQL query to execute
* @param array $bindings a list of values to be bound to query parameters
*
- * @return array
+ * @return array|NULL
*/
public static function getRow( $sql, $bindings = array() )
{
@@ -13956,7 +13241,7 @@ class Facade
* @param string $sql SQL query to execute
* @param array $bindings a list of values to be bound to query parameters
*
- * @return array
+ * @return string[]
*/
public static function getCol( $sql, $bindings = array() )
{
@@ -13975,7 +13260,7 @@ class Facade
* @param string $sql SQL query to execute
* @param array $bindings a list of values to be bound to query parameters
*
- * @return array
+ * @return string[]
*/
public static function getAssoc( $sql, $bindings = array() )
{
@@ -13983,7 +13268,7 @@ class Facade
}
/**
- *Convenience function to fire an SQL query using the RedBeanPHP
+ * Convenience function to fire an SQL query using the RedBeanPHP
* database adapter. This method allows you to directly query the
* database without having to obtain an database adapter instance first.
* Executes the specified SQL query together with the specified
@@ -14005,7 +13290,7 @@ class Facade
* Returns the insert ID for databases that support/require this
* functionality. Alias for R::getAdapter()->getInsertID().
*
- * @return mixed
+ * @return int
*/
public static function getInsertID()
{
@@ -14031,12 +13316,12 @@ class Facade
* This function has a confusing method signature, the R::duplicate() function
* only accepts two arguments: bean and filters.
*
- * @param OODBBean $bean bean to be copied
- * @param array $trail for internal usage, pass array()
- * @param boolean $pid for internal usage
- * @param array $filters white list filter with bean types to duplicate
+ * @param OODBBean $bean bean to be copied
+ * @param OODBBean[] $trail for internal usage, pass array()
+ * @param boolean $pid for internal usage
+ * @param array $filters white list filter with bean types to duplicate
*
- * @return array
+ * @return OODBBean
*/
public static function dup( $bean, $trail = array(), $pid = FALSE, $filters = array() )
{
@@ -14063,10 +13348,10 @@ class Facade
* Note:
* This is a simplified version of the deprecated R::dup() function.
*
- * @param OODBBean $bean bean to be copied
- * @param array $white white list filter with bean types to duplicate
+ * @param OODBBean $bean bean to be copied
+ * @param array $filters white list filter with bean types to duplicate
*
- * @return array
+ * @return OODBBean
*/
public static function duplicate( $bean, $filters = array() )
{
@@ -14082,12 +13367,12 @@ class Facade
* * all own bean lists (recursively)
* * all shared beans (not THEIR own lists)
*
- * @param array|OODBBean $beans beans to be exported
- * @param boolean $parents whether you want parent beans to be exported
- * @param array $filters whitelist of types
- * @param boolean $meta export meta data as well
+ * @param OODBBean|OODBBean[] $beans beans to be exported
+ * @param boolean $parents whether you want parent beans to be exported
+ * @param array $filters whitelist of types
+ * @param boolean $meta export meta data as well
*
- * @return array
+ * @return array[]
*/
public static function exportAll( $beans, $parents = FALSE, $filters = array(), $meta = FALSE )
{
@@ -14147,14 +13432,14 @@ class Facade
* New in 4.3.2: meta mask. The meta mask is a special mask to send
* data from raw result rows to the meta store of the bean. This is
* useful for bundling additional information with custom queries.
- * Values of every column whos name starts with $mask will be
+ * Values of every column who's name starts with $mask will be
* transferred to the meta section of the bean under key 'data.bundle'.
*
- * @param string $type type of beans to produce
- * @param array $rows must contain an array of array
- * @param string $metamask meta mask to apply (optional)
+ * @param string $type type of beans to produce
+ * @param string[][] $rows must contain an array of array
+ * @param string|array|NULL $metamask meta mask to apply (optional)
*
- * @return array
+ * @return OODBBean[]
*/
public static function convertToBeans( $type, $rows, $metamask = NULL )
{
@@ -14162,11 +13447,11 @@ class Facade
}
/**
- * Just like converToBeans, but for one bean.
+ * Just like convertToBeans, but for one bean.
*
- * @param string $type type of bean to produce
- * @param array $row one row from the database
- * @param string $metamask metamask (see convertToBeans)
+ * @param string $type type of bean to produce
+ * @param string[] $row one row from the database
+ * @param string|array|NULL $metamask metamask (see convertToBeans)
*
* @return OODBBean|NULL
*/
@@ -14216,7 +13501,7 @@ class Facade
* @param string $type Type of bean to produce
* @param string $sql SQL query snippet to use
* @param array $bindings bindings for query (optional)
- * @param mixed $metamask meta mask (optional, defaults to 'extra_')
+ * @param string|array $metamask meta mask (optional, defaults to 'extra_')
* @param boolean $autoExtract TRUE to return meta mask values as first item of array
*
* @return array
@@ -14260,9 +13545,9 @@ class Facade
* or 'horror' this operation will return FALSE because the third parameter
* has been set to TRUE.
*
- * @param OODBBean $bean bean to check for tags
- * @param array|string $tags list of tags
- * @param boolean $all whether they must all match or just some
+ * @param OODBBean $bean bean to check for tags
+ * @param string|string[] $tags list of tags
+ * @param boolean $all whether they must all match or just some
*
* @return boolean
*/
@@ -14287,8 +13572,8 @@ class Facade
* In the example above, the $blog bean will no longer
* be associated with the tags 'smart' and 'interesting'.
*
- * @param OODBBean $bean tagged bean
- * @param array $tagList list of tags (names)
+ * @param OODBBean $bean tagged bean
+ * @param string|string[] $tagList list of tags (names)
*
* @return void
*/
@@ -14316,10 +13601,10 @@ class Facade
* as 'TexMex' and 'Mexican Cuisine'. The second line will
* retrieve all tags attached to the meal object.
*
- * @param OODBBean $bean bean to tag
- * @param mixed $tagList tags to attach to the specified bean
+ * @param OODBBean $bean bean to tag
+ * @param string[]|NULL $tagList tags to attach to the specified bean
*
- * @return string
+ * @return string[]
*/
public static function tag( OODBBean $bean, $tagList = NULL )
{
@@ -14341,8 +13626,8 @@ class Facade
* The example adds the tag 'halloween' to the $blog
* bean.
*
- * @param OODBBean $bean bean to tag
- * @param array $tagList list of tags to add to bean
+ * @param OODBBean $bean bean to tag
+ * @param string|string[] $tagList list of tags to add to bean
*
* @return void
*/
@@ -14373,12 +13658,12 @@ class Facade
* tagged as 'horror' or 'gothic', order them by title and limit
* the number of movies to be returned to 10.
*
- * @param string $beanType type of bean you are looking for
- * @param array|string $tagList list of tags to match
- * @param string $sql additional SQL (use only for pagination)
- * @param array $bindings bindings
+ * @param string $beanType type of bean you are looking for
+ * @param string|string[] $tagList list of tags to match
+ * @param string $sql additional SQL (use only for pagination)
+ * @param array $bindings bindings
*
- * @return array
+ * @return OODBBean[]
*/
public static function tagged( $beanType, $tagList, $sql = '', $bindings = array() )
{
@@ -14407,12 +13692,12 @@ class Facade
* The example above returns at most 4 movies (due to the LIMIT clause in the SQL
* Query Snippet) that have been tagged as BOTH 'short' AND 'gothic'.
*
- * @param string $beanType type of bean you are looking for
- * @param array|string $tagList list of tags to match
- * @param string $sql additional sql snippet
- * @param array $bindings bindings
+ * @param string $beanType type of bean you are looking for
+ * @param string|string[] $tagList list of tags to match
+ * @param string $sql additional sql snippet
+ * @param array $bindings bindings
*
- * @return array
+ * @return OODBBean[]
*/
public static function taggedAll( $beanType, $tagList, $sql = '', $bindings = array() )
{
@@ -14424,10 +13709,10 @@ class Facade
*
* @see R::taggedAll
*
- * @param string $beanType type of bean you are looking for
- * @param array|string $tagList list of tags to match
- * @param string $sql additional sql snippet
- * @param array $bindings bindings
+ * @param string $beanType type of bean you are looking for
+ * @param string|string[] $tagList list of tags to match
+ * @param string $sql additional sql snippet
+ * @param array $bindings bindings
*
* @return integer
*/
@@ -14441,10 +13726,10 @@ class Facade
*
* @see R::tagged
*
- * @param string $beanType type of bean you are looking for
- * @param array|string $tagList list of tags to match
- * @param string $sql additional sql snippet
- * @param array $bindings bindings
+ * @param string $beanType type of bean you are looking for
+ * @param string|string[] $tagList list of tags to match
+ * @param string $sql additional sql snippet
+ * @param array $bindings bindings
*
* @return integer
*/
@@ -14504,7 +13789,7 @@ class Facade
self::$labelMaker = new LabelMaker( self::$toolbox );
$helper = new SimpleModelHelper();
$helper->attachEventListeners( self::$redbean );
- if (self::$redbean->getBeanHelper() == NULL) {
+ if (self::$redbean->getBeanHelper() === NULL) {
self::$redbean->setBeanHelper( new SimpleFacadeBeanHelper );
}
self::$duplicationManager = new DuplicationManager( self::$toolbox );
@@ -14513,7 +13798,7 @@ class Facade
}
/**
- * Facade Convience method for adapter transaction system.
+ * Facade Convenience method for adapter transaction system.
* Begins a transaction.
*
* Usage:
@@ -14554,7 +13839,7 @@ class Facade
}
/**
- * Facade Convience method for adapter transaction system.
+ * Facade Convenience method for adapter transaction system.
* Commits a transaction.
*
* Usage:
@@ -14595,7 +13880,7 @@ class Facade
}
/**
- * Facade Convience method for adapter transaction system.
+ * Facade Convenience method for adapter transaction system.
* Rolls back a transaction.
*
* Usage:
@@ -14643,7 +13928,7 @@ class Facade
*
* @param string $table name of the table (not type) you want to get columns of
*
- * @return array
+ * @return string[]
*/
public static function getColumns( $table )
{
@@ -14675,7 +13960,7 @@ class Facade
* ' IN( ?,? ) '.
*
* @param array $array array to generate question mark slots for
- * @param string $template template to use
+ * @param string|NULL $template template to use
*
* @return string
*/
@@ -14709,11 +13994,11 @@ class Facade
* );
*
*
- * @param array $beans a list of OODBBeans
- * @param string $type a type string
- * @param string $sqlTemplate an SQL template string for the SELECT-query
+ * @param OODBBean[]|TypedModel[] $beans a list of OODBBeans
+ * @param string $type a type string
+ * @param string $sqlTemplate an SQL template string for the SELECT-query
*
- * @return array
+ * @return OODBBean[]|TypedModel[]
*/
public static function loadJoined( $beans, $type, $sqlTemplate = 'SELECT %s.* FROM %s WHERE id IN (%s)' )
{
@@ -14795,10 +14080,10 @@ class Facade
* will automatically temporarily switch to fluid mode to attempt to store the
* bean in case of an SQLException.
*
- * @param array $beans list of beans to be stored
- * @param boolean $unfreezeIfNeeded retries in fluid mode in hybrid mode
+ * @param OODBBean[] $beans list of beans to be stored
+ * @param boolean $unfreezeIfNeeded retries in fluid mode in hybrid mode
*
- * @return array
+ * @return int[] ids
*/
public static function storeAll( $beans, $unfreezeIfNeeded = FALSE )
{
@@ -14814,9 +14099,9 @@ class Facade
* For information please consult the R::trash() function.
* A loop saver.
*
- * @param array $beans list of beans to be trashed
+ * @param OODBBean[] $beans list of beans to be trashed
*
- * @return void
+ * @return int
*/
public static function trashAll( $beans )
{
@@ -14832,13 +14117,13 @@ class Facade
* only IDs. This function combines trashAll and batch loading
* in one call. Note that while this function accepts just
* bean IDs, the beans will still be loaded first. This is because
- * the function still respects all the FUSE hooks that may have beeb
+ * the function still respects all the FUSE hooks that may have been
* associated with the domain logic associated with these beans.
* If you really want to delete just records from the database use
* a simple DELETE-FROM SQL query instead.
*
- * @param string type $type the bean type you wish to trash
- * @param string array $ids list of bean IDs
+ * @param string $type the bean type you wish to trash
+ * @param int[] $ids list of bean IDs
*
* @return void
*/
@@ -14864,9 +14149,9 @@ class Facade
*
* Returns the number of beans deleted.
*
- * @param string $type bean type to look for in database
- * @param string $sqlSnippet an SQL query snippet
- * @param array $bindings SQL parameter bindings
+ * @param string $type bean type to look for in database
+ * @param string|NULL $sqlSnippet an SQL query snippet
+ * @param array $bindings SQL parameter bindings
*
* @return int
*/
@@ -14907,10 +14192,10 @@ class Facade
* values of the array will be assigned to the name property of each
* individual bean.
*
- * @param string $type type of beans you would like to have
- * @param array $labels list of labels, names for each bean
+ * @param string $type type of beans you would like to have
+ * @param string[] $labels list of labels, names for each bean
*
- * @return array
+ * @return OODBBean[]
*/
public static function dispenseLabels( $type, $labels )
{
@@ -14919,7 +14204,7 @@ class Facade
/**
* Generates and returns an ENUM value. This is how RedBeanPHP handles ENUMs.
- * Either returns a (newly created) bean respresenting the desired ENUM
+ * Either returns a (newly created) bean representing the desired ENUM
* value or returns a list of all enums for the type.
*
* To obtain (and add if necessary) an ENUM value:
@@ -14946,7 +14231,7 @@ class Facade
*
* @param string $enum either type or type-value
*
- * @return array|OODBBean
+ * @return OODBBean|OODBBean[]
*/
public static function enum( $enum )
{
@@ -14959,9 +14244,9 @@ class Facade
* and stores the names in a new array. The array then gets sorted using the
* default sort function of PHP (sort).
*
- * @param array $beans list of beans to loop
+ * @param OODBBean[] $beans list of beans to loop
*
- * @return array
+ * @return string[]
*/
public static function gatherLabels( $beans )
{
@@ -14995,7 +14280,7 @@ class Facade
* Simple convenience function, returns ISO date formatted representation
* of $time.
*
- * @param mixed $time UNIX timestamp
+ * @param int|NULL $time UNIX timestamp
*
* @return string
*/
@@ -15013,7 +14298,7 @@ class Facade
* formatted representation
* of $time.
*
- * @param mixed $time UNIX timestamp
+ * @param int|NULL $time UNIX timestamp
*
* @return string
*/
@@ -15069,7 +14354,7 @@ class Facade
* Optional accessor for neat code.
* Sets the database adapter you want to use.
*
- * @return DBAdapter
+ * @return Adapter
*/
public static function getDatabaseAdapter()
{
@@ -15088,7 +14373,7 @@ class Facade
* If the PDO object could not be found, for whatever reason, this method
* will return NULL instead.
*
- * @return NULL|PDO
+ * @return NULL|\PDO
*/
public static function getPDO()
{
@@ -15097,6 +14382,8 @@ class Facade
$database = $databaseAdapter->getDatabase();
if ( is_null( $database ) ) return NULL;
if ( !method_exists( $database, 'getPDO' ) ) return NULL;
+
+ /** @var RPDO $database */
return $database->getPDO();
}
@@ -15168,8 +14455,8 @@ class Facade
/**
* Facade method for AQueryWriter::renameAssociation()
*
- * @param string|array $from
- * @param string $to
+ * @param string|string[] $from
+ * @param string $to
*
* @return void
*/
@@ -15185,9 +14472,9 @@ class Facade
* and shared lists, the beans are exported as-is, only loaded lists
* are exported.
*
- * @param array $beans beans
+ * @param OODBBean[] $beans beans
*
- * @return array
+ * @return array[]
*/
public static function beansToArray( $beans )
{
@@ -15247,9 +14534,9 @@ class Facade
* to 35 characters to improve readability. Nested beans will
* also be dumped.
*
- * @param OODBBean|array $data either a bean or an array of beans
+ * @param OODBBean|OODBBean[] $data either a bean or an array of beans
*
- * @return array
+ * @return string|string[]
*/
public static function dump( $data )
{
@@ -15291,7 +14578,7 @@ class Facade
* fetchAs but explicitly. For instance if you register
* the alias 'cover' for 'page' a property containing a reference to a
* page bean called 'cover' will correctly return the page bean and not
- * a (non-existant) cover bean.
+ * a (non-existent) cover bean.
*
*
* R::aliases( array( 'cover' => 'page' ) );
@@ -15315,7 +14602,7 @@ class Facade
* From that point on, every bean reference to a cover
* will return a 'page' bean.
*
- * @param array $list list of global aliases to use
+ * @param string[] $list list of global aliases to use
*
* @return void
*/
@@ -15334,13 +14621,13 @@ class Facade
*
* @param string $type type of bean to search for
* @param array $like criteria set describing the bean to search for
- * @param boolean $hasBeenCreated set to TRUE if bean has been created
+ * @param boolean &$hasBeenCreated set to TRUE if bean has been created
*
* @return OODBBean
*/
public static function findOrCreate( $type, $like = array(), $sql = '', &$hasBeenCreated = false )
{
- return self::$finder->findOrCreate( $type, $like, $sql = '', $hasBeenCreated );
+ return self::$finder->findOrCreate( $type, $like, $sql, $hasBeenCreated );
}
/**
@@ -15355,7 +14642,7 @@ class Facade
* @param string $sql optional additional SQL for sorting
* @param array $bindings bindings
*
- * @return array
+ * @return OODBBean[]
*/
public static function findLike( $type, $like = array(), $sql = '', $bindings = array() )
{
@@ -15398,7 +14685,7 @@ class Facade
/**
* Stops logging and flushes the logs,
- * convient method to stop logging of queries.
+ * convenient method to stop logging of queries.
* Use this method to stop logging SQL queries being
* executed by the adapter. Logging queries will not
* print them on the screen. Use R::getLogs() to
@@ -15473,7 +14760,7 @@ class Facade
* Therefore, only stop logging AFTER you have obtained the
* query logs using R::getLogs()
*
- * @return array
+ * @return string[]
*/
public static function getLogs()
{
@@ -15524,7 +14811,7 @@ class Facade
* Returns the current logger instance being used by the
* database object.
*
- * @return Logger
+ * @return Logger|NULL
*/
public static function getLogger()
{
@@ -15546,9 +14833,9 @@ class Facade
* for some types.
* This method will return the previous value.
*
- * @param boolean|array $yesNoBeans List of type names or 'all'
+ * @param boolean|string[] $yesNoBeans List of type names or 'all'
*
- * @return mixed
+ * @return boolean|string[]
*/
public static function usePartialBeans( $yesNoBeans )
{
@@ -15620,7 +14907,7 @@ class Facade
* @param array $onNotFoundDo task list to be considered on NOT finding the bean
* @param OODBBean &$bean reference to obtain the found bean
*
- * @return mixed
+ * @return bool|NULL
*/
public static function matchUp( $type, $sql, $bindings = array(), $onFoundDo = NULL, $onNotFoundDo = NULL, &$bean = NULL ) {
$matchUp = new MatchUp( self::$toolbox );
@@ -15665,7 +14952,7 @@ class Facade
* 'strtoupper',
* "\n"
* );
- *
+ *
*
* The example above creates an HTML fragment like this:
*
@@ -15724,11 +15011,10 @@ class Facade
* of property names that have to be skipped. By default this array is filled with
* two strings: 'created' and 'modified'.
*
- * @param OODBBean|array $bean reference beans
- * @param OODBBean|array $other beans to compare
+ * @param OODBBean|OODBBean[] $bean reference beans
+ * @param OODBBean|OODBBean[] $other beans to compare
* @param array $filters names of properties of all beans to skip
- * @param string $format the format of the key, defaults to '%s.%s.%s'
- * @param string $type type/property of bean to use for key generation
+ * @param string $pattern the format of the key, defaults to '%s.%s.%s'
*
* @return array
*/
@@ -15780,7 +15066,6 @@ class Facade
* Returns the toolbox associated with the specified key.
*
* @param string $key key to store toolbox instance under
- * @param ToolBox $toolbox toolbox to register
*
* @return ToolBox|NULL
*/
@@ -15838,7 +15123,7 @@ class Facade
/**
* Given a bean and an optional SQL snippet,
- * this method will return the bean together with all
+ * this method will return the bean together with all
* child beans in a hierarchically structured
* bean table.
*
@@ -15847,9 +15132,11 @@ class Facade
* a warning mechanism in case your database does not support this
* functionality.
*
- * @param OODBBean $bean bean to find children of
- * @param string $sql optional SQL snippet
- * @param array $bindings SQL snippet parameter bindings
+ * @param OODBBean $bean bean to find children of
+ * @param string|NULL $sql optional SQL snippet
+ * @param array $bindings SQL snippet parameter bindings
+ *
+ * @return OODBBean[]
*/
public static function children( OODBBean $bean, $sql = NULL, $bindings = array() )
{
@@ -15880,9 +15167,11 @@ class Facade
* it cannot 'predict' what or how you are trying to 'count'.
*
* @param OODBBean $bean bean to find children of
- * @param string $sql optional SQL snippet
+ * @param string|NULL $sql optional SQL snippet
* @param array $bindings SQL snippet parameter bindings
* @param string|boolean $select select snippet to use (advanced, optional, see QueryWriter::queryRecursiveCommonTableExpression)
+ *
+ * @return int
*/
public static function countChildren( OODBBean $bean, $sql = NULL, $bindings = array(), $select = QueryWriter::C_CTE_SELECT_COUNT )
{
@@ -15913,9 +15202,11 @@ class Facade
* it cannot 'predict' what or how you are trying to 'count'.
*
* @param OODBBean $bean bean to find children of
- * @param string $sql optional SQL snippet
+ * @param string|NULL $sql optional SQL snippet
* @param array $bindings SQL snippet parameter bindings
* @param string|boolean $select select snippet to use (advanced, optional, see QueryWriter::queryRecursiveCommonTableExpression)
+ *
+ * @return int
*/
public static function countParents( OODBBean $bean, $sql = NULL, $bindings = array(), $select = QueryWriter::C_CTE_SELECT_COUNT )
{
@@ -15932,9 +15223,11 @@ class Facade
* a warning mechanism in case your database does not support this
* functionality.
*
- * @param OODBBean $bean bean to find parents of
- * @param string $sql optional SQL snippet
- * @param array $bindings SQL snippet parameter bindings
+ * @param OODBBean $bean bean to find parents of
+ * @param string|NULL $sql optional SQL snippet
+ * @param array $bindings SQL snippet parameter bindings
+ *
+ * @return OODBBean[]
*/
public static function parents( OODBBean $bean, $sql = NULL, $bindings = array() )
{
@@ -15954,6 +15247,58 @@ class Facade
return AQueryWriter::forbidNuke( $yesNo );
}
+ /**
+ * Globally available service method for RedBeanPHP.
+ * Converts a snake cased string to a camel cased string.
+ * If the parameter is an array, the keys will be converted.
+ *
+ * @param string|array $snake snake_cased string to convert to camelCase
+ * @param boolean $dolphin exception for Ids - (bookId -> bookID)
+ * too complicated for the human mind, only dolphins can understand this
+ *
+ * @return string|array
+ */
+ public static function camelfy( $snake, $dolphin = false )
+ {
+ if ( is_array( $snake ) ) {
+ $newArray = array();
+ foreach( $snake as $key => $value ) {
+ $newKey = self::camelfy( $key, $dolphin );
+ if ( is_array( $value ) ) {
+ $value = self::camelfy( $value, $dolphin );
+ }
+ $newArray[ $newKey ] = $value;
+ }
+ return $newArray;
+ }
+ return AQueryWriter::snakeCamel( $snake, $dolphin );
+ }
+
+ /**
+ * Globally available service method for RedBeanPHP.
+ * Converts a camel cased string to a snake cased string.
+ * If the parameter is an array, the keys will be converted.
+ *
+ * @param string|array $camel camelCased string to convert to snake case
+ *
+ * @return string|array
+ */
+ public static function uncamelfy( $camel )
+ {
+ if ( is_array( $camel ) ) {
+ $newArray = array();
+ foreach( $camel as $key => $value ) {
+ $newKey = self::uncamelfy( $key );
+ if ( is_array( $value ) ) {
+ $value = self::uncamelfy( $value );
+ }
+ $newArray[ $newKey ] = $value;
+ }
+ return $newArray;
+ }
+ return AQueryWriter::camelsSnake( $camel );
+ }
+
/**
* Selects the feature set you want as specified by
* the label.
@@ -16090,7 +15435,7 @@ class DuplicationManager
protected $filters = array();
/**
- * @var array
+ * @var boolean
*/
protected $cacheTables = FALSE;
@@ -16300,7 +15645,7 @@ class DuplicationManager
public function camelfy( $array, $dolphinMode = FALSE ) {
$newArray = array();
foreach( $array as $key => $element ) {
- $newKey = preg_replace_callback( '/_(\w)/', function( &$matches ){
+ $newKey = preg_replace_callback( '/_(\w)/', function( $matches ){
return strtoupper( $matches[1] );
}, $key);
@@ -16367,6 +15712,8 @@ class DuplicationManager
* every time a duplication action is performed (dup()).
*
* @param boolean $yesNo TRUE to use caching, FALSE otherwise
+ *
+ * @return void
*/
public function setCacheTables( $yesNo )
{
@@ -16544,8 +15891,8 @@ class ArrayTool
* The statement in the example will produce the string:
* ' IN( ?,? ) '.
*
- * @param array $array array to generate question mark slots for
- * @param string $template template to use
+ * @param array $array array to generate question mark slots for
+ * @param string|NULL $template template to use
*
* @return string
*/
@@ -16585,13 +15932,14 @@ class ArrayTool
namespace RedBeanPHP\Util {
use RedBeanPHP\OODB as OODB;
+use RedBeanPHP\OODBBean as OODBBean;
use RedBeanPHP\RedException as RedException;
/**
* Dispense Helper
*
* A helper class containing a dispense utility.
- *
+ *
* @file RedBeanPHP/Util/DispenseHelper.php
* @author Gabor de Mooij and the RedBeanPHP Community
* @license BSD/GPLv2
@@ -16704,7 +16052,7 @@ class DispenseHelper
* @param integer $num number of beans to dispense
* @param boolean $alwaysReturnArray if TRUE always returns the result as an array
*
- * @return array|OODBBean
+ * @return OODBBean|OODBBean[]
*/
public static function dispense( OODB $oodb, $typeOrBeanArray, $num = 1, $alwaysReturnArray = FALSE ) {
@@ -16864,6 +16212,7 @@ class Dump
namespace RedBeanPHP\Util {
use RedBeanPHP\OODB as OODB;
+use RedBeanPHP\OODBBean as OODBBean;
/**
* Multi Bean Loader Helper
@@ -16874,7 +16223,7 @@ use RedBeanPHP\OODB as OODB;
*
* This helper class offers limited support for one-to-one
* relations by providing a service to load a set of beans
- * with differnt types and a common ID.
+ * with different types and a common ID.
*
* @file RedBeanPHP/Util/MultiLoader.php
* @author Gabor de Mooij and the RedBeanPHP Community
@@ -16905,7 +16254,7 @@ class MultiLoader
* @param string|array $types the set of types to load at once
* @param mixed $id the common ID
*
- * @return OODBBean
+ * @return OODBBean[]
*/
public static function load( OODB $oodb, $types, $id )
{
@@ -17021,7 +16370,7 @@ use RedBeanPHP\ToolBox as ToolBox;
* The Quick Export Utility Class provides functionality to easily
* expose the result of SQL queries as well-known formats like CSV.
*
- * @file RedBeanPHP/Util/QuickExporft.php
+ * @file RedBeanPHP/Util/QuickExport.php
* @author Gabor de Mooij and the RedBeanPHP Community
* @license BSD/GPLv2
*
@@ -17033,12 +16382,12 @@ use RedBeanPHP\ToolBox as ToolBox;
class QuickExport
{
/**
- * @var Finder
+ * @var ToolBox
*/
protected $toolbox;
/**
- * @boolean
+ * @var boolean
*/
private static $test = FALSE;
@@ -17055,7 +16404,13 @@ class QuickExport
/**
* Makes csv() testable.
- */
+ *
+ * @param string $name
+ * @param mixed $arg1
+ * @param boolean $arg2
+ *
+ * @return mixed
+ */
public static function operation( $name, $arg1, $arg2 = TRUE ) {
$out = '';
switch( $name ) {
@@ -17104,7 +16459,7 @@ class QuickExport
* @param boolean $output TRUE to output CSV directly using readfile
* @param array $options delimiter, quote and escape character respectively
*
- * @return void
+ * @return string|NULL
*/
public function csv( $sql = '', $bindings = array(), $columns = NULL, $path = '/tmp/redexport_%s.csv', $output = TRUE, $options = array(',','"','\\') )
{
@@ -17214,11 +16569,11 @@ class MatchUp
* @param string $type type of bean you're looking for
* @param string $sql SQL snippet (starting at the WHERE clause, omit WHERE-keyword)
* @param array $bindings array of parameter bindings for SQL snippet
- * @param array $onFoundDo task list to be considered on finding the bean
- * @param array $onNotFoundDo task list to be considered on NOT finding the bean
- * @param OODBBean &$bean reference to obtain the found bean
+ * @param array|NULL $onFoundDo task list to be considered on finding the bean
+ * @param array|NULL $onNotFoundDo task list to be considered on NOT finding the bean
+ * @param OODBBean|NULL &$bean reference to obtain the found bean
*
- * @return mixed
+ * @return bool|NULL
*/
public function matchUp( $type, $sql, $bindings = array(), $onFoundDo = NULL, $onNotFoundDo = NULL, &$bean = NULL )
{
@@ -17374,7 +16729,7 @@ use RedBeanPHP\Finder;
*
* The Look Utility class provides an easy way to generate
* tables and selects (pulldowns) from the database.
- *
+ *
* @file RedBeanPHP/Util/Diff.php
* @author Gabor de Mooij and the RedBeanPHP Community
* @license BSD/GPLv2
@@ -17430,7 +16785,7 @@ class Diff
* @param OODBBean|array $others beans to compare
* @param array $filters names of properties of all beans to skip
* @param string $format the format of the key, defaults to '%s.%s.%s'
- * @param string $type type/property of bean to use for key generation
+ * @param string|NULL $type type/property of bean to use for key generation
*
* @return array
*/
@@ -17481,13 +16836,15 @@ class Diff
namespace RedBeanPHP\Util {
use RedBeanPHP\ToolBox;
+use RedBeanPHP\OODB;
use RedBeanPHP\OODBBean;
+use RedBeanPHP\QueryWriter;
/**
* Tree
*
* Given a bean, finds it children or parents
- * in a hierchical structure.
+ * in a hierarchical structure.
*
* @experimental feature
*
@@ -17535,12 +16892,12 @@ class Tree {
* bean in a tree structure.
*
* @note this only works for databases that support
- * recusrive common table expressions.
- *
+ * recursive common table expressions.
+ *
* Usage:
*
*
- * $newsArticles = R::children( $newsPage, ' ORDER BY title ASC ' )
+ * $newsArticles = R::children( $newsPage, ' ORDER BY title ASC ' )
* $newsArticles = R::children( $newsPage, ' WHERE title = ? ', [ $t ] );
* $newsArticles = R::children( $newsPage, ' WHERE title = :t ', [ ':t' => $t ] );
*
@@ -17552,9 +16909,9 @@ class Tree {
* parameter binding key ':slot0' is reserved for the ID of the bean
* and used in the query.
*
- * @param OODBBean $bean reference bean to find children of
- * @param string $sql optional SQL snippet
- * @param array $bindings optional parameter bindings for SQL snippet
+ * @param OODBBean $bean reference bean to find children of
+ * @param string|NULL $sql optional SQL snippet
+ * @param array $bindings optional parameter bindings for SQL snippet
*
* @return array
*/
@@ -17573,7 +16930,7 @@ class Tree {
* bean in a tree structure.
*
* @note this only works for databases that support
- * recusrive common table expressions.
+ * recursive common table expressions.
*
*
* $newsPages = R::parents( $newsArticle, ' ORDER BY title ASC ' );
@@ -17588,9 +16945,9 @@ class Tree {
* parameter binding key ':slot0' is reserved for the ID of the bean
* and used in the query.
*
- * @param OODBBean $bean reference bean to find parents of
- * @param string $sql optional SQL snippet
- * @param array $bindings optional parameter bindings for SQL snippet
+ * @param OODBBean $bean reference bean to find parents of
+ * @param string|NULL $sql optional SQL snippet
+ * @param array $bindings optional parameter bindings for SQL snippet
*
* @return array
*/
@@ -17609,7 +16966,7 @@ class Tree {
* bean in a tree structure.
*
* @note this only works for databases that support
- * recusrive common table expressions.
+ * recursive common table expressions.
*
*
* $count = R::countChildren( $newsArticle );
@@ -17631,7 +16988,7 @@ class Tree {
* it cannot 'predict' what or how you are trying to 'count'.
*
* @param OODBBean $bean reference bean to find children of
- * @param string $sql optional SQL snippet
+ * @param string|NULL $sql optional SQL snippet
* @param array $bindings optional parameter bindings for SQL snippet
* @param string|boolean $select select snippet to use (advanced, optional, see QueryWriter::queryRecursiveCommonTableExpression)
*
@@ -17651,7 +17008,7 @@ class Tree {
* bean in a tree structure.
*
* @note this only works for databases that support
- * recusrive common table expressions.
+ * recursive common table expressions.
*
*
* $count = R::countParents( $newsArticle );
@@ -17672,9 +17029,9 @@ class Tree {
* this method assumes you take control of the resulting total yourself since
* it cannot 'predict' what or how you are trying to 'count'.
*
- * @param OODBBean $bean reference bean to find parents of
- * @param string $sql optional SQL snippet
- * @param array $bindings optional parameter bindings for SQL snippet
+ * @param OODBBean $bean reference bean to find parents of
+ * @param string|NULL $sql optional SQL snippet
+ * @param array $bindings optional parameter bindings for SQL snippet
* @param string|boolean $select select snippet to use (advanced, optional, see QueryWriter::queryRecursiveCommonTableExpression)
*
* @return integer
@@ -17759,7 +17116,7 @@ class Feature
case self::C_FEATURE_NOVICE_LATEST:
case self::C_FEATURE_NOVICE_5_4:
case self::C_FEATURE_NOVICE_5_5:
- OODBBean::useFluidCount( FALSE );
+ OODBBean::useFluidCount( TRUE );
R::noNuke( TRUE );
R::setAllowHybridMode( FALSE );
R::useISNULLConditions( TRUE );
@@ -17767,7 +17124,7 @@ class Feature
case self::C_FEATURE_LATEST:
case self::C_FEATURE_5_4:
case self::C_FEATURE_5_5:
- OODBBean::useFluidCount( FALSE );
+ OODBBean::useFluidCount( TRUE );
R::noNuke( FALSE );
R::setAllowHybridMode( TRUE );
R::useISNULLConditions( TRUE );
@@ -17798,6 +17155,158 @@ class Feature
}
}
+namespace RedBeanPHP\Util {
+
+/**
+ * Either Utility
+ *
+ * The Either Utility class provides an easy way to
+ * substitute the NULL coalesce operator in RedBeanPHP
+ * (since the lazy loading interface interferes with the ??
+ * operator) in a way that can also be used in older PHP-versions.
+ *
+ * @file RedBeanPHP/Util/Either.php
+ * @author Gabor de Mooij and the RedBeanPHP Community
+ * @license BSD/GPLv2
+ *
+ * @copyright
+ * copyright (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community
+ * This source file is subject to the BSD/GPLv2 License that is bundled
+ * with this source code in the file license.txt.
+ */
+class Either {
+
+ /**
+ * @var mixed
+ */
+ private $result;
+
+ /**
+ * Constructs a new Either-instance.
+ *
+ * Example usage:
+ *
+ *
+ * $author = $text
+ * ->either()
+ * ->page
+ * ->book
+ * ->autor
+ * ->name
+ * ->or('unknown');
+ *
+ *
+ * The Either-class lets you access bean properties without having to do
+ * NULL-checks. The mechanism resembles the use of the ?? somewhat but
+ * offers backward compatibility with older PHP versions. The mechanism also works
+ * on arrays.
+ *
+ *
+ * $budget = $company
+ * ->either()
+ * ->sharedProject
+ * ->first()
+ * ->budget
+ * ->or(0);
+ *
+ */
+ public function __construct($result) {
+ $this->result = $result;
+ }
+
+ /**
+ * Extracts a value from the wrapped object and stores
+ * it in the internal result object. If the desired
+ * value cannot be found, the internal result object will be set
+ * to NULL. Chainable.
+ *
+ * @param string $something name of the property you wish to extract the value of
+ *
+ * @return self
+ */
+ public function __get($something) {
+ if (is_object($this->result)) {
+ $this->result = $this->result->{$something};
+ } else {
+ $this->result = NULL;
+ }
+ return $this;
+ }
+
+ /**
+ * Extracts the first element of the array in the internal result
+ * object and stores it as the new value of the internal result object.
+ * Chainable.
+ *
+ * @return self
+ */
+ public function first() {
+ if (is_array($this->result)) {
+ reset($this->result);
+ $key = key($this->result);
+ if (isset($this->result[$key])) {
+ $this->result = $this->result[$key];
+ } else {
+ $this->result = NULL;
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Extracts the last element of the array in the internal result
+ * object and stores it as the new value of the internal result object.
+ * Chainable.
+ *
+ * @return self
+ */
+ public function last() {
+ if (is_array($this->result)) {
+ end($this->result);
+ $key = key($this->result);
+ if (isset($this->result[$key])) {
+ $this->result = $this->result[$key];
+ } else {
+ $this->result = NULL;
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Extracts the specified element of the array in the internal result
+ * object and stores it as the new value of the internal result object.
+ * Chainable.
+ *
+ * @return self
+ */
+ public function index( $key = 0 ) {
+ if (is_array($this->result)) {
+ if (isset($this->result[$key])) {
+ $this->result = $this->result[$key];
+ } else {
+ $this->result = NULL;
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Resolves the Either-instance to a final value, either the value
+ * contained in the internal result object or the value specified
+ * in the or() function.
+ *
+ * @param mixed $value value to resolve to if internal result equals NULL
+ *
+ * @return mixed
+ */
+ public function _or( $value ) {
+ $reference = (is_null($this->result)) ? $value : $this->result;
+ return $reference;
+ }
+}
+}
+
namespace RedBeanPHP {
/**
@@ -17911,5 +17420,61 @@ if ( !function_exists( 'array_flatten' ) ) {
}
}
+/**
+ * Function pstr() generates [ $value, \PDO::PARAM_STR ]
+ * Ensures that your parameter is being treated as a string.
+ *
+ * Usage:
+ *
+ *
+ * R::find('book', 'title = ?', [ pstr('1') ]);
+ *
+ */
+if ( !function_exists( 'pstr' ) ) {
+
+ function pstr( $value )
+ {
+ return array( strval( $value ) , \PDO::PARAM_STR );
+ }
+}
+
+
+/**
+ * Function pint() generates [ $value, \PDO::PARAM_INT ]
+ * Ensures that your parameter is being treated as an integer.
+ *
+ * Usage:
+ *
+ *
+ * R::find('book', ' pages > ? ', [ pint(2) ] );
+ *
+ */
+if ( !function_exists( 'pint' ) ) {
+
+ function pint( $value )
+ {
+ return array( intval( $value ) , \PDO::PARAM_INT );
+ }
+}
+
+/**
+ * Function DBPrefix() is a simple function to allow you to
+ * quickly set a different namespace for FUSE model resolution
+ * per database connection. It works by creating a new DynamicBeanHelper
+ * with the specified string as model prefix.
+ *
+ * Usage:
+ *
+ *
+ * R::addDatabase( ..., DBPrefix( 'Prefix1_' ) );
+ *
+ */
+if ( !function_exists( 'DBPrefix' ) ) {
+
+ function DBPrefix( $prefix = '\\Model' ) {
+ return new \RedBeanPHP\BeanHelper\DynamicBeanHelper( $prefix );
+ }
+}
+
}
diff --git a/templates/articles/article-entry.php b/templates/articles/article-entry.php
index 6b1ba88..3d570ec 100644
--- a/templates/articles/article-entry.php
+++ b/templates/articles/article-entry.php
@@ -1,5 +1,5 @@
global $lang;?>
-
+
$this -> article['language']['seo_link'] ? $url = $this -> article['language']['seo_link'] : $url = 'a-' . $this -> article['id'] . '-' . \S::seo( $this -> article['language']['title'] );?>
diff --git a/templates/shop-category/products.php b/templates/shop-category/products.php
new file mode 100644
index 0000000..358451a
--- /dev/null
+++ b/templates/shop-category/products.php
@@ -0,0 +1,14 @@
+ global $lang_id;?>
+ if ( $this -> query ):?>
+
+ = \S::lang( 'wyniki-wyszukiwania-dla-zapytania' ) . ': ' . $this -> query . '';?>
+
+ endif;?>
+
+ if ( is_array( $this -> products ) ): foreach ( $this -> products as $product_id ):
+ $product = new \shop\Product( $product_id );
+ echo \Tpl::view( 'shop-product/product-mini', [
+ 'product' => new \shop\Product( $product_id, $lang_id )
+ ] );
+ endforeach; endif;?>
+
\ No newline at end of file
diff --git a/templates/shop-order/payment-confirmation.php b/templates/shop-order/payment-confirmation.php
index 13e789b..597b130 100644
--- a/templates/shop-order/payment-confirmation.php
+++ b/templates/shop-order/payment-confirmation.php
@@ -1,4 +1,4 @@
- if ( $this -> order['status'] == 1 ):?>
+ if ( $this -> order['status'] == 1 or $this -> order['status'] == 4 ):?>
Płatność została zatwierdzona. Dziękujemy za wybranie naszych usług.
Nasz system zweryfikuje Państwa zamówienie w ciągu kilku minut.
@@ -24,8 +24,26 @@
- endif;?>
- if ( \S::get_session( 'ekomi-purchase' ) and $this -> settings['ekomi_survey'] ):?>
- unset( $_SESSION['ekomi-purchase'] );?>
- = $this -> settings['ekomi_survey'];?>
+ else:?>
+
+ Płatność oczekuje na zatwierdzenie.
+ Nasz system zweryfikuje Państwa zamówienie w ciągu kilku minut.
+
+
+
+
+ Informacje o płatności
+
+
+
+
+ Zamówienie nr: = $this -> order['number'];?>
+
+
+ Data transakcji: = date( 'Y-m-d H:i', strtotime( $this -> order['date_order'] ) );?>
+
+
+
+
+