diff --git a/public/uploads/20251028/215056a714a04ba80737f6c4ab2a5c3f.png b/public/uploads/20251028/215056a714a04ba80737f6c4ab2a5c3f.png new file mode 100644 index 0000000..f9432d3 Binary files /dev/null and b/public/uploads/20251028/215056a714a04ba80737f6c4ab2a5c3f.png differ diff --git a/public/uploads/20251028/a12597acc98293d21dd339faf65ff3b3.jpeg b/public/uploads/20251028/a12597acc98293d21dd339faf65ff3b3.jpeg new file mode 100644 index 0000000..ae172f1 Binary files /dev/null and b/public/uploads/20251028/a12597acc98293d21dd339faf65ff3b3.jpeg differ diff --git a/public/uploads/20251103/050a555d586ee99d2936809d7fe2840c.png b/public/uploads/20251103/050a555d586ee99d2936809d7fe2840c.png new file mode 100644 index 0000000..114ce37 Binary files /dev/null and b/public/uploads/20251103/050a555d586ee99d2936809d7fe2840c.png differ diff --git a/public/uploads/20251103/6b96d3f2242f9e6e8918f77f93e5d673.png b/public/uploads/20251103/6b96d3f2242f9e6e8918f77f93e5d673.png new file mode 100644 index 0000000..6f51b37 Binary files /dev/null and b/public/uploads/20251103/6b96d3f2242f9e6e8918f77f93e5d673.png differ diff --git a/public/uploads/20251108/0068a42d56512f2370427a6975c53287.jpg b/public/uploads/20251108/0068a42d56512f2370427a6975c53287.jpg new file mode 100644 index 0000000..3aa2a6d Binary files /dev/null and b/public/uploads/20251108/0068a42d56512f2370427a6975c53287.jpg differ diff --git a/public/uploads/20251108/00992742a1634677c3751a99a1f3e222.jpg b/public/uploads/20251108/00992742a1634677c3751a99a1f3e222.jpg new file mode 100644 index 0000000..194e8e7 Binary files /dev/null and b/public/uploads/20251108/00992742a1634677c3751a99a1f3e222.jpg differ diff --git a/public/uploads/20251108/01f541c30ee643e27ef5754e7665a677.jpg b/public/uploads/20251108/01f541c30ee643e27ef5754e7665a677.jpg new file mode 100644 index 0000000..45a06e0 Binary files /dev/null and b/public/uploads/20251108/01f541c30ee643e27ef5754e7665a677.jpg differ diff --git a/public/uploads/20251108/068d34dca1b90dbdf3a694672f283b9f.jpg b/public/uploads/20251108/068d34dca1b90dbdf3a694672f283b9f.jpg new file mode 100644 index 0000000..e3f0139 Binary files /dev/null and b/public/uploads/20251108/068d34dca1b90dbdf3a694672f283b9f.jpg differ diff --git a/public/uploads/20251108/0a9185aafb854e356180c57898ef0039.jpg b/public/uploads/20251108/0a9185aafb854e356180c57898ef0039.jpg new file mode 100644 index 0000000..8858c92 Binary files /dev/null and b/public/uploads/20251108/0a9185aafb854e356180c57898ef0039.jpg differ diff --git a/public/uploads/20251108/0af8a03863d6e447ebdb75c5c959067d.jpg b/public/uploads/20251108/0af8a03863d6e447ebdb75c5c959067d.jpg new file mode 100644 index 0000000..a530f76 Binary files /dev/null and b/public/uploads/20251108/0af8a03863d6e447ebdb75c5c959067d.jpg differ diff --git a/public/uploads/20251108/10229dba234cdccbcc06057e44f5e77a.jpg b/public/uploads/20251108/10229dba234cdccbcc06057e44f5e77a.jpg new file mode 100644 index 0000000..6a1c1e7 Binary files /dev/null and b/public/uploads/20251108/10229dba234cdccbcc06057e44f5e77a.jpg differ diff --git a/public/uploads/20251108/12cc90075f00c4ea4e9d51d181b6ce79.jpg b/public/uploads/20251108/12cc90075f00c4ea4e9d51d181b6ce79.jpg new file mode 100644 index 0000000..5c33d88 Binary files /dev/null and b/public/uploads/20251108/12cc90075f00c4ea4e9d51d181b6ce79.jpg differ diff --git a/public/uploads/20251108/1b045fe3ebb28aabed1dc317ddc15063.jpg b/public/uploads/20251108/1b045fe3ebb28aabed1dc317ddc15063.jpg new file mode 100644 index 0000000..6b23654 Binary files /dev/null and b/public/uploads/20251108/1b045fe3ebb28aabed1dc317ddc15063.jpg differ diff --git a/public/uploads/20251108/1cb0b1f1e395a5d28061f0e5c719fa57.jpg b/public/uploads/20251108/1cb0b1f1e395a5d28061f0e5c719fa57.jpg new file mode 100644 index 0000000..a00442e Binary files /dev/null and b/public/uploads/20251108/1cb0b1f1e395a5d28061f0e5c719fa57.jpg differ diff --git a/public/uploads/20251108/1e346740c61ae593cc59051f7af37430.jpg b/public/uploads/20251108/1e346740c61ae593cc59051f7af37430.jpg new file mode 100644 index 0000000..850c33f Binary files /dev/null and b/public/uploads/20251108/1e346740c61ae593cc59051f7af37430.jpg differ diff --git a/public/uploads/20251108/201c3efc66580a0df38cfce1a8b7bdca.jpg b/public/uploads/20251108/201c3efc66580a0df38cfce1a8b7bdca.jpg new file mode 100644 index 0000000..625f55e Binary files /dev/null and b/public/uploads/20251108/201c3efc66580a0df38cfce1a8b7bdca.jpg differ diff --git a/public/uploads/20251108/205591badacbcbd0eccd95249067c72c.jpg b/public/uploads/20251108/205591badacbcbd0eccd95249067c72c.jpg new file mode 100644 index 0000000..3316953 Binary files /dev/null and b/public/uploads/20251108/205591badacbcbd0eccd95249067c72c.jpg differ diff --git a/public/uploads/20251108/23ee120dd399a4d05fb07b71d1b79246.jpg b/public/uploads/20251108/23ee120dd399a4d05fb07b71d1b79246.jpg new file mode 100644 index 0000000..5528321 Binary files /dev/null and b/public/uploads/20251108/23ee120dd399a4d05fb07b71d1b79246.jpg differ diff --git a/public/uploads/20251108/256b677f07e3e85b006059190787b428.jpg b/public/uploads/20251108/256b677f07e3e85b006059190787b428.jpg new file mode 100644 index 0000000..861f181 Binary files /dev/null and b/public/uploads/20251108/256b677f07e3e85b006059190787b428.jpg differ diff --git a/public/uploads/20251108/26cdae62e2f77006d6d56ad98152bd1f.jpg b/public/uploads/20251108/26cdae62e2f77006d6d56ad98152bd1f.jpg new file mode 100644 index 0000000..cfd0866 Binary files /dev/null and b/public/uploads/20251108/26cdae62e2f77006d6d56ad98152bd1f.jpg differ diff --git a/public/uploads/20251108/2835055ccffd08f6846b5e093eae7cc1.jpg b/public/uploads/20251108/2835055ccffd08f6846b5e093eae7cc1.jpg new file mode 100644 index 0000000..c332eb3 Binary files /dev/null and b/public/uploads/20251108/2835055ccffd08f6846b5e093eae7cc1.jpg differ diff --git a/public/uploads/20251108/2a23b865fb7194e2388e6c5d762e08ff.jpg b/public/uploads/20251108/2a23b865fb7194e2388e6c5d762e08ff.jpg new file mode 100644 index 0000000..22c76e4 Binary files /dev/null and b/public/uploads/20251108/2a23b865fb7194e2388e6c5d762e08ff.jpg differ diff --git a/public/uploads/20251108/2c888eefc8fc75db24899d2353ea58be.jpg b/public/uploads/20251108/2c888eefc8fc75db24899d2353ea58be.jpg new file mode 100644 index 0000000..471f1d7 Binary files /dev/null and b/public/uploads/20251108/2c888eefc8fc75db24899d2353ea58be.jpg differ diff --git a/public/uploads/20251108/2fe7af3d1c94113c9a4099eeb9c73610.jpg b/public/uploads/20251108/2fe7af3d1c94113c9a4099eeb9c73610.jpg new file mode 100644 index 0000000..f7a1254 Binary files /dev/null and b/public/uploads/20251108/2fe7af3d1c94113c9a4099eeb9c73610.jpg differ diff --git a/public/uploads/20251108/322f3768c43ddcc6eb31fef6313eacab.jpg b/public/uploads/20251108/322f3768c43ddcc6eb31fef6313eacab.jpg new file mode 100644 index 0000000..c777509 Binary files /dev/null and b/public/uploads/20251108/322f3768c43ddcc6eb31fef6313eacab.jpg differ diff --git a/public/uploads/20251108/32c94d24b9aa14e00e1287c97d86798f.jpg b/public/uploads/20251108/32c94d24b9aa14e00e1287c97d86798f.jpg new file mode 100644 index 0000000..75a1525 Binary files /dev/null and b/public/uploads/20251108/32c94d24b9aa14e00e1287c97d86798f.jpg differ diff --git a/public/uploads/20251108/336650a1e4fc502a3b6bd36f1a4ab245.jpg b/public/uploads/20251108/336650a1e4fc502a3b6bd36f1a4ab245.jpg new file mode 100644 index 0000000..a61b7f9 Binary files /dev/null and b/public/uploads/20251108/336650a1e4fc502a3b6bd36f1a4ab245.jpg differ diff --git a/public/uploads/20251108/36e210235dcdc637961ce15d185d43eb.jpg b/public/uploads/20251108/36e210235dcdc637961ce15d185d43eb.jpg new file mode 100644 index 0000000..fa712db Binary files /dev/null and b/public/uploads/20251108/36e210235dcdc637961ce15d185d43eb.jpg differ diff --git a/public/uploads/20251108/38aa2d4467733f0fcb1225a13246d144.jpg b/public/uploads/20251108/38aa2d4467733f0fcb1225a13246d144.jpg new file mode 100644 index 0000000..8388dc9 Binary files /dev/null and b/public/uploads/20251108/38aa2d4467733f0fcb1225a13246d144.jpg differ diff --git a/public/uploads/20251108/3ab3332152f0c307680b5d6c505c3605.jpg b/public/uploads/20251108/3ab3332152f0c307680b5d6c505c3605.jpg new file mode 100644 index 0000000..a674509 Binary files /dev/null and b/public/uploads/20251108/3ab3332152f0c307680b5d6c505c3605.jpg differ diff --git a/public/uploads/20251108/46b766d1a56f42d63872066f700dfee6.jpg b/public/uploads/20251108/46b766d1a56f42d63872066f700dfee6.jpg new file mode 100644 index 0000000..92c59e9 Binary files /dev/null and b/public/uploads/20251108/46b766d1a56f42d63872066f700dfee6.jpg differ diff --git a/public/uploads/20251108/490cce654bb7da14e47a685204bf14e4.jpg b/public/uploads/20251108/490cce654bb7da14e47a685204bf14e4.jpg new file mode 100644 index 0000000..6ecb692 Binary files /dev/null and b/public/uploads/20251108/490cce654bb7da14e47a685204bf14e4.jpg differ diff --git a/public/uploads/20251108/4ade8519b8366e4d188855ed030f5bdb.jpg b/public/uploads/20251108/4ade8519b8366e4d188855ed030f5bdb.jpg new file mode 100644 index 0000000..3e03641 Binary files /dev/null and b/public/uploads/20251108/4ade8519b8366e4d188855ed030f5bdb.jpg differ diff --git a/public/uploads/20251108/4afb77d5a5cc1648217961730d308ebc.jpg b/public/uploads/20251108/4afb77d5a5cc1648217961730d308ebc.jpg new file mode 100644 index 0000000..8fc9ba8 Binary files /dev/null and b/public/uploads/20251108/4afb77d5a5cc1648217961730d308ebc.jpg differ diff --git a/public/uploads/20251108/4b37940f9938e4eed3118d09dc63ad91.jpg b/public/uploads/20251108/4b37940f9938e4eed3118d09dc63ad91.jpg new file mode 100644 index 0000000..99e7f6c Binary files /dev/null and b/public/uploads/20251108/4b37940f9938e4eed3118d09dc63ad91.jpg differ diff --git a/public/uploads/20251108/56f5f917cb1af2d2d8aa2139fd6884eb.jpg b/public/uploads/20251108/56f5f917cb1af2d2d8aa2139fd6884eb.jpg new file mode 100644 index 0000000..e94c7c6 Binary files /dev/null and b/public/uploads/20251108/56f5f917cb1af2d2d8aa2139fd6884eb.jpg differ diff --git a/public/uploads/20251108/5a9e915acde9d5618dcd31b661d6d737.jpg b/public/uploads/20251108/5a9e915acde9d5618dcd31b661d6d737.jpg new file mode 100644 index 0000000..5add4c5 Binary files /dev/null and b/public/uploads/20251108/5a9e915acde9d5618dcd31b661d6d737.jpg differ diff --git a/public/uploads/20251108/5b89891c7cb8a083fc49fb638f793d89.jpg b/public/uploads/20251108/5b89891c7cb8a083fc49fb638f793d89.jpg new file mode 100644 index 0000000..be7bbbf Binary files /dev/null and b/public/uploads/20251108/5b89891c7cb8a083fc49fb638f793d89.jpg differ diff --git a/public/uploads/20251108/5de69dfd6fd60a76fd7dbba1a286932f.jpg b/public/uploads/20251108/5de69dfd6fd60a76fd7dbba1a286932f.jpg new file mode 100644 index 0000000..e15c4f7 Binary files /dev/null and b/public/uploads/20251108/5de69dfd6fd60a76fd7dbba1a286932f.jpg differ diff --git a/public/uploads/20251108/6e71207c1d80f4928e1ad57a9a63c8e6.jpg b/public/uploads/20251108/6e71207c1d80f4928e1ad57a9a63c8e6.jpg new file mode 100644 index 0000000..5fb9ef3 Binary files /dev/null and b/public/uploads/20251108/6e71207c1d80f4928e1ad57a9a63c8e6.jpg differ diff --git a/public/uploads/20251108/71f0dfb2272fee090805e9129b4946c1.jpg b/public/uploads/20251108/71f0dfb2272fee090805e9129b4946c1.jpg new file mode 100644 index 0000000..a1485ed Binary files /dev/null and b/public/uploads/20251108/71f0dfb2272fee090805e9129b4946c1.jpg differ diff --git a/public/uploads/20251108/74948b73c894aebad1a92f8ce8b033df.jpg b/public/uploads/20251108/74948b73c894aebad1a92f8ce8b033df.jpg new file mode 100644 index 0000000..38c2f2a Binary files /dev/null and b/public/uploads/20251108/74948b73c894aebad1a92f8ce8b033df.jpg differ diff --git a/public/uploads/20251108/75056b3c2a7bfad7c81f99c51a72e83b.jpg b/public/uploads/20251108/75056b3c2a7bfad7c81f99c51a72e83b.jpg new file mode 100644 index 0000000..9c62a11 Binary files /dev/null and b/public/uploads/20251108/75056b3c2a7bfad7c81f99c51a72e83b.jpg differ diff --git a/public/uploads/20251108/770b92f9a91247115d80f29d4c4a9940.jpg b/public/uploads/20251108/770b92f9a91247115d80f29d4c4a9940.jpg new file mode 100644 index 0000000..979a888 Binary files /dev/null and b/public/uploads/20251108/770b92f9a91247115d80f29d4c4a9940.jpg differ diff --git a/public/uploads/20251108/7932d891fe68e9f8783522dd4d14bc47.jpg b/public/uploads/20251108/7932d891fe68e9f8783522dd4d14bc47.jpg new file mode 100644 index 0000000..9b329e5 Binary files /dev/null and b/public/uploads/20251108/7932d891fe68e9f8783522dd4d14bc47.jpg differ diff --git a/public/uploads/20251108/7c889eb6bb765a1e0d506bb2a8087762.jpg b/public/uploads/20251108/7c889eb6bb765a1e0d506bb2a8087762.jpg new file mode 100644 index 0000000..67ceed0 Binary files /dev/null and b/public/uploads/20251108/7c889eb6bb765a1e0d506bb2a8087762.jpg differ diff --git a/public/uploads/20251108/7dd995c7acc3735b52917bf75b961bb1.jpg b/public/uploads/20251108/7dd995c7acc3735b52917bf75b961bb1.jpg new file mode 100644 index 0000000..52c2185 Binary files /dev/null and b/public/uploads/20251108/7dd995c7acc3735b52917bf75b961bb1.jpg differ diff --git a/public/uploads/20251108/84af9916a7b60a3745a80ea061e08acb.jpg b/public/uploads/20251108/84af9916a7b60a3745a80ea061e08acb.jpg new file mode 100644 index 0000000..5505852 Binary files /dev/null and b/public/uploads/20251108/84af9916a7b60a3745a80ea061e08acb.jpg differ diff --git a/public/uploads/20251108/861490888fff98479dd7d7f59f98292c.jpg b/public/uploads/20251108/861490888fff98479dd7d7f59f98292c.jpg new file mode 100644 index 0000000..922d606 Binary files /dev/null and b/public/uploads/20251108/861490888fff98479dd7d7f59f98292c.jpg differ diff --git a/public/uploads/20251108/8b20ff7989f39a505aaaffa4cfa42615.jpg b/public/uploads/20251108/8b20ff7989f39a505aaaffa4cfa42615.jpg new file mode 100644 index 0000000..245367a Binary files /dev/null and b/public/uploads/20251108/8b20ff7989f39a505aaaffa4cfa42615.jpg differ diff --git a/public/uploads/20251108/909b30191d0d7910af3d2c292cf7c8f2.jpg b/public/uploads/20251108/909b30191d0d7910af3d2c292cf7c8f2.jpg new file mode 100644 index 0000000..3306ac8 Binary files /dev/null and b/public/uploads/20251108/909b30191d0d7910af3d2c292cf7c8f2.jpg differ diff --git a/public/uploads/20251108/944832c9d8e4940f2853fc5f857751ea.jpg b/public/uploads/20251108/944832c9d8e4940f2853fc5f857751ea.jpg new file mode 100644 index 0000000..9c1b603 Binary files /dev/null and b/public/uploads/20251108/944832c9d8e4940f2853fc5f857751ea.jpg differ diff --git a/public/uploads/20251108/97d6d89548611818b4f7e9bbb6264369.jpg b/public/uploads/20251108/97d6d89548611818b4f7e9bbb6264369.jpg new file mode 100644 index 0000000..a19c332 Binary files /dev/null and b/public/uploads/20251108/97d6d89548611818b4f7e9bbb6264369.jpg differ diff --git a/public/uploads/20251108/9a8d1b89a981ad9509941a6e6bf6bcdf.jpg b/public/uploads/20251108/9a8d1b89a981ad9509941a6e6bf6bcdf.jpg new file mode 100644 index 0000000..d0d7df8 Binary files /dev/null and b/public/uploads/20251108/9a8d1b89a981ad9509941a6e6bf6bcdf.jpg differ diff --git a/public/uploads/20251108/9dbafb0b102faa34d91bcc1a54b6815e.jpg b/public/uploads/20251108/9dbafb0b102faa34d91bcc1a54b6815e.jpg new file mode 100644 index 0000000..ecd0150 Binary files /dev/null and b/public/uploads/20251108/9dbafb0b102faa34d91bcc1a54b6815e.jpg differ diff --git a/public/uploads/20251108/a257c564c06e6716e8cffb32800ba3de.jpg b/public/uploads/20251108/a257c564c06e6716e8cffb32800ba3de.jpg new file mode 100644 index 0000000..8f000a0 Binary files /dev/null and b/public/uploads/20251108/a257c564c06e6716e8cffb32800ba3de.jpg differ diff --git a/public/uploads/20251108/a2e55fb2e16f6b9f5f7ac95170be67cd.jpg b/public/uploads/20251108/a2e55fb2e16f6b9f5f7ac95170be67cd.jpg new file mode 100644 index 0000000..22f1e34 Binary files /dev/null and b/public/uploads/20251108/a2e55fb2e16f6b9f5f7ac95170be67cd.jpg differ diff --git a/public/uploads/20251108/a9449dffe861d334fcf68020157bb369.jpg b/public/uploads/20251108/a9449dffe861d334fcf68020157bb369.jpg new file mode 100644 index 0000000..92b8c73 Binary files /dev/null and b/public/uploads/20251108/a9449dffe861d334fcf68020157bb369.jpg differ diff --git a/public/uploads/20251108/ad2e0e1453e57da7a94f7ba480fc7306.jpg b/public/uploads/20251108/ad2e0e1453e57da7a94f7ba480fc7306.jpg new file mode 100644 index 0000000..314323f Binary files /dev/null and b/public/uploads/20251108/ad2e0e1453e57da7a94f7ba480fc7306.jpg differ diff --git a/public/uploads/20251108/ae026956d032e4ce88bf9af0740bd0cd.jpg b/public/uploads/20251108/ae026956d032e4ce88bf9af0740bd0cd.jpg new file mode 100644 index 0000000..ed4b547 Binary files /dev/null and b/public/uploads/20251108/ae026956d032e4ce88bf9af0740bd0cd.jpg differ diff --git a/public/uploads/20251108/b0b6bc98ead735b921509176de65c64d.jpg b/public/uploads/20251108/b0b6bc98ead735b921509176de65c64d.jpg new file mode 100644 index 0000000..417e234 Binary files /dev/null and b/public/uploads/20251108/b0b6bc98ead735b921509176de65c64d.jpg differ diff --git a/public/uploads/20251108/b1fbc5e919966bb6986d9ade3d13c8d6.jpg b/public/uploads/20251108/b1fbc5e919966bb6986d9ade3d13c8d6.jpg new file mode 100644 index 0000000..091b9d5 Binary files /dev/null and b/public/uploads/20251108/b1fbc5e919966bb6986d9ade3d13c8d6.jpg differ diff --git a/public/uploads/20251108/b2d9e47d1627a4c835abceed8d1b3ef8.jpg b/public/uploads/20251108/b2d9e47d1627a4c835abceed8d1b3ef8.jpg new file mode 100644 index 0000000..cdbab26 Binary files /dev/null and b/public/uploads/20251108/b2d9e47d1627a4c835abceed8d1b3ef8.jpg differ diff --git a/public/uploads/20251108/b4c1b46512882565e4401188055f2a79.jpg b/public/uploads/20251108/b4c1b46512882565e4401188055f2a79.jpg new file mode 100644 index 0000000..9334f03 Binary files /dev/null and b/public/uploads/20251108/b4c1b46512882565e4401188055f2a79.jpg differ diff --git a/public/uploads/20251108/bb0e9e60adb0d8caa9f0f366eab6bc31.jpg b/public/uploads/20251108/bb0e9e60adb0d8caa9f0f366eab6bc31.jpg new file mode 100644 index 0000000..1502887 Binary files /dev/null and b/public/uploads/20251108/bb0e9e60adb0d8caa9f0f366eab6bc31.jpg differ diff --git a/public/uploads/20251108/bdddaa01feded153a0ef7240bc5f42cf.jpg b/public/uploads/20251108/bdddaa01feded153a0ef7240bc5f42cf.jpg new file mode 100644 index 0000000..337339e Binary files /dev/null and b/public/uploads/20251108/bdddaa01feded153a0ef7240bc5f42cf.jpg differ diff --git a/public/uploads/20251108/bf50c861cb940627237b5739e4ae0d87.jpg b/public/uploads/20251108/bf50c861cb940627237b5739e4ae0d87.jpg new file mode 100644 index 0000000..b0c5a15 Binary files /dev/null and b/public/uploads/20251108/bf50c861cb940627237b5739e4ae0d87.jpg differ diff --git a/public/uploads/20251108/bfb81b87b834cbf05a1711f1c4a90cb1.jpg b/public/uploads/20251108/bfb81b87b834cbf05a1711f1c4a90cb1.jpg new file mode 100644 index 0000000..49c4240 Binary files /dev/null and b/public/uploads/20251108/bfb81b87b834cbf05a1711f1c4a90cb1.jpg differ diff --git a/public/uploads/20251108/c21c2424d2549dce1d17bc3617ea3193.jpg b/public/uploads/20251108/c21c2424d2549dce1d17bc3617ea3193.jpg new file mode 100644 index 0000000..22bdcaf Binary files /dev/null and b/public/uploads/20251108/c21c2424d2549dce1d17bc3617ea3193.jpg differ diff --git a/public/uploads/20251108/c33715998eb67b938f085ea90280d42a.jpg b/public/uploads/20251108/c33715998eb67b938f085ea90280d42a.jpg new file mode 100644 index 0000000..834b0ca Binary files /dev/null and b/public/uploads/20251108/c33715998eb67b938f085ea90280d42a.jpg differ diff --git a/public/uploads/20251108/ce7ed8a66e15eacbf5bf4bab22bc9013.jpg b/public/uploads/20251108/ce7ed8a66e15eacbf5bf4bab22bc9013.jpg new file mode 100644 index 0000000..a55a3aa Binary files /dev/null and b/public/uploads/20251108/ce7ed8a66e15eacbf5bf4bab22bc9013.jpg differ diff --git a/public/uploads/20251108/d03e9df46c3d6373c8207ad4fa863ab5.jpg b/public/uploads/20251108/d03e9df46c3d6373c8207ad4fa863ab5.jpg new file mode 100644 index 0000000..904b6cb Binary files /dev/null and b/public/uploads/20251108/d03e9df46c3d6373c8207ad4fa863ab5.jpg differ diff --git a/public/uploads/20251108/d1b4a00717a888c0b6be85f86e07af56.jpg b/public/uploads/20251108/d1b4a00717a888c0b6be85f86e07af56.jpg new file mode 100644 index 0000000..f5ca93d Binary files /dev/null and b/public/uploads/20251108/d1b4a00717a888c0b6be85f86e07af56.jpg differ diff --git a/public/uploads/20251108/d26a6ec20dbb90b846a83774ddcf89ac.jpg b/public/uploads/20251108/d26a6ec20dbb90b846a83774ddcf89ac.jpg new file mode 100644 index 0000000..6282d1b Binary files /dev/null and b/public/uploads/20251108/d26a6ec20dbb90b846a83774ddcf89ac.jpg differ diff --git a/public/uploads/20251108/d2984a109797cab00228ce90859840ff.jpg b/public/uploads/20251108/d2984a109797cab00228ce90859840ff.jpg new file mode 100644 index 0000000..4a36d2f Binary files /dev/null and b/public/uploads/20251108/d2984a109797cab00228ce90859840ff.jpg differ diff --git a/public/uploads/20251108/dd71b5b485977890673e28c56f8b1b25.jpg b/public/uploads/20251108/dd71b5b485977890673e28c56f8b1b25.jpg new file mode 100644 index 0000000..9045c0d Binary files /dev/null and b/public/uploads/20251108/dd71b5b485977890673e28c56f8b1b25.jpg differ diff --git a/public/uploads/20251108/dec5d6b45d89e51c7048b7f0e787d741.jpg b/public/uploads/20251108/dec5d6b45d89e51c7048b7f0e787d741.jpg new file mode 100644 index 0000000..7651f1c Binary files /dev/null and b/public/uploads/20251108/dec5d6b45d89e51c7048b7f0e787d741.jpg differ diff --git a/public/uploads/20251108/e22a357974cfd1aacf172d5a60b795e4.jpg b/public/uploads/20251108/e22a357974cfd1aacf172d5a60b795e4.jpg new file mode 100644 index 0000000..5eaf3cd Binary files /dev/null and b/public/uploads/20251108/e22a357974cfd1aacf172d5a60b795e4.jpg differ diff --git a/public/uploads/20251108/eb0d81daa03e297521b897b979e6a2fa.jpg b/public/uploads/20251108/eb0d81daa03e297521b897b979e6a2fa.jpg new file mode 100644 index 0000000..3c897c5 Binary files /dev/null and b/public/uploads/20251108/eb0d81daa03e297521b897b979e6a2fa.jpg differ diff --git a/public/uploads/20251108/ed250153ed5403a67608923a9301a185.jpg b/public/uploads/20251108/ed250153ed5403a67608923a9301a185.jpg new file mode 100644 index 0000000..c6c5416 Binary files /dev/null and b/public/uploads/20251108/ed250153ed5403a67608923a9301a185.jpg differ diff --git a/public/uploads/20251108/f11120c5ae4070de0fb12a9e2b12b831.jpg b/public/uploads/20251108/f11120c5ae4070de0fb12a9e2b12b831.jpg new file mode 100644 index 0000000..9b2800b Binary files /dev/null and b/public/uploads/20251108/f11120c5ae4070de0fb12a9e2b12b831.jpg differ diff --git a/public/uploads/20251108/f2400e3c6481f0946c47edfbc0905548.jpg b/public/uploads/20251108/f2400e3c6481f0946c47edfbc0905548.jpg new file mode 100644 index 0000000..46b7a5a Binary files /dev/null and b/public/uploads/20251108/f2400e3c6481f0946c47edfbc0905548.jpg differ diff --git a/public/uploads/20251108/f532d6c4a24a42b6fca8e495fdd6beb4.jpg b/public/uploads/20251108/f532d6c4a24a42b6fca8e495fdd6beb4.jpg new file mode 100644 index 0000000..a22a9b0 Binary files /dev/null and b/public/uploads/20251108/f532d6c4a24a42b6fca8e495fdd6beb4.jpg differ diff --git a/public/uploads/20251108/f94be8f8e82911968d3d9c674b4971dd.jpg b/public/uploads/20251108/f94be8f8e82911968d3d9c674b4971dd.jpg new file mode 100644 index 0000000..f721383 Binary files /dev/null and b/public/uploads/20251108/f94be8f8e82911968d3d9c674b4971dd.jpg differ diff --git a/public/uploads/20251108/faab7cce8a4c81e780f3c01adcb63855.jpg b/public/uploads/20251108/faab7cce8a4c81e780f3c01adcb63855.jpg new file mode 100644 index 0000000..b6a85d9 Binary files /dev/null and b/public/uploads/20251108/faab7cce8a4c81e780f3c01adcb63855.jpg differ diff --git a/public/uploads/20251108/fef3ad5596e53c0cbfedf87be8192621.jpg b/public/uploads/20251108/fef3ad5596e53c0cbfedf87be8192621.jpg new file mode 100644 index 0000000..3799b7b Binary files /dev/null and b/public/uploads/20251108/fef3ad5596e53c0cbfedf87be8192621.jpg differ diff --git a/public/uploads/20251108/ffe7984c269aef891d100c98965fdaf9.jpg b/public/uploads/20251108/ffe7984c269aef891d100c98965fdaf9.jpg new file mode 100644 index 0000000..5473bcd Binary files /dev/null and b/public/uploads/20251108/ffe7984c269aef891d100c98965fdaf9.jpg differ diff --git a/public/uploads/20251113/beacf157428987643ca38139f241b58f.png b/public/uploads/20251113/beacf157428987643ca38139f241b58f.png new file mode 100644 index 0000000..f17a5d2 Binary files /dev/null and b/public/uploads/20251113/beacf157428987643ca38139f241b58f.png differ diff --git a/public/uploads/20251114/43d6d4a1634f0f491749f0ab6a4a3665.txt b/public/uploads/20251114/43d6d4a1634f0f491749f0ab6a4a3665.txt new file mode 100644 index 0000000..1d59cd8 --- /dev/null +++ b/public/uploads/20251114/43d6d4a1634f0f491749f0ab6a4a3665.txt @@ -0,0 +1 @@ +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqEMzPPPIMdfsU+tAfQHUeXoLgm3kWPD6JykLG93UhrURb9KiIhBc1z+Z07ApHGMYx2UD7eMXZYGyukj+7pkiHdt34hJnUoe+mt2/9rmQMxgFYergx/zviJgMDpNIHoJe4dA+GgDfpoi2khd4oii/QeaAWNQSHBh65Uv71wBrt6pPPneHtaMAgstCJFarYgLPahSYqlByNd1KBqrt2dWrfykayfM9TQxnlFmzh7vEbRrkgBiXDesypU+5w74xewXoWIrAsjQ6JQU2FMUb/v/zCW3MN/qMByzAG7NwGGWWQCXMz1XCLmJdQZwHH/er2JO1IyzEFc5KEF7WBqJA1q96eQIDAQAB \ No newline at end of file diff --git a/public/uploads/20251114/5c8847d3dc7bd48fdd0bb3d4be6764cf.crt b/public/uploads/20251114/5c8847d3dc7bd48fdd0bb3d4be6764cf.crt new file mode 100644 index 0000000..c460834 --- /dev/null +++ b/public/uploads/20251114/5c8847d3dc7bd48fdd0bb3d4be6764cf.crt @@ -0,0 +1,43 @@ +-----BEGIN CERTIFICATE----- +MIIDrDCCApSgAwIBAgIQICURFEiNIINwiAiSoLgY2TANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UE +BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENs +YXNzIDIgUjEwHhcNMjUxMTE0MDcxNzAyWhcNMzAxMTEzMDcxNzAyWjCBjDELMAkGA1UEBhMCQ04x +JzAlBgNVBAoMHuWuieW+vemhv+mYs+enkeaKgOaciemZkOWFrOWPuDEPMA0GA1UECwwGQWxpcGF5 +MUMwQQYDVQQDDDrmlK/ku5jlrp0o5Lit5Zu9Kee9kee7nOaKgOacr+aciemZkOWFrOWPuC0yMDg4 +MDgwNjAwMjMzODk1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAufUbyjnYKEImM5Zu +Nnn2I5q1F8LbOqqxs7vt53fEgUloLaZJuk+6FojtPHKcj0IAkGrh0ia2SJQRpPQSY3ZOy4Wn+rhb +lzi3VSUn4cUsKIzJ8ETWbNdE/is2GAKriQc2AB7k4j4z1kUlllgSyQ+9unxcIi+jVgrqtYtkzsfm +2KO0QX0W7ZltCVjHHsVB/YG/L7fccCy0295hRgenwut+qNIp/cmfErq05Hl/IkxSnUqd31ktkAqf +85Mvg9o0dFuL7+Aut1z7ItnKiSvEoh0SHYTX7j9gpUuXujHKmLh5N5gssukyrdKx7V5dUUPevfQc +AuTEWYgo4RNSCEwx0bxevQIDAQABoxIwEDAOBgNVHQ8BAf8EBAMCA/gwDQYJKoZIhvcNAQELBQAD +ggEBAJsqCdVdSDcS8fY+gQBwgyZXfLODYNv56a1wuM3kBbh/kgG5NPxS/D+ToEyhZQjcnzUcVHpp +E6JSalR/gUCL69YWd/1o9Dg4MU4aRYbC87pY7jUMe2hf2MgQCBfOvuLsRVYFx2hfekk0CSyNN91X +Tig3Rs8xdGf/+hEU5oi//mbNz4f/BJkgX3gAgyRdaXZ1CY4zpe4W5R80I0Hh+UV/gcJ3xjfGUjvi +m+5Tbx86uLKnwaz3Qtv9//fhchCYaM3JLIuzD70nI9M9ZcpQGQbdc1qOVnhra68c87izsdLqQzdO +wNHQkAM8nasZX4154XvIi8iPyI64YIEMVe7LBOymRzQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIE4jCCAsqgAwIBAgIIYsSr5bKAMl8wDQYJKoZIhvcNAQELBQAwejELMAkGA1UEBhMCQ04xFjAU +BgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEw +LwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMy +MjE0MzQxNVoXDTM3MTEyNjE0MzQxNVowgYIxCzAJBgNVBAYTAkNOMRYwFAYDVQQKDA1BbnQgRmlu +YW5jaWFsMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE5MDcGA1UEAwwwQW50IEZp +bmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDbGFzcyAyIFIxMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAsLMfYaoRoPRbmDcAfXPCmKf43pWRN5yTXa/KJWO0l+mrgQvs89bA +NEvbDUxlkGwycwtwi5DgBuBgVhLliXu+R9CYgr2dXs8D8Hx/gsggDcyGPLmVrDOnL+dyeauheARZ +fA3du60fwEwwbGcVIpIxPa/4n3IS/ElxQa6DNgqxh8J9Xwh7qMGl0JK9+bALuxf7B541Gr4p0WEN +G8fhgjBV4w4ut9eQLOoa1eddOUSZcy46Z7allwowwgt7b5VFfx/P1iKJ3LzBMgkCK7GZ2kiLrL7R +iqV+h482J7hkJD+ardoc6LnrHO/hIZymDxok+VH9fVeUdQa29IZKrIDVj65THQIDAQABo2MwYTAf +BgNVHSMEGDAWgBRfdLQEwE8HWurlsdsio4dBspzhATAdBgNVHQ4EFgQUSqHkYINtUSAtDPnS8Xoy +oP9p7qEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIB +AIQ8TzFy4bVIVb8+WhHKCkKNPcJe2EZuIcqvRoi727lZTJOfYy/JzLtckyZYfEI8J0lasZ29wkTt +a1IjSo+a6XdhudU4ONVBrL70U8Kzntplw/6TBNbLFpp7taRALjUgbCOk4EoBMbeCL0GiYYsTS0mw +7xdySzmGQku4GTyqutIGPQwKxSj9iSFw1FCZqr4VP4tyXzMUgc52SzagA6i7AyLedd3tbS6lnR5B +L+W9Kx9hwT8L7WANAxQzv/jGldeuSLN8bsTxlOYlsdjmIGu/C9OWblPYGpjQQIRyvs4Cc/mNhrh+ +14EQgwuemIIFDLOgcD+iISoN8CqegelNcJndFw1PDN6LkVoiHz9p7jzsge8RKay/QW6C03KNDpWZ +EUCgCUdfHfo8xKeR+LL1cfn24HKJmZt8L/aeRZwZ1jwePXFRVtiXELvgJuM/tJDIFj2KD337iV64 +fWcKQ/ydDVGqfDZAdcU4hQdsrPWENwPTQPfVPq2NNLMyIH9+WKx9Ed6/WzeZmIy5ZWpX1TtTolo6 +OJXQFeItMAjHxW/ZSZTok5IS3FuRhExturaInnzjYpx50a6kS34c5+c8hYq7sAtZ/CNLZmBnBCFD +aMQqT8xFZJ5uolUaSeXxg7JFY1QsYp5RKvj4SjFwCGKJ2+hPPe9UyyltxOidNtxjaknOCeBHytOr +-----END CERTIFICATE----- diff --git a/public/uploads/20251114/b6612a80b13013892c8c5c0829f62367.crt b/public/uploads/20251114/b6612a80b13013892c8c5c0829f62367.crt new file mode 100644 index 0000000..d370e5b --- /dev/null +++ b/public/uploads/20251114/b6612a80b13013892c8c5c0829f62367.crt @@ -0,0 +1,88 @@ +-----BEGIN CERTIFICATE----- +MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG +EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw +MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO +UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE +MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT +V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti +W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ +MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b +53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI +pDoiVhsLwg== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIF0zCCA7ugAwIBAgIIH8+hjWpIDREwDQYJKoZIhvcNAQELBQAwejELMAkGA1UE +BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMyMTEzNDg0MFoXDTM4MDIyODEzNDg0 +MFowejELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNV +BAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5j +aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEAtytTRcBNuur5h8xuxnlKJetT65cHGemGi8oD+beHFPTk +rUTlFt9Xn7fAVGo6QSsPb9uGLpUFGEdGmbsQ2q9cV4P89qkH04VzIPwT7AywJdt2 +xAvMs+MgHFJzOYfL1QkdOOVO7NwKxH8IvlQgFabWomWk2Ei9WfUyxFjVO1LVh0Bp +dRBeWLMkdudx0tl3+21t1apnReFNQ5nfX29xeSxIhesaMHDZFViO/DXDNW2BcTs6 +vSWKyJ4YIIIzStumD8K1xMsoaZBMDxg4itjWFaKRgNuPiIn4kjDY3kC66Sl/6yTl +YUz8AybbEsICZzssdZh7jcNb1VRfk79lgAprm/Ktl+mgrU1gaMGP1OE25JCbqli1 +Pbw/BpPynyP9+XulE+2mxFwTYhKAwpDIDKuYsFUXuo8t261pCovI1CXFzAQM2w7H +DtA2nOXSW6q0jGDJ5+WauH+K8ZSvA6x4sFo4u0KNCx0ROTBpLif6GTngqo3sj+98 +SZiMNLFMQoQkjkdN5Q5g9N6CFZPVZ6QpO0JcIc7S1le/g9z5iBKnifrKxy0TQjtG +PsDwc8ubPnRm/F82RReCoyNyx63indpgFfhN7+KxUIQ9cOwwTvemmor0A+ZQamRe +9LMuiEfEaWUDK+6O0Gl8lO571uI5onYdN1VIgOmwFbe+D8TcuzVjIZ/zvHrAGUcC +AwEAAaNdMFswCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFF90 +tATATwda6uWx2yKjh0GynOEBMB8GA1UdIwQYMBaAFF90tATATwda6uWx2yKjh0Gy +nOEBMA0GCSqGSIb3DQEBCwUAA4ICAQCVYaOtqOLIpsrEikE5lb+UARNSFJg6tpkf +tJ2U8QF/DejemEHx5IClQu6ajxjtu0Aie4/3UnIXop8nH/Q57l+Wyt9T7N2WPiNq +JSlYKYbJpPF8LXbuKYG3BTFTdOVFIeRe2NUyYh/xs6bXGr4WKTXb3qBmzR02FSy3 +IODQw5Q6zpXj8prYqFHYsOvGCEc1CwJaSaYwRhTkFedJUxiyhyB5GQwoFfExCVHW +05ZFCAVYFldCJvUzfzrWubN6wX0DD2dwultgmldOn/W/n8at52mpPNvIdbZb2F41 +T0YZeoWnCJrYXjq/32oc1cmifIHqySnyMnavi75DxPCdZsCOpSAT4j4lAQRGsfgI +kkLPGQieMfNNkMCKh7qjwdXAVtdqhf0RVtFILH3OyEodlk1HYXqX5iE5wlaKzDop +PKwf2Q3BErq1xChYGGVS+dEvyXc/2nIBlt7uLWKp4XFjqekKbaGaLJdjYP5b2s7N +1dM0MXQ/f8XoXKBkJNzEiM3hfsU6DOREgMc1DIsFKxfuMwX3EkVQM1If8ghb6x5Y +jXayv+NLbidOSzk4vl5QwngO/JYFMkoc6i9LNwEaEtR9PhnrdubxmrtM+RjfBm02 +77q3dSWFESFQ4QxYWew4pHE0DpWbWy/iMIKQ6UZ5RLvB8GEcgt8ON7BBJeMc+Dyi +kT9qhqn+lw== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIICiDCCAgygAwIBAgIIQX76UsB/30owDAYIKoZIzj0EAwMFADB6MQswCQYDVQQG +EwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UECwwXQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNpYWwgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgRTEwHhcNMTkwNDI4MTYyMDQ0WhcNNDkwNDIwMTYyMDQ0 +WjB6MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UE +CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNp +YWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRTEwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAASCCRa94QI0vR5Up9Yr9HEupz6hSoyjySYqo7v837KnmjveUIUNiuC9pWAU +WP3jwLX3HkzeiNdeg22a0IZPoSUCpasufiLAnfXh6NInLiWBrjLJXDSGaY7vaokt +rpZvAdmjXTBbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRZ +4ZTgDpksHL2qcpkFkxD2zVd16TAfBgNVHSMEGDAWgBRZ4ZTgDpksHL2qcpkFkxD2 +zVd16TAMBggqhkjOPQQDAwUAA2gAMGUCMQD4IoqT2hTUn0jt7oXLdMJ8q4vLp6sg +wHfPiOr9gxreb+e6Oidwd2LDnC4OUqCWiF8CMAzwKs4SnDJYcMLf2vpkbuVE4dTH +Rglz+HGcTLWsFs4KxLsq7MuU+vJTBUeDJeDjdA== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIUEMdk6dVgOEIS2cCP0Q43P90Ps5YwDQYJKoZIhvcNAQEF +BQAwajELMAkGA1UEBhMCQ04xEzARBgNVBAoMCmlUcnVzQ2hpbmExHDAaBgNVBAsM +E0NoaW5hIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMMH2lUcnVzQ2hpbmEgQ2xhc3Mg +MiBSb290IENBIC0gRzMwHhcNMTMwNDE4MDkzNjU2WhcNMzMwNDE4MDkzNjU2WjBq +MQswCQYDVQQGEwJDTjETMBEGA1UECgwKaVRydXNDaGluYTEcMBoGA1UECwwTQ2hp +bmEgVHJ1c3QgTmV0d29yazEoMCYGA1UEAwwfaVRydXNDaGluYSBDbGFzcyAyIFJv +b3QgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPPShpV +nJbMqqCw6Bz1kehnoPst9pkr0V9idOwU2oyS47/HjJXk9Rd5a9xfwkPO88trUpz5 +4GmmwspDXjVFu9L0eFaRuH3KMha1Ak01citbF7cQLJlS7XI+tpkTGHEY5pt3EsQg +wykfZl/A1jrnSkspMS997r2Gim54cwz+mTMgDRhZsKK/lbOeBPpWtcFizjXYCqhw +WktvQfZBYi6o4sHCshnOswi4yV1p+LuFcQ2ciYdWvULh1eZhLxHbGXyznYHi0dGN +z+I9H8aXxqAQfHVhbdHNzi77hCxFjOy+hHrGsyzjrd2swVQ2iUWP8BfEQqGLqM1g +KgWKYfcTGdbPB1MCAwEAAaNjMGEwHQYDVR0OBBYEFG/oAMxTVe7y0+408CTAK8hA +uTyRMB8GA1UdIwQYMBaAFG/oAMxTVe7y0+408CTAK8hAuTyRMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBLnUTfW7hp +emMbuUGCk7RBswzOT83bDM6824EkUnf+X0iKS95SUNGeeSWK2o/3ALJo5hi7GZr3 +U8eLaWAcYizfO99UXMRBPw5PRR+gXGEronGUugLpxsjuynoLQu8GQAeysSXKbN1I +UugDo9u8igJORYA+5ms0s5sCUySqbQ2R5z/GoceyI9LdxIVa1RjVX8pYOj8JFwtn +DJN3ftSFvNMYwRuILKuqUYSHc2GPYiHVflDh5nDymCMOQFcFG3WsEuB+EYQPFgIU +1DHmdZcz7Llx8UOZXX2JupWCYzK1XhJb+r4hK5ncf/w8qGtYlmyJpxk3hr1TfUJX +Yf4Zr0fJsGuv +-----END CERTIFICATE----- \ No newline at end of file diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php index 2052022..31e2d6a 100755 --- a/vendor/composer/InstalledVersions.php +++ b/vendor/composer/InstalledVersions.php @@ -1,396 +1,858 @@ - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ + + + + + + + + + namespace Composer; use Composer\Autoload\ClassLoader; use Composer\Semver\VersionParser; -/** - * This class is copied in every Composer installed project and available to all - * - * See also https://getcomposer.org/doc/07-runtime.md#installed-versions - * - * To require its presence, you can require `composer-runtime-api ^2.0` - * - * @final - */ + + + + + + + class InstalledVersions { - /** - * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to - * @internal - */ - private static $selfDir = null; +private static $installed = array ( + 'root' => + array ( + 'pretty_version' => 'dev-main', + 'version' => 'dev-main', + 'aliases' => + array ( + ), + 'reference' => '0a95974a63e41cca15747597241a53381c61f1df', + 'name' => 'fastadminnet/fastadmin', + ), + 'versions' => + array ( + 'composer/pcre' => + array ( + 'pretty_version' => '3.3.2', + 'version' => '3.3.2.0', + 'aliases' => + array ( + ), + 'reference' => 'b2bed4734f0cc156ee1fe9c0da2550420d99a21e', + ), + 'easywechat-composer/easywechat-composer' => + array ( + 'pretty_version' => '1.4.1', + 'version' => '1.4.1.0', + 'aliases' => + array ( + ), + 'reference' => '3fc6a7ab6d3853c0f4e2922539b56cc37ef361cd', + ), + 'ezyang/htmlpurifier' => + array ( + 'pretty_version' => 'v4.19.0', + 'version' => '4.19.0.0', + 'aliases' => + array ( + ), + 'reference' => 'b287d2a16aceffbf6e0295559b39662612b77fcf', + ), + 'fastadminnet/fastadmin' => + array ( + 'pretty_version' => 'dev-main', + 'version' => 'dev-main', + 'aliases' => + array ( + ), + 'reference' => '0a95974a63e41cca15747597241a53381c61f1df', + ), + 'fastadminnet/fastadmin-addons' => + array ( + 'pretty_version' => '1.4.2', + 'version' => '1.4.2.0', + 'aliases' => + array ( + ), + 'reference' => '14af178a62fb4cc897f954fa9d7d53798ad2cf37', + ), + 'fastadminnet/fastadmin-mailer' => + array ( + 'pretty_version' => 'v2.1.1', + 'version' => '2.1.1.0', + 'aliases' => + array ( + ), + 'reference' => 'bca635ac5f564ed6688d818d215021ffb0813746', + ), + 'guzzlehttp/guzzle' => + array ( + 'pretty_version' => '7.9.2', + 'version' => '7.9.2.0', + 'aliases' => + array ( + ), + 'reference' => 'd281ed313b989f213357e3be1a179f02196ac99b', + ), + 'guzzlehttp/promises' => + array ( + 'pretty_version' => '2.3.0', + 'version' => '2.3.0.0', + 'aliases' => + array ( + ), + 'reference' => '481557b130ef3790cf82b713667b43030dc9c957', + ), + 'guzzlehttp/psr7' => + array ( + 'pretty_version' => '2.8.0', + 'version' => '2.8.0.0', + 'aliases' => + array ( + ), + 'reference' => '21dc724a0583619cd1652f673303492272778051', + ), + 'maennchen/zipstream-php' => + array ( + 'pretty_version' => '2.4.0', + 'version' => '2.4.0.0', + 'aliases' => + array ( + ), + 'reference' => '3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3', + ), + 'markbaker/complex' => + array ( + 'pretty_version' => '3.0.2', + 'version' => '3.0.2.0', + 'aliases' => + array ( + ), + 'reference' => '95c56caa1cf5c766ad6d65b6344b807c1e8405b9', + ), + 'markbaker/matrix' => + array ( + 'pretty_version' => '3.0.1', + 'version' => '3.0.1.0', + 'aliases' => + array ( + ), + 'reference' => '728434227fe21be27ff6d86621a1b13107a2562c', + ), + 'monolog/monolog' => + array ( + 'pretty_version' => '2.10.0', + 'version' => '2.10.0.0', + 'aliases' => + array ( + ), + 'reference' => '5cf826f2991858b54d5c3809bee745560a1042a7', + ), + 'myclabs/php-enum' => + array ( + 'pretty_version' => '1.8.4', + 'version' => '1.8.4.0', + 'aliases' => + array ( + ), + 'reference' => 'a867478eae49c9f59ece437ae7f9506bfaa27483', + ), + 'nelexa/zip' => + array ( + 'pretty_version' => '4.0.2', + 'version' => '4.0.2.0', + 'aliases' => + array ( + ), + 'reference' => '88a1b6549be813278ff2dd3b6b2ac188827634a7', + ), + 'overtrue/pinyin' => + array ( + 'pretty_version' => '3.0.6', + 'version' => '3.0.6.0', + 'aliases' => + array ( + ), + 'reference' => '3b781d267197b74752daa32814d3a2cf5d140779', + ), + 'overtrue/socialite' => + array ( + 'pretty_version' => '2.0.24', + 'version' => '2.0.24.0', + 'aliases' => + array ( + ), + 'reference' => 'ee7e7b000ec7d64f2b8aba1f6a2eec5cdf3f8bec', + ), + 'overtrue/wechat' => + array ( + 'pretty_version' => '4.9.0', + 'version' => '4.9.0.0', + 'aliases' => + array ( + ), + 'reference' => '92791f5d957269c633b9aa175f842f6006f945b1', + ), + 'paragonie/constant_time_encoding' => + array ( + 'pretty_version' => 'v3.1.3', + 'version' => '3.1.3.0', + 'aliases' => + array ( + ), + 'reference' => 'd5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77', + ), + 'paragonie/random_compat' => + array ( + 'pretty_version' => 'v9.99.100', + 'version' => '9.99.100.0', + 'aliases' => + array ( + ), + 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a', + ), + 'phpoffice/phpspreadsheet' => + array ( + 'pretty_version' => '1.30.1', + 'version' => '1.30.1.0', + 'aliases' => + array ( + ), + 'reference' => 'fa8257a579ec623473eabfe49731de5967306c4c', + ), + 'phpseclib/phpseclib' => + array ( + 'pretty_version' => '3.0.47', + 'version' => '3.0.47.0', + 'aliases' => + array ( + ), + 'reference' => '9d6ca36a6c2dd434765b1071b2644a1c683b385d', + ), + 'pimple/pimple' => + array ( + 'pretty_version' => 'v3.6.0', + 'version' => '3.6.0.0', + 'aliases' => + array ( + ), + 'reference' => 'a70f552d338f9266eec6606c1f0b324da5514c96', + ), + 'psr/cache' => + array ( + 'pretty_version' => '2.0.0', + 'version' => '2.0.0.0', + 'aliases' => + array ( + ), + 'reference' => '213f9dbc5b9bfbc4f8db86d2838dc968752ce13b', + ), + 'psr/cache-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0|2.0', + ), + ), + 'psr/container' => + array ( + 'pretty_version' => '2.0.2', + 'version' => '2.0.2.0', + 'aliases' => + array ( + ), + 'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963', + ), + 'psr/event-dispatcher' => + array ( + 'pretty_version' => '1.0.0', + 'version' => '1.0.0.0', + 'aliases' => + array ( + ), + 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0', + ), + 'psr/event-dispatcher-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0', + ), + ), + 'psr/http-client' => + array ( + 'pretty_version' => '1.0.3', + 'version' => '1.0.3.0', + 'aliases' => + array ( + ), + 'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90', + ), + 'psr/http-client-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0', + ), + ), + 'psr/http-factory' => + array ( + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', + 'aliases' => + array ( + ), + 'reference' => 'e616d01114759c4c489f93b099585439f795fe35', + ), + 'psr/http-factory-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0', + ), + ), + 'psr/http-message' => + array ( + 'pretty_version' => '1.1', + 'version' => '1.1.0.0', + 'aliases' => + array ( + ), + 'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba', + ), + 'psr/http-message-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0', + ), + ), + 'psr/log' => + array ( + 'pretty_version' => '1.1.4', + 'version' => '1.1.4.0', + 'aliases' => + array ( + ), + 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11', + ), + 'psr/log-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0.0 || 2.0.0 || 3.0.0', + ), + ), + 'psr/simple-cache' => + array ( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'aliases' => + array ( + ), + 'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b', + ), + 'psr/simple-cache-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0|2.0', + ), + ), + 'ralouphie/getallheaders' => + array ( + 'pretty_version' => '3.0.3', + 'version' => '3.0.3.0', + 'aliases' => + array ( + ), + 'reference' => '120b605dfeb996808c31b6477290a714d356e822', + ), + 'symfony/cache' => + array ( + 'pretty_version' => 'v5.4.46', + 'version' => '5.4.46.0', + 'aliases' => + array ( + ), + 'reference' => '0fe08ee32cec2748fbfea10c52d3ee02049e0f6b', + ), + 'symfony/cache-contracts' => + array ( + 'pretty_version' => 'v2.5.4', + 'version' => '2.5.4.0', + 'aliases' => + array ( + ), + 'reference' => '517c3a3619dadfa6952c4651767fcadffb4df65e', + ), + 'symfony/cache-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0|2.0', + ), + ), + 'symfony/deprecation-contracts' => + array ( + 'pretty_version' => 'v3.0.2', + 'version' => '3.0.2.0', + 'aliases' => + array ( + ), + 'reference' => '26954b3d62a6c5fd0ea8a2a00c0353a14978d05c', + ), + 'symfony/event-dispatcher' => + array ( + 'pretty_version' => 'v5.4.45', + 'version' => '5.4.45.0', + 'aliases' => + array ( + ), + 'reference' => '72982eb416f61003e9bb6e91f8b3213600dcf9e9', + ), + 'symfony/event-dispatcher-contracts' => + array ( + 'pretty_version' => 'v3.0.2', + 'version' => '3.0.2.0', + 'aliases' => + array ( + ), + 'reference' => '7bc61cc2db649b4637d331240c5346dcc7708051', + ), + 'symfony/event-dispatcher-implementation' => + array ( + 'provided' => + array ( + 0 => '2.0', + ), + ), + 'symfony/finder' => + array ( + 'pretty_version' => 'v6.0.19', + 'version' => '6.0.19.0', + 'aliases' => + array ( + ), + 'reference' => '5cc9cac6586fc0c28cd173780ca696e419fefa11', + ), + 'symfony/http-foundation' => + array ( + 'pretty_version' => 'v5.4.48', + 'version' => '5.4.48.0', + 'aliases' => + array ( + ), + 'reference' => '3f38b8af283b830e1363acd79e5bc3412d055341', + ), + 'symfony/polyfill-mbstring' => + array ( + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'aliases' => + array ( + ), + 'reference' => '6d857f4d76bd4b343eac26d6b539585d2bc56493', + ), + 'symfony/polyfill-php73' => + array ( + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'aliases' => + array ( + ), + 'reference' => '0f68c03565dcaaf25a890667542e8bd75fe7e5bb', + ), + 'symfony/polyfill-php80' => + array ( + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'aliases' => + array ( + ), + 'reference' => '0cc9dd0f17f61d8131e7df6b84bd344899fe2608', + ), + 'symfony/psr-http-message-bridge' => + array ( + 'pretty_version' => 'v2.3.1', + 'version' => '2.3.1.0', + 'aliases' => + array ( + ), + 'reference' => '581ca6067eb62640de5ff08ee1ba6850a0ee472e', + ), + 'symfony/service-contracts' => + array ( + 'pretty_version' => 'v3.0.2', + 'version' => '3.0.2.0', + 'aliases' => + array ( + ), + 'reference' => 'd78d39c1599bd1188b8e26bb341da52c3c6d8a66', + ), + 'symfony/var-exporter' => + array ( + 'pretty_version' => 'v6.0.19', + 'version' => '6.0.19.0', + 'aliases' => + array ( + ), + 'reference' => 'df56f53818c2d5d9f683f4ad2e365ba73a3b69d2', + ), + 'topthink/framework' => + array ( + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'aliases' => + array ( + 0 => '9999999-dev', + ), + 'reference' => '9a2e7c2a1b6302afb61035c99c85bf0cfe0c52ec', + ), + 'topthink/think-captcha' => + array ( + 'pretty_version' => 'v1.0.9', + 'version' => '1.0.9.0', + 'aliases' => + array ( + ), + 'reference' => '9be9dd7e61c7fa3c478c4b92910d7230b94d0d23', + ), + 'topthink/think-helper' => + array ( + 'pretty_version' => 'v1.0.7', + 'version' => '1.0.7.0', + 'aliases' => + array ( + ), + 'reference' => '5f92178606c8ce131d36b37a57c58eb71e55f019', + ), + 'topthink/think-installer' => + array ( + 'pretty_version' => 'v1.0.14', + 'version' => '1.0.14.0', + 'aliases' => + array ( + ), + 'reference' => 'eae1740ac264a55c06134b6685dfb9f837d004d1', + ), + 'topthink/think-queue' => + array ( + 'pretty_version' => 'v1.1.6', + 'version' => '1.1.6.0', + 'aliases' => + array ( + ), + 'reference' => '250650eb0e8ea5af4cfdc7ae46f3f4e0a24ac245', + ), + 'workerman/channel' => + array ( + 'pretty_version' => 'v1.2.3', + 'version' => '1.2.3.0', + 'aliases' => + array ( + ), + 'reference' => '5edb0008eae35bf2da7218d911042abd23aa4370', + ), + 'workerman/phpsocket.io' => + array ( + 'pretty_version' => 'v2.2.0', + 'version' => '2.2.0.0', + 'aliases' => + array ( + ), + 'reference' => '0ba306b380e016f447f9860db95fcc1c7553fb91', + ), + 'workerman/workerman' => + array ( + 'pretty_version' => 'v4.2.1', + 'version' => '4.2.1.0', + 'aliases' => + array ( + ), + 'reference' => 'cafb5a43d93d7d30a16b32a57948581cca993562', + ), + 'yansongda/artful' => + array ( + 'pretty_version' => 'v1.1.3', + 'version' => '1.1.3.0', + 'aliases' => + array ( + ), + 'reference' => '734b97a6a03aa9702d1ce1f396d2e2c9bea845b3', + ), + 'yansongda/pay' => + array ( + 'pretty_version' => 'v3.7.16', + 'version' => '3.7.16.0', + 'aliases' => + array ( + ), + 'reference' => 'f24aea15bbfc2ec23b1201168d81f73a99433a8f', + ), + 'yansongda/supports' => + array ( + 'pretty_version' => 'v4.0.10', + 'version' => '4.0.10.0', + 'aliases' => + array ( + ), + 'reference' => '11cc73776e6d4d763a84c8c733f64820abdc44e5', + ), + ), +); +private static $canGetVendors; +private static $installedByVendor = array(); - /** - * @var mixed[]|null - * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null - */ - private static $installed; - /** - * @var bool - */ - private static $installedIsLocalDir; - /** - * @var bool|null - */ - private static $canGetVendors; - /** - * @var array[] - * @psalm-var array}> - */ - private static $installedByVendor = array(); - /** - * Returns a list of all package names which are present, either by being installed, replaced or provided - * - * @return string[] - * @psalm-return list - */ - public static function getInstalledPackages() - { - $packages = array(); - foreach (self::getInstalled() as $installed) { - $packages[] = array_keys($installed['versions']); - } - if (1 === \count($packages)) { - return $packages[0]; - } - return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); - } - - /** - * Returns a list of all package names with a specific type e.g. 'library' - * - * @param string $type - * @return string[] - * @psalm-return list - */ - public static function getInstalledPackagesByType($type) - { - $packagesByType = array(); - - foreach (self::getInstalled() as $installed) { - foreach ($installed['versions'] as $name => $package) { - if (isset($package['type']) && $package['type'] === $type) { - $packagesByType[] = $name; - } - } - } - - return $packagesByType; - } - - /** - * Checks whether the given package is installed - * - * This also returns true if the package name is provided or replaced by another package - * - * @param string $packageName - * @param bool $includeDevRequirements - * @return bool - */ - public static function isInstalled($packageName, $includeDevRequirements = true) - { - foreach (self::getInstalled() as $installed) { - if (isset($installed['versions'][$packageName])) { - return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; - } - } - - return false; - } - - /** - * Checks whether the given package satisfies a version constraint - * - * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: - * - * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') - * - * @param VersionParser $parser Install composer/semver to have access to this class and functionality - * @param string $packageName - * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package - * @return bool - */ - public static function satisfies(VersionParser $parser, $packageName, $constraint) - { - $constraint = $parser->parseConstraints((string) $constraint); - $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); - - return $provided->matches($constraint); - } - - /** - * Returns a version constraint representing all the range(s) which are installed for a given package - * - * It is easier to use this via isInstalled() with the $constraint argument if you need to check - * whether a given version of a package is installed, and not just whether it exists - * - * @param string $packageName - * @return string Version constraint usable with composer/semver - */ - public static function getVersionRanges($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - $ranges = array(); - if (isset($installed['versions'][$packageName]['pretty_version'])) { - $ranges[] = $installed['versions'][$packageName]['pretty_version']; - } - if (array_key_exists('aliases', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); - } - if (array_key_exists('replaced', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); - } - if (array_key_exists('provided', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); - } - - return implode(' || ', $ranges); - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present - */ - public static function getVersion($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['version'])) { - return null; - } - - return $installed['versions'][$packageName]['version']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present - */ - public static function getPrettyVersion($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['pretty_version'])) { - return null; - } - - return $installed['versions'][$packageName]['pretty_version']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference - */ - public static function getReference($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['reference'])) { - return null; - } - - return $installed['versions'][$packageName]['reference']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. - */ - public static function getInstallPath($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @return array - * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} - */ - public static function getRootPackage() - { - $installed = self::getInstalled(); - - return $installed[0]['root']; - } - - /** - * Returns the raw installed.php data for custom implementations - * - * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. - * @return array[] - * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} - */ - public static function getRawData() - { - @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); - - if (null === self::$installed) { - // only require the installed.php file if this file is loaded from its dumped location, - // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 - if (substr(__DIR__, -8, 1) !== 'C') { - self::$installed = include __DIR__ . '/installed.php'; - } else { - self::$installed = array(); - } - } - - return self::$installed; - } - - /** - * Returns the raw data of all installed.php which are currently loaded for custom implementations - * - * @return array[] - * @psalm-return list}> - */ - public static function getAllRawData() - { - return self::getInstalled(); - } - - /** - * Lets you reload the static array from another file - * - * This is only useful for complex integrations in which a project needs to use - * this class but then also needs to execute another project's autoloader in process, - * and wants to ensure both projects have access to their version of installed.php. - * - * A typical case would be PHPUnit, where it would need to make sure it reads all - * the data it needs from this class, then call reload() with - * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure - * the project in which it runs can then also use this class safely, without - * interference between PHPUnit's dependencies and the project's dependencies. - * - * @param array[] $data A vendor/composer/installed.php data set - * @return void - * - * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data - */ - public static function reload($data) - { - self::$installed = $data; - self::$installedByVendor = array(); - - // when using reload, we disable the duplicate protection to ensure that self::$installed data is - // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not, - // so we have to assume it does not, and that may result in duplicate data being returned when listing - // all installed packages for example - self::$installedIsLocalDir = false; - } - - /** - * @return string - */ - private static function getSelfDir() - { - if (self::$selfDir === null) { - self::$selfDir = strtr(__DIR__, '\\', '/'); - } - - return self::$selfDir; - } - - /** - * @return array[] - * @psalm-return list}> - */ - private static function getInstalled() - { - if (null === self::$canGetVendors) { - self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); - } - - $installed = array(); - $copiedLocalDir = false; - - if (self::$canGetVendors) { - $selfDir = self::getSelfDir(); - foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { - $vendorDir = strtr($vendorDir, '\\', '/'); - if (isset(self::$installedByVendor[$vendorDir])) { - $installed[] = self::$installedByVendor[$vendorDir]; - } elseif (is_file($vendorDir.'/composer/installed.php')) { - /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ - $required = require $vendorDir.'/composer/installed.php'; - self::$installedByVendor[$vendorDir] = $required; - $installed[] = $required; - if (self::$installed === null && $vendorDir.'/composer' === $selfDir) { - self::$installed = $required; - self::$installedIsLocalDir = true; - } - } - if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) { - $copiedLocalDir = true; - } - } - } - - if (null === self::$installed) { - // only require the installed.php file if this file is loaded from its dumped location, - // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 - if (substr(__DIR__, -8, 1) !== 'C') { - /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ - $required = require __DIR__ . '/installed.php'; - self::$installed = $required; - } else { - self::$installed = array(); - } - } - - if (self::$installed !== array() && !$copiedLocalDir) { - $installed[] = self::$installed; - } - - return $installed; - } +public static function getInstalledPackages() +{ +$packages = array(); +foreach (self::getInstalled() as $installed) { +$packages[] = array_keys($installed['versions']); +} + +if (1 === \count($packages)) { +return $packages[0]; +} + +return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); +} + + + + + + + + + +public static function isInstalled($packageName) +{ +foreach (self::getInstalled() as $installed) { +if (isset($installed['versions'][$packageName])) { +return true; +} +} + +return false; +} + + + + + + + + + + + + + + +public static function satisfies(VersionParser $parser, $packageName, $constraint) +{ +$constraint = $parser->parseConstraints($constraint); +$provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + +return $provided->matches($constraint); +} + + + + + + + + + + +public static function getVersionRanges($packageName) +{ +foreach (self::getInstalled() as $installed) { +if (!isset($installed['versions'][$packageName])) { +continue; +} + +$ranges = array(); +if (isset($installed['versions'][$packageName]['pretty_version'])) { +$ranges[] = $installed['versions'][$packageName]['pretty_version']; +} +if (array_key_exists('aliases', $installed['versions'][$packageName])) { +$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); +} +if (array_key_exists('replaced', $installed['versions'][$packageName])) { +$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); +} +if (array_key_exists('provided', $installed['versions'][$packageName])) { +$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); +} + +return implode(' || ', $ranges); +} + +throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); +} + + + + + +public static function getVersion($packageName) +{ +foreach (self::getInstalled() as $installed) { +if (!isset($installed['versions'][$packageName])) { +continue; +} + +if (!isset($installed['versions'][$packageName]['version'])) { +return null; +} + +return $installed['versions'][$packageName]['version']; +} + +throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); +} + + + + + +public static function getPrettyVersion($packageName) +{ +foreach (self::getInstalled() as $installed) { +if (!isset($installed['versions'][$packageName])) { +continue; +} + +if (!isset($installed['versions'][$packageName]['pretty_version'])) { +return null; +} + +return $installed['versions'][$packageName]['pretty_version']; +} + +throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); +} + + + + + +public static function getReference($packageName) +{ +foreach (self::getInstalled() as $installed) { +if (!isset($installed['versions'][$packageName])) { +continue; +} + +if (!isset($installed['versions'][$packageName]['reference'])) { +return null; +} + +return $installed['versions'][$packageName]['reference']; +} + +throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); +} + + + + + +public static function getRootPackage() +{ +$installed = self::getInstalled(); + +return $installed[0]['root']; +} + + + + + + + + +public static function getRawData() +{ +@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + +return self::$installed; +} + + + + + + + +public static function getAllRawData() +{ +return self::getInstalled(); +} + + + + + + + + + + + + + + + + + + + +public static function reload($data) +{ +self::$installed = $data; +self::$installedByVendor = array(); +} + + + + + +private static function getInstalled() +{ +if (null === self::$canGetVendors) { +self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); +} + +$installed = array(); + +if (self::$canGetVendors) { +foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { +if (isset(self::$installedByVendor[$vendorDir])) { +$installed[] = self::$installedByVendor[$vendorDir]; +} elseif (is_file($vendorDir.'/composer/installed.php')) { +$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; +} +} +} + +$installed[] = self::$installed; + +return $installed; +} } diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index d517fc2..e42813a 100755 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -12,12 +12,15 @@ return array( '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', + '6b998e7ad3182c0d21d23780badfa07b' => $vendorDir . '/yansongda/supports/src/Functions.php', '2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php', '9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php', + '988d02680beedec88d52f2787b2d2007' => $vendorDir . '/yansongda/artful/src/Functions.php', 'f0e7e63bbb278a92db02393536748c5f' => $vendorDir . '/overtrue/wechat/src/Kernel/Support/Helpers.php', '6747f579ad6817f318cc3a7e7a0abb93' => $vendorDir . '/overtrue/wechat/src/Kernel/Helpers.php', 'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php', '1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php', 'cc56288302d9df745d97c934d6a6e5f0' => $vendorDir . '/topthink/think-queue/src/common.php', 'f7e3d8cd19cf23ce3883a6a51d791b77' => $vendorDir . '/fastadminnet/fastadmin-addons/src/common.php', + '8c783b3a3de2f6d9177022b5ccdcc841' => $vendorDir . '/yansongda/pay/src/Functions.php', ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 2e82543..a0ea073 100755 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -13,6 +13,9 @@ return array( 'phpseclib3\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'), 'addons\\' => array($baseDir . '/addons'), 'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'), + 'Yansongda\\Supports\\' => array($vendorDir . '/yansongda/supports/src'), + 'Yansongda\\Pay\\' => array($vendorDir . '/yansongda/pay/src'), + 'Yansongda\\Artful\\' => array($vendorDir . '/yansongda/artful/src'), 'Workerman\\' => array($vendorDir . '/workerman/workerman'), 'Tx\\' => array($vendorDir . '/fastadminnet/fastadmin-mailer/src'), 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index f993b86..f85c602 100755 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -13,14 +13,17 @@ class ComposerStaticInitf3106b6ef3260b6914241eab0bed11c1 '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', + '6b998e7ad3182c0d21d23780badfa07b' => __DIR__ . '/..' . '/yansongda/supports/src/Functions.php', '2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php', '9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php', + '988d02680beedec88d52f2787b2d2007' => __DIR__ . '/..' . '/yansongda/artful/src/Functions.php', 'f0e7e63bbb278a92db02393536748c5f' => __DIR__ . '/..' . '/overtrue/wechat/src/Kernel/Support/Helpers.php', '6747f579ad6817f318cc3a7e7a0abb93' => __DIR__ . '/..' . '/overtrue/wechat/src/Kernel/Helpers.php', 'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php', '1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php', 'cc56288302d9df745d97c934d6a6e5f0' => __DIR__ . '/..' . '/topthink/think-queue/src/common.php', 'f7e3d8cd19cf23ce3883a6a51d791b77' => __DIR__ . '/..' . '/fastadminnet/fastadmin-addons/src/common.php', + '8c783b3a3de2f6d9177022b5ccdcc841' => __DIR__ . '/..' . '/yansongda/pay/src/Functions.php', ); public static $prefixLengthsPsr4 = array ( @@ -43,6 +46,12 @@ class ComposerStaticInitf3106b6ef3260b6914241eab0bed11c1 array ( 'ZipStream\\' => 10, ), + 'Y' => + array ( + 'Yansongda\\Supports\\' => 19, + 'Yansongda\\Pay\\' => 14, + 'Yansongda\\Artful\\' => 17, + ), 'W' => array ( 'Workerman\\' => 10, @@ -141,6 +150,18 @@ class ComposerStaticInitf3106b6ef3260b6914241eab0bed11c1 array ( 0 => __DIR__ . '/..' . '/maennchen/zipstream-php/src', ), + 'Yansongda\\Supports\\' => + array ( + 0 => __DIR__ . '/..' . '/yansongda/supports/src', + ), + 'Yansongda\\Pay\\' => + array ( + 0 => __DIR__ . '/..' . '/yansongda/pay/src', + ), + 'Yansongda\\Artful\\' => + array ( + 0 => __DIR__ . '/..' . '/yansongda/artful/src', + ), 'Workerman\\' => array ( 0 => __DIR__ . '/..' . '/workerman/workerman', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index f37ff5e..8c3897f 100755 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -199,24 +199,30 @@ }, { "name": "fastadminnet/fastadmin-addons", - "version": "1.4.3", - "version_normalized": "1.4.3.0", + "version": "1.4.2", + "version_normalized": "1.4.2.0", "source": { "type": "git", "url": "https://github.com/fastadminnet/fastadmin-addons.git", - "reference": "b7e371254f97fae7e9232984a746ffa58b64504e" + "reference": "14af178a62fb4cc897f954fa9d7d53798ad2cf37" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fastadminnet/fastadmin-addons/zipball/b7e371254f97fae7e9232984a746ffa58b64504e", - "reference": "b7e371254f97fae7e9232984a746ffa58b64504e", - "shasum": "" + "url": "https://api.github.com/repos/fastadminnet/fastadmin-addons/zipball/14af178a62fb4cc897f954fa9d7d53798ad2cf37", + "reference": "14af178a62fb4cc897f954fa9d7d53798ad2cf37", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "nelexa/zip": "^3.3 || ^4.0", - "php": ">=7.1.0" + "php": ">=7.0.0" }, - "time": "2025-06-17T03:35:34+00:00", + "time": "2025-06-03T03:09:28+00:00", "type": "library", "extra": { "think-config": { @@ -250,7 +256,7 @@ "homepage": "https://github.com/fastadminnet/fastadmin-addons", "support": { "issues": "https://github.com/fastadminnet/fastadmin-addons/issues", - "source": "https://github.com/fastadminnet/fastadmin-addons/tree/v1.4.3" + "source": "https://github.com/fastadminnet/fastadmin-addons/tree/v1.4.2" }, "install-path": "../fastadminnet/fastadmin-addons" }, @@ -314,23 +320,29 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.10.0", - "version_normalized": "7.10.0.0", + "version": "7.9.2", + "version_normalized": "7.9.2.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" + "reference": "d281ed313b989f213357e3be1a179f02196ac99b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", - "shasum": "" + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^2.3", - "guzzlehttp/psr7": "^2.8", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -351,7 +363,7 @@ "ext-intl": "Required for Internationalized Domain Name (IDN) support", "psr/log": "Required for using the Log middleware" }, - "time": "2025-08-23T22:36:01+00:00", + "time": "2024-07-24T11:22:20+00:00", "type": "library", "extra": { "bamarni-bin": { @@ -423,7 +435,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.10.0" + "source": "https://github.com/guzzle/guzzle/tree/7.9.2" }, "funding": [ { @@ -648,39 +660,41 @@ }, { "name": "maennchen/zipstream-php", - "version": "3.1.2", - "version_normalized": "3.1.2.0", + "version": "2.4.0", + "version_normalized": "2.4.0.0", "source": { "type": "git", "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f" + "reference": "3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f", - "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f", - "shasum": "" + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3", + "reference": "3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-mbstring": "*", - "ext-zlib": "*", - "php-64bit": "^8.2" + "myclabs/php-enum": "^1.5", + "php": "^8.0", + "psr/http-message": "^1.0" }, "require-dev": { - "brianium/paratest": "^7.7", "ext-zip": "*", - "friendsofphp/php-cs-fixer": "^3.16", - "guzzlehttp/guzzle": "^7.5", + "friendsofphp/php-cs-fixer": "^3.9", + "guzzlehttp/guzzle": "^6.5.3 || ^7.2.0", "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.5", - "phpunit/phpunit": "^11.0", - "vimeo/psalm": "^6.0" + "php-coveralls/php-coveralls": "^2.4", + "phpunit/phpunit": "^8.5.8 || ^9.4.2", + "vimeo/psalm": "^5.0" }, - "suggest": { - "guzzlehttp/psr7": "^2.4", - "psr/http-message": "^2.0" - }, - "time": "2025-01-27T12:07:53+00:00", + "time": "2022-12-08T12:29:14+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -717,12 +731,16 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/2.4.0" }, "funding": [ { "url": "https://github.com/maennchen", "type": "github" + }, + { + "url": "https://opencollective.com/zipstream", + "type": "open_collective" } ], "install-path": "../maennchen/zipstream-php" @@ -945,6 +963,78 @@ ], "install-path": "../monolog/monolog" }, + { + "name": "myclabs/php-enum", + "version": "1.8.4", + "version_normalized": "1.8.4.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/php-enum.git", + "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/a867478eae49c9f59ece437ae7f9506bfaa27483", + "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^4.6.2" + }, + "time": "2022-08-04T09:53:51+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + }, + "classmap": [ + "stubs/Stringable.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "description": "PHP Enum implementation", + "homepage": "http://github.com/myclabs/php-enum", + "keywords": [ + "enum" + ], + "support": { + "issues": "https://github.com/myclabs/php-enum/issues", + "source": "https://github.com/myclabs/php-enum/tree/1.8.4" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum", + "type": "tidelift" + } + ], + "install-path": "../myclabs/php-enum" + }, { "name": "nelexa/zip", "version": "4.0.2", @@ -1345,18 +1435,24 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "1.30.0", - "version_normalized": "1.30.0.0", + "version": "1.30.1", + "version_normalized": "1.30.1.0", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "2f39286e0136673778b7a142b3f0d141e43d1714" + "reference": "fa8257a579ec623473eabfe49731de5967306c4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/2f39286e0136673778b7a142b3f0d141e43d1714", - "reference": "2f39286e0136673778b7a142b3f0d141e43d1714", - "shasum": "" + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/fa8257a579ec623473eabfe49731de5967306c4c", + "reference": "fa8257a579ec623473eabfe49731de5967306c4c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "composer/pcre": "^1||^2||^3", @@ -1377,7 +1473,7 @@ "maennchen/zipstream-php": "^2.1 || ^3.0", "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", - "php": "^7.4 || ^8.0", + "php": ">=7.4.0 <8.5.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" @@ -1402,7 +1498,7 @@ "mpdf/mpdf": "Option for rendering PDF with PDF Writer", "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" }, - "time": "2025-08-10T06:28:02+00:00", + "time": "2025-10-26T16:01:04+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1448,7 +1544,7 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.30.0" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.30.1" }, "install-path": "../phpoffice/phpspreadsheet" }, @@ -1567,27 +1663,33 @@ }, { "name": "pimple/pimple", - "version": "v3.5.0", - "version_normalized": "3.5.0.0", + "version": "v3.6.0", + "version_normalized": "3.6.0.0", "source": { "type": "git", "url": "https://github.com/silexphp/Pimple.git", - "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed" + "reference": "a70f552d338f9266eec6606c1f0b324da5514c96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a94b3a4db7fb774b3d78dad2315ddc07629e1bed", - "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed", - "shasum": "" + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a70f552d338f9266eec6606c1f0b324da5514c96", + "reference": "a70f552d338f9266eec6606c1f0b324da5514c96", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.2.5", "psr/container": "^1.1 || ^2.0" }, "require-dev": { - "symfony/phpunit-bridge": "^5.4@dev" + "phpunit/phpunit": "*" }, - "time": "2021-10-28T11:13:42+00:00", + "time": "2025-11-12T12:31:38+00:00", "type": "library", "extra": { "branch-alias": { @@ -1617,7 +1719,7 @@ "dependency injection" ], "support": { - "source": "https://github.com/silexphp/Pimple/tree/v3.5.0" + "source": "https://github.com/silexphp/Pimple/tree/v3.6.0" }, "install-path": "../pimple/pimple" }, @@ -1839,24 +1941,30 @@ }, { "name": "psr/http-factory", - "version": "1.1.0", - "version_normalized": "1.1.0.0", + "version": "1.0.2", + "version_normalized": "1.0.2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + "reference": "e616d01114759c4c489f93b099585439f795fe35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", - "shasum": "" + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=7.1", + "php": ">=7.0.0", "psr/http-message": "^1.0 || ^2.0" }, - "time": "2024-04-15T12:06:14+00:00", + "time": "2023-04-10T20:10:41+00:00", "type": "library", "extra": { "branch-alias": { @@ -1879,7 +1987,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "description": "Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -1891,33 +1999,39 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory" + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" }, "install-path": "../psr/http-factory" }, { "name": "psr/http-message", - "version": "2.0", - "version_normalized": "2.0.0.0", + "version": "1.1", + "version_normalized": "1.1.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "shasum": "" + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^7.2 || ^8.0" }, - "time": "2023-04-04T09:54:51+00:00", + "time": "2023-04-04T09:50:52+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.1.x-dev" } }, "installation-source": "dist", @@ -1933,7 +2047,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "homepage": "http://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -1947,7 +2061,7 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/2.0" + "source": "https://github.com/php-fig/http-message/tree/1.1" }, "install-path": "../psr/http-message" }, @@ -2289,23 +2403,29 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.6.0", - "version_normalized": "3.6.0.0", + "version": "v3.0.2", + "version_normalized": "3.0.2.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", - "shasum": "" + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1" + "php": ">=8.0.2" }, - "time": "2024-09-25T14:21:43+00:00", + "time": "2022-01-02T09:55:41+00:00", "type": "library", "extra": { "thanks": { @@ -2313,7 +2433,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.0-dev" } }, "installation-source": "dist", @@ -2339,7 +2459,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" }, "funding": [ { @@ -2447,24 +2567,33 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.6.0", - "version_normalized": "3.6.0.0", + "version": "v3.0.2", + "version_normalized": "3.0.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + "reference": "7bc61cc2db649b4637d331240c5346dcc7708051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586", - "shasum": "" + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7bc61cc2db649b4637d331240c5346dcc7708051", + "reference": "7bc61cc2db649b4637d331240c5346dcc7708051", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1", + "php": ">=8.0.2", "psr/event-dispatcher": "^1" }, - "time": "2024-09-25T14:21:43+00:00", + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "time": "2022-01-02T09:55:41+00:00", "type": "library", "extra": { "thanks": { @@ -2472,7 +2601,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.0-dev" } }, "installation-source": "dist", @@ -2506,7 +2635,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.2" }, "funding": [ { @@ -2526,26 +2655,29 @@ }, { "name": "symfony/finder", - "version": "v7.3.2", - "version_normalized": "7.3.2.0", + "version": "v6.0.19", + "version_normalized": "6.0.19.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" + "reference": "5cc9cac6586fc0c28cd173780ca696e419fefa11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", - "shasum": "" + "url": "https://api.github.com/repos/symfony/finder/zipball/5cc9cac6586fc0c28cd173780ca696e419fefa11", + "reference": "5cc9cac6586fc0c28cd173780ca696e419fefa11", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.2" + "php": ">=8.0.2" }, - "require-dev": { - "symfony/filesystem": "^6.4|^7.0" - }, - "time": "2025-07-15T13:41:35+00:00", + "time": "2023-01-20T17:44:14+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2573,7 +2705,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.3.2" + "source": "https://github.com/symfony/finder/tree/v6.0.19" }, "funding": [ { @@ -2584,10 +2716,6 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -2676,8 +2804,8 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", - "version_normalized": "1.33.0.0", + "version": "v1.32.0", + "version_normalized": "1.32.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", @@ -2687,7 +2815,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-iconv": "*", @@ -2740,7 +2874,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -2751,10 +2885,6 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -2764,8 +2894,8 @@ }, { "name": "symfony/polyfill-php73", - "version": "v1.33.0", - "version_normalized": "1.33.0.0", + "version": "v1.32.0", + "version_normalized": "1.32.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", @@ -2775,7 +2905,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.2" @@ -2823,7 +2959,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.32.0" }, "funding": [ { @@ -2834,10 +2970,6 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -2847,8 +2979,8 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.33.0", - "version_normalized": "1.33.0.0", + "version": "v1.32.0", + "version_normalized": "1.32.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", @@ -2858,7 +2990,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.2" @@ -2910,7 +3048,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" }, "funding": [ { @@ -2921,10 +3059,6 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -3026,28 +3160,36 @@ }, { "name": "symfony/service-contracts", - "version": "v3.6.0", - "version_normalized": "3.6.0.0", + "version": "v3.0.2", + "version_normalized": "3.0.2.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "shasum": "" + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.0.2", + "psr/container": "^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "time": "2025-04-25T09:37:31+00:00", + "suggest": { + "symfony/service-implementation": "" + }, + "time": "2022-05-30T19:17:58+00:00", "type": "library", "extra": { "thanks": { @@ -3055,17 +3197,14 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.0-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3092,7 +3231,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.0.2" }, "funding": [ { @@ -3112,29 +3251,32 @@ }, { "name": "symfony/var-exporter", - "version": "v6.4.26", - "version_normalized": "6.4.26.0", + "version": "v6.0.19", + "version_normalized": "6.0.19.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc" + "reference": "df56f53818c2d5d9f683f4ad2e365ba73a3b69d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/466fcac5fa2e871f83d31173f80e9c2684743bfc", - "reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc", - "shasum": "" + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/df56f53818c2d5d9f683f4ad2e365ba73a3b69d2", + "reference": "df56f53818c2d5d9f683f4ad2e365ba73a3b69d2", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.0.2" }, "require-dev": { - "symfony/property-access": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/var-dumper": "^5.4|^6.0" }, - "time": "2025-09-11T09:57:09+00:00", + "time": "2023-01-13T08:34:10+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3167,12 +3309,10 @@ "export", "hydrate", "instantiate", - "lazy-loading", - "proxy", "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.26" + "source": "https://github.com/symfony/var-exporter/tree/v6.0.19" }, "funding": [ { @@ -3183,10 +3323,6 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -3472,18 +3608,24 @@ }, { "name": "workerman/phpsocket.io", - "version": "v2.2.2", - "version_normalized": "2.2.2.0", + "version": "v2.2.0", + "version_normalized": "2.2.0.0", "source": { "type": "git", "url": "https://github.com/walkor/phpsocket.io.git", - "reference": "5f96eace9f2bcec82555a97ac9867b732024d3b6" + "reference": "0ba306b380e016f447f9860db95fcc1c7553fb91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/walkor/phpsocket.io/zipball/5f96eace9f2bcec82555a97ac9867b732024d3b6", - "reference": "5f96eace9f2bcec82555a97ac9867b732024d3b6", - "shasum": "" + "url": "https://api.github.com/repos/walkor/phpsocket.io/zipball/0ba306b380e016f447f9860db95fcc1c7553fb91", + "reference": "0ba306b380e016f447f9860db95fcc1c7553fb91", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-json": "*", @@ -3493,7 +3635,7 @@ "require-dev": { "squizlabs/php_codesniffer": "^3.7" }, - "time": "2025-04-01T08:36:37+00:00", + "time": "2025-03-24T17:14:03+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3519,7 +3661,7 @@ ], "support": { "issues": "https://github.com/walkor/phpsocket.io/issues", - "source": "https://github.com/walkor/phpsocket.io/tree/v2.2.2" + "source": "https://github.com/walkor/phpsocket.io/tree/v2.2.0" }, "funding": [ { @@ -3612,13 +3754,19 @@ "source": { "type": "git", "url": "https://github.com/yansongda/artful.git", - "reference": "ddc203ef34ab369a5a31df057a0fda697d3ed855" + "reference": "734b97a6a03aa9702d1ce1f396d2e2c9bea845b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yansongda/artful/zipball/ddc203ef34ab369a5a31df057a0fda697d3ed855", - "reference": "ddc203ef34ab369a5a31df057a0fda697d3ed855", - "shasum": "" + "url": "https://api.github.com/repos/yansongda/artful/zipball/734b97a6a03aa9702d1ce1f396d2e2c9bea845b3", + "reference": "734b97a6a03aa9702d1ce1f396d2e2c9bea845b3", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "guzzlehttp/psr7": "^2.6", @@ -3647,7 +3795,7 @@ "hyperf/pimple": "其它/无框架下使用 SDK,请安装,任选其一", "illuminate/container": "其它/无框架下使用 SDK,请安装,任选其一" }, - "time": "2025-07-24T09:39:17+00:00", + "time": "2025-07-24T09:03:04+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3684,18 +3832,24 @@ }, { "name": "yansongda/pay", - "version": "v3.7.18", - "version_normalized": "3.7.18.0", + "version": "v3.7.16", + "version_normalized": "3.7.16.0", "source": { "type": "git", "url": "https://github.com/yansongda/pay.git", - "reference": "813c01e7abed94d2c5ac1a3abdfb87316d78c276" + "reference": "f24aea15bbfc2ec23b1201168d81f73a99433a8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yansongda/pay/zipball/813c01e7abed94d2c5ac1a3abdfb87316d78c276", - "reference": "813c01e7abed94d2c5ac1a3abdfb87316d78c276", - "shasum": "" + "url": "https://api.github.com/repos/yansongda/pay/zipball/f24aea15bbfc2ec23b1201168d81f73a99433a8f", + "reference": "f24aea15bbfc2ec23b1201168d81f73a99433a8f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-bcmath": "*", @@ -3704,7 +3858,7 @@ "ext-openssl": "*", "ext-simplexml": "*", "php": ">=8.0", - "yansongda/artful": "~1.1.3", + "yansongda/artful": "~1.1.1", "yansongda/supports": "~4.0.10" }, "conflict": { @@ -3724,7 +3878,7 @@ "symfony/psr-http-message-bridge": "^2.1", "symfony/var-dumper": "^5.1" }, - "time": "2025-08-13T14:28:14+00:00", + "time": "2025-06-12T05:51:47+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3760,22 +3914,26 @@ }, { "name": "yansongda/supports", - "version": "v4.0.12", - "version_normalized": "4.0.12.0", + "version": "v4.0.10", + "version_normalized": "4.0.10.0", "source": { "type": "git", "url": "https://github.com/yansongda/supports.git", - "reference": "308de376d20cb1cd4f959644793e0582ccd1ef6d" + "reference": "11cc73776e6d4d763a84c8c733f64820abdc44e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yansongda/supports/zipball/308de376d20cb1cd4f959644793e0582ccd1ef6d", - "reference": "308de376d20cb1cd4f959644793e0582ccd1ef6d", - "shasum": "" + "url": "https://api.github.com/repos/yansongda/supports/zipball/11cc73776e6d4d763a84c8c733f64820abdc44e5", + "reference": "11cc73776e6d4d763a84c8c733f64820abdc44e5", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "ext-ctype": "*", - "ext-mbstring": "*", "php": ">=8.0" }, "require-dev": { @@ -3788,7 +3946,7 @@ "monolog/monolog": "Use logger", "symfony/console": "Use stdout logger" }, - "time": "2025-01-08T08:55:20+00:00", + "time": "2024-06-09T15:49:21+00:00", "type": "library", "installation-source": "dist", "autoload": { diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index a32e762..315418a 100755 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -1,565 +1,583 @@ - array( - 'name' => 'fastadminnet/fastadmin', - 'pretty_version' => 'dev-main', - 'version' => 'dev-main', - 'reference' => '34d47f8d9b30ecf836fed3387e6c38b7010e9c8c', - 'type' => 'project', - 'install_path' => __DIR__ . '/../../', - 'aliases' => array(), - 'dev' => true, + + array ( + 'pretty_version' => 'dev-main', + 'version' => 'dev-main', + 'aliases' => + array ( ), - 'versions' => array( - 'composer/pcre' => array( - 'pretty_version' => '3.3.2', - 'version' => '3.3.2.0', - 'reference' => 'b2bed4734f0cc156ee1fe9c0da2550420d99a21e', - 'type' => 'library', - 'install_path' => __DIR__ . '/./pcre', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'easywechat-composer/easywechat-composer' => array( - 'pretty_version' => '1.4.1', - 'version' => '1.4.1.0', - 'reference' => '3fc6a7ab6d3853c0f4e2922539b56cc37ef361cd', - 'type' => 'composer-plugin', - 'install_path' => __DIR__ . '/../easywechat-composer/easywechat-composer', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'ezyang/htmlpurifier' => array( - 'pretty_version' => 'v4.19.0', - 'version' => '4.19.0.0', - 'reference' => 'b287d2a16aceffbf6e0295559b39662612b77fcf', - 'type' => 'library', - 'install_path' => __DIR__ . '/../ezyang/htmlpurifier', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'fastadminnet/fastadmin' => array( - 'pretty_version' => 'dev-main', - 'version' => 'dev-main', - 'reference' => '34d47f8d9b30ecf836fed3387e6c38b7010e9c8c', - 'type' => 'project', - 'install_path' => __DIR__ . '/../../', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'fastadminnet/fastadmin-addons' => array( - 'pretty_version' => '1.4.3', - 'version' => '1.4.3.0', - 'reference' => 'b7e371254f97fae7e9232984a746ffa58b64504e', - 'type' => 'library', - 'install_path' => __DIR__ . '/../fastadminnet/fastadmin-addons', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'fastadminnet/fastadmin-mailer' => array( - 'pretty_version' => 'v2.1.1', - 'version' => '2.1.1.0', - 'reference' => 'bca635ac5f564ed6688d818d215021ffb0813746', - 'type' => 'library', - 'install_path' => __DIR__ . '/../fastadminnet/fastadmin-mailer', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'guzzlehttp/guzzle' => array( - 'pretty_version' => '7.10.0', - 'version' => '7.10.0.0', - 'reference' => 'b51ac707cfa420b7bfd4e4d5e510ba8008e822b4', - 'type' => 'library', - 'install_path' => __DIR__ . '/../guzzlehttp/guzzle', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'guzzlehttp/promises' => array( - 'pretty_version' => '2.3.0', - 'version' => '2.3.0.0', - 'reference' => '481557b130ef3790cf82b713667b43030dc9c957', - 'type' => 'library', - 'install_path' => __DIR__ . '/../guzzlehttp/promises', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'guzzlehttp/psr7' => array( - 'pretty_version' => '2.8.0', - 'version' => '2.8.0.0', - 'reference' => '21dc724a0583619cd1652f673303492272778051', - 'type' => 'library', - 'install_path' => __DIR__ . '/../guzzlehttp/psr7', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'maennchen/zipstream-php' => array( - 'pretty_version' => '3.1.2', - 'version' => '3.1.2.0', - 'reference' => 'aeadcf5c412332eb426c0f9b4485f6accba2a99f', - 'type' => 'library', - 'install_path' => __DIR__ . '/../maennchen/zipstream-php', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'markbaker/complex' => array( - 'pretty_version' => '3.0.2', - 'version' => '3.0.2.0', - 'reference' => '95c56caa1cf5c766ad6d65b6344b807c1e8405b9', - 'type' => 'library', - 'install_path' => __DIR__ . '/../markbaker/complex', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'markbaker/matrix' => array( - 'pretty_version' => '3.0.1', - 'version' => '3.0.1.0', - 'reference' => '728434227fe21be27ff6d86621a1b13107a2562c', - 'type' => 'library', - 'install_path' => __DIR__ . '/../markbaker/matrix', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'monolog/monolog' => array( - 'pretty_version' => '2.10.0', - 'version' => '2.10.0.0', - 'reference' => '5cf826f2991858b54d5c3809bee745560a1042a7', - 'type' => 'library', - 'install_path' => __DIR__ . '/../monolog/monolog', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'nelexa/zip' => array( - 'pretty_version' => '4.0.2', - 'version' => '4.0.2.0', - 'reference' => '88a1b6549be813278ff2dd3b6b2ac188827634a7', - 'type' => 'library', - 'install_path' => __DIR__ . '/../nelexa/zip', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'overtrue/pinyin' => array( - 'pretty_version' => '3.0.6', - 'version' => '3.0.6.0', - 'reference' => '3b781d267197b74752daa32814d3a2cf5d140779', - 'type' => 'library', - 'install_path' => __DIR__ . '/../overtrue/pinyin', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'overtrue/socialite' => array( - 'pretty_version' => '2.0.24', - 'version' => '2.0.24.0', - 'reference' => 'ee7e7b000ec7d64f2b8aba1f6a2eec5cdf3f8bec', - 'type' => 'library', - 'install_path' => __DIR__ . '/../overtrue/socialite', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'overtrue/wechat' => array( - 'pretty_version' => '4.9.0', - 'version' => '4.9.0.0', - 'reference' => '92791f5d957269c633b9aa175f842f6006f945b1', - 'type' => 'library', - 'install_path' => __DIR__ . '/../overtrue/wechat', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'paragonie/constant_time_encoding' => array( - 'pretty_version' => 'v3.1.3', - 'version' => '3.1.3.0', - 'reference' => 'd5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77', - 'type' => 'library', - 'install_path' => __DIR__ . '/../paragonie/constant_time_encoding', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'paragonie/random_compat' => array( - 'pretty_version' => 'v9.99.100', - 'version' => '9.99.100.0', - 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a', - 'type' => 'library', - 'install_path' => __DIR__ . '/../paragonie/random_compat', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'phpoffice/phpspreadsheet' => array( - 'pretty_version' => '1.30.0', - 'version' => '1.30.0.0', - 'reference' => '2f39286e0136673778b7a142b3f0d141e43d1714', - 'type' => 'library', - 'install_path' => __DIR__ . '/../phpoffice/phpspreadsheet', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'phpseclib/phpseclib' => array( - 'pretty_version' => '3.0.47', - 'version' => '3.0.47.0', - 'reference' => '9d6ca36a6c2dd434765b1071b2644a1c683b385d', - 'type' => 'library', - 'install_path' => __DIR__ . '/../phpseclib/phpseclib', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'pimple/pimple' => array( - 'pretty_version' => 'v3.5.0', - 'version' => '3.5.0.0', - 'reference' => 'a94b3a4db7fb774b3d78dad2315ddc07629e1bed', - 'type' => 'library', - 'install_path' => __DIR__ . '/../pimple/pimple', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'psr/cache' => array( - 'pretty_version' => '2.0.0', - 'version' => '2.0.0.0', - 'reference' => '213f9dbc5b9bfbc4f8db86d2838dc968752ce13b', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/cache', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'psr/cache-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0|2.0', - ), - ), - 'psr/container' => array( - 'pretty_version' => '2.0.2', - 'version' => '2.0.2.0', - 'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/container', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'psr/event-dispatcher' => array( - 'pretty_version' => '1.0.0', - 'version' => '1.0.0.0', - 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/event-dispatcher', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'psr/event-dispatcher-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0', - ), - ), - 'psr/http-client' => array( - 'pretty_version' => '1.0.3', - 'version' => '1.0.3.0', - 'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/http-client', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'psr/http-client-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0', - ), - ), - 'psr/http-factory' => array( - 'pretty_version' => '1.1.0', - 'version' => '1.1.0.0', - 'reference' => '2b4765fddfe3b508ac62f829e852b1501d3f6e8a', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/http-factory', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'psr/http-factory-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0', - ), - ), - 'psr/http-message' => array( - 'pretty_version' => '2.0', - 'version' => '2.0.0.0', - 'reference' => '402d35bcb92c70c026d1a6a9883f06b2ead23d71', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/http-message', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'psr/http-message-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0', - ), - ), - 'psr/log' => array( - 'pretty_version' => '1.1.4', - 'version' => '1.1.4.0', - 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/log', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'psr/log-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0.0 || 2.0.0 || 3.0.0', - ), - ), - 'psr/simple-cache' => array( - 'pretty_version' => '1.0.1', - 'version' => '1.0.1.0', - 'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/simple-cache', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'psr/simple-cache-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0|2.0', - ), - ), - 'ralouphie/getallheaders' => array( - 'pretty_version' => '3.0.3', - 'version' => '3.0.3.0', - 'reference' => '120b605dfeb996808c31b6477290a714d356e822', - 'type' => 'library', - 'install_path' => __DIR__ . '/../ralouphie/getallheaders', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/cache' => array( - 'pretty_version' => 'v5.4.46', - 'version' => '5.4.46.0', - 'reference' => '0fe08ee32cec2748fbfea10c52d3ee02049e0f6b', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/cache', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/cache-contracts' => array( - 'pretty_version' => 'v2.5.4', - 'version' => '2.5.4.0', - 'reference' => '517c3a3619dadfa6952c4651767fcadffb4df65e', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/cache-contracts', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/cache-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0|2.0', - ), - ), - 'symfony/deprecation-contracts' => array( - 'pretty_version' => 'v3.6.0', - 'version' => '3.6.0.0', - 'reference' => '63afe740e99a13ba87ec199bb07bbdee937a5b62', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/event-dispatcher' => array( - 'pretty_version' => 'v5.4.45', - 'version' => '5.4.45.0', - 'reference' => '72982eb416f61003e9bb6e91f8b3213600dcf9e9', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/event-dispatcher', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/event-dispatcher-contracts' => array( - 'pretty_version' => 'v3.6.0', - 'version' => '3.6.0.0', - 'reference' => '59eb412e93815df44f05f342958efa9f46b1e586', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/event-dispatcher-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '2.0', - ), - ), - 'symfony/finder' => array( - 'pretty_version' => 'v7.3.2', - 'version' => '7.3.2.0', - 'reference' => '2a6614966ba1074fa93dae0bc804227422df4dfe', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/finder', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/http-foundation' => array( - 'pretty_version' => 'v5.4.48', - 'version' => '5.4.48.0', - 'reference' => '3f38b8af283b830e1363acd79e5bc3412d055341', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/http-foundation', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/polyfill-mbstring' => array( - 'pretty_version' => 'v1.33.0', - 'version' => '1.33.0.0', - 'reference' => '6d857f4d76bd4b343eac26d6b539585d2bc56493', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/polyfill-php73' => array( - 'pretty_version' => 'v1.33.0', - 'version' => '1.33.0.0', - 'reference' => '0f68c03565dcaaf25a890667542e8bd75fe7e5bb', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-php73', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/polyfill-php80' => array( - 'pretty_version' => 'v1.33.0', - 'version' => '1.33.0.0', - 'reference' => '0cc9dd0f17f61d8131e7df6b84bd344899fe2608', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-php80', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/psr-http-message-bridge' => array( - 'pretty_version' => 'v2.3.1', - 'version' => '2.3.1.0', - 'reference' => '581ca6067eb62640de5ff08ee1ba6850a0ee472e', - 'type' => 'symfony-bridge', - 'install_path' => __DIR__ . '/../symfony/psr-http-message-bridge', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/service-contracts' => array( - 'pretty_version' => 'v3.6.0', - 'version' => '3.6.0.0', - 'reference' => 'f021b05a130d35510bd6b25fe9053c2a8a15d5d4', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/service-contracts', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/var-exporter' => array( - 'pretty_version' => 'v6.4.26', - 'version' => '6.4.26.0', - 'reference' => '466fcac5fa2e871f83d31173f80e9c2684743bfc', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/var-exporter', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'topthink/framework' => array( - 'pretty_version' => 'dev-master', - 'version' => 'dev-master', - 'reference' => '9a2e7c2a1b6302afb61035c99c85bf0cfe0c52ec', - 'type' => 'think-framework', - 'install_path' => __DIR__ . '/../../thinkphp', - 'aliases' => array( - 0 => '9999999-dev', - ), - 'dev_requirement' => false, - ), - 'topthink/think-captcha' => array( - 'pretty_version' => 'v1.0.9', - 'version' => '1.0.9.0', - 'reference' => '9be9dd7e61c7fa3c478c4b92910d7230b94d0d23', - 'type' => 'library', - 'install_path' => __DIR__ . '/../topthink/think-captcha', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'topthink/think-helper' => array( - 'pretty_version' => 'v1.0.7', - 'version' => '1.0.7.0', - 'reference' => '5f92178606c8ce131d36b37a57c58eb71e55f019', - 'type' => 'library', - 'install_path' => __DIR__ . '/../topthink/think-helper', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'topthink/think-installer' => array( - 'pretty_version' => 'v1.0.14', - 'version' => '1.0.14.0', - 'reference' => 'eae1740ac264a55c06134b6685dfb9f837d004d1', - 'type' => 'composer-plugin', - 'install_path' => __DIR__ . '/../topthink/think-installer', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'topthink/think-queue' => array( - 'pretty_version' => 'v1.1.6', - 'version' => '1.1.6.0', - 'reference' => '250650eb0e8ea5af4cfdc7ae46f3f4e0a24ac245', - 'type' => 'think-extend', - 'install_path' => __DIR__ . '/../topthink/think-queue', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'workerman/channel' => array( - 'pretty_version' => 'v1.2.3', - 'version' => '1.2.3.0', - 'reference' => '5edb0008eae35bf2da7218d911042abd23aa4370', - 'type' => 'library', - 'install_path' => __DIR__ . '/../workerman/channel', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'workerman/phpsocket.io' => array( - 'pretty_version' => 'v2.2.2', - 'version' => '2.2.2.0', - 'reference' => '5f96eace9f2bcec82555a97ac9867b732024d3b6', - 'type' => 'library', - 'install_path' => __DIR__ . '/../workerman/phpsocket.io', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'workerman/workerman' => array( - 'pretty_version' => 'v4.2.1', - 'version' => '4.2.1.0', - 'reference' => 'cafb5a43d93d7d30a16b32a57948581cca993562', - 'type' => 'library', - 'install_path' => __DIR__ . '/../workerman/workerman', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'yansongda/artful' => array( - 'pretty_version' => 'v1.1.3', - 'version' => '1.1.3.0', - 'reference' => 'ddc203ef34ab369a5a31df057a0fda697d3ed855', - 'type' => 'library', - 'install_path' => __DIR__ . '/../yansongda/artful', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'yansongda/pay' => array( - 'pretty_version' => 'v3.7.18', - 'version' => '3.7.18.0', - 'reference' => '813c01e7abed94d2c5ac1a3abdfb87316d78c276', - 'type' => 'library', - 'install_path' => __DIR__ . '/../yansongda/pay', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'yansongda/supports' => array( - 'pretty_version' => 'v4.0.12', - 'version' => '4.0.12.0', - 'reference' => '308de376d20cb1cd4f959644793e0582ccd1ef6d', - 'type' => 'library', - 'install_path' => __DIR__ . '/../yansongda/supports', - 'aliases' => array(), - 'dev_requirement' => false, - ), + 'reference' => '0a95974a63e41cca15747597241a53381c61f1df', + 'name' => 'fastadminnet/fastadmin', + ), + 'versions' => + array ( + 'composer/pcre' => + array ( + 'pretty_version' => '3.3.2', + 'version' => '3.3.2.0', + 'aliases' => + array ( + ), + 'reference' => 'b2bed4734f0cc156ee1fe9c0da2550420d99a21e', ), + 'easywechat-composer/easywechat-composer' => + array ( + 'pretty_version' => '1.4.1', + 'version' => '1.4.1.0', + 'aliases' => + array ( + ), + 'reference' => '3fc6a7ab6d3853c0f4e2922539b56cc37ef361cd', + ), + 'ezyang/htmlpurifier' => + array ( + 'pretty_version' => 'v4.19.0', + 'version' => '4.19.0.0', + 'aliases' => + array ( + ), + 'reference' => 'b287d2a16aceffbf6e0295559b39662612b77fcf', + ), + 'fastadminnet/fastadmin' => + array ( + 'pretty_version' => 'dev-main', + 'version' => 'dev-main', + 'aliases' => + array ( + ), + 'reference' => '0a95974a63e41cca15747597241a53381c61f1df', + ), + 'fastadminnet/fastadmin-addons' => + array ( + 'pretty_version' => '1.4.2', + 'version' => '1.4.2.0', + 'aliases' => + array ( + ), + 'reference' => '14af178a62fb4cc897f954fa9d7d53798ad2cf37', + ), + 'fastadminnet/fastadmin-mailer' => + array ( + 'pretty_version' => 'v2.1.1', + 'version' => '2.1.1.0', + 'aliases' => + array ( + ), + 'reference' => 'bca635ac5f564ed6688d818d215021ffb0813746', + ), + 'guzzlehttp/guzzle' => + array ( + 'pretty_version' => '7.9.2', + 'version' => '7.9.2.0', + 'aliases' => + array ( + ), + 'reference' => 'd281ed313b989f213357e3be1a179f02196ac99b', + ), + 'guzzlehttp/promises' => + array ( + 'pretty_version' => '2.3.0', + 'version' => '2.3.0.0', + 'aliases' => + array ( + ), + 'reference' => '481557b130ef3790cf82b713667b43030dc9c957', + ), + 'guzzlehttp/psr7' => + array ( + 'pretty_version' => '2.8.0', + 'version' => '2.8.0.0', + 'aliases' => + array ( + ), + 'reference' => '21dc724a0583619cd1652f673303492272778051', + ), + 'maennchen/zipstream-php' => + array ( + 'pretty_version' => '2.4.0', + 'version' => '2.4.0.0', + 'aliases' => + array ( + ), + 'reference' => '3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3', + ), + 'markbaker/complex' => + array ( + 'pretty_version' => '3.0.2', + 'version' => '3.0.2.0', + 'aliases' => + array ( + ), + 'reference' => '95c56caa1cf5c766ad6d65b6344b807c1e8405b9', + ), + 'markbaker/matrix' => + array ( + 'pretty_version' => '3.0.1', + 'version' => '3.0.1.0', + 'aliases' => + array ( + ), + 'reference' => '728434227fe21be27ff6d86621a1b13107a2562c', + ), + 'monolog/monolog' => + array ( + 'pretty_version' => '2.10.0', + 'version' => '2.10.0.0', + 'aliases' => + array ( + ), + 'reference' => '5cf826f2991858b54d5c3809bee745560a1042a7', + ), + 'myclabs/php-enum' => + array ( + 'pretty_version' => '1.8.4', + 'version' => '1.8.4.0', + 'aliases' => + array ( + ), + 'reference' => 'a867478eae49c9f59ece437ae7f9506bfaa27483', + ), + 'nelexa/zip' => + array ( + 'pretty_version' => '4.0.2', + 'version' => '4.0.2.0', + 'aliases' => + array ( + ), + 'reference' => '88a1b6549be813278ff2dd3b6b2ac188827634a7', + ), + 'overtrue/pinyin' => + array ( + 'pretty_version' => '3.0.6', + 'version' => '3.0.6.0', + 'aliases' => + array ( + ), + 'reference' => '3b781d267197b74752daa32814d3a2cf5d140779', + ), + 'overtrue/socialite' => + array ( + 'pretty_version' => '2.0.24', + 'version' => '2.0.24.0', + 'aliases' => + array ( + ), + 'reference' => 'ee7e7b000ec7d64f2b8aba1f6a2eec5cdf3f8bec', + ), + 'overtrue/wechat' => + array ( + 'pretty_version' => '4.9.0', + 'version' => '4.9.0.0', + 'aliases' => + array ( + ), + 'reference' => '92791f5d957269c633b9aa175f842f6006f945b1', + ), + 'paragonie/constant_time_encoding' => + array ( + 'pretty_version' => 'v3.1.3', + 'version' => '3.1.3.0', + 'aliases' => + array ( + ), + 'reference' => 'd5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77', + ), + 'paragonie/random_compat' => + array ( + 'pretty_version' => 'v9.99.100', + 'version' => '9.99.100.0', + 'aliases' => + array ( + ), + 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a', + ), + 'phpoffice/phpspreadsheet' => + array ( + 'pretty_version' => '1.30.1', + 'version' => '1.30.1.0', + 'aliases' => + array ( + ), + 'reference' => 'fa8257a579ec623473eabfe49731de5967306c4c', + ), + 'phpseclib/phpseclib' => + array ( + 'pretty_version' => '3.0.47', + 'version' => '3.0.47.0', + 'aliases' => + array ( + ), + 'reference' => '9d6ca36a6c2dd434765b1071b2644a1c683b385d', + ), + 'pimple/pimple' => + array ( + 'pretty_version' => 'v3.6.0', + 'version' => '3.6.0.0', + 'aliases' => + array ( + ), + 'reference' => 'a70f552d338f9266eec6606c1f0b324da5514c96', + ), + 'psr/cache' => + array ( + 'pretty_version' => '2.0.0', + 'version' => '2.0.0.0', + 'aliases' => + array ( + ), + 'reference' => '213f9dbc5b9bfbc4f8db86d2838dc968752ce13b', + ), + 'psr/cache-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0|2.0', + ), + ), + 'psr/container' => + array ( + 'pretty_version' => '2.0.2', + 'version' => '2.0.2.0', + 'aliases' => + array ( + ), + 'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963', + ), + 'psr/event-dispatcher' => + array ( + 'pretty_version' => '1.0.0', + 'version' => '1.0.0.0', + 'aliases' => + array ( + ), + 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0', + ), + 'psr/event-dispatcher-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0', + ), + ), + 'psr/http-client' => + array ( + 'pretty_version' => '1.0.3', + 'version' => '1.0.3.0', + 'aliases' => + array ( + ), + 'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90', + ), + 'psr/http-client-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0', + ), + ), + 'psr/http-factory' => + array ( + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', + 'aliases' => + array ( + ), + 'reference' => 'e616d01114759c4c489f93b099585439f795fe35', + ), + 'psr/http-factory-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0', + ), + ), + 'psr/http-message' => + array ( + 'pretty_version' => '1.1', + 'version' => '1.1.0.0', + 'aliases' => + array ( + ), + 'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba', + ), + 'psr/http-message-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0', + ), + ), + 'psr/log' => + array ( + 'pretty_version' => '1.1.4', + 'version' => '1.1.4.0', + 'aliases' => + array ( + ), + 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11', + ), + 'psr/log-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0.0 || 2.0.0 || 3.0.0', + ), + ), + 'psr/simple-cache' => + array ( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'aliases' => + array ( + ), + 'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b', + ), + 'psr/simple-cache-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0|2.0', + ), + ), + 'ralouphie/getallheaders' => + array ( + 'pretty_version' => '3.0.3', + 'version' => '3.0.3.0', + 'aliases' => + array ( + ), + 'reference' => '120b605dfeb996808c31b6477290a714d356e822', + ), + 'symfony/cache' => + array ( + 'pretty_version' => 'v5.4.46', + 'version' => '5.4.46.0', + 'aliases' => + array ( + ), + 'reference' => '0fe08ee32cec2748fbfea10c52d3ee02049e0f6b', + ), + 'symfony/cache-contracts' => + array ( + 'pretty_version' => 'v2.5.4', + 'version' => '2.5.4.0', + 'aliases' => + array ( + ), + 'reference' => '517c3a3619dadfa6952c4651767fcadffb4df65e', + ), + 'symfony/cache-implementation' => + array ( + 'provided' => + array ( + 0 => '1.0|2.0', + ), + ), + 'symfony/deprecation-contracts' => + array ( + 'pretty_version' => 'v3.0.2', + 'version' => '3.0.2.0', + 'aliases' => + array ( + ), + 'reference' => '26954b3d62a6c5fd0ea8a2a00c0353a14978d05c', + ), + 'symfony/event-dispatcher' => + array ( + 'pretty_version' => 'v5.4.45', + 'version' => '5.4.45.0', + 'aliases' => + array ( + ), + 'reference' => '72982eb416f61003e9bb6e91f8b3213600dcf9e9', + ), + 'symfony/event-dispatcher-contracts' => + array ( + 'pretty_version' => 'v3.0.2', + 'version' => '3.0.2.0', + 'aliases' => + array ( + ), + 'reference' => '7bc61cc2db649b4637d331240c5346dcc7708051', + ), + 'symfony/event-dispatcher-implementation' => + array ( + 'provided' => + array ( + 0 => '2.0', + ), + ), + 'symfony/finder' => + array ( + 'pretty_version' => 'v6.0.19', + 'version' => '6.0.19.0', + 'aliases' => + array ( + ), + 'reference' => '5cc9cac6586fc0c28cd173780ca696e419fefa11', + ), + 'symfony/http-foundation' => + array ( + 'pretty_version' => 'v5.4.48', + 'version' => '5.4.48.0', + 'aliases' => + array ( + ), + 'reference' => '3f38b8af283b830e1363acd79e5bc3412d055341', + ), + 'symfony/polyfill-mbstring' => + array ( + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'aliases' => + array ( + ), + 'reference' => '6d857f4d76bd4b343eac26d6b539585d2bc56493', + ), + 'symfony/polyfill-php73' => + array ( + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'aliases' => + array ( + ), + 'reference' => '0f68c03565dcaaf25a890667542e8bd75fe7e5bb', + ), + 'symfony/polyfill-php80' => + array ( + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'aliases' => + array ( + ), + 'reference' => '0cc9dd0f17f61d8131e7df6b84bd344899fe2608', + ), + 'symfony/psr-http-message-bridge' => + array ( + 'pretty_version' => 'v2.3.1', + 'version' => '2.3.1.0', + 'aliases' => + array ( + ), + 'reference' => '581ca6067eb62640de5ff08ee1ba6850a0ee472e', + ), + 'symfony/service-contracts' => + array ( + 'pretty_version' => 'v3.0.2', + 'version' => '3.0.2.0', + 'aliases' => + array ( + ), + 'reference' => 'd78d39c1599bd1188b8e26bb341da52c3c6d8a66', + ), + 'symfony/var-exporter' => + array ( + 'pretty_version' => 'v6.0.19', + 'version' => '6.0.19.0', + 'aliases' => + array ( + ), + 'reference' => 'df56f53818c2d5d9f683f4ad2e365ba73a3b69d2', + ), + 'topthink/framework' => + array ( + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'aliases' => + array ( + 0 => '9999999-dev', + ), + 'reference' => '9a2e7c2a1b6302afb61035c99c85bf0cfe0c52ec', + ), + 'topthink/think-captcha' => + array ( + 'pretty_version' => 'v1.0.9', + 'version' => '1.0.9.0', + 'aliases' => + array ( + ), + 'reference' => '9be9dd7e61c7fa3c478c4b92910d7230b94d0d23', + ), + 'topthink/think-helper' => + array ( + 'pretty_version' => 'v1.0.7', + 'version' => '1.0.7.0', + 'aliases' => + array ( + ), + 'reference' => '5f92178606c8ce131d36b37a57c58eb71e55f019', + ), + 'topthink/think-installer' => + array ( + 'pretty_version' => 'v1.0.14', + 'version' => '1.0.14.0', + 'aliases' => + array ( + ), + 'reference' => 'eae1740ac264a55c06134b6685dfb9f837d004d1', + ), + 'topthink/think-queue' => + array ( + 'pretty_version' => 'v1.1.6', + 'version' => '1.1.6.0', + 'aliases' => + array ( + ), + 'reference' => '250650eb0e8ea5af4cfdc7ae46f3f4e0a24ac245', + ), + 'workerman/channel' => + array ( + 'pretty_version' => 'v1.2.3', + 'version' => '1.2.3.0', + 'aliases' => + array ( + ), + 'reference' => '5edb0008eae35bf2da7218d911042abd23aa4370', + ), + 'workerman/phpsocket.io' => + array ( + 'pretty_version' => 'v2.2.0', + 'version' => '2.2.0.0', + 'aliases' => + array ( + ), + 'reference' => '0ba306b380e016f447f9860db95fcc1c7553fb91', + ), + 'workerman/workerman' => + array ( + 'pretty_version' => 'v4.2.1', + 'version' => '4.2.1.0', + 'aliases' => + array ( + ), + 'reference' => 'cafb5a43d93d7d30a16b32a57948581cca993562', + ), + 'yansongda/artful' => + array ( + 'pretty_version' => 'v1.1.3', + 'version' => '1.1.3.0', + 'aliases' => + array ( + ), + 'reference' => '734b97a6a03aa9702d1ce1f396d2e2c9bea845b3', + ), + 'yansongda/pay' => + array ( + 'pretty_version' => 'v3.7.16', + 'version' => '3.7.16.0', + 'aliases' => + array ( + ), + 'reference' => 'f24aea15bbfc2ec23b1201168d81f73a99433a8f', + ), + 'yansongda/supports' => + array ( + 'pretty_version' => 'v4.0.10', + 'version' => '4.0.10.0', + 'aliases' => + array ( + ), + 'reference' => '11cc73776e6d4d763a84c8c733f64820abdc44e5', + ), + ), ); diff --git a/vendor/fastadminnet/fastadmin-addons/composer.json b/vendor/fastadminnet/fastadmin-addons/composer.json index 050b7c9..ad98272 100644 --- a/vendor/fastadminnet/fastadmin-addons/composer.json +++ b/vendor/fastadminnet/fastadmin-addons/composer.json @@ -3,7 +3,7 @@ "description": "addons package for fastadmin", "homepage": "https://github.com/fastadminnet/fastadmin-addons", "license": "Apache-2.0", - "version": "1.4.3", + "version": "1.4.2", "authors": [ { "name": "Karson", @@ -18,7 +18,7 @@ "issues": "https://github.com/fastadminnet/fastadmin-addons/issues" }, "require": { - "php": ">=7.1.0", + "php": ">=7.0.0", "nelexa/zip": "^3.3 || ^4.0" }, "autoload": { diff --git a/vendor/fastadminnet/fastadmin-addons/src/addons/Controller.php b/vendor/fastadminnet/fastadmin-addons/src/addons/Controller.php index 457ff5c..fea2c4f 100644 --- a/vendor/fastadminnet/fastadmin-addons/src/addons/Controller.php +++ b/vendor/fastadminnet/fastadmin-addons/src/addons/Controller.php @@ -63,7 +63,7 @@ class Controller extends \think\Controller * @param Request $request Request对象 * @access public */ - public function __construct(?Request $request = null) + public function __construct(Request $request = null) { if (is_null($request)) { $request = Request::instance(); diff --git a/vendor/guzzlehttp/guzzle/CHANGELOG.md b/vendor/guzzlehttp/guzzle/CHANGELOG.md index 5fe721e..e0b6216 100644 --- a/vendor/guzzlehttp/guzzle/CHANGELOG.md +++ b/vendor/guzzlehttp/guzzle/CHANGELOG.md @@ -2,25 +2,6 @@ Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version. -## 7.10.0 - 2025-08-23 - -### Added - -- Support for PHP 8.5 - -### Changed - -- Adjusted `guzzlehttp/promises` version constraint to `^2.3` -- Adjusted `guzzlehttp/psr7` version constraint to `^2.8` - - -## 7.9.3 - 2025-03-27 - -### Changed - -- Remove explicit content-length header for GET requests -- Improve compatibility with bad servers for boolean cookie values - ## 7.9.2 - 2024-07-24 diff --git a/vendor/guzzlehttp/guzzle/composer.json b/vendor/guzzlehttp/guzzle/composer.json index 0db75a9..cbede14 100644 --- a/vendor/guzzlehttp/guzzle/composer.json +++ b/vendor/guzzlehttp/guzzle/composer.json @@ -81,8 +81,8 @@ "require": { "php": "^7.2.5 || ^8.0", "ext-json": "*", - "guzzlehttp/promises": "^2.3", - "guzzlehttp/psr7": "^2.8", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" }, diff --git a/vendor/guzzlehttp/guzzle/package-lock.json b/vendor/guzzlehttp/guzzle/package-lock.json deleted file mode 100644 index 0e14dc1..0000000 --- a/vendor/guzzlehttp/guzzle/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "guzzle", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php b/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php index 47c4d10..c9806da 100644 --- a/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php +++ b/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php @@ -62,10 +62,6 @@ class SetCookie if (is_numeric($value)) { $data[$search] = (int) $value; } - } elseif ($search === 'Secure' || $search === 'Discard' || $search === 'HttpOnly') { - if ($value) { - $data[$search] = true; - } } else { $data[$search] = $value; } diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php index 3c1fa9c..fe36137 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php @@ -125,9 +125,7 @@ class CurlFactory implements CurlFactoryInterface unset($easy->handle); if (\count($this->handles) >= $this->maxHandles) { - if (PHP_VERSION_ID < 80000) { - \curl_close($resource); - } + \curl_close($resource); } else { // Remove all callback functions as they can hold onto references // and are not cleaned up by curl_reset. Using curl_setopt_array @@ -731,10 +729,7 @@ class CurlFactory implements CurlFactoryInterface public function __destruct() { foreach ($this->handles as $id => $handle) { - if (PHP_VERSION_ID < 80000) { - \curl_close($handle); - } - + \curl_close($handle); unset($this->handles[$id]); } } diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php index 21abbed..73a6abe 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php @@ -240,10 +240,7 @@ class CurlMultiHandler $handle = $this->handles[$id]['easy']->handle; unset($this->delays[$id], $this->handles[$id]); \curl_multi_remove_handle($this->_mh, $handle); - - if (PHP_VERSION_ID < 80000) { - \curl_close($handle); - } + \curl_close($handle); return true; } diff --git a/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php b/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php index 9df70cf..f045b52 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php @@ -17,10 +17,10 @@ class Proxy * Sends synchronous requests to a specific handler while sending all other * requests to another handler. * - * @param callable(RequestInterface, array): PromiseInterface $default Handler used for normal responses - * @param callable(RequestInterface, array): PromiseInterface $sync Handler used for synchronous responses. + * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for normal responses + * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $sync Handler used for synchronous responses. * - * @return callable(RequestInterface, array): PromiseInterface Returns the composed handler. + * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler. */ public static function wrapSync(callable $default, callable $sync): callable { @@ -37,10 +37,10 @@ class Proxy * performance benefits of curl while still supporting true streaming * through the StreamHandler. * - * @param callable(RequestInterface, array): PromiseInterface $default Handler used for non-streaming responses - * @param callable(RequestInterface, array): PromiseInterface $streaming Handler used for streaming responses + * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for non-streaming responses + * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $streaming Handler used for streaming responses * - * @return callable(RequestInterface, array): PromiseInterface Returns the composed handler. + * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler. */ public static function wrapStreaming(callable $default, callable $streaming): callable { diff --git a/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php index f24921f..1d89a8f 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php @@ -53,14 +53,8 @@ class StreamHandler $request = $request->withoutHeader('Expect'); // Append a content-length header if body size is zero to match - // the behavior of `CurlHandler` - if ( - ( - 0 === \strcasecmp('PUT', $request->getMethod()) - || 0 === \strcasecmp('POST', $request->getMethod()) - ) - && 0 === $request->getBody()->getSize() - ) { + // cURL's behavior. + if (0 === $request->getBody()->getSize()) { $request = $request->withHeader('Content-Length', '0'); } @@ -333,15 +327,8 @@ class StreamHandler ); return $this->createResource( - function () use ($uri, $contextResource, $context, $options, $request) { + function () use ($uri, &$http_response_header, $contextResource, $context, $options, $request) { $resource = @\fopen((string) $uri, 'r', false, $contextResource); - - // See https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_http_response_header_predefined_variable - if (function_exists('http_get_last_response_headers')) { - /** @var array|null */ - $http_response_header = \http_get_last_response_headers(); - } - $this->lastHeaders = $http_response_header ?? []; if (false === $resource) { diff --git a/vendor/guzzlehttp/guzzle/src/Middleware.php b/vendor/guzzlehttp/guzzle/src/Middleware.php index 9901da4..6edbb3f 100644 --- a/vendor/guzzlehttp/guzzle/src/Middleware.php +++ b/vendor/guzzlehttp/guzzle/src/Middleware.php @@ -187,12 +187,12 @@ final class Middleware * Middleware that logs requests, responses, and errors using a message * formatter. * + * @phpstan-param \Psr\Log\LogLevel::* $logLevel Level at which to log requests. + * * @param LoggerInterface $logger Logs messages. * @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings. * @param string $logLevel Level at which to log requests. * - * @phpstan-param \Psr\Log\LogLevel::* $logLevel Level at which to log requests. - * * @return callable Returns a function that accepts the next handler. */ public static function log(LoggerInterface $logger, $formatter, string $logLevel = 'info'): callable diff --git a/vendor/guzzlehttp/guzzle/src/Pool.php b/vendor/guzzlehttp/guzzle/src/Pool.php index ddc304b..6277c61 100644 --- a/vendor/guzzlehttp/guzzle/src/Pool.php +++ b/vendor/guzzlehttp/guzzle/src/Pool.php @@ -86,7 +86,7 @@ class Pool implements PromisorInterface * @param ClientInterface $client Client used to send the requests * @param array|\Iterator $requests Requests to send concurrently. * @param array $options Passes through the options available in - * {@see Pool::__construct} + * {@see \GuzzleHttp\Pool::__construct} * * @return array Returns an array containing the response or an exception * in the same order that the requests were sent. diff --git a/vendor/guzzlehttp/guzzle/src/Utils.php b/vendor/guzzlehttp/guzzle/src/Utils.php index c6a5893..df52927 100644 --- a/vendor/guzzlehttp/guzzle/src/Utils.php +++ b/vendor/guzzlehttp/guzzle/src/Utils.php @@ -79,7 +79,7 @@ final class Utils * * The returned handler is not wrapped by any default middlewares. * - * @return callable(\Psr\Http\Message\RequestInterface, array): Promise\PromiseInterface Returns the best handler for the given system. + * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system. * * @throws \RuntimeException if no viable Handler is available. */ diff --git a/vendor/guzzlehttp/guzzle/src/functions.php b/vendor/guzzlehttp/guzzle/src/functions.php index 9ab4b96..5edc66a 100644 --- a/vendor/guzzlehttp/guzzle/src/functions.php +++ b/vendor/guzzlehttp/guzzle/src/functions.php @@ -50,7 +50,7 @@ function debug_resource($value = null) * * The returned handler is not wrapped by any default middlewares. * - * @return callable(\Psr\Http\Message\RequestInterface, array): Promise\PromiseInterface Returns the best handler for the given system. + * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system. * * @throws \RuntimeException if no viable Handler is available. * diff --git a/vendor/maennchen/zipstream-php/.gitattributes b/vendor/maennchen/zipstream-php/.gitattributes deleted file mode 100644 index e058ebd..0000000 --- a/vendor/maennchen/zipstream-php/.gitattributes +++ /dev/null @@ -1,6 +0,0 @@ -.gitignore text eol=lf -.gitattributes text eol=lf -*.md text eol=lf -*.php text eol=lf -*.yml text eol=lf -*.xml text eol=lf diff --git a/vendor/maennchen/zipstream-php/.github/CODE_OF_CONDUCT.md b/vendor/maennchen/zipstream-php/.github/CODE_OF_CONDUCT.md deleted file mode 100644 index 9d75b87..0000000 --- a/vendor/maennchen/zipstream-php/.github/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,132 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, caste, color, religion, or sexual -identity and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -- Focusing on what is best not just for us as individuals, but for the overall - community - -Examples of unacceptable behavior include: - -- The use of sexualized language or imagery, and sexual attention or advances of - any kind -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email address, - without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -jonatan@maennchen.ch. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series of -actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or permanent -ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within the -community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.1, available at -[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. - -Community Impact Guidelines were inspired by -[Mozilla's code of conduct enforcement ladder][mozilla coc]. - -For answers to common questions about this code of conduct, see the FAQ at -[https://www.contributor-covenant.org/faq][faq]. Translations are available at -[https://www.contributor-covenant.org/translations][translations]. - -[homepage]: https://www.contributor-covenant.org -[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html -[mozilla coc]: https://github.com/mozilla/diversity -[faq]: https://www.contributor-covenant.org/faq -[translations]: https://www.contributor-covenant.org/translations diff --git a/vendor/maennchen/zipstream-php/.github/CONTRIBUTING.md b/vendor/maennchen/zipstream-php/.github/CONTRIBUTING.md deleted file mode 100644 index d8caee0..0000000 --- a/vendor/maennchen/zipstream-php/.github/CONTRIBUTING.md +++ /dev/null @@ -1,139 +0,0 @@ -# Contributing to ZipStream-PHP - -## Welcome! - -We look forward to your contributions! Here are some examples how you can -contribute: - -- [Report a bug](https://github.com/maennchen/ZipStream-PHP/issues/new?labels=bug&template=BUG.md) -- [Propose a new feature](https://github.com/maennchen/ZipStream-PHP/issues/new?labels=enhancement&template=FEATURE.md) -- [Send a pull request](https://github.com/maennchen/ZipStream-PHP/pulls) - -## We have a Code of Conduct - -Please note that this project is released with a -[Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this -project you agree to abide by its terms. - -## Any contributions you make will be under the MIT License - -When you submit code changes, your submissions are understood to be under the -same [MIT License](https://github.com/maennchen/ZipStream-PHP/blob/main/LICENSE) -that covers the project. By contributing to this project, you agree that your -contributions will be licensed under its MIT License. - -## Write bug reports with detail, background, and sample code - -In your bug report, please provide the following: - -- A quick summary and/or background -- Steps to reproduce - - Be specific! - - Give sample code if you can. -- What you expected would happen -- What actually happens -- Notes (possibly including why you think this might be happening, or stuff you -- tried that didn't work) - -Please do not report a bug for a version of ZIPStream-PHP that is no longer -supported (`< 3.0.0`). Please do not report a bug if you are using a version of -PHP that is not supported by the version of ZipStream-PHP you are using. - -Please post code and output as text -([using proper markup](https://guides.github.com/features/mastering-markdown/)). -Do not post screenshots of code or output. - -Please include the output of `composer info | sort`. - -## Workflow for Pull Requests - -1. Fork the repository. -2. Create your branch from `main` if you plan to implement new functionality or - change existing code significantly; create your branch from the oldest branch - that is affected by the bug if you plan to fix a bug. -3. Implement your change and add tests for it. -4. Ensure the test suite passes. -5. Ensure the code complies with our coding guidelines (see below). -6. Send that pull request! - -Please make sure you have -[set up your user name and email address](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup) -for use with Git. Strings such as `silly nick name ` look really -stupid in the commit history of a project. - -We encourage you to -[sign your Git commits with your GPG key](https://docs.github.com/en/github/authenticating-to-github/signing-commits). - -Pull requests for new features must be based on the `main` branch. - -We are trying to keep backwards compatibility breaks in ZipStream-PHP to a -minimum. Please take this into account when proposing changes. - -Due to time constraints, we are not always able to respond as quickly as we -would like. Please do not take delays personal and feel free to remind us if you -feel that we forgot to respond. - -## Coding Guidelines - -This project comes with a configuration file (located at `/psalm.yml` in the -repository) that you can use to perform static analysis (with a focus on type -checking): - -```bash -$ .composer run test:lint -``` - -This project comes with a configuration file (located at -`/.php-cs-fixer.dist.php` in the repository) that you can use to (re)format your -source code for compliance with this project's coding guidelines: - -```bash -$ composer run format -``` - -Please understand that we will not accept a pull request when its changes -violate this project's coding guidelines. - -## Using ZipStream-PHP from a Git checkout - -The following commands can be used to perform the initial checkout of -ZipStream-PHP: - -```bash -$ git clone git@github.com:maennchen/ZipStream-PHP.git - -$ cd ZipStream-PHP -``` - -Install ZipStream-PHP's dependencies using [Composer](https://getcomposer.org/): - -```bash -$ composer install -$ composer run install:tools # Install phpDocumentor using phive -``` - -## Running ZipStream-PHP's test suite - -After following the steps shown above, ZipStream-PHP's test suite is run like -this: - -```bash -$ composer run test:unit -``` - -There's some slow tests in the test suite that test the handling of big files in -the archives. To skip them use the following command instead: - -```bash -$ composer run test:unit:fast -``` - -## Generating ZipStream-PHP Documentation - -To generate the documentation for the library, run: - -```bash -$ composer run docs:generate -``` - -The guide documentation pages can be found in the `/guides/` directory. diff --git a/vendor/maennchen/zipstream-php/.github/FUNDING.yml b/vendor/maennchen/zipstream-php/.github/FUNDING.yml deleted file mode 100644 index 5a46127..0000000 --- a/vendor/maennchen/zipstream-php/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: maennchen diff --git a/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/BUG.yml b/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/BUG.yml deleted file mode 100644 index 0eb8cc7..0000000 --- a/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/BUG.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: 🐞 Bug Report -description: Something is broken? -labels: ["bug"] -body: - - type: markdown - attributes: - value: | - - Create a discussion instead if you are looking for support: - https://github.com/maennchen/ZipStream-PHP/discussions - - type: input - id: version - attributes: - label: ZipStream-PHP version - placeholder: x.y.z - validations: - required: true - - type: input - id: php-version - attributes: - label: PHP version - placeholder: x.y.z - validations: - required: true - - type: checkboxes - id: constraints - attributes: - label: Constraints for Bug Report - options: - - label: | - I'm using a version of ZipStream that is currently supported: - https://github.com/maennchen/ZipStream-PHP#version-support - required: true - - label: | - I'm using a version of PHP that has active support: - https://www.php.net/supported-versions.php - required: true - - label: | - I'm using a version of PHP that is compatible with your used - ZipStream version. - required: true - - label: | - I'm using the latest release of the used ZipStream major version. - required: true - - type: textarea - id: summary - attributes: - label: Summary - description: Provide a summary describing the problem you are experiencing. - validations: - required: true - - type: textarea - id: current-behaviour - attributes: - label: Current behavior - description: What is the current (buggy) behavior? - validations: - required: true - - type: textarea - id: reproduction - attributes: - label: How to reproduce - description: Provide steps to reproduce the bug. - validations: - required: true - - type: textarea - id: expected-behaviour - attributes: - label: Expected behavior - description: What was the expected (correct) behavior? - validations: - required: true diff --git a/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/FEATURE.yml b/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/FEATURE.yml deleted file mode 100644 index e5dec63..0000000 --- a/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/FEATURE.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: 🎉 Feature Request -description: You have a neat idea that should be implemented? -labels: ["enhancement"] -body: - - type: textarea - id: description - attributes: - label: Description - description: Provide a summary of the feature you would like to see implemented. - validations: - required: true diff --git a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE.md b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 6892c57..0000000 --- a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,6 +0,0 @@ -Please go the the `Preview` tab and select the appropriate sub-template: - -* [🐞 Failing Test](?expand=1&template=FAILING_TEST.md) -* [🐞 Bug Fix](?expand=1&template=FIX.md) -* [⚙ Improvement](?expand=1&template=IMPROVEMENT.md) -* [🎉 New Feature](?expand=1&template=NEW_FEATURE.md) diff --git a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FAILING_TEST.md b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FAILING_TEST.md deleted file mode 100644 index 24603cb..0000000 --- a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FAILING_TEST.md +++ /dev/null @@ -1,13 +0,0 @@ - - - diff --git a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FIX.md b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FIX.md deleted file mode 100644 index 77f65a0..0000000 --- a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FIX.md +++ /dev/null @@ -1,13 +0,0 @@ - - - diff --git a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/IMPROVEMENT.md b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/IMPROVEMENT.md deleted file mode 100644 index 3ac8e31..0000000 --- a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/IMPROVEMENT.md +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/NEW_FEATURE.md b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/NEW_FEATURE.md deleted file mode 100644 index ca53939..0000000 --- a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/NEW_FEATURE.md +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/vendor/maennchen/zipstream-php/.github/SECURITY.md b/vendor/maennchen/zipstream-php/.github/SECURITY.md deleted file mode 100644 index 3046c31..0000000 --- a/vendor/maennchen/zipstream-php/.github/SECURITY.md +++ /dev/null @@ -1,22 +0,0 @@ -# Security Policy - -[![OpenSSF Vulnerability Disclosure](https://img.shields.io/badge/OpenSSF-Vulnerability_Disclosure-green)](https://github.com/ossf/oss-vulnerability-guide/blob/main/finder-guide.md) -[![GitHub Report](https://img.shields.io/badge/GitHub-Security_Advisories-blue)](https://github.com/maennchen/ZipStream-PHP/security/advisories/new) -[![Email Report](https://img.shields.io/badge/Email-jonatan%40maennchen.ch-blue)](mailto:jonatan@maennchen.ch) - -This repository follows the -[OpenSSF Vulnerability Disclosure guide](https://github.com/ossf/oss-vulnerability-guide/tree/main). -You can learn more about it in the -[Finders Guide](https://github.com/ossf/oss-vulnerability-guide/blob/main/finder-guide.md). - -Please report vulnerabilities via the -[GitHub Security Vulnerability Reporting](https://github.com/maennchen/ZipStream-PHP/security/advisories/new) -or via email to [`jonatan@maennchen.ch`](mailto:jonatan@maennchen.ch) if this does -not work for you. - -Our vulnerability management team will respond within 3 working days of your -report. If the issue is confirmed as a vulnerability, we will open a Security -Advisory. This project follows a 90 day disclosure timeline. - -If you have questions about reporting security issues, email the vulnerability -management team: [`jonatan@maennchen.ch`](mailto:jonatan@maennchen.ch) diff --git a/vendor/maennchen/zipstream-php/.github/dependabot.yml b/vendor/maennchen/zipstream-php/.github/dependabot.yml deleted file mode 100644 index 9d20742..0000000 --- a/vendor/maennchen/zipstream-php/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "composer" - directory: "/" - schedule: - interval: "daily" - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - groups: - github-actions: - applies-to: version-updates - patterns: - - "*" diff --git a/vendor/maennchen/zipstream-php/.github/scorecard.yml b/vendor/maennchen/zipstream-php/.github/scorecard.yml deleted file mode 100644 index 219fc0b..0000000 --- a/vendor/maennchen/zipstream-php/.github/scorecard.yml +++ /dev/null @@ -1,14 +0,0 @@ -annotations: - - checks: - - fuzzing - reasons: - - reason: not-applicable # PHP is memory safe - - checks: - - packaging - reasons: - - reason: not-supported # Using Composer - - checks: - - signed-releases - reasons: - - reason: not-applicable # Releases are distributed via Composer - diff --git a/vendor/maennchen/zipstream-php/.github/workflows/branch_main.yml b/vendor/maennchen/zipstream-php/.github/workflows/branch_main.yml deleted file mode 100644 index 15ff278..0000000 --- a/vendor/maennchen/zipstream-php/.github/workflows/branch_main.yml +++ /dev/null @@ -1,24 +0,0 @@ -on: - push: - branches: - - "main" - -name: "Main Branch" - -permissions: - contents: read - -jobs: - test: - name: "Test" - - permissions: - contents: read - security-events: write - - uses: ./.github/workflows/part_test.yml - - docs: - name: "Docs" - - uses: ./.github/workflows/part_docs.yml diff --git a/vendor/maennchen/zipstream-php/.github/workflows/part_dependabot.yml b/vendor/maennchen/zipstream-php/.github/workflows/part_dependabot.yml deleted file mode 100644 index 20a13a2..0000000 --- a/vendor/maennchen/zipstream-php/.github/workflows/part_dependabot.yml +++ /dev/null @@ -1,30 +0,0 @@ -on: - workflow_call: {} - -name: "Dependabot" - -permissions: - contents: read - -jobs: - automerge_dependabot: - name: "Automerge PRs" - - runs-on: ubuntu-latest - - permissions: - pull-requests: write - contents: write - - steps: - - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 - with: - egress-policy: audit - - - uses: fastify/github-action-merge-dependabot@c3bde0759d4f24db16f7b250b2122bc2df57e817 # v3.11.0 - with: - github-token: ${{ github.token }} - use-github-auto-merge: true - # Major Updates need to be merged manually - target: minor diff --git a/vendor/maennchen/zipstream-php/.github/workflows/part_docs.yml b/vendor/maennchen/zipstream-php/.github/workflows/part_docs.yml deleted file mode 100644 index 9b779eb..0000000 --- a/vendor/maennchen/zipstream-php/.github/workflows/part_docs.yml +++ /dev/null @@ -1,51 +0,0 @@ -on: - workflow_call: {} - -name: "Documentation" - -permissions: - contents: read - -jobs: - generate: - name: "Generate" - - runs-on: ubuntu-latest - - steps: - - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 - with: - egress-policy: audit - - - name: Checkout Code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: SetUp PHP - id: setup-php - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2 - with: - php-version: "8.3" - tools: phive - - name: Cache Tools - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: cache - with: - path: ~/.phive - key: tools-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-${{ hashFiles('**/phars.xml') }} - restore-keys: | - tools-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}- - tools-${{ steps.setup-php.outputs.php-version }}- - tools- - - name: Install Tools - run: composer run install:tools - - name: Generate Docs - run: composer run docs:generate - - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 - with: - name: docs - path: docs - - name: Package for GitHub Pages - uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 - with: - path: docs - diff --git a/vendor/maennchen/zipstream-php/.github/workflows/part_release.yml b/vendor/maennchen/zipstream-php/.github/workflows/part_release.yml deleted file mode 100644 index 112d72a..0000000 --- a/vendor/maennchen/zipstream-php/.github/workflows/part_release.yml +++ /dev/null @@ -1,94 +0,0 @@ -on: - workflow_call: - inputs: - releaseName: - required: true - type: string - stable: - required: false - type: boolean - default: false - -name: "Release" - -permissions: - contents: read - -jobs: - create: - name: Create Release - - runs-on: ubuntu-latest - - permissions: - contents: write - - steps: - - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 - with: - egress-policy: audit - - - name: Create prerelease - if: ${{ !inputs.stable }} - env: - GITHUB_TOKEN: ${{ github.token }} - run: | - gh release create \ - --repo ${{ github.repository }} \ - --title ${{ inputs.releaseName }} \ - --prerelease \ - --generate-notes \ - ${{ inputs.releaseName }} - - - name: Create release - if: ${{ inputs.stable }} - env: - GITHUB_TOKEN: ${{ github.token }} - run: | - gh release create \ - --repo ${{ github.repository }} \ - --title ${{ inputs.releaseName }} \ - --generate-notes \ - ${{ inputs.releaseName }} - - upload_release: - name: "Upload" - - needs: ["create"] - - runs-on: ubuntu-latest - - permissions: - id-token: write - contents: write - attestations: write - - steps: - - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 - with: - egress-policy: audit - - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - name: docs - path: docs - - run: | - tar -czvf docs.tar.gz docs - - name: "Attest Documentation" - id: attestation - uses: actions/attest-build-provenance@520d128f165991a6c774bcb264f323e3d70747f4 # v2.2.0 - with: - subject-path: "docs.tar.gz" - - name: Copy Attestation - run: cp "$ATTESTATION" docs.tar.gz.sigstore - env: - ATTESTATION: "${{ steps.attestation.outputs.bundle-path }}" - - name: Upload - env: - GITHUB_TOKEN: ${{ github.token }} - run: | - gh release upload --clobber "${{ github.ref_name }}" \ - docs.tar.gz docs.tar.gz.sigstore diff --git a/vendor/maennchen/zipstream-php/.github/workflows/part_test.yml b/vendor/maennchen/zipstream-php/.github/workflows/part_test.yml deleted file mode 100644 index d4f8180..0000000 --- a/vendor/maennchen/zipstream-php/.github/workflows/part_test.yml +++ /dev/null @@ -1,181 +0,0 @@ -on: - workflow_call: - -name: "Test" - -permissions: - contents: read - -jobs: - phpunit: - name: PHPUnit (PHP ${{ matrix.php }} on ${{ matrix.os }}) - - runs-on: ${{ matrix.os }} - - continue-on-error: ${{ matrix.experimental }} - - strategy: - fail-fast: false - matrix: - php: ["8.2", "8.3", "8.4"] - os: [ubuntu-latest] - experimental: [false] - include: - - php: nightly - os: ubuntu-latest - experimental: true - - php: "8.4" - os: windows-latest - experimental: false - - php: "8.4" - os: macos-latest - experimental: false - - steps: - - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 - with: - egress-policy: audit - - - name: Checkout Code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: SetUp PHP - id: setup-php - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2 - with: - php-version: "${{ matrix.php }}" - tools: phpunit - coverage: xdebug - extensions: xdebug,zip - - name: Get composer cache directory - id: composer-cache-common - if: "${{ runner.os != 'Windows' }}" - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: Get composer cache directory - id: composer-cache-windows - if: "${{ runner.os == 'Windows' }}" - run: echo "dir=$(composer config cache-files-dir)" >> $env:GITHUB_OUTPUT - - name: Cache Deps - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: cache - with: - path: ${{ steps.composer-cache-common.outputs.dir }}${{ steps.composer-cache-windows.outputs.dir }} - key: deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer- - deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}- - deps-${{ steps.setup-php.outputs.php-version }}- - deps- - - name: Install Deps - if: matrix.php != 'nightly' - run: composer install --prefer-dist - - name: Install Deps (ignore PHP requirement) - if: matrix.php == 'nightly' - run: composer install --prefer-dist --ignore-platform-req=php+ - - name: Run PHPUnit - run: composer run test:unit:cov - - name: Upload coverage results to Coveralls - env: - COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COVERALLS_PARALLEL: true - COVERALLS_FLAG_NAME: ${{ runner.os }}-${{ steps.setup-php.outputs.php-version }} - run: composer run coverage:report - continue-on-error: ${{ matrix.experimental }} - - mark_coverage_done: - needs: ["phpunit"] - - runs-on: ubuntu-latest - - steps: - - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 - with: - egress-policy: audit - - - name: Coveralls Finished - uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b # v2.3.6 - with: - github-token: ${{ secrets.github_token }} - parallel-finished: true - - psalm: - name: Run Psalm - - runs-on: "ubuntu-latest" - - permissions: - security-events: write - - steps: - - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 - with: - egress-policy: audit - - - name: Checkout Code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: SetUp PHP - id: setup-php - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2 - with: - php-version: "8.3" - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: Cache Deps - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: cache - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer- - deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}- - deps-${{ steps.setup-php.outputs.php-version }}- - deps- - - name: Install Deps - run: composer install --prefer-dist - - name: Run Psalm - run: composer run test:lint -- --report=results.sarif - - name: "Upload SARIF" - uses: github/codeql-action/upload-sarif@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3 - with: - sarif_file: results.sarif - - php-cs: - name: Run PHP-CS - - runs-on: "ubuntu-latest" - - steps: - - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 - with: - egress-policy: audit - - - name: Checkout Code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: SetUp PHP - id: setup-php - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2 - with: - php-version: "8.3" - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: Cache Deps - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - id: cache - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer- - deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}- - deps-${{ steps.setup-php.outputs.php-version }}- - deps- - - name: Install Deps - run: composer install --prefer-dist - - name: Run PHP-CS - run: composer run test:formatted diff --git a/vendor/maennchen/zipstream-php/.github/workflows/pr.yml b/vendor/maennchen/zipstream-php/.github/workflows/pr.yml deleted file mode 100644 index d21f398..0000000 --- a/vendor/maennchen/zipstream-php/.github/workflows/pr.yml +++ /dev/null @@ -1,50 +0,0 @@ -on: - pull_request: - branches: - - "*" - workflow_dispatch: {} - -name: "Pull Request" - -permissions: - contents: read - -jobs: - test: - name: "Test" - - permissions: - contents: read - security-events: write - - uses: ./.github/workflows/part_test.yml - - docs: - name: "Docs" - - uses: ./.github/workflows/part_docs.yml - - dependabot: - name: "Dependabot" - - if: ${{ github.actor == 'dependabot[bot]'}} - - permissions: - pull-requests: write - contents: write - - uses: ./.github/workflows/part_dependabot.yml - - dependency-review: - name: Dependency Review - runs-on: ubuntu-latest - steps: - - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 - with: - egress-policy: audit - - - name: 'Checkout Repository' - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: 'Dependency Review' - uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 diff --git a/vendor/maennchen/zipstream-php/.github/workflows/scorecard.yml b/vendor/maennchen/zipstream-php/.github/workflows/scorecard.yml deleted file mode 100644 index c1d08a2..0000000 --- a/vendor/maennchen/zipstream-php/.github/workflows/scorecard.yml +++ /dev/null @@ -1,78 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. They are provided -# by a third-party and are governed by separate terms of service, privacy -# policy, and support documentation. - -name: Scorecard supply-chain security -on: - # For Branch-Protection check. Only the default branch is supported. See - # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection - branch_protection_rule: - # To guarantee Maintained check is occasionally updated. See - # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained - schedule: - - cron: '28 11 * * 3' - push: - branches: [ "main" ] - -# Declare default permissions as read only. -permissions: read-all - -jobs: - analysis: - name: Scorecard analysis - runs-on: ubuntu-latest - permissions: - # Needed to upload the results to code-scanning dashboard. - security-events: write - # Needed to publish results and get a badge (see publish_results below). - id-token: write - # Uncomment the permissions below if installing in a private repository. - # contents: read - # actions: read - - steps: - - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 - with: - egress-policy: audit - - - name: "Checkout code" - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - - - name: "Run analysis" - uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 - with: - results_file: results.sarif - results_format: sarif - # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: - # - you want to enable the Branch-Protection check on a *public* repository, or - # - you are installing Scorecard on a *private* repository - # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. - # repo_token: ${{ secrets.SCORECARD_TOKEN }} - - # Public repositories: - # - Publish results to OpenSSF REST API for easy access by consumers - # - Allows the repository to include the Scorecard badge. - # - See https://github.com/ossf/scorecard-action#publishing-results. - # For private repositories: - # - `publish_results` will always be set to `false`, regardless - # of the value entered here. - publish_results: true - - # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF - # format to the repository Actions tab. - - name: "Upload artifact" - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 - with: - name: SARIF file - path: results.sarif - retention-days: 5 - - # Upload the results to GitHub's code scanning dashboard (optional). - # Commenting out will disable upload of results to your repo's Code Scanning dashboard - - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5 - with: - sarif_file: results.sarif diff --git a/vendor/maennchen/zipstream-php/.github/workflows/tag-beta.yml b/vendor/maennchen/zipstream-php/.github/workflows/tag-beta.yml deleted file mode 100644 index b339945..0000000 --- a/vendor/maennchen/zipstream-php/.github/workflows/tag-beta.yml +++ /dev/null @@ -1,29 +0,0 @@ -on: - push: - tags: - - "[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+" - -name: "Beta Tag" - -permissions: - contents: read - -jobs: - docs: - name: "Docs" - - uses: ./.github/workflows/part_docs.yml - - release: - name: "Release" - - needs: ["docs"] - - permissions: - id-token: write - contents: write - attestations: write - - uses: ./.github/workflows/part_release.yml - with: - releaseName: "${{ github.ref_name }}" diff --git a/vendor/maennchen/zipstream-php/.github/workflows/tag-stable.yml b/vendor/maennchen/zipstream-php/.github/workflows/tag-stable.yml deleted file mode 100644 index dfc1438..0000000 --- a/vendor/maennchen/zipstream-php/.github/workflows/tag-stable.yml +++ /dev/null @@ -1,55 +0,0 @@ -on: - push: - tags: - - "[0-9]+.[0-9]+.[0-9]+" - -name: "Stable Tag" - -permissions: - contents: read - -jobs: - docs: - name: "Docs" - - uses: ./.github/workflows/part_docs.yml - - release: - name: "Release" - - needs: ["docs"] - - permissions: - id-token: write - contents: write - attestations: write - - uses: ./.github/workflows/part_release.yml - with: - releaseName: "${{ github.ref_name }}" - stable: true - - deploy_pages: - name: "Deploy to GitHub Pages" - - needs: ["release", "docs"] - - runs-on: ubuntu-latest - - permissions: - pages: write - id-token: write - - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - - steps: - - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 - with: - egress-policy: audit - - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/vendor/maennchen/zipstream-php/.gitignore b/vendor/maennchen/zipstream-php/.gitignore deleted file mode 100644 index e52a498..0000000 --- a/vendor/maennchen/zipstream-php/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -/composer.lock -/cov -/coverage.clover.xml -/docs -.idea -/.php-cs-fixer.cache -/.phpdoc/cache -/.phpunit.result.cache -/phpunit.xml -/.phpunit.cache -/tools -/vendor diff --git a/vendor/maennchen/zipstream-php/.phive/phars.xml b/vendor/maennchen/zipstream-php/.phive/phars.xml index c958402..569106a 100644 --- a/vendor/maennchen/zipstream-php/.phive/phars.xml +++ b/vendor/maennchen/zipstream-php/.phive/phars.xml @@ -1,4 +1,4 @@ - + diff --git a/vendor/maennchen/zipstream-php/.php-cs-fixer.dist.php b/vendor/maennchen/zipstream-php/.php-cs-fixer.dist.php index 9d47c38..3ba86a4 100644 --- a/vendor/maennchen/zipstream-php/.php-cs-fixer.dist.php +++ b/vendor/maennchen/zipstream-php/.php-cs-fixer.dist.php @@ -13,7 +13,6 @@ declare(strict_types=1); use PhpCsFixer\Config; use PhpCsFixer\Finder; -use PhpCsFixer\Runner; $finder = Finder::create() ->exclude('.github') @@ -27,8 +26,7 @@ $config = new Config(); return $config->setRules([ '@PER' => true, '@PER:risky' => true, - '@PHP83Migration' => true, - '@PHP84Migration' => true, + '@PHP81Migration' => true, '@PHPUnit84Migration:risky' => true, 'array_syntax' => ['syntax' => 'short'], 'class_attributes_separation' => true, @@ -52,6 +50,7 @@ return $config->setRules([ 'semicolon_after_instruction' => true, 'short_scalar_cast' => true, 'simplified_null_return' => true, + 'single_blank_line_before_namespace' => true, 'single_class_element_per_statement' => true, 'single_line_comment_style' => true, 'single_quote' => true, @@ -69,5 +68,4 @@ return $config->setRules([ ], ]) ->setFinder($finder) - ->setRiskyAllowed(true) - ->setParallelConfig(Runner\Parallel\ParallelConfigFactory::detect()); + ->setRiskyAllowed(true); \ No newline at end of file diff --git a/vendor/maennchen/zipstream-php/.phpdoc/template/base.html.twig b/vendor/maennchen/zipstream-php/.phpdoc/template/base.html.twig index 2a70c0a..b7507fb 100644 --- a/vendor/maennchen/zipstream-php/.phpdoc/template/base.html.twig +++ b/vendor/maennchen/zipstream-php/.phpdoc/template/base.html.twig @@ -9,7 +9,7 @@ "social": [ { "iconClass": "fab fa-github", "url": "https://github.com/maennchen/ZipStream-PHP"}, { "iconClass": "fas fa-envelope-open-text", "url": "https://github.com/maennchen/ZipStream-PHP/discussions"}, - { "iconClass": "fas fa-money-bill", "url": "https://github.com/sponsors/maennchen"}, + { "iconClass": "fas fa-money-bill", "url": "https://opencollective.com/zipstream"}, ] } %} \ No newline at end of file diff --git a/vendor/maennchen/zipstream-php/.tool-versions b/vendor/maennchen/zipstream-php/.tool-versions index 150c1ee..54f6ff0 100644 --- a/vendor/maennchen/zipstream-php/.tool-versions +++ b/vendor/maennchen/zipstream-php/.tool-versions @@ -1 +1 @@ -php 8.4.3 +php 8.2.0 diff --git a/vendor/maennchen/zipstream-php/README.md b/vendor/maennchen/zipstream-php/README.md index 1e6d679..155a265 100644 --- a/vendor/maennchen/zipstream-php/README.md +++ b/vendor/maennchen/zipstream-php/README.md @@ -4,8 +4,7 @@ [![Coverage Status](https://coveralls.io/repos/github/maennchen/ZipStream-PHP/badge.svg?branch=main)](https://coveralls.io/github/maennchen/ZipStream-PHP?branch=main) [![Latest Stable Version](https://poser.pugx.org/maennchen/zipstream-php/v/stable)](https://packagist.org/packages/maennchen/zipstream-php) [![Total Downloads](https://poser.pugx.org/maennchen/zipstream-php/downloads)](https://packagist.org/packages/maennchen/zipstream-php) -[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9524/badge)](https://www.bestpractices.dev/projects/9524) -[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/maennchen/ZipStream-PHP/badge)](https://scorecard.dev/viewer/?uri=github.com/maennchen/ZipStream-PHP) +[![Financial Contributors on Open Collective](https://opencollective.com/zipstream/all/badge.svg?label=financial+contributors)](https://opencollective.com/zipstream) [![License](https://img.shields.io/github/license/maennchen/zipstream-php.svg)](LICENSE) ## Unstable Branch @@ -15,17 +14,13 @@ version. ## Overview -A fast and simple streaming zip file downloader for PHP. Using this library will -save you from having to write the Zip to disk. You can directly send it to the -user, which is much faster. It can work with S3 buckets or any PSR7 Stream. +A fast and simple streaming zip file downloader for PHP. Using this library will save you from having to write the Zip to disk. You can directly send it to the user, which is much faster. It can work with S3 buckets or any PSR7 Stream. Please see the [LICENSE](LICENSE) file for licensing and warranty information. ## Installation -Simply add a dependency on maennchen/zipstream-php to your project's -`composer.json` file if you use Composer to manage the dependencies of your -project. Use following command to add the package to your project's dependencies: +Simply add a dependency on maennchen/zipstream-php to your project's composer.json file if you use Composer to manage the dependencies of your project. Use following command to add the package to your project's dependencies: ```bash composer require maennchen/zipstream-php @@ -34,120 +29,51 @@ composer require maennchen/zipstream-php ## Usage For detailed instructions, please check the -[Documentation](https://maennchen.github.io/ZipStream-PHP/). +[Documentation](https://maennchen.dev/ZipStream-PHP/). + +Here's a simple example: ```php // Autoload the dependencies require 'vendor/autoload.php'; -// create a new zipstream object -$zip = new ZipStream\ZipStream( - outputName: 'example.zip', +// enable output of HTTP headers +$options = new ZipStream\Option\Archive(); +$options->setSendHttpHeaders(true); - // enable output of HTTP headers - sendHttpHeaders: true, -); +// create a new zipstream object +$zip = new ZipStream\ZipStream('example.zip', $options); // create a file named 'hello.txt' -$zip->addFile( - fileName: 'hello.txt', - data: 'This is the contents of hello.txt', -); +$zip->addFile('hello.txt', 'This is the contents of hello.txt'); // add a file named 'some_image.jpg' from a local file 'path/to/image.jpg' -$zip->addFileFromPath( - fileName: 'some_image.jpg', - path: 'path/to/image.jpg', -); +$zip->addFileFromPath('some_image.jpg', 'path/to/image.jpg'); // finish the zip stream $zip->finish(); ``` -## Upgrade to version 3.1.2 - -- Minimum PHP Version: `8.2` - -## Upgrade to version 3.0.0 - -### General - -- Minimum PHP Version: `8.1` -- Only 64bit Architecture is supported. -- The class `ZipStream\Option\Method` has been replaced with the enum - `ZipStream\CompressionMethod`. -- Most clases have been flagged as `@internal` and should not be used from the - outside. - If you're using internal resources to extend this library, please open an - issue so that a clean interface can be added & published. - The externally available classes & enums are: - - `ZipStream\CompressionMethod` - - `ZipStream\Exception*` - - `ZipStream\ZipStream` - -### Archive Options - -- The class `ZipStream\Option\Archive` has been replaced in favor of named - arguments in the `ZipStream\ZipStream` constuctor. -- The archive options `largeFileSize` & `largeFileMethod` has been removed. If - you want different `compressionMethods` based on the file size, you'll have to - implement this yourself. -- The archive option `httpHeaderCallback` changed the type from `callable` to - `Closure`. -- The archive option `zeroHeader` has been replaced with the option - `defaultEnableZeroHeader` and can be overridden for every file. Its default - value changed from `false` to `true`. -- The archive option `statFiles` was removed since the library no longer checks - filesizes this way. -- The archive option `deflateLevel` has been replaced with the option - `defaultDeflateLevel` and can be overridden for every file. -- The first argument (`name`) of the `ZipStream\ZipStream` constuctor has been - replaced with the named argument `outputName`. -- Headers are now also sent if the `outputName` is empty. If you do not want to - automatically send http headers, set `sendHttpHeaders` to `false`. - -### File Options - -- The class `ZipStream\Option\File` has been replaced in favor of named - arguments in the `ZipStream\ZipStream->addFile*` functions. -- The file option `method` has been renamed to `compressionMethod`. -- The file option `time` has been renamed to `lastModificationDateTime`. -- The file option `size` has been renamed to `maxSize`. - ## Upgrade to version 2.0.0 -https://github.com/maennchen/ZipStream-PHP/tree/2.0.0#upgrade-to-version-200 +- Only the self opened streams will be closed (#139) + If you were relying on ZipStream to close streams that the library didn't open, + you'll need to close them yourself now. ## Upgrade to version 1.0.0 -https://github.com/maennchen/ZipStream-PHP/tree/2.0.0#upgrade-to-version-100 +- All options parameters to all function have been moved from an `array` to structured option objects. See [the wiki](https://github.com/maennchen/ZipStream-PHP/wiki/Available-options) for examples. +- The whole library has been refactored. The minimal PHP requirement has been raised to PHP 7.1. + +## Usage with Symfony and S3 + +You can find example code on [the wiki](https://github.com/maennchen/ZipStream-PHP/wiki/Symfony-example). ## Contributing ZipStream-PHP is a collaborative project. Please take a look at the [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) file. -## Version Support - -Versions are supported according to the table below. - -Please do not open any pull requests contradicting the current version support -status. - -Careful: Always check the `README` on `main` for up-to-date information. - -| Version | New Features | Bugfixes | Security | -|---------|--------------|----------|----------| -| *3* | ✓ | ✓ | ✓ | -| *2* | ✗ | ✗ | ✓ | -| *1* | ✗ | ✗ | ✗ | -| *0* | ✗ | ✗ | ✗ | - -This library aligns itself with the PHP core support. New features and bugfixes -will only target PHP versions according to their current status. - -See: https://www.php.net/supported-versions.php - ## About the Authors - Paul Duncan - https://pablotron.org/ @@ -155,3 +81,34 @@ See: https://www.php.net/supported-versions.php - Jesse G. Donat - https://donatstudios.com - Nicolas CARPi - https://www.deltablot.com - Nik Barham - https://www.brokencube.co.uk + +## Contributors + +### Code Contributors + +This project exists thanks to all the people who contribute. +[[Contribute](.github/CONTRIBUTING.md)]. + + +### Financial Contributors + +Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/zipstream/contribute)] + +#### Individuals + + + +#### Organizations + +Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/zipstream/contribute)] + + + + + + + + + + + diff --git a/vendor/maennchen/zipstream-php/composer.json b/vendor/maennchen/zipstream-php/composer.json index 6ecd503..2746da1 100644 --- a/vendor/maennchen/zipstream-php/composer.json +++ b/vendor/maennchen/zipstream-php/composer.json @@ -22,42 +22,28 @@ } ], "require": { - "php-64bit": "^8.2", + "php": "^8.0", "ext-mbstring": "*", - "ext-zlib": "*" + "psr/http-message": "^1.0", + "myclabs/php-enum": "^1.5" }, "require-dev": { - "phpunit/phpunit": "^11.0", - "guzzlehttp/guzzle": "^7.5", + "phpunit/phpunit": "^8.5.8 || ^9.4.2", + "guzzlehttp/guzzle": "^6.5.3 || ^7.2.0", "ext-zip": "*", "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.5", - "friendsofphp/php-cs-fixer": "^3.16", - "vimeo/psalm": "^6.0", - "brianium/paratest": "^7.7" - }, - "suggest": { - "psr/http-message": "^2.0", - "guzzlehttp/psr7": "^2.4" + "vimeo/psalm": "^5.0", + "php-coveralls/php-coveralls": "^2.4", + "friendsofphp/php-cs-fixer": "^3.9" }, "scripts": { - "format": "php-cs-fixer fix", - "test": [ - "@test:unit", - "@test:formatted", - "@test:lint" - ], - "test:unit:setup-cov": "@putenv XDEBUG_MODE=coverage", - "test:unit": "paratest --functional", - "test:unit:cov": ["@test:unit:setup-cov", "@test:unit --coverage-clover=coverage.clover.xml --coverage-html cov"], - "test:unit:slow": "@test:unit --group slow", - "test:unit:slow:cov": ["@test:unit:setup-cov", "@test:unit --coverage-clover=coverage.clover.xml --coverage-html cov --group slow"], - "test:unit:fast": "@test:unit --exclude-group slow", - "test:unit:fast:cov": ["@test:unit:setup-cov", "@test:unit --coverage-clover=coverage.clover.xml --coverage-html cov --exclude-group slow"], - "test:formatted": "@format --dry-run --stop-on-violation --using-cache=no", - "test:lint": "psalm --stats --show-info=true --find-unused-psalm-suppress", + "format": "PHP_CS_FIXER_IGNORE_ENV=true php-cs-fixer fix", + "test": "composer run test:unit && composer run test:formatted && composer run test:lint", + "test:unit": "phpunit --coverage-clover=coverage.clover.xml --coverage-html cov", + "test:formatted": "composer run format -- --dry-run --stop-on-violation --using-cache=no", + "test:lint": "psalm --stats --show-info --find-unused-psalm-suppress", "coverage:report": "php-coveralls --coverage_clover=coverage.clover.xml --json_path=coveralls-upload.json --insecure", - "install:tools": "phive install --trust-gpg-keys 0x67F861C3D889C656 --trust-gpg-keys 0x8AC0BAA79732DD42", + "install:tools": "phive install --trust-gpg-keys 0x67F861C3D889C656", "docs:generate": "tools/phpdocumentor --sourcecode" }, "autoload": { @@ -65,9 +51,6 @@ "ZipStream\\": "src/" } }, - "autoload-dev": { - "psr-4": { "ZipStream\\Test\\": "test/" } - }, "archive": { "exclude": [ "/composer.lock", diff --git a/vendor/maennchen/zipstream-php/guides/ContentLength.rst b/vendor/maennchen/zipstream-php/guides/ContentLength.rst index 21fea34..e51e692 100644 --- a/vendor/maennchen/zipstream-php/guides/ContentLength.rst +++ b/vendor/maennchen/zipstream-php/guides/ContentLength.rst @@ -1,47 +1,79 @@ Adding Content-Length header ============= -Adding a ``Content-Length`` header for ``ZipStream`` can be achieved by -using the options ``SIMULATION_STRICT`` or ``SIMULATION_LAX`` in the -``operationMode`` parameter. +Adding a ``Content-Length`` header for ``ZipStream`` is not trivial since the +size is not known beforehand. -In the ``SIMULATION_STRICT`` mode, ``ZipStream`` will not allow to calculate the -size based on reading the whole file. ``SIMULATION_LAX`` will read the whole -file if neccessary. - -``SIMULATION_STRICT`` is therefore useful to make sure that the size can be -calculated efficiently. +The following workaround adds an approximated header: .. code-block:: php - use ZipStream\OperationMode; - use ZipStream\ZipStream; - $zip = new ZipStream( - operationMode: OperationMode::SIMULATE_STRICT, // or SIMULATE_LAX - defaultEnableZeroHeader: false, - sendHttpHeaders: true, - outputStream: $stream, - ); + class Zip + { + /** @var string */ + private $name; - // Normally add files - $zip->addFile('sample.txt', 'Sample String Data'); + private $files = []; - // Use addFileFromCallback and exactSize if you want to defer opening of - // the file resource - $zip->addFileFromCallback( - 'sample.txt', - exactSize: 18, - callback: function () { - return fopen('...'); + public function __construct($name) + { + $this->name = $name; } - ); - // Read resulting file size - $size = $zip->finish(); - - // Tell it to the browser - header('Content-Length: '. $size); - - // Execute the Simulation and stream the actual zip to the client - $zip->executeSimulation(); + public function addFile($name, $data) + { + $this->files[] = ['type' => 'addFile', 'name' => $name, 'data' => $data]; + } + public function addFileFromPath($name, $path) + { + $this->files[] = ['type' => 'addFileFromPath', 'name' => $name, 'path' => $path]; + } + + public function getEstimate() + { + $estimate = 22; + foreach ($this->files as $file) { + $estimate += 76 + 2 * strlen($file['name']); + if ($file['type'] === 'addFile') { + $estimate += strlen($file['data']); + } + if ($file['type'] === 'addFileFromPath') { + $estimate += filesize($file['path']); + } + } + return $estimate; + } + + public function finish() + { + header('Content-Length: ' . $this->getEstimate()); + $options = new \ZipStream\Option\Archive(); + $options->setSendHttpHeaders(true); + $options->setEnableZip64(false); + $options->setDeflateLevel(-1); + $zip = new \ZipStream\ZipStream($this->name, $options); + + $fileOptions = new \ZipStream\Option\File(); + $fileOptions->setMethod(\ZipStream\Option\Method::STORE()); + foreach ($this->files as $file) { + if ($file['type'] === 'addFile') { + $zip->addFile($file['name'], $file['data'], $fileOptions); + } + if ($file['type'] === 'addFileFromPath') { + $zip->addFileFromPath($file['name'], $file['path'], $fileOptions); + } + } + $zip->finish(); + exit; + } + } + +It only works with the following constraints: + +- All file content is known beforehand. +- Content Deflation is disabled + +Thanks to +`partiellkorrekt `_ +for this workaround. \ No newline at end of file diff --git a/vendor/maennchen/zipstream-php/guides/FlySystem.rst b/vendor/maennchen/zipstream-php/guides/FlySystem.rst index 4e6c6fb..0243f24 100644 --- a/vendor/maennchen/zipstream-php/guides/FlySystem.rst +++ b/vendor/maennchen/zipstream-php/guides/FlySystem.rst @@ -14,21 +14,20 @@ default one, and pass it to Flysystem ``putStream`` method. // the content is lost when closing the stream / opening another one $tempStream = fopen('php://memory', 'w+'); + // Init Options + $zipStreamOptions = new Archive(); + $zipStreamOptions->setOutputStream($tempStream); + // Create Zip Archive - $zipStream = new ZipStream( - outputStream: $tempStream, - outputName: 'test.zip', - ); + $zipStream = new ZipStream('test.zip', $zipStreamOptions); $zipStream->addFile('test.txt', 'text'); $zipStream->finish(); - // Store File - // (see Flysystem documentation, and all its framework integration) - // Can be any adapter (AWS, Google, Ftp, etc.) - $adapter = new Local(__DIR__.'/path/to/folder'); + // Store File (see Flysystem documentation, and all its framework integration) + $adapter = new Local(__DIR__.'/path/to/folder'); // Can be any adapter (AWS, Google, Ftp, etc.) $filesystem = new Filesystem($adapter); - $filesystem->writeStream('test.zip', $tempStream) + $filesystem->putStream('test.zip', $tempStream) // Close Stream - fclose($tempStream); + fclose($tempStream); \ No newline at end of file diff --git a/vendor/maennchen/zipstream-php/guides/Options.rst b/vendor/maennchen/zipstream-php/guides/Options.rst index 5e92e94..eabaa6f 100644 --- a/vendor/maennchen/zipstream-php/guides/Options.rst +++ b/vendor/maennchen/zipstream-php/guides/Options.rst @@ -2,65 +2,60 @@ Available options =============== Here is the full list of options available to you. You can also have a look at -``src/ZipStream.php`` file. +``src/Option/Archive.php`` file. + +First, an instance of ``ZipStream\Option\Archive`` needs to be created, and +after that you use setters methods to modify the values. .. code-block:: php - use ZipStream\ZipStream; + use ZipStream\Option\Archive as ArchiveOptions; require_once 'vendor/autoload.php'; - $zip = new ZipStream( - // Define output stream - // (argument is eiter a resource or implementing - // `Psr\Http\Message\StreamInterface`) - // - // Setup with `psr/http-message` & `guzzlehttp/psr7` dependencies - // required when using `Psr\Http\Message\StreamInterface`. - outputStream: $filePointer, + $opt = new ArchiveOptions(); - // Set the deflate level (default is 6; use -1 to disable it) - defaultDeflateLevel: 6, + // Define output stream (argument is of type resource) + $opt->setOutputStream($fd); - // Add a comment to the zip file - comment: 'This is a comment.', + // Set the deflate level (default is 6; use -1 to disable it) + $opt->setDeflateLevel(6); - // Send http headers (default is true) - sendHttpHeaders: false, + // Add a comment to the zip file + $opt->setComment('This is a comment.'); - // HTTP Content-Disposition. - // Defaults to 'attachment', where FILENAME is the specified filename. - // Note that this does nothing if you are not sending HTTP headers. - contentDisposition: 'attachment', + // Size, in bytes, of the largest file to try and load into memory (used by addFileFromPath()). Large files may also be compressed differently; see the 'largeFileMethod' option. + $opt->setLargeFileSize(30000000); - // Output Name for HTTP Content-Disposition - // Defaults to no name - outputName: "example.zip", + // How to handle large files. Legal values are STORE (the default), or DEFLATE. Store sends the file raw and is significantly faster, while DEFLATE compresses the file and is much, much slower. Note that deflate must compress the file twice and is extremely slow. + $opt->setLargeFileMethod(ZipStream\Option\Method::STORE()); + $opt->setLargeFileMethod(ZipStream\Option\Method::DEFLATE()); - // HTTP Content-Type. - // Defaults to 'application/x-zip'. - // Note that this does nothing if you are not sending HTTP headers. - contentType: 'application/x-zip', + // Send http headers (default is false) + $opt->setSendHttpHeaders(false); - // Set the function called for setting headers. - // Default is the `header()` of PHP - httpHeaderCallback: header(...), + // HTTP Content-Disposition. Defaults to 'attachment', where FILENAME is the specified filename. Note that this does nothing if you are not sending HTTP headers. + $opt->setContentDisposition('attachment'); - // Enable streaming files with single read where general purpose bit 3 - // indicates local file header contain zero values in crc and size - // fields, these appear only after file contents in data descriptor - // block. - // Set to true if your input stream is remote - // (used with addFileFromStream()). - // Default is false. - defaultEnableZeroHeader: false, + // Set the content type (does nothing if you are not sending HTTP headers) + $opt->setContentType('application/x-zip'); - // Enable zip64 extension, allowing very large archives - // (> 4Gb or file count > 64k) - // Default is true - enableZip64: true, + // Set the function called for setting headers. Default is the `header()` of PHP + $opt->setHttpHeaderCallback('header'); - // Flush output buffer after every write - // Default is false - flushOutput: true, - ); + // Enable streaming files with single read where general purpose bit 3 indicates local file header contain zero values in crc and size fields, these appear only after file contents in data descriptor block. Default is false. Set to true if your input stream is remote (used with addFileFromStream()). + $opt->setZeroHeader(false); + + // Enable reading file stat for determining file size. When a 32-bit system reads file size that is over 2 GB, invalid value appears in file size due to integer overflow. Should be disabled on 32-bit systems with method addFileFromPath if any file may exceed 2 GB. In this case file will be read in blocks and correct size will be determined from content. Default is true. + $opt->setStatFiles(true); + + // Enable zip64 extension, allowing very large archives (> 4Gb or file count > 64k) + // default is true + $opt->setEnableZip64(true); + + // Flush output buffer after every write + // default is false + $opt->setFlushOutput(true); + + // Now that everything is set you can pass the options to the ZipStream instance + $zip = new ZipStream('example.zip', $opt); diff --git a/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst b/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst index 22af71d..4b4ca4b 100644 --- a/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst +++ b/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst @@ -12,10 +12,7 @@ Example --------------- .. code-block:: php - + $stream = $response->getBody(); // add a file named 'streamfile.txt' from the content of the stream - $zip->addFileFromPsr7Stream( - fileName: 'streamfile.txt', - stream: $stream, - ); + $zip->addFileFromPsr7Stream('streamfile.txt', $stream); diff --git a/vendor/maennchen/zipstream-php/guides/StreamOutput.rst b/vendor/maennchen/zipstream-php/guides/StreamOutput.rst index 9f3165b..1a0495f 100644 --- a/vendor/maennchen/zipstream-php/guides/StreamOutput.rst +++ b/vendor/maennchen/zipstream-php/guides/StreamOutput.rst @@ -5,9 +5,9 @@ Stream to S3 Bucket --------------- .. code-block:: php - use Aws\S3\S3Client; use Aws\Credentials\CredentialProvider; + use ZipStream\Option\Archive; use ZipStream\ZipStream; $bucket = 'your bucket name'; @@ -21,19 +21,13 @@ Stream to S3 Bucket $zipFile = fopen("s3://$bucket/example.zip", 'w'); - $zip = new ZipStream( - enableZip64: false, - outputStream: $zipFile, - ); + $options = new Archive(); + $options->setEnableZip64(false); + $options->setOutputStream($zipFile); - $zip->addFile( - fileName: 'file1.txt', - data: 'File1 data', - ); - $zip->addFile( - fileName: 'file2.txt', - data: 'File2 data', - ); + $zip = new ZipStream(null, $options); + $zip->addFile('file1.txt', 'File1 data'); + $zip->addFile('file2.txt', 'File2 data'); $zip->finish(); - fclose($zipFile); + fclose($zipFile); \ No newline at end of file diff --git a/vendor/maennchen/zipstream-php/guides/Symfony.rst b/vendor/maennchen/zipstream-php/guides/Symfony.rst index 902552c..18f9059 100644 --- a/vendor/maennchen/zipstream-php/guides/Symfony.rst +++ b/vendor/maennchen/zipstream-php/guides/Symfony.rst @@ -31,7 +31,7 @@ stored in an AWS S3 bucket by key: */ public function zipStreamAction() { - // sample test file on s3 + //sample test file on s3 $s3keys = array( "ziptestfolder/file1.txt" ); @@ -39,18 +39,18 @@ stored in an AWS S3 bucket by key: $s3Client = $this->get('app.amazon.s3'); //s3client service $s3Client->registerStreamWrapper(); //required - // using StreamedResponse to wrap ZipStream functionality - // for files on AWS s3. + //using StreamedResponse to wrap ZipStream functionality for files on AWS s3. $response = new StreamedResponse(function() use($s3keys, $s3Client) { // Define suitable options for ZipStream Archive. + $options = new \ZipStream\Option\Archive(); + $options->setContentType('application/octet-stream'); // this is needed to prevent issues with truncated zip files + $options->setZeroHeader(true); + $options->setComment('test zip file.'); + //initialise zipstream with output zip filename and options. - $zip = new ZipStream\ZipStream( - outputName: 'test.zip', - defaultEnableZeroHeader: true, - contentType: 'application/octet-stream', - ); + $zip = new ZipStream\ZipStream('test.zip', $options); //loop keys - useful for multiple files foreach ($s3keys as $key) { @@ -58,19 +58,15 @@ stored in an AWS S3 bucket by key: //file using the same name. $fileName = basename($key); - // concatenate s3path. - // replace with your bucket name or get from parameters file. - $bucket = 'bucketname'; + //concatenate s3path. + $bucket = 'bucketname'; //replace with your bucket name or get from parameters file. $s3path = "s3://" . $bucket . "/" . $key; //addFileFromStream if ($streamRead = fopen($s3path, 'r')) { - $zip->addFileFromStream( - fileName: $fileName, - stream: $streamRead, - ); + $zip->addFileFromStream($fileName, $streamRead); } else { - die('Could not open stream for reading'); + die('Could not open stream for reading'); } } @@ -127,4 +123,4 @@ You need to add correct permissions 's3' => ['ACL' => 'public-read'], ]); - fopen($path, 'w', null, $outputContext); + fopen($path, 'w', null, $outputContext); \ No newline at end of file diff --git a/vendor/maennchen/zipstream-php/guides/index.rst b/vendor/maennchen/zipstream-php/guides/index.rst index 48f465a..67f504b 100644 --- a/vendor/maennchen/zipstream-php/guides/index.rst +++ b/vendor/maennchen/zipstream-php/guides/index.rst @@ -22,20 +22,11 @@ Installation Simply add a dependency on ``maennchen/zipstream-php`` to your project's ``composer.json`` file if you use Composer to manage the dependencies of your -project. Use following command to add the package to your project's -dependencies: +project. Use following command to add the package to your project's dependencies: .. code-block:: sh composer require maennchen/zipstream-php -If you want to use``addFileFromPsr7Stream``` -(``Psr\Http\Message\StreamInterface``) or use a stream instead of a -``resource`` as ``outputStream``, the following dependencies must be installed -as well: - -.. code-block:: sh - composer require psr/http-message guzzlehttp/psr7 - If ``composer install`` yields the following error, your installation is missing the `mbstring extension `_, either `install it `_ @@ -61,42 +52,25 @@ Here's a simple example: // Autoload the dependencies require 'vendor/autoload.php'; - // create a new zipstream object - $zip = new ZipStream\ZipStream( - outputName: 'example.zip', + // enable output of HTTP headers + $options = new ZipStream\Option\Archive(); + $options->setSendHttpHeaders(true); - // enable output of HTTP headers - sendHttpHeaders: true, - ); + // create a new zipstream object + $zip = new ZipStream\ZipStream('example.zip', $options); // create a file named 'hello.txt' - $zip->addFile( - fileName: 'hello.txt', - data: 'This is the contents of hello.txt', - ); + $zip->addFile('hello.txt', 'This is the contents of hello.txt'); // add a file named 'some_image.jpg' from a local file 'path/to/image.jpg' - $zip->addFileFromPath( - fileName: 'some_image.jpg', - path: 'path/to/image.jpg', - ); + $zip->addFileFromPath('some_image.jpg', 'path/to/image.jpg'); // add a file named 'goodbye.txt' from an open stream resource - $filePointer = tmpfile(); - fwrite($filePointer, 'The quick brown fox jumped over the lazy dog.'); - rewind($filePointer); - $zip->addFileFromStream( - fileName: 'goodbye.txt', - stream: $filePointer, - ); - fclose($filePointer); - - // add a file named 'streamfile.txt' from the body of a `guzzle` response - // Setup with `psr/http-message` & `guzzlehttp/psr7` dependencies required. - $zip->addFileFromPsr7Stream( - fileName: 'streamfile.txt', - stream: $response->getBody(), - ); + $fp = tmpfile(); + fwrite($fp, 'The quick brown fox jumped over the lazy dog.'); + rewind($fp); + $zip->addFileFromStream('goodbye.txt', $fp); + fclose($fp); // finish the zip stream $zip->finish(); @@ -113,7 +87,7 @@ The native Mac OS archive extraction tool prior to macOS 10.15 might not open archives in some conditions. A workaround is to disable the Zip64 feature with the option ``enableZip64: false``. This limits the archive to 4 Gb and 64k files but will allow users on macOS 10.14 and below to open them without issue. -See `#116 `_. +See `#116 `_. The linux ``unzip`` utility might not handle properly unicode characters. It is recommended to extract with another tool like diff --git a/vendor/maennchen/zipstream-php/phpunit.xml.dist b/vendor/maennchen/zipstream-php/phpunit.xml.dist index 1b02a3a..8a2f318 100644 --- a/vendor/maennchen/zipstream-php/phpunit.xml.dist +++ b/vendor/maennchen/zipstream-php/phpunit.xml.dist @@ -1,15 +1,14 @@ - - + + + + src + + test - - - src - - diff --git a/vendor/maennchen/zipstream-php/psalm.xml b/vendor/maennchen/zipstream-php/psalm.xml index 56af0e6..4e4c4f6 100644 --- a/vendor/maennchen/zipstream-php/psalm.xml +++ b/vendor/maennchen/zipstream-php/psalm.xml @@ -1,25 +1,53 @@ - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/maennchen/zipstream-php/src/Bigint.php b/vendor/maennchen/zipstream-php/src/Bigint.php new file mode 100644 index 0000000..f2565e9 --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Bigint.php @@ -0,0 +1,174 @@ +fillBytes($value, 0, 8); + } + + /** + * Get an instance + * + * @param int $value + * @return Bigint + */ + public static function init(int $value = 0): self + { + return new self($value); + } + + /** + * Fill bytes from low to high + * + * @param int $low + * @param int $high + * @return Bigint + */ + public static function fromLowHigh(int $low, int $high): self + { + $bigint = new self(); + $bigint->fillBytes($low, 0, 4); + $bigint->fillBytes($high, 4, 4); + return $bigint; + } + + /** + * Get high 32 + * + * @return int + */ + public function getHigh32(): int + { + return $this->getValue(4, 4); + } + + /** + * Get value from bytes array + * + * @param int $end + * @param int $length + * @return int + */ + public function getValue(int $end = 0, int $length = 8): int + { + $result = 0; + for ($i = $end + $length - 1; $i >= $end; $i--) { + $result <<= 8; + $result |= $this->bytes[$i]; + } + return $result; + } + + /** + * Get low FF + * + * @param bool $force + * @return float + */ + public function getLowFF(bool $force = false): float + { + if ($force || $this->isOver32()) { + return (float)0xFFFFFFFF; + } + return (float)$this->getLow32(); + } + + /** + * Check if is over 32 + * + * @psalm-suppress ArgumentTypeCoercion + * @param bool $force + * @return bool + */ + public function isOver32(bool $force = false): bool + { + // value 0xFFFFFFFF already needs a Zip64 header + return $force || + max(array_slice($this->bytes, 4, 4)) > 0 || + min(array_slice($this->bytes, 0, 4)) === 0xFF; + } + + /** + * Get low 32 + * + * @return int + */ + public function getLow32(): int + { + return $this->getValue(0, 4); + } + + /** + * Get hexadecimal + * + * @return string + */ + public function getHex64(): string + { + $result = '0x'; + for ($i = 7; $i >= 0; $i--) { + $result .= sprintf('%02X', $this->bytes[$i]); + } + return $result; + } + + /** + * Add + * + * @param Bigint $other + * @return Bigint + */ + public function add(self $other): self + { + $result = clone $this; + $overflow = false; + for ($i = 0; $i < 8; $i++) { + $result->bytes[$i] += $other->bytes[$i]; + if ($overflow) { + $result->bytes[$i]++; + $overflow = false; + } + if ($result->bytes[$i] & 0x100) { + $overflow = true; + $result->bytes[$i] &= 0xFF; + } + } + if ($overflow) { + throw new OverflowException(); + } + return $result; + } + + /** + * Fill the bytes field with int + * + * @param int $value + * @param int $start + * @param int $count + * @return void + */ + protected function fillBytes(int $value, int $start, int $count): void + { + for ($i = 0; $i < $count; $i++) { + $this->bytes[$start + $i] = $i >= PHP_INT_SIZE ? 0 : $value & 0xFF; + $value >>= 8; + } + } +} diff --git a/vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php b/vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php deleted file mode 100644 index ffcfc6e..0000000 --- a/vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php +++ /dev/null @@ -1,52 +0,0 @@ -value), - new PackField(format: 'V', value: Time::dateTimeToDosTime($lastModificationDateTime)), - new PackField(format: 'V', value: $crc32), - new PackField(format: 'V', value: $compressedSize), - new PackField(format: 'V', value: $uncompressedSize), - new PackField(format: 'v', value: strlen($fileName)), - new PackField(format: 'v', value: strlen($extraField)), - new PackField(format: 'v', value: strlen($fileComment)), - new PackField(format: 'v', value: $diskNumberStart), - new PackField(format: 'v', value: $internalFileAttributes), - new PackField(format: 'V', value: $externalFileAttributes), - new PackField(format: 'V', value: $relativeOffsetOfLocalHeader), - ) . $fileName . $extraField . $fileComment; - } -} diff --git a/vendor/maennchen/zipstream-php/src/CompressionMethod.php b/vendor/maennchen/zipstream-php/src/CompressionMethod.php deleted file mode 100644 index 51e4363..0000000 --- a/vendor/maennchen/zipstream-php/src/CompressionMethod.php +++ /dev/null @@ -1,106 +0,0 @@ -format(DateTimeInterface::ATOM) . " can't be represented as DOS time / date."); - } -} diff --git a/vendor/maennchen/zipstream-php/src/Exception/EncodingException.php b/vendor/maennchen/zipstream-php/src/Exception/EncodingException.php new file mode 100644 index 0000000..5b0267d --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Exception/EncodingException.php @@ -0,0 +1,14 @@ +resource = $resource; - parent::__construct('Function ' . $function . 'failed on resource.'); - } -} diff --git a/vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php b/vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php deleted file mode 100644 index 717c1aa..0000000 --- a/vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php +++ /dev/null @@ -1,19 +0,0 @@ -fileName = self::filterFilename($fileName); - $this->checkEncoding(); + public $opt; - if ($this->enableZeroHeader) { - $this->generalPurposeBitFlag |= GeneralPurposeBitFlag::ZERO_HEADER; - } + /** + * @var Bigint + */ + public $len; - $this->version = $this->compressionMethod === CompressionMethod::DEFLATE ? Version::DEFLATE : Version::STORE; + /** + * @var Bigint + */ + public $zlen; + + /** @var int */ + public $crc; + + /** + * @var Bigint + */ + public $hlen; + + /** + * @var Bigint + */ + public $ofs; + + /** + * @var int + */ + public $bits; + + /** + * @var Version + */ + public $version; + + /** + * @var ZipStream + */ + public $zip; + + /** + * @var resource + */ + private $deflate; + + /** + * @var HashContext + */ + private $hash; + + /** + * @var Method + */ + private $method; + + /** + * @var Bigint + */ + private $totalLength; + + public function __construct(ZipStream $zip, string $name, ?FileOptions $opt = null) + { + $this->zip = $zip; + + $this->name = $name; + $this->opt = $opt ?: new FileOptions(); + $this->method = $this->opt->getMethod(); + $this->version = Version::STORE(); + $this->ofs = new Bigint(); } - public function cloneSimulationExecution(): self + public function processPath(string $path): void { - return new self( - $this->fileName, - $this->dataCallback, - OperationMode::NORMAL, - $this->startOffset, - $this->compressionMethod, - $this->comment, - $this->lastModificationDateTime, - $this->deflateLevel, - $this->maxSize, - $this->exactSize, - $this->enableZip64, - $this->enableZeroHeader, - $this->send, - $this->recordSentBytes, - ); - } - - public function process(): string - { - $forecastSize = $this->forecastSize(); - - if ($this->enableZeroHeader) { - // No calculation required - } elseif ($this->isSimulation() && $forecastSize !== null) { - $this->uncompressedSize = $forecastSize; - $this->compressedSize = $forecastSize; - } else { - $this->readStream(send: false); - if (rewind($this->unpackStream()) === false) { - throw new ResourceActionException('rewind', $this->unpackStream()); + if (!is_readable($path)) { + if (!file_exists($path)) { + throw new FileNotFoundException($path); } + throw new FileNotReadableException($path); } - - $this->addFileHeader(); - - $detectedSize = $forecastSize ?? ($this->compressedSize > 0 ? $this->compressedSize : null); - - if ( - $this->isSimulation() && - $detectedSize !== null - ) { - $this->uncompressedSize = $detectedSize; - $this->compressedSize = $detectedSize; - ($this->recordSentBytes)($detectedSize); + if ($this->zip->isLargeFile($path) === false) { + $data = file_get_contents($path); + $this->processData($data); } else { - $this->readStream(send: true); + $this->method = $this->zip->opt->getLargeFileMethod(); + + $stream = new Stream(fopen($path, 'rb')); + $this->processStream($stream); + $stream->close(); + } + } + + public function processData(string $data): void + { + $this->len = new Bigint(strlen($data)); + $this->crc = crc32($data); + + // compress data if needed + if ($this->method->equals(Method::DEFLATE())) { + $data = gzdeflate($data); } + $this->zlen = new Bigint(strlen($data)); + $this->addFileHeader(); + $this->zip->send($data); $this->addFileFooter(); - return $this->getCdrFile(); - } - - /** - * @return resource - */ - private function unpackStream() - { - if ($this->stream) { - return $this->stream; - } - - if ($this->operationMode === OperationMode::SIMULATE_STRICT) { - throw new SimulationFileUnknownException(); - } - - $this->stream = ($this->dataCallback)(); - - if (!$this->enableZeroHeader && !stream_get_meta_data($this->stream)['seekable']) { - throw new StreamNotSeekableException(); - } - if (!( - str_contains(stream_get_meta_data($this->stream)['mode'], 'r') - || str_contains(stream_get_meta_data($this->stream)['mode'], 'w+') - || str_contains(stream_get_meta_data($this->stream)['mode'], 'a+') - || str_contains(stream_get_meta_data($this->stream)['mode'], 'x+') - || str_contains(stream_get_meta_data($this->stream)['mode'], 'c+') - )) { - throw new StreamNotReadableException(); - } - - return $this->stream; - } - - private function forecastSize(): ?int - { - if ($this->compressionMethod !== CompressionMethod::STORE) { - return null; - } - if ($this->exactSize !== null) { - return $this->exactSize; - } - $fstat = fstat($this->unpackStream()); - if (!$fstat || !array_key_exists('size', $fstat) || $fstat['size'] < 1) { - return null; - } - - if ($this->maxSize !== null && $this->maxSize < $fstat['size']) { - return $this->maxSize; - } - - return $fstat['size']; } /** * Create and send zip header for this file. + * + * @return void + * @throws \ZipStream\Exception\EncodingException */ - private function addFileHeader(): void + public function addFileHeader(): void { - $forceEnableZip64 = $this->enableZeroHeader && $this->enableZip64; + $name = static::filterFilename($this->name); - $footer = $this->buildZip64ExtraBlock($forceEnableZip64); + // calculate name length + $nameLength = strlen($name); - $zip64Enabled = $footer !== ''; + // create dos timestamp + $time = static::dosTime($this->opt->getTime()->getTimestamp()); - if ($zip64Enabled) { - $this->version = Version::ZIP64; + $comment = $this->opt->getComment(); + + if (!mb_check_encoding($name, 'ASCII') || + !mb_check_encoding($comment, 'ASCII')) { + // Sets Bit 11: Language encoding flag (EFS). If this bit is set, + // the filename and comment fields for this file + // MUST be encoded using UTF-8. (see APPENDIX D) + if (mb_check_encoding($name, 'UTF-8') && + mb_check_encoding($comment, 'UTF-8')) { + $this->bits |= self::BIT_EFS_UTF8; + } } - if ($this->generalPurposeBitFlag & GeneralPurposeBitFlag::EFS) { - // Put the tricky entry to - // force Linux unzip to lookup EFS flag. - $footer .= Zs\ExtendedInformationExtraField::generate(); + if ($this->method->equals(Method::DEFLATE())) { + $this->version = Version::DEFLATE(); } - $data = LocalFileHeader::generate( - versionNeededToExtract: $this->version->value, - generalPurposeBitFlag: $this->generalPurposeBitFlag, - compressionMethod: $this->compressionMethod, - lastModificationDateTime: $this->lastModificationDateTime, - crc32UncompressedData: $this->crc, - compressedSize: $zip64Enabled - ? 0xFFFFFFFF - : $this->compressedSize, - uncompressedSize: $zip64Enabled - ? 0xFFFFFFFF - : $this->uncompressedSize, - fileName: $this->fileName, - extraField: $footer, - ); + $force = (bool)($this->bits & self::BIT_ZERO_HEADER) && + $this->zip->opt->isEnableZip64(); + $footer = $this->buildZip64ExtraBlock($force); - ($this->send)($data); + // If this file will start over 4GB limit in ZIP file, + // CDR record will have to use Zip64 extension to describe offset + // to keep consistency we use the same value here + if ($this->zip->ofs->isOver32()) { + $this->version = Version::ZIP64(); + } + + $fields = [ + ['V', ZipStream::FILE_HEADER_SIGNATURE], + ['v', $this->version->getValue()], // Version needed to Extract + ['v', $this->bits], // General purpose bit flags - data descriptor flag set + ['v', $this->method->getValue()], // Compression method + ['V', $time], // Timestamp (DOS Format) + ['V', $this->crc], // CRC32 of data (0 -> moved to data descriptor footer) + ['V', $this->zlen->getLowFF($force)], // Length of compressed data (forced to 0xFFFFFFFF for zero header) + ['V', $this->len->getLowFF($force)], // Length of original data (forced to 0xFFFFFFFF for zero header) + ['v', $nameLength], // Length of filename + ['v', strlen($footer)], // Extra data (see above) + ]; + + // pack fields and calculate "total" length + $header = ZipStream::packFields($fields); + + // print header and filename + $data = $header . $name . $footer; + $this->zip->send($data); + + // save header length + $this->hlen = Bigint::init(strlen($data)); } /** * Strip characters that are not legal in Windows filenames * to prevent compatibility issues + * + * @param string $filename Unprocessed filename + * @return string */ - private static function filterFilename( - /** - * Unprocessed filename - */ - string $fileName - ): string { + public static function filterFilename(string $filename): string + { // strip leading slashes from file name // (fixes bug in windows archive viewer) - $fileName = ltrim($fileName, '/'); + $filename = preg_replace('/^\\/+/', '', $filename); - return str_replace(['\\', ':', '*', '?', '"', '<', '>', '|'], '_', $fileName); + return str_replace(['\\', ':', '*', '?', '"', '<', '>', '|'], '_', $filename); } - private function checkEncoding(): void + /** + * Create and send data descriptor footer for this file. + * + * @return void + */ + public function addFileFooter(): void { - // Sets Bit 11: Language encoding flag (EFS). If this bit is set, - // the filename and comment fields for this file - // MUST be encoded using UTF-8. (see APPENDIX D) - if (mb_check_encoding($this->fileName, 'UTF-8') && - mb_check_encoding($this->comment, 'UTF-8')) { - $this->generalPurposeBitFlag |= GeneralPurposeBitFlag::EFS; - } - } + if ($this->bits & self::BIT_ZERO_HEADER) { + // compressed and uncompressed size + $sizeFormat = 'V'; + if ($this->zip->opt->isEnableZip64()) { + $sizeFormat = 'P'; + } + $fields = [ + ['V', ZipStream::DATA_DESCRIPTOR_SIGNATURE], + ['V', $this->crc], // CRC32 + [$sizeFormat, $this->zlen], // Length of compressed data + [$sizeFormat, $this->len], // Length of original data + ]; - private function buildZip64ExtraBlock(bool $force = false): string - { - $outputZip64ExtraBlock = false; - - $originalSize = null; - if ($force || $this->uncompressedSize > 0xFFFFFFFF) { - $outputZip64ExtraBlock = true; - $originalSize = $this->uncompressedSize; - } - - $compressedSize = null; - if ($force || $this->compressedSize > 0xFFFFFFFF) { - $outputZip64ExtraBlock = true; - $compressedSize = $this->compressedSize; - } - - // If this file will start over 4GB limit in ZIP file, - // CDR record will have to use Zip64 extension to describe offset - // to keep consistency we use the same value here - $relativeHeaderOffset = null; - if ($this->startOffset > 0xFFFFFFFF) { - $outputZip64ExtraBlock = true; - $relativeHeaderOffset = $this->startOffset; - } - - if (!$outputZip64ExtraBlock) { - return ''; - } - - if (!$this->enableZip64) { - throw new OverflowException(); - } - - return Zip64\ExtendedInformationExtraField::generate( - originalSize: $originalSize, - compressedSize: $compressedSize, - relativeHeaderOffset: $relativeHeaderOffset, - diskStartNumber: null, - ); - } - - private function addFileFooter(): void - { - if (($this->compressedSize > 0xFFFFFFFF || $this->uncompressedSize > 0xFFFFFFFF) && $this->version !== Version::ZIP64) { - throw new OverflowException(); - } - - if (!$this->enableZeroHeader) { - return; - } - - if ($this->version === Version::ZIP64) { - $footer = Zip64\DataDescriptor::generate( - crc32UncompressedData: $this->crc, - compressedSize: $this->compressedSize, - uncompressedSize: $this->uncompressedSize, - ); + $footer = ZipStream::packFields($fields); + $this->zip->send($footer); } else { - $footer = DataDescriptor::generate( - crc32UncompressedData: $this->crc, - compressedSize: $this->compressedSize, - uncompressedSize: $this->uncompressedSize, - ); + $footer = ''; } - - ($this->send)($footer); + $this->totalLength = $this->hlen->add($this->zlen)->add(Bigint::init(strlen($footer))); + $this->zip->addToCdr($this); } - private function readStream(bool $send): void + public function processStream(StreamInterface $stream): void { - $this->compressedSize = 0; - $this->uncompressedSize = 0; - $hash = hash_init('crc32b'); + $this->zlen = new Bigint(); + $this->len = new Bigint(); - $deflate = $this->compressionInit(); - - while ( - !feof($this->unpackStream()) && - ($this->maxSize === null || $this->uncompressedSize < $this->maxSize) && - ($this->exactSize === null || $this->uncompressedSize < $this->exactSize) - ) { - $readLength = min( - ($this->maxSize ?? PHP_INT_MAX) - $this->uncompressedSize, - ($this->exactSize ?? PHP_INT_MAX) - $this->uncompressedSize, - self::CHUNKED_READ_BLOCK_SIZE - ); - - $data = fread($this->unpackStream(), $readLength); - - if ($data === false) { - throw new ResourceActionException('fread', $this->unpackStream()); - } - - hash_update($hash, $data); - - $this->uncompressedSize += strlen($data); - - if ($deflate) { - $data = deflate_add( - $deflate, - $data, - feof($this->unpackStream()) ? ZLIB_FINISH : ZLIB_NO_FLUSH - ); - - if ($data === false) { - throw new RuntimeException('deflate_add failed'); - } - } - - $this->compressedSize += strlen($data); - - if ($send) { - ($this->send)($data); - } - } - - if ($this->exactSize !== null && $this->uncompressedSize !== $this->exactSize) { - throw new FileSizeIncorrectException(expectedSize: $this->exactSize, actualSize: $this->uncompressedSize); - } - - $this->crc = hexdec(hash_final($hash)); - } - - private function compressionInit(): ?DeflateContext - { - switch ($this->compressionMethod) { - case CompressionMethod::STORE: - // Noting to do - return null; - case CompressionMethod::DEFLATE: - $deflateContext = deflate_init( - ZLIB_ENCODING_RAW, - ['level' => $this->deflateLevel] - ); - - if (!$deflateContext) { - // @codeCoverageIgnoreStart - throw new RuntimeException("Can't initialize deflate context."); - // @codeCoverageIgnoreEnd - } - - // False positive, resource is no longer returned from this function - return $deflateContext; - default: - // @codeCoverageIgnoreStart - throw new RuntimeException('Unsupported Compression Method ' . print_r($this->compressionMethod, true)); - // @codeCoverageIgnoreEnd + if ($this->zip->opt->isZeroHeader()) { + $this->processStreamWithZeroHeader($stream); + } else { + $this->processStreamWithComputedHeader($stream); } } - private function getCdrFile(): string + /** + * Send CDR record for specified file. + * + * @return string + */ + public function getCdrFile(): string { + $name = static::filterFilename($this->name); + + // get attributes + $comment = $this->opt->getComment(); + + // get dos timestamp + $time = static::dosTime($this->opt->getTime()->getTimestamp()); + $footer = $this->buildZip64ExtraBlock(); - return CentralDirectoryFileHeader::generate( - versionMadeBy: ZipStream::ZIP_VERSION_MADE_BY, - versionNeededToExtract: $this->version->value, - generalPurposeBitFlag: $this->generalPurposeBitFlag, - compressionMethod: $this->compressionMethod, - lastModificationDateTime: $this->lastModificationDateTime, - crc32: $this->crc, - compressedSize: $this->compressedSize > 0xFFFFFFFF - ? 0xFFFFFFFF - : $this->compressedSize, - uncompressedSize: $this->uncompressedSize > 0xFFFFFFFF - ? 0xFFFFFFFF - : $this->uncompressedSize, - fileName: $this->fileName, - extraField: $footer, - fileComment: $this->comment, - diskNumberStart: 0, - internalFileAttributes: 0, - externalFileAttributes: 32, - relativeOffsetOfLocalHeader: $this->startOffset > 0xFFFFFFFF - ? 0xFFFFFFFF - : $this->startOffset, - ); + $fields = [ + ['V', ZipStream::CDR_FILE_SIGNATURE], // Central file header signature + ['v', ZipStream::ZIP_VERSION_MADE_BY], // Made by version + ['v', $this->version->getValue()], // Extract by version + ['v', $this->bits], // General purpose bit flags - data descriptor flag set + ['v', $this->method->getValue()], // Compression method + ['V', $time], // Timestamp (DOS Format) + ['V', $this->crc], // CRC32 + ['V', $this->zlen->getLowFF()], // Compressed Data Length + ['V', $this->len->getLowFF()], // Original Data Length + ['v', strlen($name)], // Length of filename + ['v', strlen($footer)], // Extra data len (see above) + ['v', strlen($comment)], // Length of comment + ['v', 0], // Disk number + ['v', 0], // Internal File Attributes + ['V', 32], // External File Attributes + ['V', $this->ofs->getLowFF()], // Relative offset of local header + ]; + + // pack fields, then append name and comment + $header = ZipStream::packFields($fields); + + return $header . $name . $footer . $comment; } - private function isSimulation(): bool + /** + * @return Bigint + */ + public function getTotalLength(): Bigint { - return $this->operationMode === OperationMode::SIMULATE_LAX || $this->operationMode === OperationMode::SIMULATE_STRICT; + return $this->totalLength; + } + + /** + * Convert a UNIX timestamp to a DOS timestamp. + * + * @param int $when + * @return int DOS Timestamp + */ + final protected static function dosTime(int $when): int + { + // get date array for timestamp + $d = getdate($when); + + // set lower-bound on dates + if ($d['year'] < 1980) { + $d = [ + 'year' => 1980, + 'mon' => 1, + 'mday' => 1, + 'hours' => 0, + 'minutes' => 0, + 'seconds' => 0, + ]; + } + + // remove extra years from 1980 + $d['year'] -= 1980; + + // return date string + return + ($d['year'] << 25) | + ($d['mon'] << 21) | + ($d['mday'] << 16) | + ($d['hours'] << 11) | + ($d['minutes'] << 5) | + ($d['seconds'] >> 1); + } + + protected function buildZip64ExtraBlock(bool $force = false): string + { + $fields = []; + if ($this->len->isOver32($force)) { + $fields[] = ['P', $this->len]; // Length of original data + } + + if ($this->len->isOver32($force)) { + $fields[] = ['P', $this->zlen]; // Length of compressed data + } + + if ($this->ofs->isOver32()) { + $fields[] = ['P', $this->ofs]; // Offset of local header record + } + + if (!empty($fields)) { + if (!$this->zip->opt->isEnableZip64()) { + throw new OverflowException(); + } + + array_unshift( + $fields, + ['v', 0x0001], // 64 bit extension + ['v', count($fields) * 8] // Length of data block + ); + $this->version = Version::ZIP64(); + } + + if ($this->bits & self::BIT_EFS_UTF8) { + // Put the tricky entry to + // force Linux unzip to lookup EFS flag. + $fields[] = ['v', 0x5653]; // Choose 'ZS' for proprietary usage + $fields[] = ['v', 0x0000]; // zero length + } + + return ZipStream::packFields($fields); + } + + protected function processStreamWithZeroHeader(StreamInterface $stream): void + { + $this->bits |= self::BIT_ZERO_HEADER; + $this->addFileHeader(); + $this->readStream($stream, self::COMPUTE | self::SEND); + $this->addFileFooter(); + } + + protected function readStream(StreamInterface $stream, ?int $options = null): void + { + $this->deflateInit(); + $total = 0; + $size = $this->opt->getSize(); + while (!$stream->eof() && ($size === 0 || $total < $size)) { + $data = $stream->read(self::CHUNKED_READ_BLOCK_SIZE); + $total += strlen($data); + if ($size > 0 && $total > $size) { + $data = substr($data, 0, strlen($data)-($total - $size)); + } + $this->deflateData($stream, $data, $options); + if ($options & self::SEND) { + $this->zip->send($data); + } + } + $this->deflateFinish($options); + } + + protected function deflateInit(): void + { + $hash = hash_init(self::HASH_ALGORITHM); + $this->hash = $hash; + if ($this->method->equals(Method::DEFLATE())) { + $this->deflate = deflate_init( + ZLIB_ENCODING_RAW, + ['level' => $this->opt->getDeflateLevel()] + ); + } + } + + protected function deflateData(StreamInterface $stream, string &$data, ?int $options = null): void + { + if ($options & self::COMPUTE) { + $this->len = $this->len->add(Bigint::init(strlen($data))); + hash_update($this->hash, $data); + } + if ($this->deflate) { + $data = deflate_add( + $this->deflate, + $data, + $stream->eof() + ? ZLIB_FINISH + : ZLIB_NO_FLUSH + ); + } + if ($options & self::COMPUTE) { + $this->zlen = $this->zlen->add(Bigint::init(strlen($data))); + } + } + + protected function deflateFinish(?int $options = null): void + { + if ($options & self::COMPUTE) { + $this->crc = hexdec(hash_final($this->hash)); + } + } + + protected function processStreamWithComputedHeader(StreamInterface $stream): void + { + $this->readStream($stream, self::COMPUTE); + $stream->rewind(); + + $this->addFileHeader(); + $this->readStream($stream, self::SEND); + $this->addFileFooter(); } } diff --git a/vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php b/vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php deleted file mode 100644 index 23a66d8..0000000 --- a/vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php +++ /dev/null @@ -1,89 +0,0 @@ -value), - new PackField(format: 'V', value: Time::dateTimeToDosTime($lastModificationDateTime)), - new PackField(format: 'V', value: $crc32UncompressedData), - new PackField(format: 'V', value: $compressedSize), - new PackField(format: 'V', value: $uncompressedSize), - new PackField(format: 'v', value: strlen($fileName)), - new PackField(format: 'v', value: strlen($extraField)), - ) . $fileName . $extraField; - } -} diff --git a/vendor/maennchen/zipstream-php/src/OperationMode.php b/vendor/maennchen/zipstream-php/src/OperationMode.php deleted file mode 100644 index dd650f0..0000000 --- a/vendor/maennchen/zipstream-php/src/OperationMode.php +++ /dev/null @@ -1,35 +0,0 @@ - 4 GB or file count > 64k) + * + * @var bool + */ + private $enableZip64 = true; + + /** + * Enable streaming files with single read where + * general purpose bit 3 indicates local file header + * contain zero values in crc and size fields, + * these appear only after file contents + * in data descriptor block. + * + * @var bool + */ + private $zeroHeader = false; + + /** + * Enable reading file stat for determining file size. + * When a 32-bit system reads file size that is + * over 2 GB, invalid value appears in file size + * due to integer overflow. Should be disabled on + * 32-bit systems with method addFileFromPath + * if any file may exceed 2 GB. In this case file + * will be read in blocks and correct size will be + * determined from content. + * + * @var bool + */ + private $statFiles = true; + + /** + * Enable flush after every write to output stream. + * @var bool + */ + private $flushOutput = false; + + /** + * HTTP Content-Disposition. Defaults to + * 'attachment', where + * FILENAME is the specified filename. + * + * Note that this does nothing if you are + * not sending HTTP headers. + * + * @var string + */ + private $contentDisposition = 'attachment'; + + /** + * Note that this does nothing if you are + * not sending HTTP headers. + * + * @var string + */ + private $contentType = 'application/x-zip'; + + /** + * @var int + */ + private $deflateLevel = 6; + + /** + * @var StreamInterface|resource + */ + private $outputStream; + + /** + * Options constructor. + */ + public function __construct() + { + $this->largeFileMethod = Method::STORE(); + $this->outputStream = fopen('php://output', 'wb'); + } + + public function getComment(): string + { + return $this->comment; + } + + public function setComment(string $comment): void + { + $this->comment = $comment; + } + + public function getLargeFileSize(): int + { + return $this->largeFileSize; + } + + public function setLargeFileSize(int $largeFileSize): void + { + $this->largeFileSize = $largeFileSize; + } + + public function getLargeFileMethod(): Method + { + return $this->largeFileMethod; + } + + public function setLargeFileMethod(Method $largeFileMethod): void + { + $this->largeFileMethod = $largeFileMethod; + } + + public function isSendHttpHeaders(): bool + { + return $this->sendHttpHeaders; + } + + public function setSendHttpHeaders(bool $sendHttpHeaders): void + { + $this->sendHttpHeaders = $sendHttpHeaders; + } + + public function getHttpHeaderCallback(): callable + { + return $this->httpHeaderCallback; + } + + public function setHttpHeaderCallback(callable $httpHeaderCallback): void + { + $this->httpHeaderCallback = $httpHeaderCallback; + } + + public function isEnableZip64(): bool + { + return $this->enableZip64; + } + + public function setEnableZip64(bool $enableZip64): void + { + $this->enableZip64 = $enableZip64; + } + + public function isZeroHeader(): bool + { + return $this->zeroHeader; + } + + public function setZeroHeader(bool $zeroHeader): void + { + $this->zeroHeader = $zeroHeader; + } + + public function isFlushOutput(): bool + { + return $this->flushOutput; + } + + public function setFlushOutput(bool $flushOutput): void + { + $this->flushOutput = $flushOutput; + } + + public function isStatFiles(): bool + { + return $this->statFiles; + } + + public function setStatFiles(bool $statFiles): void + { + $this->statFiles = $statFiles; + } + + public function getContentDisposition(): string + { + return $this->contentDisposition; + } + + public function setContentDisposition(string $contentDisposition): void + { + $this->contentDisposition = $contentDisposition; + } + + public function getContentType(): string + { + return $this->contentType; + } + + public function setContentType(string $contentType): void + { + $this->contentType = $contentType; + } + + /** + * @return StreamInterface|resource + */ + public function getOutputStream() + { + return $this->outputStream; + } + + /** + * @param StreamInterface|resource $outputStream + */ + public function setOutputStream($outputStream): void + { + $this->outputStream = $outputStream; + } + + /** + * @return int + */ + public function getDeflateLevel(): int + { + return $this->deflateLevel; + } + + /** + * @param int $deflateLevel + */ + public function setDeflateLevel(int $deflateLevel): void + { + $this->deflateLevel = $deflateLevel; + } +} diff --git a/vendor/maennchen/zipstream-php/src/Option/File.php b/vendor/maennchen/zipstream-php/src/Option/File.php new file mode 100644 index 0000000..37e37ce --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Option/File.php @@ -0,0 +1,122 @@ +deflateLevel = $this->deflateLevel ?: $archiveOptions->getDeflateLevel(); + $this->time = $this->time ?: new DateTime(); + } + + /** + * @return string + */ + public function getComment(): string + { + return $this->comment; + } + + /** + * @param string $comment + */ + public function setComment(string $comment): void + { + $this->comment = $comment; + } + + /** + * @return Method + */ + public function getMethod(): Method + { + return $this->method ?: Method::DEFLATE(); + } + + /** + * @param Method $method + */ + public function setMethod(Method $method): void + { + $this->method = $method; + } + + /** + * @return int + */ + public function getDeflateLevel(): int + { + return $this->deflateLevel ?: Archive::DEFAULT_DEFLATE_LEVEL; + } + + /** + * @param int $deflateLevel + */ + public function setDeflateLevel(int $deflateLevel): void + { + $this->deflateLevel = $deflateLevel; + } + + /** + * @return DateTimeInterface + */ + public function getTime(): DateTimeInterface + { + return $this->time; + } + + /** + * @param DateTimeInterface $time + */ + public function setTime(DateTimeInterface $time): void + { + $this->time = $time; + } + + /** + * @return int + */ + public function getSize(): int + { + return $this->size; + } + + /** + * @param int $size + */ + public function setSize(int $size): void + { + $this->size = $size; + } +} diff --git a/vendor/maennchen/zipstream-php/src/Option/Method.php b/vendor/maennchen/zipstream-php/src/Option/Method.php new file mode 100644 index 0000000..0dfce1b --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Option/Method.php @@ -0,0 +1,23 @@ + + */ +class Method extends Enum +{ + public const STORE = 0x00; + + public const DEFLATE = 0x08; +} diff --git a/vendor/maennchen/zipstream-php/src/Option/Version.php b/vendor/maennchen/zipstream-php/src/Option/Version.php new file mode 100644 index 0000000..f3daa85 --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Option/Version.php @@ -0,0 +1,27 @@ + + */ +class Version extends Enum +{ + public const STORE = 0x000A; // 1.00 + + public const DEFLATE = 0x0014; // 2.00 + + public const ZIP64 = 0x002D; // 4.50 +} diff --git a/vendor/maennchen/zipstream-php/src/PackField.php b/vendor/maennchen/zipstream-php/src/PackField.php deleted file mode 100644 index 892b400..0000000 --- a/vendor/maennchen/zipstream-php/src/PackField.php +++ /dev/null @@ -1,56 +0,0 @@ -format; - }, ''); - - $args = array_map(function (self $field) { - switch ($field->format) { - case 'V': - if ($field->value > self::MAX_V) { - throw new RuntimeException(print_r($field->value, true) . ' is larger than 32 bits'); - } - break; - case 'v': - if ($field->value > self::MAX_v) { - throw new RuntimeException(print_r($field->value, true) . ' is larger than 16 bits'); - } - break; - case 'P': break; - default: - break; - } - - return $field->value; - }, $fields); - - return pack($fmt, ...$args); - } -} diff --git a/vendor/maennchen/zipstream-php/src/Stream.php b/vendor/maennchen/zipstream-php/src/Stream.php new file mode 100644 index 0000000..d80e70f --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Stream.php @@ -0,0 +1,265 @@ +stream = $stream; + } + + /** + * Reads all data from the stream into a string, from the beginning to end. + * + * This method MUST attempt to seek to the beginning of the stream before + * reading data and read the stream until the end is reached. + * + * Warning: This could attempt to load a large amount of data into memory. + * + * This method MUST NOT raise an exception in order to conform with PHP's + * string casting operations. + * + * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring + * @return string + */ + public function __toString(): string + { + try { + $this->seek(0); + } catch (RuntimeException $e) { + } + return (string) stream_get_contents($this->stream); + } + + /** + * Closes the stream and any underlying resources. + * + * @return void + */ + public function close(): void + { + if (is_resource($this->stream)) { + fclose($this->stream); + } + $this->detach(); + } + + /** + * Separates any underlying resources from the stream. + * + * After the stream has been detached, the stream is in an unusable state. + * + * @return resource|null Underlying PHP stream, if any + */ + public function detach() + { + $result = $this->stream; + $this->stream = null; + return $result; + } + + /** + * Seek to a position in the stream. + * + * @link http://www.php.net/manual/en/function.fseek.php + * @param int $offset Stream offset + * @param int $whence Specifies how the cursor position will be calculated + * based on the seek offset. Valid values are identical to the built-in + * PHP $whence values for `fseek()`. SEEK_SET: Set position equal to + * offset bytes SEEK_CUR: Set position to current location plus offset + * SEEK_END: Set position to end-of-stream plus offset. + * @throws RuntimeException on failure. + */ + public function seek($offset, $whence = SEEK_SET): void + { + if (!$this->isSeekable()) { + throw new RuntimeException(); + } + if (fseek($this->stream, $offset, $whence) !== 0) { + throw new RuntimeException(); + } + } + + /** + * Returns whether or not the stream is seekable. + * + * @return bool + */ + public function isSeekable(): bool + { + return (bool)$this->getMetadata('seekable'); + } + + /** + * Get stream metadata as an associative array or retrieve a specific key. + * + * The keys returned are identical to the keys returned from PHP's + * stream_get_meta_data() function. + * + * @link http://php.net/manual/en/function.stream-get-meta-data.php + * @param string $key Specific metadata to retrieve. + * @return array|mixed|null Returns an associative array if no key is + * provided. Returns a specific key value if a key is provided and the + * value is found, or null if the key is not found. + */ + public function getMetadata($key = null) + { + $metadata = stream_get_meta_data($this->stream); + return $key !== null ? @$metadata[$key] : $metadata; + } + + /** + * Get the size of the stream if known. + * + * @return int|null Returns the size in bytes if known, or null if unknown. + */ + public function getSize(): ?int + { + $stats = fstat($this->stream); + return $stats['size']; + } + + /** + * Returns the current position of the file read/write pointer + * + * @return int Position of the file pointer + * @throws RuntimeException on error. + */ + public function tell(): int + { + $position = ftell($this->stream); + if ($position === false) { + throw new RuntimeException(); + } + return $position; + } + + /** + * Returns true if the stream is at the end of the stream. + * + * @return bool + */ + public function eof(): bool + { + return feof($this->stream); + } + + /** + * Seek to the beginning of the stream. + * + * If the stream is not seekable, this method will raise an exception; + * otherwise, it will perform a seek(0). + * + * @see seek() + * @link http://www.php.net/manual/en/function.fseek.php + * @throws RuntimeException on failure. + */ + public function rewind(): void + { + $this->seek(0); + } + + /** + * Write data to the stream. + * + * @param string $string The string that is to be written. + * @return int Returns the number of bytes written to the stream. + * @throws RuntimeException on failure. + */ + public function write($string): int + { + if (!$this->isWritable()) { + throw new RuntimeException(); + } + if (fwrite($this->stream, $string) === false) { + throw new RuntimeException(); + } + return mb_strlen($string); + } + + /** + * Returns whether or not the stream is writable. + * + * @return bool + */ + public function isWritable(): bool + { + $mode = $this->getMetadata('mode'); + if (!is_string($mode)) { + throw new RuntimeException('Could not get stream mode from metadata!'); + } + return preg_match('/[waxc+]/', $mode) === 1; + } + + /** + * Read data from the stream. + * + * @param int $length Read up to $length bytes from the object and return + * them. Fewer than $length bytes may be returned if underlying stream + * call returns fewer bytes. + * @return string Returns the data read from the stream, or an empty string + * if no bytes are available. + * @throws RuntimeException if an error occurs. + */ + public function read($length): string + { + if (!$this->isReadable()) { + throw new RuntimeException(); + } + $result = fread($this->stream, $length); + if ($result === false) { + throw new RuntimeException(); + } + return $result; + } + + /** + * Returns whether or not the stream is readable. + * + * @return bool + */ + public function isReadable(): bool + { + $mode = $this->getMetadata('mode'); + if (!is_string($mode)) { + throw new RuntimeException('Could not get stream mode from metadata!'); + } + return preg_match('/[r+]/', $mode) === 1; + } + + /** + * Returns the remaining contents in a string + * + * @return string + * @throws RuntimeException if unable to read or an error occurs while + * reading. + */ + public function getContents(): string + { + if (!$this->isReadable()) { + throw new RuntimeException(); + } + $result = stream_get_contents($this->stream); + if ($result === false) { + throw new RuntimeException(); + } + return $result; + } +} diff --git a/vendor/maennchen/zipstream-php/src/Time.php b/vendor/maennchen/zipstream-php/src/Time.php deleted file mode 100644 index 1b4121c..0000000 --- a/vendor/maennchen/zipstream-php/src/Time.php +++ /dev/null @@ -1,39 +0,0 @@ -getTimestamp() < $dosMinimumDate->getTimestamp()) { - throw new DosTimeOverflowException(dateTime: $dateTime); - } - - $dateTime = DateTimeImmutable::createFromInterface($dateTime)->sub(new DateInterval('P1980Y')); - - [$year, $month, $day, $hour, $minute, $second] = explode(' ', $dateTime->format('Y n j G i s')); - - return - ((int) $year << 25) | - ((int) $month << 21) | - ((int) $day << 16) | - ((int) $hour << 11) | - ((int) $minute << 5) | - ((int) $second >> 1); - } -} diff --git a/vendor/maennchen/zipstream-php/src/Version.php b/vendor/maennchen/zipstream-php/src/Version.php deleted file mode 100644 index c014f8a..0000000 --- a/vendor/maennchen/zipstream-php/src/Version.php +++ /dev/null @@ -1,12 +0,0 @@ -addFile(fileName: 'world.txt', data: 'Hello World'); + * * add first file + * $data = file_get_contents('some_file.gif'); + * $zip->addFile('some_file.gif', $data); * - * // add second file - * $zip->addFile(fileName: 'moon.txt', data: 'Hello Moon'); - * ``` + * * add second file + * $data = file_get_contents('some_file.gif'); + * $zip->addFile('another_file.png', $data); * * 3. Finish the zip stream: * - * ```php - * $zip->finish(); - * ``` + * $zip->finish(); * * You can also add an archive comment, add comments to individual files, * and adjust the timestamp of files. See the API documentation for each * method below for additional information. * - * ## Example + * Example: * - * ```php - * // create a new zip stream object - * $zip = new ZipStream(outputName: 'some_files.zip'); + * // create a new zip stream object + * $zip = new ZipStream('some_files.zip'); * - * // list of local files - * $files = array('foo.txt', 'bar.jpg'); + * // list of local files + * $files = array('foo.txt', 'bar.jpg'); * - * // read and add each file to the archive - * foreach ($files as $path) - * $zip->addFileFromPath(fileName: $path, $path); + * // read and add each file to the archive + * foreach ($files as $path) + * $zip->addFile($path, file_get_contents($path)); * - * // write archive footer to stream - * $zip->finish(); - * ``` + * // write archive footer to stream + * $zip->finish(); */ class ZipStream { @@ -89,783 +80,529 @@ class ZipStream * Here we are using 6 for the OS, indicating OS/2 H.P.F.S. * to prevent file permissions issues upon extract (see #84) * 0x603 is 00000110 00000011 in binary, so 6 and 3 - * - * @internal */ public const ZIP_VERSION_MADE_BY = 0x603; - private bool $ready = true; + /** + * The following signatures end with 0x4b50, which in ASCII is PK, + * the initials of the inventor Phil Katz. + * See https://en.wikipedia.org/wiki/Zip_(file_format)#File_headers + */ + public const FILE_HEADER_SIGNATURE = 0x04034b50; - private int $offset = 0; + public const CDR_FILE_SIGNATURE = 0x02014b50; + + public const CDR_EOF_SIGNATURE = 0x06054b50; + + public const DATA_DESCRIPTOR_SIGNATURE = 0x08074b50; + + public const ZIP64_CDR_EOF_SIGNATURE = 0x06064b50; + + public const ZIP64_CDR_LOCATOR_SIGNATURE = 0x07064b50; /** - * @var string[] + * Global Options + * + * @var ArchiveOptions */ - private array $centralDirectoryRecords = []; + public $opt; /** - * @var resource + * @var array */ - private $outputStream; - - private readonly Closure $httpHeaderCallback; + public $files = []; /** - * @var File[] + * @var Bigint */ - private array $recordedSimulation = []; + public $cdr_ofs; + + /** + * @var Bigint + */ + public $ofs; + + /** + * @var bool + */ + protected $need_headers; + + /** + * @var null|String + */ + protected $output_name; /** * Create a new ZipStream object. * - * ##### Examples + * Parameters: * - * ```php - * // create a new zip file named 'foo.zip' - * $zip = new ZipStream(outputName: 'foo.zip'); + * @param String $name - Name of output file (optional). + * @param ArchiveOptions $opt - Archive Options * - * // create a new zip file named 'bar.zip' with a comment - * $zip = new ZipStream( - * outputName: 'bar.zip', - * comment: 'this is a comment for the zip file.', - * ); - * ``` + * Large File Support: * - * @param OperationMode $operationMode - * The mode can be used to switch between `NORMAL` and `SIMULATION_*` modes. - * For details see the `OperationMode` documentation. + * By default, the method addFileFromPath() will send send files + * larger than 20 megabytes along raw rather than attempting to + * compress them. You can change both the maximum size and the + * compression behavior using the largeFile* options above, with the + * following caveats: * - * Default to `NORMAL`. + * * For "small" files (e.g. files smaller than largeFileSize), the + * memory use can be up to twice that of the actual file. In other + * words, adding a 10 megabyte file to the archive could potentially + * occupy 20 megabytes of memory. * - * @param string $comment - * Archive Level Comment + * * Enabling compression on large files (e.g. files larger than + * large_file_size) is extremely slow, because ZipStream has to pass + * over the large file once to calculate header information, and then + * again to compress and send the actual data. * - * @param StreamInterface|resource|null $outputStream - * Override the output of the archive to a different target. + * Examples: * - * By default the archive is sent to `STDOUT`. + * // create a new zip file named 'foo.zip' + * $zip = new ZipStream('foo.zip'); * - * @param CompressionMethod $defaultCompressionMethod - * How to handle file compression. Legal values are - * `CompressionMethod::DEFLATE` (the default), or - * `CompressionMethod::STORE`. `STORE` sends the file raw and is - * significantly faster, while `DEFLATE` compresses the file and - * is much, much slower. + * // create a new zip file named 'bar.zip' with a comment + * $opt->setComment = 'this is a comment for the zip file.'; + * $zip = new ZipStream('bar.zip', $opt); * - * @param int $defaultDeflateLevel - * Default deflation level. Only relevant if `compressionMethod` - * is `DEFLATE`. + * Notes: * - * See details of [`deflate_init`](https://www.php.net/manual/en/function.deflate-init.php#refsect1-function.deflate-init-parameters) - * - * @param bool $enableZip64 - * Enable Zip64 extension, supporting very large - * archives (any size > 4 GB or file count > 64k) - * - * @param bool $defaultEnableZeroHeader - * Enable streaming files with single read. - * - * When the zero header is set, the file is streamed into the output - * and the size & checksum are added at the end of the file. This is the - * fastest method and uses the least memory. Unfortunately not all - * ZIP clients fully support this and can lead to clients reporting - * the generated ZIP files as corrupted in combination with other - * circumstances. (Zip64 enabled, using UTF8 in comments / names etc.) - * - * When the zero header is not set, the length & checksum need to be - * defined before the file is actually added. To prevent loading all - * the data into memory, the data has to be read twice. If the data - * which is added is not seekable, this call will fail. - * - * @param bool $sendHttpHeaders - * Boolean indicating whether or not to send - * the HTTP headers for this file. - * - * @param ?Closure $httpHeaderCallback - * The method called to send HTTP headers - * - * @param string|null $outputName - * The name of the created archive. - * - * Only relevant if `$sendHttpHeaders = true`. - * - * @param string $contentDisposition - * HTTP Content-Disposition - * - * Only relevant if `sendHttpHeaders = true`. - * - * @param string $contentType - * HTTP Content Type - * - * Only relevant if `sendHttpHeaders = true`. - * - * @param bool $flushOutput - * Enable flush after every write to output stream. - * - * @return self + * In order to let this library send HTTP headers, a filename must be given + * _and_ the option `sendHttpHeaders` must be `true`. This behavior is to + * allow software to send its own headers (including the filename), and + * still use this library. */ - public function __construct( - private OperationMode $operationMode = OperationMode::NORMAL, - private readonly string $comment = '', - $outputStream = null, - private readonly CompressionMethod $defaultCompressionMethod = CompressionMethod::DEFLATE, - private readonly int $defaultDeflateLevel = 6, - private readonly bool $enableZip64 = true, - private readonly bool $defaultEnableZeroHeader = true, - private bool $sendHttpHeaders = true, - ?Closure $httpHeaderCallback = null, - private readonly ?string $outputName = null, - private readonly string $contentDisposition = 'attachment', - private readonly string $contentType = 'application/x-zip', - private bool $flushOutput = false, - ) { - $this->outputStream = self::normalizeStream($outputStream); - $this->httpHeaderCallback = $httpHeaderCallback ?? header(...); + public function __construct(?string $name = null, ?ArchiveOptions $opt = null) + { + $this->opt = $opt ?: new ArchiveOptions(); + + $this->output_name = $name; + $this->need_headers = $name && $this->opt->isSendHttpHeaders(); + + $this->cdr_ofs = new Bigint(); + $this->ofs = new Bigint(); } /** + * addFile + * * Add a file to the archive. * - * ##### File Options + * @param String $name - path of file in archive (including directory). + * @param String $data - contents of file + * @param FileOptions $options * - * See {@see addFileFromPsr7Stream()} + * File Options: + * time - Last-modified timestamp (seconds since the epoch) of + * this file. Defaults to the current time. + * comment - Comment related to this file. + * method - Storage method for file ("store" or "deflate") * - * ##### Examples + * Examples: * - * ```php - * // add a file named 'world.txt' - * $zip->addFile(fileName: 'world.txt', data: 'Hello World!'); + * // add a file named 'foo.txt' + * $data = file_get_contents('foo.txt'); + * $zip->addFile('foo.txt', $data); * - * // add a file named 'bar.jpg' with a comment and a last-modified - * // time of two hours ago - * $zip->addFile( - * fileName: 'bar.jpg', - * data: $data, - * comment: 'this is a comment about bar.jpg', - * lastModificationDateTime: new DateTime('2 hours ago'), - * ); - * ``` - * - * @param string $data - * - * contents of file + * // add a file named 'bar.jpg' with a comment and a last-modified + * // time of two hours ago + * $data = file_get_contents('bar.jpg'); + * $opt->setTime = time() - 2 * 3600; + * $opt->setComment = 'this is a comment about bar.jpg'; + * $zip->addFile('bar.jpg', $data, $opt); */ - public function addFile( - string $fileName, - string $data, - string $comment = '', - ?CompressionMethod $compressionMethod = null, - ?int $deflateLevel = null, - ?DateTimeInterface $lastModificationDateTime = null, - ?int $maxSize = null, - ?int $exactSize = null, - ?bool $enableZeroHeader = null, - ): void { - $this->addFileFromCallback( - fileName: $fileName, - callback: fn() => $data, - comment: $comment, - compressionMethod: $compressionMethod, - deflateLevel: $deflateLevel, - lastModificationDateTime: $lastModificationDateTime, - maxSize: $maxSize, - exactSize: $exactSize, - enableZeroHeader: $enableZeroHeader, - ); + public function addFile(string $name, string $data, ?FileOptions $options = null): void + { + $options = $options ?: new FileOptions(); + $options->defaultTo($this->opt); + + $file = new File($this, $name, $options); + $file->processData($data); } /** + * addFileFromPath + * * Add a file at path to the archive. * - * ##### File Options + * Note that large files may be compressed differently than smaller + * files; see the "Large File Support" section above for more + * information. * - * See {@see addFileFromPsr7Stream()} + * @param String $name - name of file in archive (including directory path). + * @param String $path - path to file on disk (note: paths should be encoded using + * UNIX-style forward slashes -- e.g '/path/to/some/file'). + * @param FileOptions $options * - * ###### Examples + * File Options: + * time - Last-modified timestamp (seconds since the epoch) of + * this file. Defaults to the current time. + * comment - Comment related to this file. + * method - Storage method for file ("store" or "deflate") * - * ```php - * // add a file named 'foo.txt' from the local file '/tmp/foo.txt' - * $zip->addFileFromPath( - * fileName: 'foo.txt', - * path: '/tmp/foo.txt', - * ); + * Examples: * - * // add a file named 'bigfile.rar' from the local file - * // '/usr/share/bigfile.rar' with a comment and a last-modified - * // time of two hours ago - * $zip->addFileFromPath( - * fileName: 'bigfile.rar', - * path: '/usr/share/bigfile.rar', - * comment: 'this is a comment about bigfile.rar', - * lastModificationDateTime: new DateTime('2 hours ago'), - * ); - * ``` + * // add a file named 'foo.txt' from the local file '/tmp/foo.txt' + * $zip->addFileFromPath('foo.txt', '/tmp/foo.txt'); * + * // add a file named 'bigfile.rar' from the local file + * // '/usr/share/bigfile.rar' with a comment and a last-modified + * // time of two hours ago + * $path = '/usr/share/bigfile.rar'; + * $opt->setTime = time() - 2 * 3600; + * $opt->setComment = 'this is a comment about bar.jpg'; + * $zip->addFileFromPath('bigfile.rar', $path, $opt); + * + * @return void * @throws \ZipStream\Exception\FileNotFoundException * @throws \ZipStream\Exception\FileNotReadableException */ - public function addFileFromPath( - /** - * name of file in archive (including directory path). - */ - string $fileName, + public function addFileFromPath(string $name, string $path, ?FileOptions $options = null): void + { + $options = $options ?: new FileOptions(); + $options->defaultTo($this->opt); - /** - * path to file on disk (note: paths should be encoded using - * UNIX-style forward slashes -- e.g '/path/to/some/file'). - */ - string $path, - string $comment = '', - ?CompressionMethod $compressionMethod = null, - ?int $deflateLevel = null, - ?DateTimeInterface $lastModificationDateTime = null, - ?int $maxSize = null, - ?int $exactSize = null, - ?bool $enableZeroHeader = null, - ): void { - if (!is_readable($path)) { - if (!file_exists($path)) { - throw new FileNotFoundException($path); - } - throw new FileNotReadableException($path); - } - - $fileTime = filemtime($path); - if ($fileTime !== false) { - $lastModificationDateTime ??= (new DateTimeImmutable())->setTimestamp($fileTime); - } - - $this->addFileFromCallback( - fileName: $fileName, - callback: function () use ($path) { - - $stream = fopen($path, 'rb'); - - if (!$stream) { - // @codeCoverageIgnoreStart - throw new ResourceActionException('fopen'); - // @codeCoverageIgnoreEnd - } - - return $stream; - }, - comment: $comment, - compressionMethod: $compressionMethod, - deflateLevel: $deflateLevel, - lastModificationDateTime: $lastModificationDateTime, - maxSize: $maxSize, - exactSize: $exactSize, - enableZeroHeader: $enableZeroHeader, - ); + $file = new File($this, $name, $options); + $file->processPath($path); } /** - * Add an open stream (resource) to the archive. + * addFileFromStream * - * ##### File Options - * - * See {@see addFileFromPsr7Stream()} - * - * ##### Examples - * - * ```php - * // create a temporary file stream and write text to it - * $filePointer = tmpfile(); - * fwrite($filePointer, 'The quick brown fox jumped over the lazy dog.'); - * - * // add a file named 'streamfile.txt' from the content of the stream - * $archive->addFileFromStream( - * fileName: 'streamfile.txt', - * stream: $filePointer, - * ); - * ``` - * - * @param resource $stream contents of file as a stream resource - */ - public function addFileFromStream( - string $fileName, - $stream, - string $comment = '', - ?CompressionMethod $compressionMethod = null, - ?int $deflateLevel = null, - ?DateTimeInterface $lastModificationDateTime = null, - ?int $maxSize = null, - ?int $exactSize = null, - ?bool $enableZeroHeader = null, - ): void { - $this->addFileFromCallback( - fileName: $fileName, - callback: fn() => $stream, - comment: $comment, - compressionMethod: $compressionMethod, - deflateLevel: $deflateLevel, - lastModificationDateTime: $lastModificationDateTime, - maxSize: $maxSize, - exactSize: $exactSize, - enableZeroHeader: $enableZeroHeader, - ); - } - - /** * Add an open stream to the archive. * - * ##### Examples + * @param String $name - path of file in archive (including directory). + * @param resource $stream - contents of file as a stream resource + * @param FileOptions $options * - * ```php - * $stream = $response->getBody(); - * // add a file named 'streamfile.txt' from the content of the stream - * $archive->addFileFromPsr7Stream( - * fileName: 'streamfile.txt', - * stream: $stream, - * ); - * ``` + * File Options: + * time - Last-modified timestamp (seconds since the epoch) of + * this file. Defaults to the current time. + * comment - Comment related to this file. * - * @param string $fileName - * path of file in archive (including directory) + * Examples: * - * @param StreamInterface $stream - * contents of file as a stream resource + * // create a temporary file stream and write text to it + * $fp = tmpfile(); + * fwrite($fp, 'The quick brown fox jumped over the lazy dog.'); * - * @param string $comment - * ZIP comment for this file + * // add a file named 'streamfile.txt' from the content of the stream + * $x->addFileFromStream('streamfile.txt', $fp); * - * @param ?CompressionMethod $compressionMethod - * Override `defaultCompressionMethod` + * @return void + */ + public function addFileFromStream(string $name, $stream, ?FileOptions $options = null): void + { + $options = $options ?: new FileOptions(); + $options->defaultTo($this->opt); + + $file = new File($this, $name, $options); + $file->processStream(new Stream($stream)); + } + + /** + * addFileFromPsr7Stream * - * See {@see __construct()} + * Add an open stream to the archive. * - * @param ?int $deflateLevel - * Override `defaultDeflateLevel` + * @param String $name - path of file in archive (including directory). + * @param StreamInterface $stream - contents of file as a stream resource + * @param FileOptions $options * - * See {@see __construct()} + * File Options: + * time - Last-modified timestamp (seconds since the epoch) of + * this file. Defaults to the current time. + * comment - Comment related to this file. * - * @param ?DateTimeInterface $lastModificationDateTime - * Set last modification time of file. + * Examples: * - * Default: `now` + * $stream = $response->getBody(); + * // add a file named 'streamfile.txt' from the content of the stream + * $x->addFileFromPsr7Stream('streamfile.txt', $stream); * - * @param ?int $maxSize - * Only read `maxSize` bytes from file. - * - * The file is considered done when either reaching `EOF` - * or the `maxSize`. - * - * @param ?int $exactSize - * Read exactly `exactSize` bytes from file. - * If `EOF` is reached before reading `exactSize` bytes, an error will be - * thrown. The parameter allows for faster size calculations if the `stream` - * does not support `fstat` size or is slow and otherwise known beforehand. - * - * @param ?bool $enableZeroHeader - * Override `defaultEnableZeroHeader` - * - * See {@see __construct()} + * @return void */ public function addFileFromPsr7Stream( - string $fileName, + string $name, StreamInterface $stream, - string $comment = '', - ?CompressionMethod $compressionMethod = null, - ?int $deflateLevel = null, - ?DateTimeInterface $lastModificationDateTime = null, - ?int $maxSize = null, - ?int $exactSize = null, - ?bool $enableZeroHeader = null, + ?FileOptions $options = null ): void { - $this->addFileFromCallback( - fileName: $fileName, - callback: fn() => $stream, - comment: $comment, - compressionMethod: $compressionMethod, - deflateLevel: $deflateLevel, - lastModificationDateTime: $lastModificationDateTime, - maxSize: $maxSize, - exactSize: $exactSize, - enableZeroHeader: $enableZeroHeader, - ); + $options = $options ?: new FileOptions(); + $options->defaultTo($this->opt); + + $file = new File($this, $name, $options); + $file->processStream($stream); } /** - * Add a file based on a callback. + * finish * - * This is useful when you want to simulate a lot of files without keeping - * all of the file handles open at the same time. - * - * ##### Examples - * - * ```php - * foreach($files as $name => $size) { - * $archive->addFileFromCallback( - * fileName: 'streamfile.txt', - * exactSize: $size, - * callback: function() use($name): Psr\Http\Message\StreamInterface { - * $response = download($name); - * return $response->getBody(); - * } - * ); - * } - * ``` - * - * @param string $fileName - * path of file in archive (including directory) - * - * @param Closure $callback - * @psalm-param Closure(): (resource|StreamInterface|string) $callback - * A callback to get the file contents in the shape of a PHP stream, - * a Psr StreamInterface implementation, or a string. - * - * @param string $comment - * ZIP comment for this file - * - * @param ?CompressionMethod $compressionMethod - * Override `defaultCompressionMethod` - * - * See {@see __construct()} - * - * @param ?int $deflateLevel - * Override `defaultDeflateLevel` - * - * See {@see __construct()} - * - * @param ?DateTimeInterface $lastModificationDateTime - * Set last modification time of file. - * - * Default: `now` - * - * @param ?int $maxSize - * Only read `maxSize` bytes from file. - * - * The file is considered done when either reaching `EOF` - * or the `maxSize`. - * - * @param ?int $exactSize - * Read exactly `exactSize` bytes from file. - * If `EOF` is reached before reading `exactSize` bytes, an error will be - * thrown. The parameter allows for faster size calculations if the `stream` - * does not support `fstat` size or is slow and otherwise known beforehand. - * - * @param ?bool $enableZeroHeader - * Override `defaultEnableZeroHeader` - * - * See {@see __construct()} - */ - public function addFileFromCallback( - string $fileName, - Closure $callback, - string $comment = '', - ?CompressionMethod $compressionMethod = null, - ?int $deflateLevel = null, - ?DateTimeInterface $lastModificationDateTime = null, - ?int $maxSize = null, - ?int $exactSize = null, - ?bool $enableZeroHeader = null, - ): void { - $file = new File( - dataCallback: function () use ($callback, $maxSize) { - $data = $callback(); - - if (is_resource($data)) { - return $data; - } - - if ($data instanceof StreamInterface) { - return StreamWrapper::getResource($data); - } - - - $stream = fopen('php://memory', 'rw+'); - if ($stream === false) { - // @codeCoverageIgnoreStart - throw new ResourceActionException('fopen'); - // @codeCoverageIgnoreEnd - } - if ($maxSize !== null && fwrite($stream, $data, $maxSize) === false) { - // @codeCoverageIgnoreStart - throw new ResourceActionException('fwrite', $stream); - // @codeCoverageIgnoreEnd - } elseif (fwrite($stream, $data) === false) { - // @codeCoverageIgnoreStart - throw new ResourceActionException('fwrite', $stream); - // @codeCoverageIgnoreEnd - } - if (rewind($stream) === false) { - // @codeCoverageIgnoreStart - throw new ResourceActionException('rewind', $stream); - // @codeCoverageIgnoreEnd - } - - return $stream; - - }, - send: $this->send(...), - recordSentBytes: $this->recordSentBytes(...), - operationMode: $this->operationMode, - fileName: $fileName, - startOffset: $this->offset, - compressionMethod: $compressionMethod ?? $this->defaultCompressionMethod, - comment: $comment, - deflateLevel: $deflateLevel ?? $this->defaultDeflateLevel, - lastModificationDateTime: $lastModificationDateTime ?? new DateTimeImmutable(), - maxSize: $maxSize, - exactSize: $exactSize, - enableZip64: $this->enableZip64, - enableZeroHeader: $enableZeroHeader ?? $this->defaultEnableZeroHeader, - ); - - if ($this->operationMode !== OperationMode::NORMAL) { - $this->recordedSimulation[] = $file; - } - - $this->centralDirectoryRecords[] = $file->process(); - } - - /** - * Add a directory to the archive. - * - * ##### File Options - * - * See {@see addFileFromPsr7Stream()} - * - * ##### Examples - * - * ```php - * // add a directory named 'world/' - * $zip->addDirectory(fileName: 'world/'); - * ``` - */ - public function addDirectory( - string $fileName, - string $comment = '', - ?DateTimeInterface $lastModificationDateTime = null, - ): void { - if (!str_ends_with($fileName, '/')) { - $fileName .= '/'; - } - - $this->addFile( - fileName: $fileName, - data: '', - comment: $comment, - compressionMethod: CompressionMethod::STORE, - deflateLevel: null, - lastModificationDateTime: $lastModificationDateTime, - maxSize: 0, - exactSize: 0, - enableZeroHeader: false, - ); - } - - /** - * Executes a previously calculated simulation. - * - * ##### Example - * - * ```php - * $zip = new ZipStream( - * outputName: 'foo.zip', - * operationMode: OperationMode::SIMULATE_STRICT, - * ); - * - * $zip->addFile('test.txt', 'Hello World'); - * - * $size = $zip->finish(); - * - * header('Content-Length: '. $size); - * - * $zip->executeSimulation(); - * ``` - */ - public function executeSimulation(): void - { - if ($this->operationMode !== OperationMode::NORMAL) { - throw new RuntimeException('Zip simulation is not finished.'); - } - - foreach ($this->recordedSimulation as $file) { - $this->centralDirectoryRecords[] = $file->cloneSimulationExecution()->process(); - } - - $this->finish(); - } - - /** * Write zip footer to stream. * - * The clase is left in an unusable state after `finish`. + * Example: * - * ##### Example + * // add a list of files to the archive + * $files = array('foo.txt', 'bar.jpg'); + * foreach ($files as $path) + * $zip->addFile($path, file_get_contents($path)); * - * ```php - * // write footer to stream - * $zip->finish(); - * ``` + * // write footer to stream + * $zip->finish(); + * @return void + * + * @throws OverflowException */ - public function finish(): int + public function finish(): void { - $centralDirectoryStartOffsetOnDisk = $this->offset; - $sizeOfCentralDirectory = 0; - // add trailing cdr file records - foreach ($this->centralDirectoryRecords as $centralDirectoryRecord) { - $this->send($centralDirectoryRecord); - $sizeOfCentralDirectory += strlen($centralDirectoryRecord); + foreach ($this->files as $cdrFile) { + $this->send($cdrFile); + $this->cdr_ofs = $this->cdr_ofs->add(Bigint::init(strlen($cdrFile))); } // Add 64bit headers (if applicable) - if (count($this->centralDirectoryRecords) >= 0xFFFF || - $centralDirectoryStartOffsetOnDisk > 0xFFFFFFFF || - $sizeOfCentralDirectory > 0xFFFFFFFF) { - if (!$this->enableZip64) { + if (count($this->files) >= 0xFFFF || + $this->cdr_ofs->isOver32() || + $this->ofs->isOver32()) { + if (!$this->opt->isEnableZip64()) { throw new OverflowException(); } - $this->send(Zip64\EndOfCentralDirectory::generate( - versionMadeBy: self::ZIP_VERSION_MADE_BY, - versionNeededToExtract: Version::ZIP64->value, - numberOfThisDisk: 0, - numberOfTheDiskWithCentralDirectoryStart: 0, - numberOfCentralDirectoryEntriesOnThisDisk: count($this->centralDirectoryRecords), - numberOfCentralDirectoryEntries: count($this->centralDirectoryRecords), - sizeOfCentralDirectory: $sizeOfCentralDirectory, - centralDirectoryStartOffsetOnDisk: $centralDirectoryStartOffsetOnDisk, - extensibleDataSector: '', - )); - - $this->send(Zip64\EndOfCentralDirectoryLocator::generate( - numberOfTheDiskWithZip64CentralDirectoryStart: 0x00, - zip64centralDirectoryStartOffsetOnDisk: $centralDirectoryStartOffsetOnDisk + $sizeOfCentralDirectory, - totalNumberOfDisks: 1, - )); + $this->addCdr64Eof(); + $this->addCdr64Locator(); } // add trailing cdr eof record - $numberOfCentralDirectoryEntries = min(count($this->centralDirectoryRecords), 0xFFFF); - $this->send(EndOfCentralDirectory::generate( - numberOfThisDisk: 0x00, - numberOfTheDiskWithCentralDirectoryStart: 0x00, - numberOfCentralDirectoryEntriesOnThisDisk: $numberOfCentralDirectoryEntries, - numberOfCentralDirectoryEntries: $numberOfCentralDirectoryEntries, - sizeOfCentralDirectory: min($sizeOfCentralDirectory, 0xFFFFFFFF), - centralDirectoryStartOffsetOnDisk: min($centralDirectoryStartOffsetOnDisk, 0xFFFFFFFF), - zipFileComment: $this->comment, - )); - - $size = $this->offset; + $this->addCdrEof(); // The End $this->clear(); - - return $size; } /** - * @param StreamInterface|resource|null $outputStream - * @return resource + * Create a format string and argument list for pack(), then call + * pack() and return the result. + * + * @param array $fields + * @return string */ - private static function normalizeStream($outputStream) + public static function packFields(array $fields): string { - if ($outputStream instanceof StreamInterface) { - return StreamWrapper::getResource($outputStream); - } - if (is_resource($outputStream)) { - return $outputStream; - } - $resource = fopen('php://output', 'wb'); + $fmt = ''; + $args = []; - if ($resource === false) { - throw new RuntimeException('fopen of php://output failed'); + // populate format string and argument list + foreach ($fields as [$format, $value]) { + if ($format === 'P') { + $fmt .= 'VV'; + if ($value instanceof Bigint) { + $args[] = $value->getLow32(); + $args[] = $value->getHigh32(); + } else { + $args[] = $value; + $args[] = 0; + } + } else { + if ($value instanceof Bigint) { + $value = $value->getLow32(); + } + $fmt .= $format; + $args[] = $value; + } } - return $resource; - } + // prepend format string to argument list + array_unshift($args, $fmt); - /** - * Record sent bytes - */ - private function recordSentBytes(int $sentBytes): void - { - $this->offset += $sentBytes; + // build output string from header and compressed data + return pack(...$args); } /** * Send string, sending HTTP headers if necessary. * Flush output after write if configure option is set. + * + * @param String $str + * @return void */ - private function send(string $data): void + public function send(string $str): void { - if (!$this->ready) { - throw new RuntimeException('Archive is already finished'); - } - - if ($this->operationMode === OperationMode::NORMAL && $this->sendHttpHeaders) { + if ($this->need_headers) { $this->sendHttpHeaders(); - $this->sendHttpHeaders = false; + } + $this->need_headers = false; + + $outputStream = $this->opt->getOutputStream(); + + if ($outputStream instanceof StreamInterface) { + $outputStream->write($str); + } else { + fwrite($outputStream, $str); } - $this->recordSentBytes(strlen($data)); - - if ($this->operationMode === OperationMode::NORMAL) { - if (fwrite($this->outputStream, $data) === false) { - throw new ResourceActionException('fwrite', $this->outputStream); + if ($this->opt->isFlushOutput()) { + // flush output buffer if it is on and flushable + $status = ob_get_status(); + if (isset($status['flags']) && ($status['flags'] & PHP_OUTPUT_HANDLER_FLUSHABLE)) { + ob_flush(); } - if ($this->flushOutput) { - // flush output buffer if it is on and flushable - $status = ob_get_status(); - if (isset($status['flags']) && is_int($status['flags']) && ($status['flags'] & PHP_OUTPUT_HANDLER_FLUSHABLE)) { - ob_flush(); - } - - // Flush system buffers after flushing userspace output buffer - flush(); - } + // Flush system buffers after flushing userspace output buffer + flush(); } } /** - * Send HTTP headers for this stream. - */ - private function sendHttpHeaders(): void + * Is this file larger than large_file_size? + * + * @param string $path + * @return bool + */ + public function isLargeFile(string $path): bool + { + if (!$this->opt->isStatFiles()) { + return false; + } + $stat = stat($path); + return $stat['size'] > $this->opt->getLargeFileSize(); + } + + /** + * Save file attributes for trailing CDR record. + * + * @param File $file + * @return void + */ + public function addToCdr(File $file): void + { + $file->ofs = $this->ofs; + $this->ofs = $this->ofs->add($file->getTotalLength()); + $this->files[] = $file->getCdrFile(); + } + + /** + * Send ZIP64 CDR EOF (Central Directory Record End-of-File) record. + * + * @return void + */ + protected function addCdr64Eof(): void + { + $num_files = count($this->files); + $cdr_length = $this->cdr_ofs; + $cdr_offset = $this->ofs; + + $fields = [ + ['V', static::ZIP64_CDR_EOF_SIGNATURE], // ZIP64 end of central file header signature + ['P', 44], // Length of data below this header (length of block - 12) = 44 + ['v', static::ZIP_VERSION_MADE_BY], // Made by version + ['v', Version::ZIP64], // Extract by version + ['V', 0x00], // disk number + ['V', 0x00], // no of disks + ['P', $num_files], // no of entries on disk + ['P', $num_files], // no of entries in cdr + ['P', $cdr_length], // CDR size + ['P', $cdr_offset], // CDR offset + ]; + + $ret = static::packFields($fields); + $this->send($ret); + } + + /** + * Send HTTP headers for this stream. + * + * @return void + */ + protected function sendHttpHeaders(): void { // grab content disposition - $disposition = $this->contentDisposition; + $disposition = $this->opt->getContentDisposition(); - if ($this->outputName !== null) { + if ($this->output_name) { // Various different browsers dislike various characters here. Strip them all for safety. - $safeOutput = trim(str_replace(['"', "'", '\\', ';', "\n", "\r"], '', $this->outputName)); + $safe_output = trim(str_replace(['"', "'", '\\', ';', "\n", "\r"], '', $this->output_name)); // Check if we need to UTF-8 encode the filename - $urlencoded = rawurlencode($safeOutput); + $urlencoded = rawurlencode($safe_output); $disposition .= "; filename*=UTF-8''{$urlencoded}"; } $headers = [ - 'Content-Type' => $this->contentType, + 'Content-Type' => $this->opt->getContentType(), 'Content-Disposition' => $disposition, 'Pragma' => 'public', 'Cache-Control' => 'public, must-revalidate', 'Content-Transfer-Encoding' => 'binary', ]; + $call = $this->opt->getHttpHeaderCallback(); foreach ($headers as $key => $val) { - ($this->httpHeaderCallback)("$key: $val"); + $call("$key: $val"); } } + /** + * Send ZIP64 CDR Locator (Central Directory Record Locator) record. + * + * @return void + */ + protected function addCdr64Locator(): void + { + $cdr_offset = $this->ofs->add($this->cdr_ofs); + + $fields = [ + ['V', static::ZIP64_CDR_LOCATOR_SIGNATURE], // ZIP64 end of central file header signature + ['V', 0x00], // Disc number containing CDR64EOF + ['P', $cdr_offset], // CDR offset + ['V', 1], // Total number of disks + ]; + + $ret = static::packFields($fields); + $this->send($ret); + } + + /** + * Send CDR EOF (Central Directory Record End-of-File) record. + * + * @return void + */ + protected function addCdrEof(): void + { + $num_files = count($this->files); + $cdr_length = $this->cdr_ofs; + $cdr_offset = $this->ofs; + + // grab comment (if specified) + $comment = $this->opt->getComment(); + + $fields = [ + ['V', static::CDR_EOF_SIGNATURE], // end of central file header signature + ['v', 0x00], // disk number + ['v', 0x00], // no of disks + ['v', min($num_files, 0xFFFF)], // no of entries on disk + ['v', min($num_files, 0xFFFF)], // no of entries in cdr + ['V', $cdr_length->getLowFF()], // CDR size + ['V', $cdr_offset->getLowFF()], // CDR offset + ['v', strlen($comment)], // Zip Comment size + ]; + + $ret = static::packFields($fields) . $comment; + $this->send($ret); + } + /** * Clear all internal variables. Note that the stream object is not * usable after this. + * + * @return void */ - private function clear(): void + protected function clear(): void { - $this->centralDirectoryRecords = []; - $this->offset = 0; - - if ($this->operationMode === OperationMode::NORMAL) { - $this->ready = false; - $this->recordedSimulation = []; - } else { - $this->operationMode = OperationMode::NORMAL; - } + $this->files = []; + $this->ofs = new Bigint(); + $this->cdr_ofs = new Bigint(); + $this->opt = new ArchiveOptions(); } } diff --git a/vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php b/vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php deleted file mode 100644 index bf621bc..0000000 --- a/vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php +++ /dev/null @@ -1,23 +0,0 @@ -fail("File {$filePath} must contain {$needle}"); - } - - protected function assertFileDoesNotContain(string $filePath, string $needle): void - { - $last = ''; - - $handle = fopen($filePath, 'r'); - while (!feof($handle)) { - $line = fgets($handle, 1024); - - if (str_contains($last . $line, $needle)) { - fclose($handle); - - $this->fail("File {$filePath} must not contain {$needle}"); - } - - $last = $line; - } - - fclose($handle); - } -} diff --git a/vendor/maennchen/zipstream-php/test/BigintTest.php b/vendor/maennchen/zipstream-php/test/BigintTest.php new file mode 100644 index 0000000..4d26fcd --- /dev/null +++ b/vendor/maennchen/zipstream-php/test/BigintTest.php @@ -0,0 +1,66 @@ +assertSame('0x0000000012345678', $bigint->getHex64()); + $this->assertSame(0x12345678, $bigint->getLow32()); + $this->assertSame(0, $bigint->getHigh32()); + } + + public function testConstructLarge(): void + { + $bigint = new Bigint(0x87654321); + $this->assertSame('0x0000000087654321', $bigint->getHex64()); + $this->assertSame('87654321', bin2hex(pack('N', $bigint->getLow32()))); + $this->assertSame(0, $bigint->getHigh32()); + } + + public function testAddSmallValue(): void + { + $bigint = new Bigint(1); + $bigint = $bigint->add(Bigint::init(2)); + $this->assertSame(3, $bigint->getLow32()); + $this->assertFalse($bigint->isOver32()); + $this->assertTrue($bigint->isOver32(true)); + $this->assertSame($bigint->getLowFF(), (float)$bigint->getLow32()); + $this->assertSame($bigint->getLowFF(true), (float)0xFFFFFFFF); + } + + public function testAddWithOverflowAtLowestByte(): void + { + $bigint = new Bigint(0xFF); + $bigint = $bigint->add(Bigint::init(0x01)); + $this->assertSame(0x100, $bigint->getLow32()); + } + + public function testAddWithOverflowAtInteger32(): void + { + $bigint = new Bigint(0xFFFFFFFE); + $this->assertFalse($bigint->isOver32()); + $bigint = $bigint->add(Bigint::init(0x01)); + $this->assertTrue($bigint->isOver32()); + $bigint = $bigint->add(Bigint::init(0x01)); + $this->assertSame('0x0000000100000000', $bigint->getHex64()); + $this->assertTrue($bigint->isOver32()); + $this->assertSame((float)0xFFFFFFFF, $bigint->getLowFF()); + } + + public function testAddWithOverflowAtInteger64(): void + { + $bigint = Bigint::fromLowHigh(0xFFFFFFFF, 0xFFFFFFFF); + $this->assertSame('0xFFFFFFFFFFFFFFFF', $bigint->getHex64()); + $this->expectException(OverflowException::class); + $bigint->add(Bigint::init(1)); + } +} diff --git a/vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php b/vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php deleted file mode 100644 index 5457b4f..0000000 --- a/vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php +++ /dev/null @@ -1,60 +0,0 @@ -assertSame( - bin2hex($header), - '504b0102' . // 4 bytes; central file header signature - '0306' . // 2 bytes; version made by - '2d00' . // 2 bytes; version needed to extract - '2222' . // 2 bytes; general purpose bit flag - '0800' . // 2 bytes; compression method - '2008' . // 2 bytes; last mod file time - '2154' . // 2 bytes; last mod file date - '11111111' . // 4 bytes; crc-32 - '77777777' . // 4 bytes; compressed size - '99999999' . // 4 bytes; uncompressed size - '0800' . // 2 bytes; file name length (n) - '0c00' . // 2 bytes; extra field length (m) - '0c00' . // 2 bytes; file comment length (o) - '0000' . // 2 bytes; disk number start - '0000' . // 2 bytes; internal file attributes - '20000000' . // 4 bytes; external file attributes - '34120000' . // 4 bytes; relative offset of local header - '746573742e706e67' . // n bytes; file name - '736f6d6520636f6e74656e74' . // m bytes; extra field - '736f6d6520636f6d6d656e74' // o bytes; file comment - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/DataDescriptorTest.php b/vendor/maennchen/zipstream-php/test/DataDescriptorTest.php deleted file mode 100644 index cc886c7..0000000 --- a/vendor/maennchen/zipstream-php/test/DataDescriptorTest.php +++ /dev/null @@ -1,26 +0,0 @@ -assertSame( - bin2hex(DataDescriptor::generate( - crc32UncompressedData: 0x11111111, - compressedSize: 0x77777777, - uncompressedSize: 0x99999999, - )), - '504b0708' . // 4 bytes; Optional data descriptor signature = 0x08074b50 - '11111111' . // 4 bytes; CRC-32 of uncompressed data - '77777777' . // 4 bytes; Compressed size - '99999999' // 4 bytes; Uncompressed size - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php b/vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php deleted file mode 100644 index be0a907..0000000 --- a/vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php +++ /dev/null @@ -1,35 +0,0 @@ -assertSame( - bin2hex(EndOfCentralDirectory::generate( - numberOfThisDisk: 0x00, - numberOfTheDiskWithCentralDirectoryStart: 0x00, - numberOfCentralDirectoryEntriesOnThisDisk: 0x10, - numberOfCentralDirectoryEntries: 0x10, - sizeOfCentralDirectory: 0x22, - centralDirectoryStartOffsetOnDisk: 0x33, - zipFileComment: 'foo', - )), - '504b0506' . // 4 bytes; end of central dir signature 0x06054b50 - '0000' . // 2 bytes; number of this disk - '0000' . // 2 bytes; number of the disk with the start of the central directory - '1000' . // 2 bytes; total number of entries in the central directory on this disk - '1000' . // 2 bytes; total number of entries in the central directory - '22000000' . // 4 bytes; size of the central directory - '33000000' . // 4 bytes; offset of start of central directory with respect to the starting disk number - '0300' . // 2 bytes; .ZIP file comment length - bin2hex('foo') - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/EndlessCycleStream.php b/vendor/maennchen/zipstream-php/test/EndlessCycleStream.php deleted file mode 100644 index d9e7df1..0000000 --- a/vendor/maennchen/zipstream-php/test/EndlessCycleStream.php +++ /dev/null @@ -1,104 +0,0 @@ -detach(); - } - - /** - * @return null - */ - public function detach() - { - return; - } - - public function getSize(): ?int - { - return null; - } - - public function tell(): int - { - return $this->offset; - } - - public function eof(): bool - { - return false; - } - - public function isSeekable(): bool - { - return true; - } - - public function seek(int $offset, int $whence = SEEK_SET): void - { - switch ($whence) { - case SEEK_SET: - $this->offset = $offset; - break; - case SEEK_CUR: - $this->offset += $offset; - break; - case SEEK_END: - throw new RuntimeException('Infinite Stream!'); - break; - } - } - - public function rewind(): void - { - $this->seek(0); - } - - public function isWritable(): bool - { - return false; - } - - public function write(string $string): int - { - throw new RuntimeException('Not writeable'); - } - - public function isReadable(): bool - { - return true; - } - - public function read(int $length): string - { - $this->offset += $length; - return substr(str_repeat($this->toRepeat, (int) ceil($length / strlen($this->toRepeat))), 0, $length); - } - - public function getContents(): string - { - throw new RuntimeException('Infinite Stream!'); - } - - public function getMetadata(?string $key = null): array|null - { - return $key !== null ? null : []; - } -} diff --git a/vendor/maennchen/zipstream-php/test/FaultInjectionResource.php b/vendor/maennchen/zipstream-php/test/FaultInjectionResource.php deleted file mode 100644 index af9305b..0000000 --- a/vendor/maennchen/zipstream-php/test/FaultInjectionResource.php +++ /dev/null @@ -1,141 +0,0 @@ -context); - - if (!isset($options[self::NAME]['injectFaults'])) { - return false; - } - - $this->mode = $mode; - $this->injectFaults = $options[self::NAME]['injectFaults']; - - if ($this->shouldFail(__FUNCTION__)) { - return false; - } - - return true; - } - - public function stream_write(string $data) - { - if ($this->shouldFail(__FUNCTION__)) { - return false; - } - return true; - } - - public function stream_eof() - { - return true; - } - - public function stream_seek(int $offset, int $whence): bool - { - if ($this->shouldFail(__FUNCTION__)) { - return false; - } - - return true; - } - - public function stream_tell(): int - { - if ($this->shouldFail(__FUNCTION__)) { - return false; - } - - return 0; - } - - public static function register(): void - { - if (!in_array(self::NAME, stream_get_wrappers(), true)) { - stream_wrapper_register(self::NAME, __CLASS__); - } - } - - public function stream_stat(): array - { - static $modeMap = [ - 'r' => 33060, - 'rb' => 33060, - 'r+' => 33206, - 'w' => 33188, - 'wb' => 33188, - ]; - - return [ - 'dev' => 0, - 'ino' => 0, - 'mode' => $modeMap[$this->mode], - 'nlink' => 0, - 'uid' => 0, - 'gid' => 0, - 'rdev' => 0, - 'size' => 0, - 'atime' => 0, - 'mtime' => 0, - 'ctime' => 0, - 'blksize' => 0, - 'blocks' => 0, - ]; - } - - public function url_stat(string $path, int $flags): array - { - return [ - 'dev' => 0, - 'ino' => 0, - 'mode' => 0, - 'nlink' => 0, - 'uid' => 0, - 'gid' => 0, - 'rdev' => 0, - 'size' => 0, - 'atime' => 0, - 'mtime' => 0, - 'ctime' => 0, - 'blksize' => 0, - 'blocks' => 0, - ]; - } - - private static function createStreamContext(array $injectFaults) - { - return stream_context_create([ - self::NAME => ['injectFaults' => $injectFaults], - ]); - } - - private function shouldFail(string $function): bool - { - return in_array($function, $this->injectFaults, true); - } -} diff --git a/vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php b/vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php deleted file mode 100644 index 196dd0f..0000000 --- a/vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php +++ /dev/null @@ -1,47 +0,0 @@ -assertSame( - bin2hex((string) $header), - '504b0304' . // 4 bytes; Local file header signature - '2d00' . // 2 bytes; Version needed to extract (minimum) - '2222' . // 2 bytes; General purpose bit flag - '0800' . // 2 bytes; Compression method; e.g. none = 0, DEFLATE = 8 - '2008' . // 2 bytes; File last modification time - '2154' . // 2 bytes; File last modification date - '11111111' . // 4 bytes; CRC-32 of uncompressed data - '77777777' . // 4 bytes; Compressed size (or 0xffffffff for ZIP64) - '99999999' . // 4 bytes; Uncompressed size (or 0xffffffff for ZIP64) - '0800' . // 2 bytes; File name length (n) - '0c00' . // 2 bytes; Extra field length (m) - '746573742e706e67' . // n bytes; File name - '736f6d6520636f6e74656e74' // m bytes; Extra field - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/PackFieldTest.php b/vendor/maennchen/zipstream-php/test/PackFieldTest.php deleted file mode 100644 index ecd66ba..0000000 --- a/vendor/maennchen/zipstream-php/test/PackFieldTest.php +++ /dev/null @@ -1,42 +0,0 @@ -assertSame( - bin2hex(PackField::pack(new PackField(format: 'v', value: 0x1122))), - '2211', - ); - } - - public function testOverflow2(): void - { - $this->expectException(RuntimeException::class); - - PackField::pack(new PackField(format: 'v', value: 0xFFFFF)); - } - - public function testOverflow4(): void - { - $this->expectException(RuntimeException::class); - - PackField::pack(new PackField(format: 'V', value: 0xFFFFFFFFF)); - } - - public function testUnknownOperator(): void - { - $this->assertSame( - bin2hex(PackField::pack(new PackField(format: 'a', value: 0x1122))), - '34', - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/ResourceStream.php b/vendor/maennchen/zipstream-php/test/ResourceStream.php deleted file mode 100644 index 752a1a3..0000000 --- a/vendor/maennchen/zipstream-php/test/ResourceStream.php +++ /dev/null @@ -1,159 +0,0 @@ -isSeekable()) { - $this->seek(0); - } - return (string) stream_get_contents($this->stream); - } - - public function close(): void - { - $stream = $this->detach(); - if ($stream) { - fclose($stream); - } - } - - public function detach() - { - $result = $this->stream; - // According to the interface, the stream is left in an unusable state; - /** @psalm-suppress PossiblyNullPropertyAssignmentValue */ - $this->stream = null; - return $result; - } - - public function seek(int $offset, int $whence = SEEK_SET): void - { - if (!$this->isSeekable()) { - throw new RuntimeException(); - } - if (fseek($this->stream, $offset, $whence) !== 0) { - // @codeCoverageIgnoreStart - throw new RuntimeException(); - // @codeCoverageIgnoreEnd - } - } - - public function isSeekable(): bool - { - return (bool) $this->getMetadata('seekable'); - } - - public function getMetadata(?string $key = null) - { - $metadata = stream_get_meta_data($this->stream); - return $key !== null ? @$metadata[$key] : $metadata; - } - - public function getSize(): ?int - { - $stats = fstat($this->stream); - return $stats['size']; - } - - public function tell(): int - { - $position = ftell($this->stream); - if ($position === false) { - // @codeCoverageIgnoreStart - throw new RuntimeException(); - // @codeCoverageIgnoreEnd - } - return $position; - } - - public function eof(): bool - { - return feof($this->stream); - } - - public function rewind(): void - { - $this->seek(0); - } - - public function write(string $string): int - { - if (!$this->isWritable()) { - throw new RuntimeException(); - } - if (fwrite($this->stream, $string) === false) { - // @codeCoverageIgnoreStart - throw new RuntimeException(); - // @codeCoverageIgnoreEnd - } - return strlen($string); - } - - public function isWritable(): bool - { - $mode = $this->getMetadata('mode'); - if (!is_string($mode)) { - // @codeCoverageIgnoreStart - throw new RuntimeException('Could not get stream mode from metadata!'); - // @codeCoverageIgnoreEnd - } - return preg_match('/[waxc+]/', $mode) === 1; - } - - public function read(int $length): string - { - if (!$this->isReadable()) { - throw new RuntimeException(); - } - $result = fread($this->stream, $length); - if ($result === false) { - // @codeCoverageIgnoreStart - throw new RuntimeException(); - // @codeCoverageIgnoreEnd - } - return $result; - } - - public function isReadable(): bool - { - $mode = $this->getMetadata('mode'); - if (!is_string($mode)) { - // @codeCoverageIgnoreStart - throw new RuntimeException('Could not get stream mode from metadata!'); - // @codeCoverageIgnoreEnd - } - return preg_match('/[r+]/', $mode) === 1; - } - - public function getContents(): string - { - if (!$this->isReadable()) { - throw new RuntimeException(); - } - $result = stream_get_contents($this->stream); - if ($result === false) { - // @codeCoverageIgnoreStart - throw new RuntimeException(); - // @codeCoverageIgnoreEnd - } - return $result; - } -} diff --git a/vendor/maennchen/zipstream-php/test/Tempfile.php b/vendor/maennchen/zipstream-php/test/Tempfile.php deleted file mode 100644 index 7ef9c61..0000000 --- a/vendor/maennchen/zipstream-php/test/Tempfile.php +++ /dev/null @@ -1,42 +0,0 @@ -getTmpFileStream(); - - $this->tempfile = $tempfile; - $this->tempfileStream = $tempfileStream; - } - - protected function tearDown(): void - { - unlink($this->tempfile); - if (is_resource($this->tempfileStream)) { - fclose($this->tempfileStream); - } - - $this->tempfile = null; - $this->tempfileStream = null; - } - - protected function getTmpFileStream(): array - { - $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest'); - $stream = fopen($tmp, 'wb+'); - - return [$tmp, $stream]; - } -} diff --git a/vendor/maennchen/zipstream-php/test/TimeTest.php b/vendor/maennchen/zipstream-php/test/TimeTest.php deleted file mode 100644 index 61cfe03..0000000 --- a/vendor/maennchen/zipstream-php/test/TimeTest.php +++ /dev/null @@ -1,44 +0,0 @@ -assertSame( - Time::dateTimeToDosTime(new DateTimeImmutable('2014-11-17T17:46:08Z')), - 1165069764 - ); - - // January 1 1980 - DOS Epoch. - $this->assertSame( - Time::dateTimeToDosTime(new DateTimeImmutable('1980-01-01T00:00:00+00:00')), - 2162688 - ); - - // Local timezone different than UTC. - $prevLocalTimezone = date_default_timezone_get(); - date_default_timezone_set('Europe/Berlin'); - $this->assertSame( - Time::dateTimeToDosTime(new DateTimeImmutable('1980-01-01T00:00:00+00:00')), - 2162688 - ); - date_default_timezone_set($prevLocalTimezone); - } - - public function testTooEarlyDateToDosTime(): void - { - $this->expectException(DosTimeOverflowException::class); - - // January 1 1980 is the minimum DOS Epoch. - Time::dateTimeToDosTime(new DateTimeImmutable('1970-01-01T00:00:00+00:00')); - } -} diff --git a/vendor/maennchen/zipstream-php/test/Util.php b/vendor/maennchen/zipstream-php/test/Util.php deleted file mode 100644 index 86592b4..0000000 --- a/vendor/maennchen/zipstream-php/test/Util.php +++ /dev/null @@ -1,127 +0,0 @@ -cmdExists('hexdump')) { - return ''; - } - - $output = []; - - if (!exec("hexdump -C \"$path\" | head -n 50", $output)) { - return ''; - } - - return "\nHexdump:\n" . implode("\n", $output); - } - - protected function validateAndExtractZip(string $zipPath): string - { - $tmpDir = $this->getTmpDir(); - - $zipArchive = new ZipArchive(); - $result = $zipArchive->open($zipPath); - - if ($result !== true) { - $codeName = $this->zipArchiveOpenErrorCodeName($result); - $debugInformation = $this->dumpZipContents($zipPath); - - $this->fail("Failed to open {$zipPath}. Code: $result ($codeName)$debugInformation"); - - return $tmpDir; - } - - $this->assertSame(0, $zipArchive->status); - $this->assertSame(0, $zipArchive->statusSys); - - $zipArchive->extractTo($tmpDir); - $zipArchive->close(); - - return $tmpDir; - } - - protected function zipArchiveOpenErrorCodeName(int $code): string - { - switch ($code) { - case ZipArchive::ER_EXISTS: return 'ER_EXISTS'; - case ZipArchive::ER_INCONS: return 'ER_INCONS'; - case ZipArchive::ER_INVAL: return 'ER_INVAL'; - case ZipArchive::ER_MEMORY: return 'ER_MEMORY'; - case ZipArchive::ER_NOENT: return 'ER_NOENT'; - case ZipArchive::ER_NOZIP: return 'ER_NOZIP'; - case ZipArchive::ER_OPEN: return 'ER_OPEN'; - case ZipArchive::ER_READ: return 'ER_READ'; - case ZipArchive::ER_SEEK: return 'ER_SEEK'; - default: return 'unknown'; - } - } - - protected function getTmpDir(): string - { - $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest'); - unlink($tmp); - mkdir($tmp) or $this->fail('Failed to make directory'); - - return $tmp; - } - - /** - * @return string[] - */ - protected function getRecursiveFileList(string $path, bool $includeDirectories = false): array - { - $data = []; - $path = (string) realpath($path); - $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); - - $pathLen = strlen($path); - foreach ($files as $file) { - $filePath = $file->getRealPath(); - - if (is_dir($filePath) && !$includeDirectories) { - continue; - } - - $data[] = substr($filePath, $pathLen + 1); - } - - sort($data); - - return $data; - } -} diff --git a/vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php b/vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php deleted file mode 100644 index 49fb2cc..0000000 --- a/vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -assertSame( - bin2hex($descriptor), - '504b0708' . // 4 bytes; Optional data descriptor signature = 0x08074b50 - '11111111' . // 4 bytes; CRC-32 of uncompressed data - '6666666677777777' . // 8 bytes; Compressed size - '8888888899999999' // 8 bytes; Uncompressed size - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php b/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php deleted file mode 100644 index 271a298..0000000 --- a/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -assertSame( - bin2hex($descriptor), - '504b0607' . // 4 bytes; zip64 end of central dir locator signature - 0x07064b50 - '11111111' . // 4 bytes; number of the disk with the start of the zip64 end of central directory - '3333333322222222' . // 28 bytes; relative offset of the zip64 end of central directory record - '44444444' // 4 bytes;total number of disks - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php b/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php deleted file mode 100644 index b86fb17..0000000 --- a/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php +++ /dev/null @@ -1,41 +0,0 @@ -assertSame( - bin2hex($descriptor), - '504b0606' . // 4 bytes;zip64 end of central dir signature - 0x06064b50 - '2f00000000000000' . // 8 bytes; size of zip64 end of central directory record - '3333' . // 2 bytes; version made by - '4444' . // 2 bytes; version needed to extract - '55555555' . // 4 bytes; number of this disk - '66666666' . // 4 bytes; number of the disk with the start of the central directory - '8888888877777777' . // 8 bytes; total number of entries in the central directory on this disk - 'aaaaaaaa99999999' . // 8 bytes; total number of entries in the central directory - 'ccccccccbbbbbbbb' . // 8 bytes; size of the central directory - 'eeeeeeeedddddddd' . // 8 bytes; offset of start of central directory with respect to the starting disk number - bin2hex('foo') - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php b/vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php deleted file mode 100644 index 904783d..0000000 --- a/vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php +++ /dev/null @@ -1,42 +0,0 @@ -assertSame( - bin2hex($extraField), - '0100' . // 2 bytes; Tag for this "extra" block type - '1c00' . // 2 bytes; Size of this "extra" block - '6666666677777777' . // 8 bytes; Original uncompressed file size - '8888888899999999' . // 8 bytes; Size of compressed data - '1111111122222222' . // 8 bytes; Offset of local header record - '33333333' // 4 bytes; Number of the disk on which this file starts - ); - } - - public function testSerializesEmptyCorrectly(): void - { - $extraField = ExtendedInformationExtraField::generate(); - - $this->assertSame( - bin2hex($extraField), - '0100' . // 2 bytes; Tag for this "extra" block type - '0000' // 2 bytes; Size of this "extra" block - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/ZipStreamTest.php b/vendor/maennchen/zipstream-php/test/ZipStreamTest.php index f4ead1d..0aa6535 100644 --- a/vendor/maennchen/zipstream-php/test/ZipStreamTest.php +++ b/vendor/maennchen/zipstream-php/test/ZipStreamTest.php @@ -2,49 +2,80 @@ declare(strict_types=1); -namespace ZipStream\Test; +namespace ZipStreamTest; -use DateTimeImmutable; use GuzzleHttp\Psr7\Response; -use GuzzleHttp\Psr7\StreamWrapper; use org\bovigo\vfs\vfsStream; -use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use Psr\Http\Message\StreamInterface; -use RuntimeException; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use ReflectionClass; use ZipArchive; -use ZipStream\CompressionMethod; -use ZipStream\Exception\FileNotFoundException; -use ZipStream\Exception\FileNotReadableException; -use ZipStream\Exception\FileSizeIncorrectException; -use ZipStream\Exception\OverflowException; -use ZipStream\Exception\ResourceActionException; -use ZipStream\Exception\SimulationFileUnknownException; -use ZipStream\Exception\StreamNotReadableException; -use ZipStream\Exception\StreamNotSeekableException; -use ZipStream\OperationMode; -use ZipStream\PackField; +use ZipStream\File; +use ZipStream\Option\Archive as ArchiveOptions; +use ZipStream\Option\File as FileOptions; +use ZipStream\Option\Method; +use ZipStream\Stream; use ZipStream\ZipStream; +/** + * Test Class for the Main ZipStream CLass + */ class ZipStreamTest extends TestCase { - use Util; - use Assertions; - use Tempfile; + public function testFileNotFoundException(): void + { + $this->expectException(\ZipStream\Exception\FileNotFoundException::class); + // Get ZipStream Object + $zip = new ZipStream(); + + // Trigger error by adding a file which doesn't exist + $zip->addFileFromPath('foobar.php', '/foo/bar/foobar.php'); + } + + public function testFileNotReadableException(): void + { + // create new virtual filesystem + $root = vfsStream::setup('vfs'); + // create a virtual file with no permissions + $file = vfsStream::newFile('foo.txt', 0)->at($root)->setContent('bar'); + $zip = new ZipStream(); + $this->expectException(\ZipStream\Exception\FileNotReadableException::class); + $zip->addFileFromPath('foo.txt', $file->url()); + } + + public function testDostime(): void + { + // Allows testing of protected method + $class = new ReflectionClass(File::class); + $method = $class->getMethod('dostime'); + $method->setAccessible(true); + + $this->assertSame($method->invoke(null, 1416246368), 1165069764); + + // January 1 1980 - DOS Epoch. + $this->assertSame($method->invoke(null, 315532800), 2162688); + + // January 1 1970 -> January 1 1980 due to minimum DOS Epoch. @todo Throw Exception? + $this->assertSame($method->invoke(null, 0), 2162688); + } public function testAddFile(): void { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); $zip->addFile('sample.txt', 'Sample String Data'); $zip->addFile('test/sample.txt', 'More Simple Sample Data'); $zip->finish(); + fclose($stream); - $tmpDir = $this->validateAndExtractZip($this->tempfile); + $tmpDir = $this->validateAndExtractZip($tmp); $files = $this->getRecursiveFileList($tmpDir); $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files); @@ -55,10 +86,12 @@ class ZipStreamTest extends TestCase public function testAddFileUtf8NameComment(): void { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); $name = 'árvíztűrő tükörfúrógép.txt'; $content = 'Sample String Data'; @@ -67,26 +100,32 @@ class ZipStreamTest extends TestCase 'from Hungarian language in lowercase. ' . 'In uppercase: ÁÍŰŐÜÖÚÓÉ'; - $zip->addFile(fileName: $name, data: $content, comment: $comment); - $zip->finish(); + $fileOptions = new FileOptions(); + $fileOptions->setComment($comment); - $tmpDir = $this->validateAndExtractZip($this->tempfile); + $zip->addFile($name, $content, $fileOptions); + $zip->finish(); + fclose($stream); + + $tmpDir = $this->validateAndExtractZip($tmp); $files = $this->getRecursiveFileList($tmpDir); $this->assertSame([$name], $files); $this->assertStringEqualsFile($tmpDir . '/' . $name, $content); - $zipArchive = new ZipArchive(); - $zipArchive->open($this->tempfile); - $this->assertSame($comment, $zipArchive->getCommentName($name)); + $zipArch = new ZipArchive(); + $zipArch->open($tmp); + $this->assertSame($comment, $zipArch->getCommentName($name)); } public function testAddFileUtf8NameNonUtfComment(): void { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); $name = 'á.txt'; $content = 'any'; @@ -98,111 +137,101 @@ class ZipStreamTest extends TestCase // nearly CP850 (DOS-Latin-1) $guessComment = mb_convert_encoding($comment, 'UTF-8', 'CP850'); - $zip->addFile(fileName: $name, data: $content, comment: $comment); + $fileOptions = new FileOptions(); + $fileOptions->setComment($comment); + $zip->addFile($name, $content, $fileOptions); $zip->finish(); + fclose($stream); $zipArch = new ZipArchive(); - $zipArch->open($this->tempfile); + $zipArch->open($tmp); $this->assertSame($guessComment, $zipArch->getCommentName($name)); $this->assertSame($comment, $zipArch->getCommentName($name, ZipArchive::FL_ENC_RAW)); } + public function testAddFileNonUtf8NameUtfComment(): void + { + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); + + $name = mb_convert_encoding('á.txt', 'ISO-8859-2', 'UTF-8'); + $content = 'any'; + $comment = 'á'; + + // @see https://libzip.org/documentation/zip_get_name.html + // + // mb_convert_encoding hasn't CP437. + // nearly CP850 (DOS-Latin-1) + $guessName = mb_convert_encoding($name, 'UTF-8', 'CP850'); + + $fileOptions = new FileOptions(); + $fileOptions->setComment($comment); + + $zip->addFile($name, $content, $fileOptions); + $zip->finish(); + fclose($stream); + + $tmpDir = $this->validateAndExtractZip($tmp); + + $files = $this->getRecursiveFileList($tmpDir); + + $this->assertNotSame([$name], $files); + $this->assertSame([$guessName], $files); + $this->assertStringEqualsFile($tmpDir . '/' . $guessName, $content); + + $zipArch = new ZipArchive(); + $zipArch->open($tmp); + $this->assertSame($guessName, $zipArch->getNameIndex(0)); + $this->assertSame($name, $zipArch->getNameIndex(0, ZipArchive::FL_ENC_RAW)); + $this->assertSame($comment, $zipArch->getCommentName($guessName)); + } + public function testAddFileWithStorageMethod(): void { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); + [$tmp, $stream] = $this->getTmpFileStream(); - $zip->addFile(fileName: 'sample.txt', data: 'Sample String Data', compressionMethod: CompressionMethod::STORE); - $zip->addFile(fileName: 'test/sample.txt', data: 'More Simple Sample Data'); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + + $zip->addFile('sample.txt', 'Sample String Data', $fileOptions); + $zip->addFile('test/sample.txt', 'More Simple Sample Data'); $zip->finish(); + fclose($stream); - $zipArchive = new ZipArchive(); - $zipArchive->open($this->tempfile); + $zipArch = new ZipArchive(); + $zipArch->open($tmp); - $sample1 = $zipArchive->statName('sample.txt'); - $sample12 = $zipArchive->statName('test/sample.txt'); - $this->assertSame($sample1['comp_method'], CompressionMethod::STORE->value); - $this->assertSame($sample12['comp_method'], CompressionMethod::DEFLATE->value); + $sample1 = $zipArch->statName('sample.txt'); + $sample12 = $zipArch->statName('test/sample.txt'); + $this->assertSame($sample1['comp_method'], Method::STORE); + $this->assertSame($sample12['comp_method'], Method::DEFLATE); - $zipArchive->close(); + $zipArch->close(); } public function testAddFileFromPath(): void { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); [$tmpExample, $streamExample] = $this->getTmpFileStream(); fwrite($streamExample, 'Sample String Data'); fclose($streamExample); - $zip->addFileFromPath(fileName: 'sample.txt', path: $tmpExample); - - [$tmpExample, $streamExample] = $this->getTmpFileStream(); - fwrite($streamExample, 'More Simple Sample Data'); - fclose($streamExample); - $zip->addFileFromPath(fileName: 'test/sample.txt', path: $tmpExample); - - $zip->finish(); - - $tmpDir = $this->validateAndExtractZip($this->tempfile); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files); - - $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data'); - $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data'); - - unlink($tmpExample); - } - - public function testAddFileFromPathFileNotFoundException(): void - { - $this->expectException(FileNotFoundException::class); - - // Get ZipStream Object - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); - - // Trigger error by adding a file which doesn't exist - $zip->addFileFromPath(fileName: 'foobar.php', path: '/foo/bar/foobar.php'); - } - - public function testAddFileFromPathFileNotReadableException(): void - { - $this->expectException(FileNotReadableException::class); - - // create new virtual filesystem - $root = vfsStream::setup('vfs'); - // create a virtual file with no permissions - $file = vfsStream::newFile('foo.txt', 0)->at($root)->setContent('bar'); - - // Get ZipStream Object - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); - - $zip->addFileFromPath('foo.txt', $file->url()); - } - - public function testAddFileFromPathWithStorageMethod(): void - { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); - - [$tmpExample, $streamExample] = $this->getTmpFileStream(); - fwrite($streamExample, 'Sample String Data'); - fclose($streamExample); - $zip->addFileFromPath(fileName: 'sample.txt', path: $tmpExample, compressionMethod: CompressionMethod::STORE); + $zip->addFileFromPath('sample.txt', $tmpExample); [$tmpExample, $streamExample] = $this->getTmpFileStream(); fwrite($streamExample, 'More Simple Sample Data'); @@ -210,32 +239,65 @@ class ZipStreamTest extends TestCase $zip->addFileFromPath('test/sample.txt', $tmpExample); $zip->finish(); + fclose($stream); - $zipArchive = new ZipArchive(); - $zipArchive->open($this->tempfile); + $tmpDir = $this->validateAndExtractZip($tmp); - $sample1 = $zipArchive->statName('sample.txt'); - $this->assertSame(CompressionMethod::STORE->value, $sample1['comp_method']); + $files = $this->getRecursiveFileList($tmpDir); + $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files); - $sample2 = $zipArchive->statName('test/sample.txt'); - $this->assertSame(CompressionMethod::DEFLATE->value, $sample2['comp_method']); + $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data'); + $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data'); + } - $zipArchive->close(); + public function testAddFileFromPathWithStorageMethod(): void + { + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + + [$tmpExample, $streamExample] = $this->getTmpFileStream(); + fwrite($streamExample, 'Sample String Data'); + fclose($streamExample); + $zip->addFileFromPath('sample.txt', $tmpExample, $fileOptions); + + [$tmpExample, $streamExample] = $this->getTmpFileStream(); + fwrite($streamExample, 'More Simple Sample Data'); + fclose($streamExample); + $zip->addFileFromPath('test/sample.txt', $tmpExample); + + $zip->finish(); + fclose($stream); + + $zipArch = new ZipArchive(); + $zipArch->open($tmp); + + $sample1 = $zipArch->statName('sample.txt'); + $this->assertSame(Method::STORE, $sample1['comp_method']); + + $sample2 = $zipArch->statName('test/sample.txt'); + $this->assertSame(Method::DEFLATE, $sample2['comp_method']); + + $zipArch->close(); } public function testAddLargeFileFromPath(): void { - foreach ([CompressionMethod::DEFLATE, CompressionMethod::STORE] as $compressionMethod) { - foreach ([false, true] as $zeroHeader) { - foreach ([false, true] as $zip64) { - if ($zeroHeader && $compressionMethod === CompressionMethod::DEFLATE) { + $methods = [Method::DEFLATE(), Method::STORE()]; + $falseTrue = [false, true]; + foreach ($methods as $method) { + foreach ($falseTrue as $zeroHeader) { + foreach ($falseTrue as $zip64) { + if ($zeroHeader && $method->equals(Method::DEFLATE())) { continue; } - $this->addLargeFileFileFromPath( - compressionMethod: $compressionMethod, - zeroHeader: $zeroHeader, - zip64: $zip64 - ); + $this->addLargeFileFileFromPath($method, $zeroHeader, $zip64); } } } @@ -243,27 +305,33 @@ class ZipStreamTest extends TestCase public function testAddFileFromStream(): void { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); // In this test we can't use temporary stream to feed data // because zlib.deflate filter gives empty string before PHP 7 // it works fine with file stream $streamExample = fopen(__FILE__, 'rb'); $zip->addFileFromStream('sample.txt', $streamExample); - fclose($streamExample); +// fclose($streamExample); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); $streamExample2 = fopen('php://temp', 'wb+'); fwrite($streamExample2, 'More Simple Sample Data'); rewind($streamExample2); // move the pointer back to the beginning of file. - $zip->addFileFromStream('test/sample.txt', $streamExample2); //, $fileOptions); - fclose($streamExample2); + $zip->addFileFromStream('test/sample.txt', $streamExample2, $fileOptions); +// fclose($streamExample2); $zip->finish(); + fclose($stream); - $tmpDir = $this->validateAndExtractZip($this->tempfile); + $tmpDir = $this->validateAndExtractZip($tmp); $files = $this->getRecursiveFileList($tmpDir); $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files); @@ -272,409 +340,92 @@ class ZipStreamTest extends TestCase $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data'); } - public function testAddFileFromStreamUnreadableInput(): void - { - $this->expectException(StreamNotReadableException::class); - - [$tmpInput] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); - - $streamUnreadable = fopen($tmpInput, 'w'); - - $zip->addFileFromStream('sample.json', $streamUnreadable); - } - - public function testAddFileFromStreamBrokenOutputWrite(): void - { - $this->expectException(ResourceActionException::class); - - $outputStream = FaultInjectionResource::getResource(['stream_write']); - - $zip = new ZipStream( - outputStream: $outputStream, - sendHttpHeaders: false, - ); - - $zip->addFile('sample.txt', 'foobar'); - } - - public function testAddFileFromStreamBrokenInputRewind(): void - { - $this->expectException(ResourceActionException::class); - - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - defaultEnableZeroHeader: false, - ); - - $fileStream = FaultInjectionResource::getResource(['stream_seek']); - - $zip->addFileFromStream('sample.txt', $fileStream, maxSize: 0); - } - - public function testAddFileFromStreamUnseekableInputWithoutZeroHeader(): void - { - $this->expectException(StreamNotSeekableException::class); - - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - defaultEnableZeroHeader: false, - ); - - if (file_exists('/dev/null')) { - $streamUnseekable = fopen('/dev/null', 'w+'); - } elseif (file_exists('NUL')) { - $streamUnseekable = fopen('NUL', 'w+'); - } else { - $this->markTestSkipped('Needs file /dev/null'); - } - - $zip->addFileFromStream('sample.txt', $streamUnseekable, maxSize: 2); - } - - public function testAddFileFromStreamUnseekableInputWithZeroHeader(): void - { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - defaultEnableZeroHeader: true, - defaultCompressionMethod: CompressionMethod::STORE, - ); - - $streamUnseekable = StreamWrapper::getResource(new class ('test') extends EndlessCycleStream { - public function isSeekable(): bool - { - return false; - } - - public function seek(int $offset, int $whence = SEEK_SET): void - { - throw new RuntimeException('Not seekable'); - } - }); - - $zip->addFileFromStream('sample.txt', $streamUnseekable, maxSize: 7); - - $zip->finish(); - - $tmpDir = $this->validateAndExtractZip($this->tempfile); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.txt'], $files); - - $this->assertSame(filesize($tmpDir . '/sample.txt'), 7); - } - public function testAddFileFromStreamWithStorageMethod(): void { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); $streamExample = fopen('php://temp', 'wb+'); fwrite($streamExample, 'Sample String Data'); rewind($streamExample); // move the pointer back to the beginning of file. - $zip->addFileFromStream('sample.txt', $streamExample, compressionMethod: CompressionMethod::STORE); - fclose($streamExample); + $zip->addFileFromStream('sample.txt', $streamExample, $fileOptions); +// fclose($streamExample); $streamExample2 = fopen('php://temp', 'bw+'); fwrite($streamExample2, 'More Simple Sample Data'); rewind($streamExample2); // move the pointer back to the beginning of file. - $zip->addFileFromStream('test/sample.txt', $streamExample2, compressionMethod: CompressionMethod::DEFLATE); - fclose($streamExample2); + $zip->addFileFromStream('test/sample.txt', $streamExample2); +// fclose($streamExample2); $zip->finish(); + fclose($stream); - $zipArchive = new ZipArchive(); - $zipArchive->open($this->tempfile); + $zipArch = new ZipArchive(); + $zipArch->open($tmp); - $sample1 = $zipArchive->statName('sample.txt'); - $this->assertSame(CompressionMethod::STORE->value, $sample1['comp_method']); + $sample1 = $zipArch->statName('sample.txt'); + $this->assertSame(Method::STORE, $sample1['comp_method']); - $sample2 = $zipArchive->statName('test/sample.txt'); - $this->assertSame(CompressionMethod::DEFLATE->value, $sample2['comp_method']); + $sample2 = $zipArch->statName('test/sample.txt'); + $this->assertSame(Method::DEFLATE, $sample2['comp_method']); - $zipArchive->close(); + $zipArch->close(); } public function testAddFileFromPsr7Stream(): void { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); $body = 'Sample String Data'; $response = new Response(200, [], $body); - $zip->addFileFromPsr7Stream('sample.json', $response->getBody()); - $zip->finish(); + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); - $tmpDir = $this->validateAndExtractZip($this->tempfile); + $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); + $zip->finish(); + fclose($stream); + + $tmpDir = $this->validateAndExtractZip($tmp); $files = $this->getRecursiveFileList($tmpDir); $this->assertSame(['sample.json'], $files); $this->assertStringEqualsFile($tmpDir . '/sample.json', $body); } - #[Group('slow')] - public function testAddLargeFileFromPsr7Stream(): void - { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - enableZip64: true, - ); - - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: new EndlessCycleStream('0'), - maxSize: 0x100000000, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - $zip->finish(); - - $tmpDir = $this->validateAndExtractZip($this->tempfile); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.json'], $files); - $this->assertFileIsReadable($tmpDir . '/sample.json'); - $this->assertStringStartsWith('000000', file_get_contents(filename: $tmpDir . '/sample.json', length: 20)); - } - - public function testContinueFinishedZip(): void - { - $this->expectException(RuntimeException::class); - - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); - $zip->finish(); - - $zip->addFile('sample.txt', '1234'); - } - - #[Group('slow')] - public function testManyFilesWithoutZip64(): void - { - $this->expectException(OverflowException::class); - - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - enableZip64: false, - ); - - for ($i = 0; $i <= 0xFFFF; $i++) { - $zip->addFile('sample' . $i, ''); - } - - $zip->finish(); - } - - #[Group('slow')] - public function testManyFilesWithZip64(): void - { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - enableZip64: true, - ); - - for ($i = 0; $i <= 0xFFFF; $i++) { - $zip->addFile('sample' . $i, ''); - } - - $zip->finish(); - - $tmpDir = $this->validateAndExtractZip($this->tempfile); - - $files = $this->getRecursiveFileList($tmpDir); - - $this->assertSame(count($files), 0x10000); - } - - #[Group('slow')] - public function testLongZipWithout64(): void - { - $this->expectException(OverflowException::class); - - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - enableZip64: false, - defaultCompressionMethod: CompressionMethod::STORE, - ); - - for ($i = 0; $i < 4; $i++) { - $zip->addFileFromPsr7Stream( - fileName: 'sample' . $i, - stream: new EndlessCycleStream('0'), - maxSize: 0xFFFFFFFF, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - } - } - - #[Group('slow')] - public function testLongZipWith64(): void - { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - enableZip64: true, - defaultCompressionMethod: CompressionMethod::STORE, - ); - - for ($i = 0; $i < 4; $i++) { - $zip->addFileFromPsr7Stream( - fileName: 'sample' . $i, - stream: new EndlessCycleStream('0'), - maxSize: 0x5FFFFFFF, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - } - - $zip->finish(); - - $tmpDir = $this->validateAndExtractZip($this->tempfile); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample0', 'sample1', 'sample2', 'sample3'], $files); - } - - #[Group('slow')] - public function testAddLargeFileWithoutZip64WithZeroHeader(): void - { - $this->expectException(OverflowException::class); - - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - enableZip64: false, - defaultEnableZeroHeader: true, - ); - - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: new EndlessCycleStream('0'), - maxSize: 0x100000000, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - } - - #[Group('slow')] - public function testAddsZip64HeaderWhenNeeded(): void - { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - enableZip64: true, - defaultEnableZeroHeader: false, - ); - - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: new EndlessCycleStream('0'), - maxSize: 0x100000000, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - - $zip->finish(); - - $tmpDir = $this->validateAndExtractZip($this->tempfile); - $files = $this->getRecursiveFileList($tmpDir); - - $this->assertSame(['sample.json'], $files); - $this->assertFileContains($this->tempfile, PackField::pack( - new PackField(format: 'V', value: 0x06064b50) - )); - } - - #[Group('slow')] - public function testDoesNotAddZip64HeaderWhenNotNeeded(): void - { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - enableZip64: true, - defaultEnableZeroHeader: false, - ); - - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: new EndlessCycleStream('0'), - maxSize: 0x10, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - - $zip->finish(); - - $tmpDir = $this->validateAndExtractZip($this->tempfile); - $files = $this->getRecursiveFileList($tmpDir); - - $this->assertSame(['sample.json'], $files); - $this->assertFileDoesNotContain($this->tempfile, PackField::pack( - new PackField(format: 'V', value: 0x06064b50) - )); - } - - #[Group('slow')] - public function testAddLargeFileWithoutZip64WithoutZeroHeader(): void - { - $this->expectException(OverflowException::class); - - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - enableZip64: false, - defaultEnableZeroHeader: false, - ); - - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: new EndlessCycleStream('0'), - maxSize: 0x100000000, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - } - public function testAddFileFromPsr7StreamWithOutputToPsr7Stream(): void { - $psr7OutputStream = new ResourceStream($this->tempfileStream); + [$tmp, $resource] = $this->getTmpFileStream(); + $psr7OutputStream = new Stream($resource); - $zip = new ZipStream( - outputStream: $psr7OutputStream, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($psr7OutputStream); + + $zip = new ZipStream(null, $options); $body = 'Sample String Data'; $response = new Response(200, [], $body); - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: $response->getBody(), - compressionMethod: CompressionMethod::STORE, - ); + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + + $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); $zip->finish(); $psr7OutputStream->close(); - $tmpDir = $this->validateAndExtractZip($this->tempfile); + $tmpDir = $this->validateAndExtractZip($tmp); $files = $this->getRecursiveFileList($tmpDir); $this->assertSame(['sample.json'], $files); @@ -683,10 +434,12 @@ class ZipStreamTest extends TestCase public function testAddFileFromPsr7StreamWithFileSizeSet(): void { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); $body = 'Sample String Data'; $fileSize = strlen($body); @@ -694,63 +447,37 @@ class ZipStreamTest extends TestCase $fakePadding = "\0\0\0\0\0\0"; $response = new Response(200, [], $body . $fakePadding); - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: $response->getBody(), - compressionMethod: CompressionMethod::STORE, - maxSize: $fileSize - ); + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + $fileOptions->setSize($fileSize); + $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); $zip->finish(); + fclose($stream); - $tmpDir = $this->validateAndExtractZip($this->tempfile); + $tmpDir = $this->validateAndExtractZip($tmp); $files = $this->getRecursiveFileList($tmpDir); $this->assertSame(['sample.json'], $files); $this->assertStringEqualsFile($tmpDir . '/sample.json', $body); } - public function testCreateArchiveHeaders(): void - { - $headers = []; - - $httpHeaderCallback = function (string $header) use (&$headers) { - $headers[] = $header; - }; - - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: true, - outputName: 'example.zip', - httpHeaderCallback: $httpHeaderCallback, - ); - - $zip->addFile( - fileName: 'sample.json', - data: 'foo', - ); - $zip->finish(); - - $this->assertContains('Content-Type: application/x-zip', $headers); - $this->assertContains("Content-Disposition: attachment; filename*=UTF-8''example.zip", $headers); - $this->assertContains('Pragma: public', $headers); - $this->assertContains('Cache-Control: public, must-revalidate', $headers); - $this->assertContains('Content-Transfer-Encoding: binary', $headers); - } - public function testCreateArchiveWithFlushOptionSet(): void { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - flushOutput: true, - sendHttpHeaders: false, - ); + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + $options->setFlushOutput(true); + + $zip = new ZipStream(null, $options); $zip->addFile('sample.txt', 'Sample String Data'); $zip->addFile('test/sample.txt', 'More Simple Sample Data'); $zip->finish(); + fclose($stream); - $tmpDir = $this->validateAndExtractZip($this->tempfile); + $tmpDir = $this->validateAndExtractZip($tmp); $files = $this->getRecursiveFileList($tmpDir); $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files); @@ -765,433 +492,111 @@ class ZipStreamTest extends TestCase ob_end_flush(); $this->assertSame(0, ob_get_level()); - $zip = new ZipStream( - outputStream: $this->tempfileStream, - flushOutput: true, - sendHttpHeaders: false, - ); + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + $options->setFlushOutput(true); + + $zip = new ZipStream(null, $options); $zip->addFile('sample.txt', 'Sample String Data'); $zip->finish(); + fclose($stream); - $tmpDir = $this->validateAndExtractZip($this->tempfile); + $tmpDir = $this->validateAndExtractZip($tmp); $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data'); // WORKAROUND (2/2): add back output buffering so that PHPUnit doesn't complain that it is missing ob_start(); } - public function testAddEmptyDirectory(): void + /** + * @return array + */ + protected function getTmpFileStream(): array { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - ); + $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest'); + $stream = fopen($tmp, 'wb+'); - $zip->addDirectory('foo'); - - $zip->finish(); - - $tmpDir = $this->validateAndExtractZip($this->tempfile); - - $files = $this->getRecursiveFileList($tmpDir, includeDirectories: true); - - $this->assertContains('foo', $files); - - $this->assertFileExists($tmpDir . DIRECTORY_SEPARATOR . 'foo'); - $this->assertDirectoryExists($tmpDir . DIRECTORY_SEPARATOR . 'foo'); + return [$tmp, $stream]; } - public function testAddFileSimulate(): void + /** + * @param string $tmp + * @return string + */ + protected function validateAndExtractZip($tmp): string { - $create = function (OperationMode $operationMode): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultEnableZeroHeader: true, - outputStream: $this->tempfileStream, - ); + $tmpDir = $this->getTmpDir(); - $zip->addFile('sample.txt', 'Sample String Data'); - $zip->addFile('test/sample.txt', 'More Simple Sample Data'); + $zipArch = new ZipArchive(); + $res = $zipArch->open($tmp); - return $zip->finish(); - }; + if ($res !== true) { + $this->fail("Failed to open {$tmp}. Code: $res"); + return $tmpDir; + } - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); + $this->assertSame(0, $zipArch->status); + $this->assertSame(0, $zipArch->statusSys); - $this->assertEquals($sizeExpected, $sizeActual); + $zipArch->extractTo($tmpDir); + $zipArch->close(); + + return $tmpDir; } - public function testAddFileSimulateWithMaxSize(): void + protected function getTmpDir(): string { - $create = function (OperationMode $operationMode): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultCompressionMethod: CompressionMethod::STORE, - defaultEnableZeroHeader: true, - outputStream: $this->tempfileStream, - ); + $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest'); + unlink($tmp); + mkdir($tmp) or $this->fail('Failed to make directory'); - $zip->addFile('sample.txt', 'Sample String Data', maxSize: 0); - - return $zip->finish(); - }; - - - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); - - $this->assertEquals($sizeExpected, $sizeActual); + return $tmp; } - public function testAddFileSimulateWithFstat(): void + /** + * @param string $path + * @return string[] + */ + protected function getRecursiveFileList(string $path): array { - $create = function (OperationMode $operationMode): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultCompressionMethod: CompressionMethod::STORE, - defaultEnableZeroHeader: true, - outputStream: $this->tempfileStream, - ); + $data = []; + $path = (string)realpath($path); + $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); - $zip->addFile('sample.txt', 'Sample String Data'); - $zip->addFile('test/sample.txt', 'More Simple Sample Data'); - - return $zip->finish(); - }; - - - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); - - $this->assertEquals($sizeExpected, $sizeActual); - } - - public function testAddFileSimulateWithExactSizeZero(): void - { - $create = function (OperationMode $operationMode): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultCompressionMethod: CompressionMethod::STORE, - defaultEnableZeroHeader: true, - outputStream: $this->tempfileStream, - ); - - $zip->addFile('sample.txt', 'Sample String Data', exactSize: 18); - - return $zip->finish(); - }; - - - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); - - $this->assertEquals($sizeExpected, $sizeActual); - } - - public function testAddFileSimulateWithExactSizeInitial(): void - { - $create = function (OperationMode $operationMode): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultCompressionMethod: CompressionMethod::STORE, - defaultEnableZeroHeader: false, - outputStream: $this->tempfileStream, - ); - - $zip->addFile('sample.txt', 'Sample String Data', exactSize: 18); - - return $zip->finish(); - }; - - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); - - $this->assertEquals($sizeExpected, $sizeActual); - } - - public function testAddFileSimulateWithZeroSizeInFstat(): void - { - $create = function (OperationMode $operationMode): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultCompressionMethod: CompressionMethod::STORE, - defaultEnableZeroHeader: false, - outputStream: $this->tempfileStream, - ); - - $zip->addFileFromPsr7Stream('sample.txt', new class implements StreamInterface { - public $pos = 0; - - public function __toString(): string - { - return 'test'; - } - - public function close(): void {} - - public function detach() {} - - public function getSize(): ?int - { - return null; - } - - public function tell(): int - { - return $this->pos; - } - - public function eof(): bool - { - return $this->pos >= 4; - } - - public function isSeekable(): bool - { - return true; - } - - public function seek(int $offset, int $whence = SEEK_SET): void - { - $this->pos = $offset; - } - - public function rewind(): void - { - $this->pos = 0; - } - - public function isWritable(): bool - { - return false; - } - - public function write(string $string): int - { - return 0; - } - - public function isReadable(): bool - { - return true; - } - - public function read(int $length): string - { - $data = substr('test', $this->pos, $length); - $this->pos += strlen($data); - return $data; - } - - public function getContents(): string - { - return $this->read(4); - } - - public function getMetadata(?string $key = null) - { - return $key !== null ? null : []; - } - }); - - return $zip->finish(); - }; - - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); - - - $this->assertEquals($sizeExpected, $sizeActual); - } - - public function testAddFileSimulateWithWrongExactSize(): void - { - $this->expectException(FileSizeIncorrectException::class); - - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: OperationMode::SIMULATE_LAX, - ); - - $zip->addFile('sample.txt', 'Sample String Data', exactSize: 1000); - } - - public function testAddFileSimulateStrictZero(): void - { - $this->expectException(SimulationFileUnknownException::class); - - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: OperationMode::SIMULATE_STRICT, - defaultEnableZeroHeader: true - ); - - $zip->addFile('sample.txt', 'Sample String Data'); - } - - public function testAddFileSimulateStrictInitial(): void - { - $this->expectException(SimulationFileUnknownException::class); - - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: OperationMode::SIMULATE_STRICT, - defaultEnableZeroHeader: false - ); - - $zip->addFile('sample.txt', 'Sample String Data'); - } - - public function testAddFileCallbackStrict(): void - { - $this->expectException(SimulationFileUnknownException::class); - - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: OperationMode::SIMULATE_STRICT, - defaultEnableZeroHeader: false - ); - - $zip->addFileFromCallback('sample.txt', callback: function () { - return ''; - }); - } - - public function testAddFileCallbackLax(): void - { - $zip = new ZipStream( - operationMode: OperationMode::SIMULATE_LAX, - defaultEnableZeroHeader: false, - sendHttpHeaders: false, - ); - - $zip->addFileFromCallback('sample.txt', callback: function () { - return 'Sample String Data'; - }); - - $size = $zip->finish(); - - $this->assertEquals($size, 142); - } - - public function testExecuteSimulation(): void - { - $zip = new ZipStream( - operationMode: OperationMode::SIMULATE_STRICT, - defaultCompressionMethod: CompressionMethod::STORE, - defaultEnableZeroHeader: false, - sendHttpHeaders: false, - outputStream: $this->tempfileStream, - ); - - $zip->addFileFromCallback( - 'sample.txt', - exactSize: 18, - callback: function () { - return 'Sample String Data'; + $pathLen = strlen($path); + foreach ($files as $file) { + $filePath = $file->getRealPath(); + if (!is_dir($filePath)) { + $data[] = substr($filePath, $pathLen + 1); } - ); + } - $zip->addFileFromCallback( - '.gitkeep', - exactSize: 0, - callback: function () { - return ''; - } - ); + sort($data); - $size = $zip->finish(); - - $this->assertEquals(filesize($this->tempfile), 0); - - $zip->executeSimulation(); - - clearstatcache(); - - $this->assertEquals(filesize($this->tempfile), $size); - - $tmpDir = $this->validateAndExtractZip($this->tempfile); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['.gitkeep', 'sample.txt'], $files); + return $data; } - public function testExecuteSimulationBeforeFinish(): void - { - $this->expectException(RuntimeException::class); - - $zip = new ZipStream( - operationMode: OperationMode::SIMULATE_LAX, - defaultEnableZeroHeader: false, - sendHttpHeaders: false, - outputStream: $this->tempfileStream, - ); - - $zip->executeSimulation(); - } - - #[Group('slow')] - public function testSimulationWithLargeZip64AndZeroHeader(): void - { - $zip = new ZipStream( - outputStream: $this->tempfileStream, - sendHttpHeaders: false, - operationMode: OperationMode::SIMULATE_STRICT, - defaultCompressionMethod: CompressionMethod::STORE, - outputName: 'archive.zip', - enableZip64: true, - defaultEnableZeroHeader: true - ); - - $zip->addFileFromPsr7Stream( - fileName: 'large', - stream: new EndlessCycleStream('large'), - exactSize: 0x120000000, // ~5gb - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - - $zip->addFileFromPsr7Stream( - fileName: 'small', - stream: new EndlessCycleStream('small'), - exactSize: 0x20, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - - $forecastedSize = $zip->finish(); - - $zip->executeSimulation(); - - $this->assertSame($forecastedSize, filesize($this->tempfile)); - - $this->validateAndExtractZip($this->tempfile); - } - - private function addLargeFileFileFromPath(CompressionMethod $compressionMethod, $zeroHeader, $zip64): void + protected function addLargeFileFileFromPath($method, $zeroHeader, $zip64): void { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - defaultEnableZeroHeader: $zeroHeader, - enableZip64: $zip64, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + $options->setLargeFileMethod($method); + $options->setLargeFileSize(5); + $options->setZeroHeader($zeroHeader); + $options->setEnableZip64($zip64); + + $zip = new ZipStream(null, $options); [$tmpExample, $streamExample] = $this->getTmpFileStream(); for ($i = 0; $i <= 10000; $i++) { - fwrite($streamExample, sha1((string) $i)); + fwrite($streamExample, sha1((string)$i)); if ($i % 100 === 0) { fwrite($streamExample, "\n"); } @@ -1209,8 +614,6 @@ class ZipStreamTest extends TestCase $files = $this->getRecursiveFileList($tmpDir); $this->assertSame(['sample.txt'], $files); - $this->assertSame(sha1_file($tmpDir . '/sample.txt'), $shaExample, "SHA-1 Mismatch Method: {$compressionMethod->value}"); - - unlink($tmp); + $this->assertSame(sha1_file($tmpDir . '/sample.txt'), $shaExample, "SHA-1 Mismatch Method: {$method}"); } } diff --git a/vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php b/vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php deleted file mode 100644 index 2b8dbed..0000000 --- a/vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php +++ /dev/null @@ -1,22 +0,0 @@ -assertSame( - bin2hex((string) $extraField), - '5356' . // 2 bytes; Tag for this "extra" block type - '0000' // 2 bytes; TODO: Document - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/bug/BugHonorFileTimeTest.php b/vendor/maennchen/zipstream-php/test/bug/BugHonorFileTimeTest.php new file mode 100644 index 0000000..05de4fe --- /dev/null +++ b/vendor/maennchen/zipstream-php/test/bug/BugHonorFileTimeTest.php @@ -0,0 +1,40 @@ +setOutputStream(fopen('php://memory', 'wb')); + $fileOpt->setTime(clone $expectedTime); + + $zip = new ZipStream(null, $archiveOpt); + + $zip->addFile('sample.txt', 'Sample', $fileOpt); + + $zip->finish(); + + $this->assertEquals($expectedTime, $fileOpt->getTime()); + } +} diff --git a/vendor/myclabs/php-enum/LICENSE b/vendor/myclabs/php-enum/LICENSE new file mode 100644 index 0000000..2a8cf22 --- /dev/null +++ b/vendor/myclabs/php-enum/LICENSE @@ -0,0 +1,18 @@ +The MIT License (MIT) + +Copyright (c) 2015 My C-Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/myclabs/php-enum/README.md b/vendor/myclabs/php-enum/README.md new file mode 100644 index 0000000..681d55e --- /dev/null +++ b/vendor/myclabs/php-enum/README.md @@ -0,0 +1,194 @@ +# PHP Enum implementation inspired from SplEnum + +[![GitHub Actions][GA Image]][GA Link] +[![Latest Stable Version](https://poser.pugx.org/myclabs/php-enum/version.png)](https://packagist.org/packages/myclabs/php-enum) +[![Total Downloads](https://poser.pugx.org/myclabs/php-enum/downloads.png)](https://packagist.org/packages/myclabs/php-enum) +[![Psalm Shepherd][Shepherd Image]][Shepherd Link] + +Maintenance for this project is [supported via Tidelift](https://tidelift.com/subscription/pkg/packagist-myclabs-php-enum?utm_source=packagist-myclabs-php-enum&utm_medium=referral&utm_campaign=readme). + +## Why? + +First, and mainly, `SplEnum` is not integrated to PHP, you have to install the extension separately. + +Using an enum instead of class constants provides the following advantages: + +- You can use an enum as a parameter type: `function setAction(Action $action) {` +- You can use an enum as a return type: `function getAction() : Action {` +- You can enrich the enum with methods (e.g. `format`, `parse`, …) +- You can extend the enum to add new values (make your enum `final` to prevent it) +- You can get a list of all the possible values (see below) + +This Enum class is not intended to replace class constants, but only to be used when it makes sense. + +## Installation + +``` +composer require myclabs/php-enum +``` + +## Declaration + +```php +use MyCLabs\Enum\Enum; + +/** + * Action enum + */ +final class Action extends Enum +{ + private const VIEW = 'view'; + private const EDIT = 'edit'; +} +``` + +## Usage + +```php +$action = Action::VIEW(); + +// or with a dynamic key: +$action = Action::$key(); +// or with a dynamic value: +$action = Action::from($value); +// or +$action = new Action($value); +``` + +As you can see, static methods are automatically implemented to provide quick access to an enum value. + +One advantage over using class constants is to be able to use an enum as a parameter type: + +```php +function setAction(Action $action) { + // ... +} +``` + +## Documentation + +- `__construct()` The constructor checks that the value exist in the enum +- `__toString()` You can `echo $myValue`, it will display the enum value (value of the constant) +- `getValue()` Returns the current value of the enum +- `getKey()` Returns the key of the current value on Enum +- `equals()` Tests whether enum instances are equal (returns `true` if enum values are equal, `false` otherwise) + +Static methods: + +- `from()` Creates an Enum instance, checking that the value exist in the enum +- `toArray()` method Returns all possible values as an array (constant name in key, constant value in value) +- `keys()` Returns the names (keys) of all constants in the Enum class +- `values()` Returns instances of the Enum class of all Enum constants (constant name in key, Enum instance in value) +- `isValid()` Check if tested value is valid on enum set +- `isValidKey()` Check if tested key is valid on enum set +- `assertValidValue()` Assert the value is valid on enum set, throwing exception otherwise +- `search()` Return key for searched value + +### Static methods + +```php +final class Action extends Enum +{ + private const VIEW = 'view'; + private const EDIT = 'edit'; +} + +// Static method: +$action = Action::VIEW(); +$action = Action::EDIT(); +``` + +Static method helpers are implemented using [`__callStatic()`](http://www.php.net/manual/en/language.oop5.overloading.php#object.callstatic). + +If you care about IDE autocompletion, you can either implement the static methods yourself: + +```php +final class Action extends Enum +{ + private const VIEW = 'view'; + + /** + * @return Action + */ + public static function VIEW() { + return new Action(self::VIEW); + } +} +``` + +or you can use phpdoc (this is supported in PhpStorm for example): + +```php +/** + * @method static Action VIEW() + * @method static Action EDIT() + */ +final class Action extends Enum +{ + private const VIEW = 'view'; + private const EDIT = 'edit'; +} +``` + +## Native enums and migration +Native enum arrived to PHP in version 8.1: https://www.php.net/enumerations +If your project is running PHP 8.1+ or your library has it as a minimum requirement you should use it instead of this library. + +When migrating from `myclabs/php-enum`, the effort should be small if the usage was in the recommended way: +- private constants +- final classes +- no method overridden + +Changes for migration: +- Class definition should be changed from +```php +/** + * @method static Action VIEW() + * @method static Action EDIT() + */ +final class Action extends Enum +{ + private const VIEW = 'view'; + private const EDIT = 'edit'; +} +``` + to +```php +enum Action: string +{ + case VIEW = 'view'; + case EDIT = 'edit'; +} +``` +All places where the class was used as a type will continue to work. + +Usages and the change needed: + +| Operation | myclabs/php-enum | native enum | +|----------------------------------------------------------------|----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Obtain an instance will change from | `$enumCase = Action::VIEW()` | `$enumCase = Action::VIEW` | +| Create an enum from a backed value | `$enumCase = new Action('view')` | `$enumCase = Action::from('view')` | +| Get the backed value of the enum instance | `$enumCase->getValue()` | `$enumCase->value` | +| Compare two enum instances | `$enumCase1 == $enumCase2`
or
`$enumCase1->equals($enumCase2)` | `$enumCase1 === $enumCase2` | +| Get the key/name of the enum instance | `$enumCase->getKey()` | `$enumCase->name` | +| Get a list of all the possible instances of the enum | `Action::values()` | `Action::cases()` | +| Get a map of possible instances of the enum mapped by name | `Action::values()` | `array_combine(array_map(fn($case) => $case->name, Action::cases()), Action::cases())`
or
`(new ReflectionEnum(Action::class))->getConstants()` | +| Get a list of all possible names of the enum | `Action::keys()` | `array_map(fn($case) => $case->name, Action::cases())` | +| Get a list of all possible backed values of the enum | `Action::toArray()` | `array_map(fn($case) => $case->value, Action::cases())` | +| Get a map of possible backed values of the enum mapped by name | `Action::toArray()` | `array_combine(array_map(fn($case) => $case->name, Action::cases()), array_map(fn($case) => $case->value, Action::cases()))`
or
`array_map(fn($case) => $case->value, (new ReflectionEnum(Action::class))->getConstants()))` | + +## Related projects + +- [PHP 8.1+ native enum](https://www.php.net/enumerations) +- [Doctrine enum mapping](https://github.com/acelaya/doctrine-enum-type) +- [Symfony ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter) +- [PHPStan integration](https://github.com/timeweb/phpstan-enum) + + +[GA Image]: https://github.com/myclabs/php-enum/workflows/CI/badge.svg + +[GA Link]: https://github.com/myclabs/php-enum/actions?query=workflow%3A%22CI%22+branch%3Amaster + +[Shepherd Image]: https://shepherd.dev/github/myclabs/php-enum/coverage.svg + +[Shepherd Link]: https://shepherd.dev/github/myclabs/php-enum diff --git a/vendor/myclabs/php-enum/SECURITY.md b/vendor/myclabs/php-enum/SECURITY.md new file mode 100644 index 0000000..84fd4e3 --- /dev/null +++ b/vendor/myclabs/php-enum/SECURITY.md @@ -0,0 +1,11 @@ +# Security Policy + +## Supported Versions + +Only the latest stable release is supported. + +## Reporting a Vulnerability + +To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). + +Tidelift will coordinate the fix and disclosure. diff --git a/vendor/myclabs/php-enum/composer.json b/vendor/myclabs/php-enum/composer.json new file mode 100644 index 0000000..978cb19 --- /dev/null +++ b/vendor/myclabs/php-enum/composer.json @@ -0,0 +1,36 @@ +{ + "name": "myclabs/php-enum", + "type": "library", + "description": "PHP Enum implementation", + "keywords": ["enum"], + "homepage": "http://github.com/myclabs/php-enum", + "license": "MIT", + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + }, + "classmap": [ + "stubs/Stringable.php" + ] + }, + "autoload-dev": { + "psr-4": { + "MyCLabs\\Tests\\Enum\\": "tests/" + } + }, + "require": { + "php": "^7.3 || ^8.0", + "ext-json": "*" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^4.6.2" + } +} diff --git a/vendor/myclabs/php-enum/src/Enum.php b/vendor/myclabs/php-enum/src/Enum.php new file mode 100644 index 0000000..4c94cf6 --- /dev/null +++ b/vendor/myclabs/php-enum/src/Enum.php @@ -0,0 +1,318 @@ + + * @author Daniel Costa + * @author Mirosław Filip + * + * @psalm-template T + * @psalm-immutable + * @psalm-consistent-constructor + */ +abstract class Enum implements \JsonSerializable, \Stringable +{ + /** + * Enum value + * + * @var mixed + * @psalm-var T + */ + protected $value; + + /** + * Enum key, the constant name + * + * @var string + */ + private $key; + + /** + * Store existing constants in a static cache per object. + * + * + * @var array + * @psalm-var array> + */ + protected static $cache = []; + + /** + * Cache of instances of the Enum class + * + * @var array + * @psalm-var array> + */ + protected static $instances = []; + + /** + * Creates a new value of some type + * + * @psalm-pure + * @param mixed $value + * + * @psalm-param T $value + * @throws \UnexpectedValueException if incompatible type is given. + */ + public function __construct($value) + { + if ($value instanceof static) { + /** @psalm-var T */ + $value = $value->getValue(); + } + + /** @psalm-suppress ImplicitToStringCast assertValidValueReturningKey returns always a string but psalm has currently an issue here */ + $this->key = static::assertValidValueReturningKey($value); + + /** @psalm-var T */ + $this->value = $value; + } + + /** + * This method exists only for the compatibility reason when deserializing a previously serialized version + * that didn't had the key property + */ + public function __wakeup() + { + /** @psalm-suppress DocblockTypeContradiction key can be null when deserializing an enum without the key */ + if ($this->key === null) { + /** + * @psalm-suppress InaccessibleProperty key is not readonly as marked by psalm + * @psalm-suppress PossiblyFalsePropertyAssignmentValue deserializing a case that was removed + */ + $this->key = static::search($this->value); + } + } + + /** + * @param mixed $value + * @return static + */ + public static function from($value): self + { + $key = static::assertValidValueReturningKey($value); + + return self::__callStatic($key, []); + } + + /** + * @psalm-pure + * @return mixed + * @psalm-return T + */ + public function getValue() + { + return $this->value; + } + + /** + * Returns the enum key (i.e. the constant name). + * + * @psalm-pure + * @return string + */ + public function getKey() + { + return $this->key; + } + + /** + * @psalm-pure + * @psalm-suppress InvalidCast + * @return string + */ + public function __toString() + { + return (string)$this->value; + } + + /** + * Determines if Enum should be considered equal with the variable passed as a parameter. + * Returns false if an argument is an object of different class or not an object. + * + * This method is final, for more information read https://github.com/myclabs/php-enum/issues/4 + * + * @psalm-pure + * @psalm-param mixed $variable + * @return bool + */ + final public function equals($variable = null): bool + { + return $variable instanceof self + && $this->getValue() === $variable->getValue() + && static::class === \get_class($variable); + } + + /** + * Returns the names (keys) of all constants in the Enum class + * + * @psalm-pure + * @psalm-return list + * @return array + */ + public static function keys() + { + return \array_keys(static::toArray()); + } + + /** + * Returns instances of the Enum class of all Enum constants + * + * @psalm-pure + * @psalm-return array + * @return static[] Constant name in key, Enum instance in value + */ + public static function values() + { + $values = array(); + + /** @psalm-var T $value */ + foreach (static::toArray() as $key => $value) { + $values[$key] = new static($value); + } + + return $values; + } + + /** + * Returns all possible values as an array + * + * @psalm-pure + * @psalm-suppress ImpureStaticProperty + * + * @psalm-return array + * @return array Constant name in key, constant value in value + */ + public static function toArray() + { + $class = static::class; + + if (!isset(static::$cache[$class])) { + /** @psalm-suppress ImpureMethodCall this reflection API usage has no side-effects here */ + $reflection = new \ReflectionClass($class); + /** @psalm-suppress ImpureMethodCall this reflection API usage has no side-effects here */ + static::$cache[$class] = $reflection->getConstants(); + } + + return static::$cache[$class]; + } + + /** + * Check if is valid enum value + * + * @param $value + * @psalm-param mixed $value + * @psalm-pure + * @psalm-assert-if-true T $value + * @return bool + */ + public static function isValid($value) + { + return \in_array($value, static::toArray(), true); + } + + /** + * Asserts valid enum value + * + * @psalm-pure + * @psalm-assert T $value + * @param mixed $value + */ + public static function assertValidValue($value): void + { + self::assertValidValueReturningKey($value); + } + + /** + * Asserts valid enum value + * + * @psalm-pure + * @psalm-assert T $value + * @param mixed $value + * @return string + */ + private static function assertValidValueReturningKey($value): string + { + if (false === ($key = static::search($value))) { + throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); + } + + return $key; + } + + /** + * Check if is valid enum key + * + * @param $key + * @psalm-param string $key + * @psalm-pure + * @return bool + */ + public static function isValidKey($key) + { + $array = static::toArray(); + + return isset($array[$key]) || \array_key_exists($key, $array); + } + + /** + * Return key for value + * + * @param mixed $value + * + * @psalm-param mixed $value + * @psalm-pure + * @return string|false + */ + public static function search($value) + { + return \array_search($value, static::toArray(), true); + } + + /** + * Returns a value when called statically like so: MyEnum::SOME_VALUE() given SOME_VALUE is a class constant + * + * @param string $name + * @param array $arguments + * + * @return static + * @throws \BadMethodCallException + * + * @psalm-pure + */ + public static function __callStatic($name, $arguments) + { + $class = static::class; + if (!isset(self::$instances[$class][$name])) { + $array = static::toArray(); + if (!isset($array[$name]) && !\array_key_exists($name, $array)) { + $message = "No static method or enum constant '$name' in class " . static::class; + throw new \BadMethodCallException($message); + } + return self::$instances[$class][$name] = new static($array[$name]); + } + return clone self::$instances[$class][$name]; + } + + /** + * Specify data which should be serialized to JSON. This method returns data that can be serialized by json_encode() + * natively. + * + * @return mixed + * @link http://php.net/manual/en/jsonserializable.jsonserialize.php + * @psalm-pure + */ + #[\ReturnTypeWillChange] + public function jsonSerialize() + { + return $this->getValue(); + } +} diff --git a/vendor/myclabs/php-enum/src/PHPUnit/Comparator.php b/vendor/myclabs/php-enum/src/PHPUnit/Comparator.php new file mode 100644 index 0000000..302bf80 --- /dev/null +++ b/vendor/myclabs/php-enum/src/PHPUnit/Comparator.php @@ -0,0 +1,54 @@ +register(new \MyCLabs\Enum\PHPUnit\Comparator()); + */ +final class Comparator extends \SebastianBergmann\Comparator\Comparator +{ + public function accepts($expected, $actual) + { + return $expected instanceof Enum && ( + $actual instanceof Enum || $actual === null + ); + } + + /** + * @param Enum $expected + * @param Enum|null $actual + * + * @return void + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) + { + if ($expected->equals($actual)) { + return; + } + + throw new ComparisonFailure( + $expected, + $actual, + $this->formatEnum($expected), + $this->formatEnum($actual), + false, + 'Failed asserting that two Enums are equal.' + ); + } + + private function formatEnum(Enum $enum = null) + { + if ($enum === null) { + return "null"; + } + + return get_class($enum)."::{$enum->getKey()}()"; + } +} diff --git a/vendor/myclabs/php-enum/stubs/Stringable.php b/vendor/myclabs/php-enum/stubs/Stringable.php new file mode 100644 index 0000000..4811af7 --- /dev/null +++ b/vendor/myclabs/php-enum/stubs/Stringable.php @@ -0,0 +1,11 @@ +=7.4.0 <8.5.0", "ext-ctype": "*", "ext-dom": "*", "ext-fileinfo": "*", diff --git a/vendor/pimple/pimple/.github/workflows/tests.yml b/vendor/pimple/pimple/.github/workflows/tests.yml old mode 100755 new mode 100644 index 09b6760..0255c77 --- a/vendor/pimple/pimple/.github/workflows/tests.yml +++ b/vendor/pimple/pimple/.github/workflows/tests.yml @@ -12,11 +12,11 @@ jobs: fail-fast: false matrix: php: - - "7.2" - - "7.3" - - "7.4" - - "8.0" - "8.1" + - "8.2" + - "8.3" + - "8.4" + - "8.5" dependencies: - "psr/container:^1.1" - "psr/container:^2.0" @@ -44,4 +44,4 @@ jobs: composer update --prefer-dist --no-progress - name: Run PHPUnit tests - run: vendor/bin/simple-phpunit --verbose + run: vendor/bin/phpunit diff --git a/vendor/pimple/pimple/.gitignore b/vendor/pimple/pimple/.gitignore old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/.php_cs.dist b/vendor/pimple/pimple/.php_cs.dist old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/CHANGELOG b/vendor/pimple/pimple/CHANGELOG old mode 100755 new mode 100644 index 08059e5..cb109a8 --- a/vendor/pimple/pimple/CHANGELOG +++ b/vendor/pimple/pimple/CHANGELOG @@ -1,3 +1,12 @@ +* 3.6.0 (2025-11-12) + + * Add support for PHP 8.5 + +* 3.5.0 (2021-10-28) + + * Add support for PHP 8.1 + * Add support for version 2.0 of PSR-11 + * 3.4.0 (2021-03-06) * Implement version 1.1 of PSR-11 diff --git a/vendor/pimple/pimple/LICENSE b/vendor/pimple/pimple/LICENSE old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/README.rst b/vendor/pimple/pimple/README.rst old mode 100755 new mode 100644 index 7081839..75927cb --- a/vendor/pimple/pimple/README.rst +++ b/vendor/pimple/pimple/README.rst @@ -52,13 +52,9 @@ object: .. code-block:: php // define some services - $container['session_storage'] = function ($c) { - return new SessionStorage('SESSION_ID'); - }; + $container['session_storage'] = fn($c) => new SessionStorage('SESSION_ID'); - $container['session'] = function ($c) { - return new Session($c['session_storage']); - }; + $container['session'] = fn($c) => new Session($c['session_storage']); Notice that the anonymous function has access to the current container instance, allowing references to other services or parameters. @@ -86,9 +82,7 @@ anonymous function with the ``factory()`` method .. code-block:: php - $container['session'] = $container->factory(function ($c) { - return new Session($c['session_storage']); - }); + $container['session'] = $container->factory(fn($c) => new Session($c['session_storage'])); Now, each call to ``$container['session']`` returns a new instance of the session. @@ -109,9 +103,7 @@ If you change the ``session_storage`` service definition like below: .. code-block:: php - $container['session_storage'] = function ($c) { - return new $c['session_storage_class']($c['cookie_name']); - }; + $container['session_storage'] = fn($c) => new $c['session_storage_class']($c['cookie_name']); You can now easily change the cookie name by overriding the ``cookie_name`` parameter instead of redefining the service @@ -126,9 +118,7 @@ parameters: .. code-block:: php - $container['random_func'] = $container->protect(function () { - return rand(); - }); + $container['random_func'] = $container->protect(fn() => rand()); Modifying Services after Definition ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -139,9 +129,7 @@ run on your service just after it is created: .. code-block:: php - $container['session_storage'] = function ($c) { - return new $c['session_storage_class']($c['cookie_name']); - }; + $container['session_storage'] = fn($c) => new $c['session_storage_class']($c['cookie_name']); $container->extend('session_storage', function ($storage, $c) { $storage->...(); @@ -187,9 +175,7 @@ raw access to this function, you can use the ``raw()`` method: .. code-block:: php - $container['session'] = function ($c) { - return new Session($c['session_storage']); - }; + $container['session'] = fn($c) => new Session($c['session_storage']); $sessionFunction = $container->raw('session'); @@ -213,9 +199,7 @@ methods: use Pimple\Psr11\Container as PsrContainer; $container = new Container(); - $container['service'] = function ($c) { - return new Service(); - }; + $container['service'] = fn($c) => new Service(); $psr11 = new PsrContainer($container); $controller = function (PsrContainer $container) { @@ -265,13 +249,9 @@ registered under the name ``dispatcher``: } } - $container['logger'] = function ($c) { - return new Monolog\Logger(); - }; - $container['dispatcher'] = function () { - return new EventDispatcher(); - }; - + $container['logger'] = fn($c) => new Monolog\Logger(); + $container['dispatcher'] = fn($c) => new EventDispatcher(); + $container['service'] = function ($c) { $locator = new ServiceLocator($c, array('logger', 'event_dispatcher' => 'dispatcher')); @@ -319,14 +299,8 @@ when iterated over: $container = new Container(); - $container['voter1'] = function ($c) { - return new SomeVoter(); - } - $container['voter2'] = function ($c) { - return new SomeOtherVoter($c['auth']); - } - $container['auth'] = function ($c) { - return new AuthorizationService(new ServiceIterator($c, array('voter1', 'voter2')); - } + $container['voter1'] = fn($c) => new SomeVoter(); + $container['voter2'] = fn($c) => new SomeOtherVoter($c['auth']); + $container['auth'] = fn ($c) => new AuthorizationService(new ServiceIterator($c, array('voter1', 'voter2')); .. _Pimple 1.x documentation: https://github.com/silexphp/Pimple/tree/1.1 diff --git a/vendor/pimple/pimple/composer.json b/vendor/pimple/pimple/composer.json old mode 100755 new mode 100644 index ca6a581..7e3923f --- a/vendor/pimple/pimple/composer.json +++ b/vendor/pimple/pimple/composer.json @@ -16,7 +16,7 @@ "psr/container": "^1.1 || ^2.0" }, "require-dev": { - "symfony/phpunit-bridge": "^5.4@dev" + "phpunit/phpunit": "*" }, "autoload": { "psr-0": { "Pimple": "src/" } diff --git a/vendor/pimple/pimple/phpunit.xml.dist b/vendor/pimple/pimple/phpunit.xml.dist old mode 100755 new mode 100644 index 8990202..5c8d487 --- a/vendor/pimple/pimple/phpunit.xml.dist +++ b/vendor/pimple/pimple/phpunit.xml.dist @@ -11,8 +11,4 @@ ./src/Pimple/Tests - - - -
diff --git a/vendor/pimple/pimple/src/Pimple/Container.php b/vendor/pimple/pimple/src/Pimple/Container.php old mode 100755 new mode 100644 index 586a0b7..23e851b --- a/vendor/pimple/pimple/src/Pimple/Container.php +++ b/vendor/pimple/pimple/src/Pimple/Container.php @@ -174,7 +174,7 @@ class Container implements \ArrayAccess throw new ExpectedInvokableException('Service definition is not a Closure or invokable object.'); } - $this->factories->attach($callable); + $this->factories->offsetSet($callable); return $callable; } diff --git a/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php b/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php b/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php b/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php b/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Psr11/Container.php b/vendor/pimple/pimple/src/Pimple/Psr11/Container.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php b/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/ServiceIterator.php b/vendor/pimple/pimple/src/Pimple/ServiceIterator.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php b/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php old mode 100755 new mode 100644 index ffa50a6..40e87f4 --- a/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php +++ b/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php @@ -26,6 +26,7 @@ namespace Pimple\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Pimple\Container; @@ -150,6 +151,7 @@ class PimpleTest extends TestCase /** * @dataProvider serviceDefinitionProvider */ + #[DataProvider('serviceDefinitionProvider')] public function testShare($service) { $pimple = new Container(); @@ -167,6 +169,7 @@ class PimpleTest extends TestCase /** * @dataProvider serviceDefinitionProvider */ + #[DataProvider('serviceDefinitionProvider')] public function testProtect($service) { $pimple = new Container(); @@ -228,6 +231,7 @@ class PimpleTest extends TestCase /** * @dataProvider serviceDefinitionProvider */ + #[DataProvider('serviceDefinitionProvider')] public function testExtend($service) { $pimple = new Container(); @@ -332,6 +336,7 @@ class PimpleTest extends TestCase /** * @dataProvider badServiceDefinitionProvider */ + #[DataProvider('badServiceDefinitionProvider')] public function testFactoryFailsForInvalidServiceDefinitions($service) { $this->expectException(\Pimple\Exception\ExpectedInvokableException::class); @@ -345,6 +350,7 @@ class PimpleTest extends TestCase * @group legacy * @dataProvider badServiceDefinitionProvider */ + #[DataProvider('badServiceDefinitionProvider')] public function testLegacyFactoryFailsForInvalidServiceDefinitions($service) { $this->expectException(\InvalidArgumentException::class); @@ -357,6 +363,7 @@ class PimpleTest extends TestCase /** * @dataProvider badServiceDefinitionProvider */ + #[DataProvider('badServiceDefinitionProvider')] public function testProtectFailsForInvalidServiceDefinitions($service) { $this->expectException(\Pimple\Exception\ExpectedInvokableException::class); @@ -370,6 +377,7 @@ class PimpleTest extends TestCase * @group legacy * @dataProvider badServiceDefinitionProvider */ + #[DataProvider('badServiceDefinitionProvider')] public function testLegacyProtectFailsForInvalidServiceDefinitions($service) { $this->expectException(\InvalidArgumentException::class); @@ -382,6 +390,7 @@ class PimpleTest extends TestCase /** * @dataProvider badServiceDefinitionProvider */ + #[DataProvider('badServiceDefinitionProvider')] public function testExtendFailsForKeysNotContainingServiceDefinitions($service) { $this->expectException(\Pimple\Exception\InvalidServiceIdentifierException::class); @@ -397,6 +406,7 @@ class PimpleTest extends TestCase * @group legacy * @dataProvider badServiceDefinitionProvider */ + #[DataProvider('badServiceDefinitionProvider')] public function testLegacyExtendFailsForKeysNotContainingServiceDefinitions($service) { $this->expectException(\InvalidArgumentException::class); @@ -412,7 +422,8 @@ class PimpleTest extends TestCase * @group legacy * @expectedDeprecation How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "foo" should be protected? */ - public function testExtendingProtectedClosureDeprecation() + #[DataProvider('badServiceDefinitionProvider')] + public function testExtendingProtectedClosureDeprecation($service) { $pimple = new Container(); $pimple['foo'] = $pimple->protect(function () { @@ -429,6 +440,7 @@ class PimpleTest extends TestCase /** * @dataProvider badServiceDefinitionProvider */ + #[DataProvider('badServiceDefinitionProvider')] public function testExtendFailsForInvalidServiceDefinitions($service) { $this->expectException(\Pimple\Exception\ExpectedInvokableException::class); @@ -444,6 +456,7 @@ class PimpleTest extends TestCase * @group legacy * @dataProvider badServiceDefinitionProvider */ + #[DataProvider('badServiceDefinitionProvider')] public function testLegacyExtendFailsForInvalidServiceDefinitions($service) { $this->expectException(\InvalidArgumentException::class); @@ -488,7 +501,7 @@ class PimpleTest extends TestCase /** * Provider for invalid service definitions. */ - public function badServiceDefinitionProvider() + public static function badServiceDefinitionProvider() { return [ [123], @@ -499,7 +512,7 @@ class PimpleTest extends TestCase /** * Provider for service definitions. */ - public function serviceDefinitionProvider() + public static function serviceDefinitionProvider() { return [ [function ($value) { diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php b/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php b/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php old mode 100755 new mode 100644 diff --git a/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php b/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php old mode 100755 new mode 100644 diff --git a/vendor/psr/http-factory/composer.json b/vendor/psr/http-factory/composer.json index 82a1d32..d1bbdde 100644 --- a/vendor/psr/http-factory/composer.json +++ b/vendor/psr/http-factory/composer.json @@ -1,6 +1,6 @@ { "name": "psr/http-factory", - "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "description": "Common interfaces for PSR-7 HTTP message factories", "keywords": [ "psr", "psr-7", @@ -18,11 +18,8 @@ "homepage": "https://www.php-fig.org/" } ], - "support": { - "source": "https://github.com/php-fig/http-factory" - }, "require": { - "php": ">=7.1", + "php": ">=7.0.0", "psr/http-message": "^1.0 || ^2.0" }, "autoload": { diff --git a/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php b/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php index d7adbf0..7db4e30 100644 --- a/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php +++ b/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php @@ -15,10 +15,10 @@ interface UploadedFileFactoryInterface * * @param StreamInterface $stream Underlying stream representing the * uploaded file content. - * @param int|null $size in bytes + * @param int $size in bytes * @param int $error PHP file upload error - * @param string|null $clientFilename Filename as provided by the client, if any. - * @param string|null $clientMediaType Media type as provided by the client, if any. + * @param string $clientFilename Filename as provided by the client, if any. + * @param string $clientMediaType Media type as provided by the client, if any. * * @return UploadedFileInterface * @@ -26,9 +26,9 @@ interface UploadedFileFactoryInterface */ public function createUploadedFile( StreamInterface $stream, - ?int $size = null, + int $size = null, int $error = \UPLOAD_ERR_OK, - ?string $clientFilename = null, - ?string $clientMediaType = null + string $clientFilename = null, + string $clientMediaType = null ): UploadedFileInterface; } diff --git a/vendor/psr/http-message/composer.json b/vendor/psr/http-message/composer.json index c66e5ab..56e8c0a 100644 --- a/vendor/psr/http-message/composer.json +++ b/vendor/psr/http-message/composer.json @@ -7,7 +7,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "homepage": "http://www.php-fig.org/" } ], "require": { @@ -20,7 +20,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.1.x-dev" } } } diff --git a/vendor/psr/http-message/src/MessageInterface.php b/vendor/psr/http-message/src/MessageInterface.php index a83c985..8cdb4ed 100644 --- a/vendor/psr/http-message/src/MessageInterface.php +++ b/vendor/psr/http-message/src/MessageInterface.php @@ -1,5 +1,7 @@ =8.1" + "php": ">=8.0.2" }, "autoload": { "files": [ @@ -25,7 +25,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/vendor/symfony/event-dispatcher-contracts/.gitignore b/vendor/symfony/event-dispatcher-contracts/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/vendor/symfony/event-dispatcher-contracts/Event.php b/vendor/symfony/event-dispatcher-contracts/Event.php index 2e7f998..384a650 100644 --- a/vendor/symfony/event-dispatcher-contracts/Event.php +++ b/vendor/symfony/event-dispatcher-contracts/Event.php @@ -32,6 +32,9 @@ class Event implements StoppableEventInterface { private bool $propagationStopped = false; + /** + * {@inheritdoc} + */ public function isPropagationStopped(): bool { return $this->propagationStopped; diff --git a/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php index 2d7840d..351dc51 100644 --- a/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php +++ b/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php @@ -21,13 +21,11 @@ interface EventDispatcherInterface extends PsrEventDispatcherInterface /** * Dispatches an event to all registered listeners. * - * @template T of object - * - * @param T $event The event to pass to the event handlers/listeners + * @param object $event The event to pass to the event handlers/listeners * @param string|null $eventName The name of the event to dispatch. If not supplied, * the class of $event should be used instead. * - * @return T The passed $event MUST be returned + * @return object The passed $event MUST be returned */ - public function dispatch(object $event, ?string $eventName = null): object; + public function dispatch(object $event, string $eventName = null): object; } diff --git a/vendor/symfony/event-dispatcher-contracts/LICENSE b/vendor/symfony/event-dispatcher-contracts/LICENSE index 7536cae..74cdc2d 100644 --- a/vendor/symfony/event-dispatcher-contracts/LICENSE +++ b/vendor/symfony/event-dispatcher-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/event-dispatcher-contracts/README.md b/vendor/symfony/event-dispatcher-contracts/README.md index 332b961..b1ab4c0 100644 --- a/vendor/symfony/event-dispatcher-contracts/README.md +++ b/vendor/symfony/event-dispatcher-contracts/README.md @@ -3,7 +3,7 @@ Symfony EventDispatcher Contracts A set of abstractions extracted out of the Symfony components. -Can be used to build on semantics that the Symfony components proved useful and +Can be used to build on semantics that the Symfony components proved useful - and that already have battle tested implementations. See https://github.com/symfony/contracts/blob/main/README.md for more information. diff --git a/vendor/symfony/event-dispatcher-contracts/composer.json b/vendor/symfony/event-dispatcher-contracts/composer.json index d156b44..b4c3933 100644 --- a/vendor/symfony/event-dispatcher-contracts/composer.json +++ b/vendor/symfony/event-dispatcher-contracts/composer.json @@ -16,16 +16,19 @@ } ], "require": { - "php": ">=8.1", + "php": ">=8.0.2", "psr/event-dispatcher": "^1" }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, "autoload": { "psr-4": { "Symfony\\Contracts\\EventDispatcher\\": "" } }, "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/vendor/symfony/finder/CHANGELOG.md b/vendor/symfony/finder/CHANGELOG.md index e838302..9e2fc5a 100644 --- a/vendor/symfony/finder/CHANGELOG.md +++ b/vendor/symfony/finder/CHANGELOG.md @@ -1,17 +1,6 @@ CHANGELOG ========= -6.4 ---- - - * Add early directory pruning to `Finder::filter()` - -6.2 ---- - - * Add `Finder::sortByExtension()` and `Finder::sortBySize()` - * Add `Finder::sortByCaseInsensitiveName()` to sort by name with case insensitive sorting methods - 6.0 --- diff --git a/vendor/symfony/finder/Comparator/Comparator.php b/vendor/symfony/finder/Comparator/Comparator.php index 41c02ac..f1ba97d 100644 --- a/vendor/symfony/finder/Comparator/Comparator.php +++ b/vendor/symfony/finder/Comparator/Comparator.php @@ -16,16 +16,16 @@ namespace Symfony\Component\Finder\Comparator; */ class Comparator { + private string $target; private string $operator; - public function __construct( - private string $target, - string $operator = '==', - ) { + public function __construct(string $target, string $operator = '==') + { if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) { - throw new \InvalidArgumentException(\sprintf('Invalid operator "%s".', $operator)); + throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); } + $this->target = $target; $this->operator = $operator; } @@ -50,13 +50,19 @@ class Comparator */ public function test(mixed $test): bool { - return match ($this->operator) { - '>' => $test > $this->target, - '>=' => $test >= $this->target, - '<' => $test < $this->target, - '<=' => $test <= $this->target, - '!=' => $test != $this->target, - default => $test == $this->target, - }; + switch ($this->operator) { + case '>': + return $test > $this->target; + case '>=': + return $test >= $this->target; + case '<': + return $test < $this->target; + case '<=': + return $test <= $this->target; + case '!=': + return $test != $this->target; + } + + return $test == $this->target; } } diff --git a/vendor/symfony/finder/Comparator/DateComparator.php b/vendor/symfony/finder/Comparator/DateComparator.php index bcf93cf..8f651e1 100644 --- a/vendor/symfony/finder/Comparator/DateComparator.php +++ b/vendor/symfony/finder/Comparator/DateComparator.php @@ -26,17 +26,17 @@ class DateComparator extends Comparator public function __construct(string $test) { if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { - throw new \InvalidArgumentException(\sprintf('Don\'t understand "%s" as a date test.', $test)); + throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); } try { - $date = new \DateTimeImmutable($matches[2]); + $date = new \DateTime($matches[2]); $target = $date->format('U'); - } catch (\Exception) { - throw new \InvalidArgumentException(\sprintf('"%s" is not a valid date.', $matches[2])); + } catch (\Exception $e) { + throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); } - $operator = $matches[1] ?: '=='; + $operator = $matches[1] ?? '=='; if ('since' === $operator || 'after' === $operator) { $operator = '>'; } diff --git a/vendor/symfony/finder/Comparator/NumberComparator.php b/vendor/symfony/finder/Comparator/NumberComparator.php index 0ec0049..ff85d96 100644 --- a/vendor/symfony/finder/Comparator/NumberComparator.php +++ b/vendor/symfony/finder/Comparator/NumberComparator.php @@ -19,7 +19,7 @@ namespace Symfony\Component\Finder\Comparator; * magnitudes. * * The target value may use magnitudes of kilobytes (k, ki), - * megabytes (m, mi), or gigabytes (g, gi). Those suffixed + * megabytes (m, mi), or gigabytes (g, gi). Those suffixed * with an i use the appropriate 2**n version in accordance with the * IEC standard: http://physics.nist.gov/cuu/Units/binary.html * @@ -35,19 +35,19 @@ namespace Symfony\Component\Finder\Comparator; class NumberComparator extends Comparator { /** - * @param string|null $test A comparison string or null + * @param string|int $test A comparison string or an integer * * @throws \InvalidArgumentException If the test is not understood */ public function __construct(?string $test) { if (null === $test || !preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { - throw new \InvalidArgumentException(\sprintf('Don\'t understand "%s" as a number test.', $test ?? 'null')); + throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test ?? 'null')); } $target = $matches[2]; if (!is_numeric($target)) { - throw new \InvalidArgumentException(\sprintf('Invalid number "%s".', $target)); + throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target)); } if (isset($matches[3])) { // magnitude diff --git a/vendor/symfony/finder/Finder.php b/vendor/symfony/finder/Finder.php index 78673af..e5772c4 100644 --- a/vendor/symfony/finder/Finder.php +++ b/vendor/symfony/finder/Finder.php @@ -50,7 +50,6 @@ class Finder implements \IteratorAggregate, \Countable private array $notNames = []; private array $exclude = []; private array $filters = []; - private array $pruneFilters = []; private array $depths = []; private array $sizes = []; private bool $followLinks = false; @@ -124,7 +123,7 @@ class Finder implements \IteratorAggregate, \Countable public function depth(string|int|array $levels): static { foreach ((array) $levels as $level) { - $this->depths[] = new NumberComparator($level); + $this->depths[] = new Comparator\NumberComparator($level); } return $this; @@ -152,7 +151,7 @@ class Finder implements \IteratorAggregate, \Countable public function date(string|array $dates): static { foreach ((array) $dates as $date) { - $this->dates[] = new DateComparator($date); + $this->dates[] = new Comparator\DateComparator($date); } return $this; @@ -163,8 +162,8 @@ class Finder implements \IteratorAggregate, \Countable * * You can use patterns (delimited with / sign), globs or simple strings. * - * $finder->name('/\.php$/') - * $finder->name('*.php') // same as above, without dot files + * $finder->name('*.php') + * $finder->name('/\.php$/') // same as above * $finder->name('test.php') * $finder->name(['test.py', 'test.php']) * @@ -307,7 +306,7 @@ class Finder implements \IteratorAggregate, \Countable public function size(string|int|array $sizes): static { foreach ((array) $sizes as $size) { - $this->sizes[] = new NumberComparator($size); + $this->sizes[] = new Comparator\NumberComparator($size); } return $this; @@ -398,7 +397,7 @@ class Finder implements \IteratorAggregate, \Countable * * @param string|string[] $pattern VCS patterns to ignore */ - public static function addVCSPattern(string|array $pattern): void + public static function addVCSPattern(string|array $pattern) { foreach ((array) $pattern as $p) { self::$vcsPatterns[] = $p; @@ -425,22 +424,6 @@ class Finder implements \IteratorAggregate, \Countable return $this; } - /** - * Sorts files and directories by extension. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByExtension(): static - { - $this->sort = SortableIterator::SORT_BY_EXTENSION; - - return $this; - } - /** * Sorts files and directories by name. * @@ -452,39 +435,7 @@ class Finder implements \IteratorAggregate, \Countable */ public function sortByName(bool $useNaturalSort = false): static { - $this->sort = $useNaturalSort ? SortableIterator::SORT_BY_NAME_NATURAL : SortableIterator::SORT_BY_NAME; - - return $this; - } - - /** - * Sorts files and directories by name case insensitive. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByCaseInsensitiveName(bool $useNaturalSort = false): static - { - $this->sort = $useNaturalSort ? SortableIterator::SORT_BY_NAME_NATURAL_CASE_INSENSITIVE : SortableIterator::SORT_BY_NAME_CASE_INSENSITIVE; - - return $this; - } - - /** - * Sorts files and directories by size. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortBySize(): static - { - $this->sort = SortableIterator::SORT_BY_SIZE; + $this->sort = $useNaturalSort ? Iterator\SortableIterator::SORT_BY_NAME_NATURAL : Iterator\SortableIterator::SORT_BY_NAME; return $this; } @@ -500,7 +451,7 @@ class Finder implements \IteratorAggregate, \Countable */ public function sortByType(): static { - $this->sort = SortableIterator::SORT_BY_TYPE; + $this->sort = Iterator\SortableIterator::SORT_BY_TYPE; return $this; } @@ -518,7 +469,7 @@ class Finder implements \IteratorAggregate, \Countable */ public function sortByAccessedTime(): static { - $this->sort = SortableIterator::SORT_BY_ACCESSED_TIME; + $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME; return $this; } @@ -550,7 +501,7 @@ class Finder implements \IteratorAggregate, \Countable */ public function sortByChangedTime(): static { - $this->sort = SortableIterator::SORT_BY_CHANGED_TIME; + $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME; return $this; } @@ -568,7 +519,7 @@ class Finder implements \IteratorAggregate, \Countable */ public function sortByModifiedTime(): static { - $this->sort = SortableIterator::SORT_BY_MODIFIED_TIME; + $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME; return $this; } @@ -579,21 +530,14 @@ class Finder implements \IteratorAggregate, \Countable * The anonymous function receives a \SplFileInfo and must return false * to remove files. * - * @param \Closure(SplFileInfo): bool $closure - * @param bool $prune Whether to skip traversing directories further - * * @return $this * * @see CustomFilterIterator */ - public function filter(\Closure $closure, bool $prune = false): static + public function filter(\Closure $closure): static { $this->filters[] = $closure; - if ($prune) { - $this->pruneFilters[] = $closure; - } - return $this; } @@ -641,9 +585,9 @@ class Finder implements \IteratorAggregate, \Countable $resolvedDirs[] = [$this->normalizeDir($dir)]; } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? \GLOB_BRACE : 0) | \GLOB_ONLYDIR | \GLOB_NOSORT)) { sort($glob); - $resolvedDirs[] = array_map($this->normalizeDir(...), $glob); + $resolvedDirs[] = array_map([$this, 'normalizeDir'], $glob); } else { - throw new DirectoryNotFoundException(\sprintf('The "%s" directory does not exist.', $dir)); + throw new DirectoryNotFoundException(sprintf('The "%s" directory does not exist.', $dir)); } } @@ -671,7 +615,7 @@ class Finder implements \IteratorAggregate, \Countable $iterator = $this->searchInDirectory($this->dirs[0]); if ($this->sort || $this->reverseSorting) { - $iterator = (new SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator(); + $iterator = (new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator(); } return $iterator; @@ -679,7 +623,9 @@ class Finder implements \IteratorAggregate, \Countable $iterator = new \AppendIterator(); foreach ($this->dirs as $dir) { - $iterator->append(new \IteratorIterator(new LazyIterator(fn () => $this->searchInDirectory($dir)))); + $iterator->append(new \IteratorIterator(new LazyIterator(function () use ($dir) { + return $this->searchInDirectory($dir); + }))); } foreach ($this->iterators as $it) { @@ -687,7 +633,7 @@ class Finder implements \IteratorAggregate, \Countable } if ($this->sort || $this->reverseSorting) { - $iterator = (new SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator(); + $iterator = (new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator(); } return $iterator; @@ -699,6 +645,8 @@ class Finder implements \IteratorAggregate, \Countable * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. * * @return $this + * + * @throws \InvalidArgumentException when the given argument is not iterable */ public function append(iterable $iterator): static { @@ -706,13 +654,15 @@ class Finder implements \IteratorAggregate, \Countable $this->iterators[] = $iterator->getIterator(); } elseif ($iterator instanceof \Iterator) { $this->iterators[] = $iterator; - } else { + } elseif (is_iterable($iterator)) { $it = new \ArrayIterator(); foreach ($iterator as $file) { $file = $file instanceof \SplFileInfo ? $file : new \SplFileInfo($file); $it[$file->getPathname()] = $file; } $this->iterators[] = $it; + } else { + throw new \InvalidArgumentException('Finder::append() method wrong argument type.'); } return $this; @@ -743,10 +693,6 @@ class Finder implements \IteratorAggregate, \Countable $exclude = $this->exclude; $notPaths = $this->notPaths; - if ($this->pruneFilters) { - $exclude = array_merge($exclude, $this->pruneFilters); - } - if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { $exclude = array_merge($exclude, self::$vcsPatterns); } @@ -786,13 +732,13 @@ class Finder implements \IteratorAggregate, \Countable $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs); if ($exclude) { - $iterator = new ExcludeDirectoryFilterIterator($iterator, $exclude); + $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $exclude); } $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST); if ($minDepth > 0 || $maxDepth < \PHP_INT_MAX) { - $iterator = new DepthRangeFilterIterator($iterator, $minDepth, $maxDepth); + $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth); } if ($this->mode) { @@ -800,23 +746,23 @@ class Finder implements \IteratorAggregate, \Countable } if ($this->names || $this->notNames) { - $iterator = new FilenameFilterIterator($iterator, $this->names, $this->notNames); + $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); } if ($this->contains || $this->notContains) { - $iterator = new FilecontentFilterIterator($iterator, $this->contains, $this->notContains); + $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); } if ($this->sizes) { - $iterator = new SizeRangeFilterIterator($iterator, $this->sizes); + $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes); } if ($this->dates) { - $iterator = new DateRangeFilterIterator($iterator, $this->dates); + $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates); } if ($this->filters) { - $iterator = new CustomFilterIterator($iterator, $this->filters); + $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } if ($this->paths || $notPaths) { diff --git a/vendor/symfony/finder/Gitignore.php b/vendor/symfony/finder/Gitignore.php index bf05c5b..d42cca1 100644 --- a/vendor/symfony/finder/Gitignore.php +++ b/vendor/symfony/finder/Gitignore.php @@ -43,7 +43,7 @@ class Gitignore foreach ($gitignoreLines as $line) { $line = preg_replace('~(? '['.('' !== $matches[1] ? '^' : '').str_replace('\\-', '-', $matches[2]).']', $regex); + $regex = preg_replace_callback('~\\\\\[((?:\\\\!)?)([^\[\]]*)\\\\\]~', function (array $matches): string { + return '['.('' !== $matches[1] ? '^' : '').str_replace('\\-', '-', $matches[2]).']'; + }, $regex); $regex = preg_replace('~(?:(?:\\\\\*){2,}(/?))+~', '(?:(?:(?!//).(? * - * @extends \FilterIterator - * - * @implements \RecursiveIterator + * @extends \FilterIterator + * @implements \RecursiveIterator */ class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator { - /** @var \Iterator */ private \Iterator $iterator; private bool $isRecursive; - /** @var array */ private array $excludedDirs = []; private ?string $excludedPattern = null; - /** @var list */ - private array $pruneFilters = []; /** - * @param \Iterator $iterator The Iterator to filter - * @param list $directories An array of directories to exclude + * @param \Iterator $iterator The Iterator to filter + * @param string[] $directories An array of directories to exclude */ public function __construct(\Iterator $iterator, array $directories) { @@ -43,16 +36,6 @@ class ExcludeDirectoryFilterIterator extends \FilterIterator implements \Recursi $this->isRecursive = $iterator instanceof \RecursiveIterator; $patterns = []; foreach ($directories as $directory) { - if (!\is_string($directory)) { - if (!\is_callable($directory)) { - throw new \InvalidArgumentException('Invalid PHP callback.'); - } - - $this->pruneFilters[] = $directory; - - continue; - } - $directory = rtrim($directory, '/'); if (!$this->isRecursive || str_contains($directory, '/')) { $patterns[] = preg_quote($directory, '#'); @@ -83,14 +66,6 @@ class ExcludeDirectoryFilterIterator extends \FilterIterator implements \Recursi return !preg_match($this->excludedPattern, $path); } - if ($this->pruneFilters && $this->hasChildren()) { - foreach ($this->pruneFilters as $pruneFilter) { - if (!$pruneFilter($this->current())) { - return false; - } - } - } - return true; } diff --git a/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php b/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php index 0d4a5fd..2ed48fb 100644 --- a/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php +++ b/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php @@ -23,14 +23,16 @@ class FileTypeFilterIterator extends \FilterIterator public const ONLY_FILES = 1; public const ONLY_DIRECTORIES = 2; + private int $mode; + /** - * @param \Iterator $iterator The Iterator to filter - * @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) + * @param \Iterator $iterator The Iterator to filter + * @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) */ - public function __construct( - \Iterator $iterator, - private int $mode, - ) { + public function __construct(\Iterator $iterator, int $mode) + { + $this->mode = $mode; + parent::__construct($iterator); } diff --git a/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php b/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php index bdc71ff..eaa7a5d 100644 --- a/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php +++ b/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php @@ -11,15 +11,13 @@ namespace Symfony\Component\Finder\Iterator; -use Symfony\Component\Finder\SplFileInfo; - /** * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings). * * @author Fabien Potencier * @author Włodzimierz Gajda * - * @extends MultiplePcreFilterIterator + * @extends MultiplePcreFilterIterator */ class FilecontentFilterIterator extends MultiplePcreFilterIterator { diff --git a/vendor/symfony/finder/Iterator/LazyIterator.php b/vendor/symfony/finder/Iterator/LazyIterator.php index 5b5806b..71c4be8 100644 --- a/vendor/symfony/finder/Iterator/LazyIterator.php +++ b/vendor/symfony/finder/Iterator/LazyIterator.php @@ -22,7 +22,7 @@ class LazyIterator implements \IteratorAggregate public function __construct(callable $iteratorFactory) { - $this->iteratorFactory = $iteratorFactory(...); + $this->iteratorFactory = $iteratorFactory instanceof \Closure ? $iteratorFactory : \Closure::fromCallable($iteratorFactory); } public function getIterator(): \Traversable diff --git a/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php b/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php index 3450c49..1e9e7ff 100644 --- a/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php +++ b/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php @@ -23,13 +23,13 @@ namespace Symfony\Component\Finder\Iterator; */ abstract class MultiplePcreFilterIterator extends \FilterIterator { - protected array $matchRegexps = []; - protected array $noMatchRegexps = []; + protected $matchRegexps = []; + protected $noMatchRegexps = []; /** - * @param \Iterator $iterator The Iterator to filter - * @param string[] $matchPatterns An array of patterns that need to match - * @param string[] $noMatchPatterns An array of patterns that need to not match + * @param \Iterator $iterator The Iterator to filter + * @param string[] $matchPatterns An array of patterns that need to match + * @param string[] $noMatchPatterns An array of patterns that need to not match */ public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) { @@ -80,7 +80,11 @@ abstract class MultiplePcreFilterIterator extends \FilterIterator */ protected function isRegex(string $str): bool { - $availableModifiers = 'imsxuADUn'; + $availableModifiers = 'imsxuADU'; + + if (\PHP_VERSION_ID >= 80200) { + $availableModifiers .= 'n'; + } if (preg_match('/^(.{3,}?)['.$availableModifiers.']*$/', $str, $m)) { $start = substr($m[1], 0, 1); diff --git a/vendor/symfony/finder/Iterator/PathFilterIterator.php b/vendor/symfony/finder/Iterator/PathFilterIterator.php index c6d5813..bfe402a 100644 --- a/vendor/symfony/finder/Iterator/PathFilterIterator.php +++ b/vendor/symfony/finder/Iterator/PathFilterIterator.php @@ -11,15 +11,13 @@ namespace Symfony\Component\Finder\Iterator; -use Symfony\Component\Finder\SplFileInfo; - /** * PathFilterIterator filters files by path patterns (e.g. some/special/dir). * * @author Fabien Potencier * @author Włodzimierz Gajda * - * @extends MultiplePcreFilterIterator + * @extends MultiplePcreFilterIterator */ class PathFilterIterator extends MultiplePcreFilterIterator { diff --git a/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php b/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php index f5fd2d4..4c9779f 100644 --- a/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php +++ b/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php @@ -18,13 +18,11 @@ use Symfony\Component\Finder\SplFileInfo; * Extends the \RecursiveDirectoryIterator to support relative paths. * * @author Victor Berchet - * - * @extends \RecursiveDirectoryIterator */ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator { private bool $ignoreUnreadableDirs; - private bool $ignoreFirstRewind = true; + private ?bool $rewindable = null; // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations private string $rootPath; @@ -63,9 +61,8 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator $subPathname .= $this->directorySeparator; } $subPathname .= $this->getFilename(); - $basePath = $this->rootPath; - if ('/' !== $basePath && !str_ends_with($basePath, $this->directorySeparator) && !str_ends_with($basePath, '/')) { + if ('/' !== $basePath = $this->rootPath) { $basePath .= $this->directorySeparator; } @@ -84,7 +81,7 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator parent::getChildren(); return true; - } catch (\UnexpectedValueException) { + } catch (\UnexpectedValueException $e) { // If directory is unreadable and finder is set to ignore it, skip children return false; } @@ -103,6 +100,7 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs; // performance optimization to avoid redoing the same work in all children + $children->rewindable = &$this->rewindable; $children->rootPath = $this->rootPath; } @@ -112,23 +110,36 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator } } - public function next(): void - { - $this->ignoreFirstRewind = false; - - parent::next(); - } - + /** + * Do nothing for non rewindable stream. + */ public function rewind(): void { - // some streams like FTP are not rewindable, ignore the first rewind after creation, - // as newly created DirectoryIterator does not need to be rewound - if ($this->ignoreFirstRewind) { - $this->ignoreFirstRewind = false; - + if (false === $this->isRewindable()) { return; } parent::rewind(); } + + /** + * Checks if the stream is rewindable. + */ + public function isRewindable(): bool + { + if (null !== $this->rewindable) { + return $this->rewindable; + } + + if (false !== $stream = @opendir($this->getPath())) { + $infos = stream_get_meta_data($stream); + closedir($stream); + + if ($infos['seekable']) { + return $this->rewindable = true; + } + } + + return $this->rewindable = false; + } } diff --git a/vendor/symfony/finder/Iterator/SortableIterator.php b/vendor/symfony/finder/Iterator/SortableIterator.php index 177cd0b..b6c34b6 100644 --- a/vendor/symfony/finder/Iterator/SortableIterator.php +++ b/vendor/symfony/finder/Iterator/SortableIterator.php @@ -27,12 +27,7 @@ class SortableIterator implements \IteratorAggregate public const SORT_BY_CHANGED_TIME = 4; public const SORT_BY_MODIFIED_TIME = 5; public const SORT_BY_NAME_NATURAL = 6; - public const SORT_BY_NAME_CASE_INSENSITIVE = 7; - public const SORT_BY_NAME_NATURAL_CASE_INSENSITIVE = 8; - public const SORT_BY_EXTENSION = 9; - public const SORT_BY_SIZE = 10; - /** @var \Traversable */ private \Traversable $iterator; private \Closure|int $sort; @@ -48,13 +43,13 @@ class SortableIterator implements \IteratorAggregate $order = $reverseOrder ? -1 : 1; if (self::SORT_BY_NAME === $sort) { - $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); + }; } elseif (self::SORT_BY_NAME_NATURAL === $sort) { - $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * strnatcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); - } elseif (self::SORT_BY_NAME_CASE_INSENSITIVE === $sort) { - $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * strcasecmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); - } elseif (self::SORT_BY_NAME_NATURAL_CASE_INSENSITIVE === $sort) { - $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * strnatcasecmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * strnatcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); + }; } elseif (self::SORT_BY_TYPE === $sort) { $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { if ($a->isDir() && $b->isFile()) { @@ -66,19 +61,21 @@ class SortableIterator implements \IteratorAggregate return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); }; } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { - $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getATime() - $b->getATime()); + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * ($a->getATime() - $b->getATime()); + }; } elseif (self::SORT_BY_CHANGED_TIME === $sort) { - $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getCTime() - $b->getCTime()); + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * ($a->getCTime() - $b->getCTime()); + }; } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { - $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getMTime() - $b->getMTime()); - } elseif (self::SORT_BY_EXTENSION === $sort) { - $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * strnatcmp($a->getExtension(), $b->getExtension()); - } elseif (self::SORT_BY_SIZE === $sort) { - $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getSize() - $b->getSize()); + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * ($a->getMTime() - $b->getMTime()); + }; } elseif (self::SORT_BY_NONE === $sort) { $this->sort = $order; } elseif (\is_callable($sort)) { - $this->sort = $reverseOrder ? static fn (\SplFileInfo $a, \SplFileInfo $b) => -$sort($a, $b) : $sort(...); + $this->sort = $reverseOrder ? static function (\SplFileInfo $a, \SplFileInfo $b) use ($sort) { return -$sort($a, $b); } : \Closure::fromCallable($sort); } else { throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.'); } diff --git a/vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php b/vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php index b278706..e27158c 100644 --- a/vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php +++ b/vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php @@ -13,37 +13,27 @@ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Gitignore; -/** - * @extends \FilterIterator - */ final class VcsIgnoredFilterIterator extends \FilterIterator { - private string $baseDir; + /** + * @var string + */ + private $baseDir; /** * @var array */ - private array $gitignoreFilesCache = []; + private $gitignoreFilesCache = []; /** * @var array */ - private array $ignoredPathsCache = []; + private $ignoredPathsCache = []; - /** - * @param \Iterator $iterator - */ public function __construct(\Iterator $iterator, string $baseDir) { $this->baseDir = $this->normalizePath($baseDir); - foreach ([$this->baseDir, ...$this->parentDirectoriesUpwards($this->baseDir)] as $directory) { - if (@is_dir("{$directory}/.git")) { - $this->baseDir = $directory; - break; - } - } - parent::__construct($iterator); } @@ -68,7 +58,7 @@ final class VcsIgnoredFilterIterator extends \FilterIterator $ignored = false; - foreach ($this->parentDirectoriesDownwards($fileRealPath) as $parentDirectory) { + foreach ($this->parentsDirectoryDownward($fileRealPath) as $parentDirectory) { if ($this->isIgnored($parentDirectory)) { // rules in ignored directories are ignored, no need to check further. break; @@ -99,11 +89,11 @@ final class VcsIgnoredFilterIterator extends \FilterIterator /** * @return list */ - private function parentDirectoriesUpwards(string $from): array + private function parentsDirectoryDownward(string $fileRealPath): array { $parentDirectories = []; - $parentDirectory = $from; + $parentDirectory = $fileRealPath; while (true) { $newParentDirectory = \dirname($parentDirectory); @@ -113,28 +103,16 @@ final class VcsIgnoredFilterIterator extends \FilterIterator break; } - $parentDirectories[] = $parentDirectory = $newParentDirectory; + $parentDirectory = $newParentDirectory; + + if (0 !== strpos($parentDirectory, $this->baseDir)) { + break; + } + + $parentDirectories[] = $parentDirectory; } - return $parentDirectories; - } - - private function parentDirectoriesUpTo(string $from, string $upTo): array - { - return array_filter( - $this->parentDirectoriesUpwards($from), - static fn (string $directory): bool => str_starts_with($directory, $upTo) - ); - } - - /** - * @return list - */ - private function parentDirectoriesDownwards(string $fileRealPath): array - { - return array_reverse( - $this->parentDirectoriesUpTo($fileRealPath, $this->baseDir) - ); + return array_reverse($parentDirectories); } /** diff --git a/vendor/symfony/finder/LICENSE b/vendor/symfony/finder/LICENSE index 0138f8f..0083704 100644 --- a/vendor/symfony/finder/LICENSE +++ b/vendor/symfony/finder/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-present Fabien Potencier +Copyright (c) 2004-2023 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/finder/SplFileInfo.php b/vendor/symfony/finder/SplFileInfo.php index 2afc378..867e8e8 100644 --- a/vendor/symfony/finder/SplFileInfo.php +++ b/vendor/symfony/finder/SplFileInfo.php @@ -18,17 +18,19 @@ namespace Symfony\Component\Finder; */ class SplFileInfo extends \SplFileInfo { + private string $relativePath; + private string $relativePathname; + /** * @param string $file The file name * @param string $relativePath The relative path * @param string $relativePathname The relative path name */ - public function __construct( - string $file, - private string $relativePath, - private string $relativePathname, - ) { + public function __construct(string $file, string $relativePath, string $relativePathname) + { parent::__construct($file); + $this->relativePath = $relativePath; + $this->relativePathname = $relativePathname; } /** diff --git a/vendor/symfony/finder/composer.json b/vendor/symfony/finder/composer.json index 2b70600..2e4b324 100644 --- a/vendor/symfony/finder/composer.json +++ b/vendor/symfony/finder/composer.json @@ -16,10 +16,7 @@ } ], "require": { - "php": ">=8.2" - }, - "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "php": ">=8.0.2" }, "autoload": { "psr-4": { "Symfony\\Component\\Finder\\": "" }, diff --git a/vendor/symfony/service-contracts/.gitignore b/vendor/symfony/service-contracts/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/vendor/symfony/service-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/vendor/symfony/service-contracts/Attribute/SubscribedService.php b/vendor/symfony/service-contracts/Attribute/SubscribedService.php index f850b84..10d1bc3 100644 --- a/vendor/symfony/service-contracts/Attribute/SubscribedService.php +++ b/vendor/symfony/service-contracts/Attribute/SubscribedService.php @@ -11,15 +11,10 @@ namespace Symfony\Contracts\Service\Attribute; -use Symfony\Contracts\Service\ServiceMethodsSubscriberTrait; -use Symfony\Contracts\Service\ServiceSubscriberInterface; +use Symfony\Contracts\Service\ServiceSubscriberTrait; /** - * For use as the return value for {@see ServiceSubscriberInterface}. - * - * @example new SubscribedService('http_client', HttpClientInterface::class, false, new Target('githubApi')) - * - * Use with {@see ServiceMethodsSubscriberTrait} to mark a method's return type + * Use with {@see ServiceSubscriberTrait} to mark a method's return type * as a subscribed service. * * @author Kevin Bond @@ -27,21 +22,12 @@ use Symfony\Contracts\Service\ServiceSubscriberInterface; #[\Attribute(\Attribute::TARGET_METHOD)] final class SubscribedService { - /** @var object[] */ - public array $attributes; - /** - * @param string|null $key The key to use for the service - * @param class-string|null $type The service class - * @param bool $nullable Whether the service is optional - * @param object|object[] $attributes One or more dependency injection attributes to use + * @param string|null $key The key to use for the service + * If null, use "ClassName::methodName" */ public function __construct( - public ?string $key = null, - public ?string $type = null, - public bool $nullable = false, - array|object $attributes = [], + public ?string $key = null ) { - $this->attributes = \is_array($attributes) ? $attributes : [$attributes]; } } diff --git a/vendor/symfony/service-contracts/LICENSE b/vendor/symfony/service-contracts/LICENSE index 7536cae..74cdc2d 100644 --- a/vendor/symfony/service-contracts/LICENSE +++ b/vendor/symfony/service-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/service-contracts/README.md b/vendor/symfony/service-contracts/README.md index 42841a5..41e054a 100644 --- a/vendor/symfony/service-contracts/README.md +++ b/vendor/symfony/service-contracts/README.md @@ -3,7 +3,7 @@ Symfony Service Contracts A set of abstractions extracted out of the Symfony components. -Can be used to build on semantics that the Symfony components proved useful and +Can be used to build on semantics that the Symfony components proved useful - and that already have battle tested implementations. See https://github.com/symfony/contracts/blob/main/README.md for more information. diff --git a/vendor/symfony/service-contracts/ResetInterface.php b/vendor/symfony/service-contracts/ResetInterface.php index a4f389b..1af1075 100644 --- a/vendor/symfony/service-contracts/ResetInterface.php +++ b/vendor/symfony/service-contracts/ResetInterface.php @@ -26,8 +26,5 @@ namespace Symfony\Contracts\Service; */ interface ResetInterface { - /** - * @return void - */ public function reset(); } diff --git a/vendor/symfony/service-contracts/ServiceCollectionInterface.php b/vendor/symfony/service-contracts/ServiceCollectionInterface.php deleted file mode 100644 index 2333139..0000000 --- a/vendor/symfony/service-contracts/ServiceCollectionInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -/** - * A ServiceProviderInterface that is also countable and iterable. - * - * @author Kevin Bond - * - * @template-covariant T of mixed - * - * @extends ServiceProviderInterface - * @extends \IteratorAggregate - */ -interface ServiceCollectionInterface extends ServiceProviderInterface, \Countable, \IteratorAggregate -{ -} diff --git a/vendor/symfony/service-contracts/ServiceLocatorTrait.php b/vendor/symfony/service-contracts/ServiceLocatorTrait.php index bbe4548..19d3e80 100644 --- a/vendor/symfony/service-contracts/ServiceLocatorTrait.php +++ b/vendor/symfony/service-contracts/ServiceLocatorTrait.php @@ -26,22 +26,29 @@ class_exists(NotFoundExceptionInterface::class); */ trait ServiceLocatorTrait { + private array $factories; private array $loading = []; private array $providedTypes; /** - * @param array $factories + * @param callable[] $factories */ - public function __construct( - private array $factories, - ) { + public function __construct(array $factories) + { + $this->factories = $factories; } + /** + * {@inheritdoc} + */ public function has(string $id): bool { return isset($this->factories[$id]); } + /** + * {@inheritdoc} + */ public function get(string $id): mixed { if (!isset($this->factories[$id])) { @@ -64,6 +71,9 @@ trait ServiceLocatorTrait } } + /** + * {@inheritdoc} + */ public function getProvidedServices(): array { if (!isset($this->providedTypes)) { @@ -90,16 +100,16 @@ trait ServiceLocatorTrait } else { $last = array_pop($alternatives); if ($alternatives) { - $message = \sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last); + $message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last); } else { - $message = \sprintf('only knows about the "%s" service.', $last); + $message = sprintf('only knows about the "%s" service.', $last); } } if ($this->loading) { - $message = \sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message); + $message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message); } else { - $message = \sprintf('Service "%s" not found: the current service locator %s', $id, $message); + $message = sprintf('Service "%s" not found: the current service locator %s', $id, $message); } return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface { @@ -108,7 +118,7 @@ trait ServiceLocatorTrait private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface { - return new class(\sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface { + return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface { }; } } diff --git a/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php b/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php deleted file mode 100644 index 844be89..0000000 --- a/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -use Psr\Container\ContainerInterface; -use Symfony\Contracts\Service\Attribute\Required; -use Symfony\Contracts\Service\Attribute\SubscribedService; - -/** - * Implementation of ServiceSubscriberInterface that determines subscribed services - * from methods that have the #[SubscribedService] attribute. - * - * Service ids are available as "ClassName::methodName" so that the implementation - * of subscriber methods can be just `return $this->container->get(__METHOD__);`. - * - * @author Kevin Bond - */ -trait ServiceMethodsSubscriberTrait -{ - protected ContainerInterface $container; - - public static function getSubscribedServices(): array - { - $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; - - foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { - if (self::class !== $method->getDeclaringClass()->name) { - continue; - } - - if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { - continue; - } - - if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { - throw new \LogicException(\sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); - } - - if (!$returnType = $method->getReturnType()) { - throw new \LogicException(\sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); - } - - /* @var SubscribedService $attribute */ - $attribute = $attribute->newInstance(); - $attribute->key ??= self::class.'::'.$method->name; - $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; - $attribute->nullable = $attribute->nullable ?: $returnType->allowsNull(); - - if ($attribute->attributes) { - $services[] = $attribute; - } else { - $services[$attribute->key] = ($attribute->nullable ? '?' : '').$attribute->type; - } - } - - return $services; - } - - #[Required] - public function setContainer(ContainerInterface $container): ?ContainerInterface - { - $ret = null; - if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { - $ret = parent::setContainer($container); - } - - $this->container = $container; - - return $ret; - } -} diff --git a/vendor/symfony/service-contracts/ServiceProviderInterface.php b/vendor/symfony/service-contracts/ServiceProviderInterface.php index 2e71f00..c60ad0b 100644 --- a/vendor/symfony/service-contracts/ServiceProviderInterface.php +++ b/vendor/symfony/service-contracts/ServiceProviderInterface.php @@ -18,18 +18,9 @@ use Psr\Container\ContainerInterface; * * @author Nicolas Grekas * @author Mateusz Sip - * - * @template-covariant T of mixed */ interface ServiceProviderInterface extends ContainerInterface { - /** - * @return T - */ - public function get(string $id): mixed; - - public function has(string $id): bool; - /** * Returns an associative array of service types keyed by the identifiers provided by the current container. * @@ -39,7 +30,7 @@ interface ServiceProviderInterface extends ContainerInterface * * ['foo' => '?'] means the container provides service name "foo" of unspecified type * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null * - * @return array The provided service types, keyed by service names + * @return string[] The provided service types, keyed by service names */ public function getProvidedServices(): array; } diff --git a/vendor/symfony/service-contracts/ServiceSubscriberInterface.php b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php index 3da1916..881ab97 100644 --- a/vendor/symfony/service-contracts/ServiceSubscriberInterface.php +++ b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php @@ -11,8 +11,6 @@ namespace Symfony\Contracts\Service; -use Symfony\Contracts\Service\Attribute\SubscribedService; - /** * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. * @@ -31,8 +29,7 @@ use Symfony\Contracts\Service\Attribute\SubscribedService; interface ServiceSubscriberInterface { /** - * Returns an array of service types (or {@see SubscribedService} objects) required - * by such instances, optionally keyed by the service names used internally. + * Returns an array of service types required by such instances, optionally keyed by the service names used internally. * * For mandatory dependencies: * @@ -50,13 +47,7 @@ interface ServiceSubscriberInterface * * ['?Psr\Log\LoggerInterface'] is a shortcut for * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] * - * additionally, an array of {@see SubscribedService}'s can be returned: - * - * * [new SubscribedService('logger', Psr\Log\LoggerInterface::class)] - * * [new SubscribedService(type: Psr\Log\LoggerInterface::class, nullable: true)] - * * [new SubscribedService('http_client', HttpClientInterface::class, attributes: new Target('githubApi'))] - * - * @return string[]|SubscribedService[] The required service types, optionally keyed by service names + * @return string[] The required service types, optionally keyed by service names */ public static function getSubscribedServices(): array; } diff --git a/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php index ed4cec0..ee9d9d9 100644 --- a/vendor/symfony/service-contracts/ServiceSubscriberTrait.php +++ b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php @@ -12,26 +12,22 @@ namespace Symfony\Contracts\Service; use Psr\Container\ContainerInterface; -use Symfony\Contracts\Service\Attribute\Required; use Symfony\Contracts\Service\Attribute\SubscribedService; -trigger_deprecation('symfony/contracts', 'v3.5', '"%s" is deprecated, use "ServiceMethodsSubscriberTrait" instead.', ServiceSubscriberTrait::class); - /** - * Implementation of ServiceSubscriberInterface that determines subscribed services - * from methods that have the #[SubscribedService] attribute. - * - * Service ids are available as "ClassName::methodName" so that the implementation - * of subscriber methods can be just `return $this->container->get(__METHOD__);`. - * - * @property ContainerInterface $container + * Implementation of ServiceSubscriberInterface that determines subscribed services from + * method return types. Service ids are available as "ClassName::methodName". * * @author Kevin Bond - * - * @deprecated since symfony/contracts v3.5, use ServiceMethodsSubscriberTrait instead */ trait ServiceSubscriberTrait { + /** @var ContainerInterface */ + protected $container; + + /** + * {@inheritdoc} + */ public static function getSubscribedServices(): array { $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; @@ -46,39 +42,36 @@ trait ServiceSubscriberTrait } if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { - throw new \LogicException(\sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); + throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); } if (!$returnType = $method->getReturnType()) { - throw new \LogicException(\sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); + throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); } - /* @var SubscribedService $attribute */ - $attribute = $attribute->newInstance(); - $attribute->key ??= self::class.'::'.$method->name; - $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; - $attribute->nullable = $attribute->nullable ?: $returnType->allowsNull(); + $serviceId = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; - if ($attribute->attributes) { - $services[] = $attribute; - } else { - $services[$attribute->key] = ($attribute->nullable ? '?' : '').$attribute->type; + if ($returnType->allowsNull()) { + $serviceId = '?'.$serviceId; } + + $services[$attribute->newInstance()->key ?? self::class.'::'.$method->name] = $serviceId; } return $services; } - #[Required] + /** + * @required + */ public function setContainer(ContainerInterface $container): ?ContainerInterface { - $ret = null; - if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { - $ret = parent::setContainer($container); - } - $this->container = $container; - return $ret; + if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { + return parent::setContainer($container); + } + + return null; } } diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php index 07d12b4..88f6a06 100644 --- a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php +++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php @@ -11,13 +11,82 @@ namespace Symfony\Contracts\Service\Test; -class_alias(ServiceLocatorTestCase::class, ServiceLocatorTest::class); +use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\ServiceLocatorTrait; -if (false) { - /** - * @deprecated since PHPUnit 9.6 - */ - class ServiceLocatorTest +abstract class ServiceLocatorTest extends TestCase +{ + protected function getServiceLocator(array $factories): ContainerInterface { + return new class($factories) implements ContainerInterface { + use ServiceLocatorTrait; + }; + } + + public function testHas() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + function () { return 'dummy'; }, + ]); + + $this->assertTrue($locator->has('foo')); + $this->assertTrue($locator->has('bar')); + $this->assertFalse($locator->has('dummy')); + } + + public function testGet() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('baz', $locator->get('bar')); + } + + public function testGetDoesNotMemoize() + { + $i = 0; + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$i) { + ++$i; + + return 'bar'; + }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame(2, $i); + } + + public function testThrowsOnUndefinedInternalService() + { + if (!$this->getExpectedException()) { + $this->expectException(\Psr\Container\NotFoundExceptionInterface::class); + $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); + } + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); + } + + public function testThrowsOnCircularReference() + { + $this->expectException(\Psr\Container\ContainerExceptionInterface::class); + $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + 'bar' => function () use (&$locator) { return $locator->get('baz'); }, + 'baz' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); } } diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php deleted file mode 100644 index fdd5b27..0000000 --- a/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service\Test; - -use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\ContainerInterface; -use Psr\Container\NotFoundExceptionInterface; -use Symfony\Contracts\Service\ServiceLocatorTrait; - -abstract class ServiceLocatorTestCase extends TestCase -{ - /** - * @param array $factories - */ - protected function getServiceLocator(array $factories): ContainerInterface - { - return new class($factories) implements ContainerInterface { - use ServiceLocatorTrait; - }; - } - - public function testHas() - { - $locator = $this->getServiceLocator([ - 'foo' => fn () => 'bar', - 'bar' => fn () => 'baz', - fn () => 'dummy', - ]); - - $this->assertTrue($locator->has('foo')); - $this->assertTrue($locator->has('bar')); - $this->assertFalse($locator->has('dummy')); - } - - public function testGet() - { - $locator = $this->getServiceLocator([ - 'foo' => fn () => 'bar', - 'bar' => fn () => 'baz', - ]); - - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame('baz', $locator->get('bar')); - } - - public function testGetDoesNotMemoize() - { - $i = 0; - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$i) { - ++$i; - - return 'bar'; - }, - ]); - - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame(2, $i); - } - - public function testThrowsOnUndefinedInternalService() - { - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$locator) { return $locator->get('bar'); }, - ]); - - $this->expectException(NotFoundExceptionInterface::class); - $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); - - $locator->get('foo'); - } - - public function testThrowsOnCircularReference() - { - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$locator) { return $locator->get('bar'); }, - 'bar' => function () use (&$locator) { return $locator->get('baz'); }, - 'baz' => function () use (&$locator) { return $locator->get('bar'); }, - ]); - - $this->expectException(ContainerExceptionInterface::class); - $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); - - $locator->get('foo'); - } -} diff --git a/vendor/symfony/service-contracts/composer.json b/vendor/symfony/service-contracts/composer.json index bc2e99a..d3b047f 100644 --- a/vendor/symfony/service-contracts/composer.json +++ b/vendor/symfony/service-contracts/composer.json @@ -16,23 +16,22 @@ } ], "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.0.2", + "psr/container": "^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" }, + "suggest": { + "symfony/service-implementation": "" + }, "autoload": { - "psr-4": { "Symfony\\Contracts\\Service\\": "" }, - "exclude-from-classmap": [ - "/Test/" - ] + "psr-4": { "Symfony\\Contracts\\Service\\": "" } }, "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/vendor/symfony/var-exporter/CHANGELOG.md b/vendor/symfony/var-exporter/CHANGELOG.md index fdca002..3406c30 100644 --- a/vendor/symfony/var-exporter/CHANGELOG.md +++ b/vendor/symfony/var-exporter/CHANGELOG.md @@ -1,19 +1,6 @@ CHANGELOG ========= -6.4 ---- - - * Deprecate per-property lazy-initializers - -6.2 ---- - - * Add support for lazy ghost objects and virtual proxies - * Add `Hydrator::hydrate()` - * Preserve PHP references also when using `Hydrator::hydrate()` or `Instantiator::instantiate()` - * Add support for hydrating from native (array) casts - 5.1.0 ----- diff --git a/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php b/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php index 2acecc4..4cebe44 100644 --- a/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php +++ b/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php @@ -13,8 +13,8 @@ namespace Symfony\Component\VarExporter\Exception; class ClassNotFoundException extends \Exception implements ExceptionInterface { - public function __construct(string $class, ?\Throwable $previous = null) + public function __construct(string $class, \Throwable $previous = null) { - parent::__construct(\sprintf('Class "%s" not found.', $class), 0, $previous); + parent::__construct(sprintf('Class "%s" not found.', $class), 0, $previous); } } diff --git a/vendor/symfony/var-exporter/Exception/LogicException.php b/vendor/symfony/var-exporter/Exception/LogicException.php deleted file mode 100644 index 619d055..0000000 --- a/vendor/symfony/var-exporter/Exception/LogicException.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Exception; - -class LogicException extends \LogicException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php b/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php index bc2bcaa..771ee61 100644 --- a/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php +++ b/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php @@ -13,8 +13,8 @@ namespace Symfony\Component\VarExporter\Exception; class NotInstantiableTypeException extends \Exception implements ExceptionInterface { - public function __construct(string $type, ?\Throwable $previous = null) + public function __construct(string $type, \Throwable $previous = null) { - parent::__construct(\sprintf('Type "%s" is not instantiable.', $type), 0, $previous); + parent::__construct(sprintf('Type "%s" is not instantiable.', $type), 0, $previous); } } diff --git a/vendor/symfony/var-exporter/Hydrator.php b/vendor/symfony/var-exporter/Hydrator.php deleted file mode 100644 index b718921..0000000 --- a/vendor/symfony/var-exporter/Hydrator.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\VarExporter\Internal\Hydrator as InternalHydrator; - -/** - * Utility class to hydrate the properties of an object. - * - * @author Nicolas Grekas - */ -final class Hydrator -{ - /** - * Sets the properties of an object, including private and protected ones. - * - * For example: - * - * // Sets the public or protected $object->propertyName property - * Hydrator::hydrate($object, ['propertyName' => $propertyValue]); - * - * // Sets a private property defined on its parent Bar class: - * Hydrator::hydrate($object, ["\0Bar\0privateBarProperty" => $propertyValue]); - * - * // Alternative way to set the private $object->privateBarProperty property - * Hydrator::hydrate($object, [], [ - * Bar::class => ['privateBarProperty' => $propertyValue], - * ]); - * - * Instances of ArrayObject, ArrayIterator and SplObjectStorage can be hydrated - * by using the special "\0" property name to define their internal value: - * - * // Hydrates an SplObjectStorage where $info1 is attached to $obj1, etc. - * Hydrator::hydrate($object, ["\0" => [$obj1, $info1, $obj2, $info2...]]); - * - * // Hydrates an ArrayObject populated with $inputArray - * Hydrator::hydrate($object, ["\0" => [$inputArray]]); - * - * @template T of object - * - * @param T $instance The object to hydrate - * @param array $properties The properties to set on the instance - * @param array> $scopedProperties The properties to set on the instance, - * keyed by their declaring class - * - * @return T - */ - public static function hydrate(object $instance, array $properties = [], array $scopedProperties = []): object - { - if ($properties) { - $class = $instance::class; - $propertyScopes = InternalHydrator::$propertyScopes[$class] ??= InternalHydrator::getPropertyScopes($class); - - foreach ($properties as $name => &$value) { - [$scope, $name, $writeScope] = $propertyScopes[$name] ?? [$class, $name, $class]; - $scopedProperties[$writeScope ?? $scope][$name] = &$value; - } - unset($value); - } - - foreach ($scopedProperties as $scope => $properties) { - if ($properties) { - (InternalHydrator::$simpleHydrators[$scope] ??= InternalHydrator::getSimpleHydrator($scope))($properties, $instance); - } - } - - return $instance; - } -} diff --git a/vendor/symfony/var-exporter/Instantiator.php b/vendor/symfony/var-exporter/Instantiator.php index 10200c0..38fce27 100644 --- a/vendor/symfony/var-exporter/Instantiator.php +++ b/vendor/symfony/var-exporter/Instantiator.php @@ -13,6 +13,7 @@ namespace Symfony\Component\VarExporter; use Symfony\Component\VarExporter\Exception\ExceptionInterface; use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; +use Symfony\Component\VarExporter\Internal\Hydrator; use Symfony\Component\VarExporter\Internal\Registry; /** @@ -25,35 +26,67 @@ final class Instantiator /** * Creates an object and sets its properties without calling its constructor nor any other methods. * - * @see Hydrator::hydrate() for examples + * For example: * - * @template T of object + * // creates an empty instance of Foo + * Instantiator::instantiate(Foo::class); * - * @param class-string $class The class of the instance to create - * @param array $properties The properties to set on the instance - * @param array> $scopedProperties The properties to set on the instance, - * keyed by their declaring class + * // creates a Foo instance and sets one of its properties + * Instantiator::instantiate(Foo::class, ['propertyName' => $propertyValue]); * - * @return T + * // creates a Foo instance and sets a private property defined on its parent Bar class + * Instantiator::instantiate(Foo::class, [], [ + * Bar::class => ['privateBarProperty' => $propertyValue], + * ]); + * + * Instances of ArrayObject, ArrayIterator and SplObjectStorage can be created + * by using the special "\0" property name to define their internal value: + * + * // creates an SplObjectStorage where $info1 is attached to $obj1, etc. + * Instantiator::instantiate(SplObjectStorage::class, ["\0" => [$obj1, $info1, $obj2, $info2...]]); + * + * // creates an ArrayObject populated with $inputArray + * Instantiator::instantiate(ArrayObject::class, ["\0" => [$inputArray]]); + * + * @param string $class The class of the instance to create + * @param array $properties The properties to set on the instance + * @param array $privateProperties The private properties to set on the instance, + * keyed by their declaring class * * @throws ExceptionInterface When the instance cannot be created */ - public static function instantiate(string $class, array $properties = [], array $scopedProperties = []): object + public static function instantiate(string $class, array $properties = [], array $privateProperties = []): object { - $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class); + $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); if (Registry::$cloneable[$class]) { - $instance = clone Registry::$prototypes[$class]; + $wrappedInstance = [clone Registry::$prototypes[$class]]; } elseif (Registry::$instantiableWithoutConstructor[$class]) { - $instance = $reflector->newInstanceWithoutConstructor(); + $wrappedInstance = [$reflector->newInstanceWithoutConstructor()]; } elseif (null === Registry::$prototypes[$class]) { throw new NotInstantiableTypeException($class); } elseif ($reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize')) { - $instance = unserialize('C:'.\strlen($class).':"'.$class.'":0:{}'); + $wrappedInstance = [unserialize('C:'.\strlen($class).':"'.$class.'":0:{}')]; } else { - $instance = unserialize('O:'.\strlen($class).':"'.$class.'":0:{}'); + $wrappedInstance = [unserialize('O:'.\strlen($class).':"'.$class.'":0:{}')]; } - return $properties || $scopedProperties ? Hydrator::hydrate($instance, $properties, $scopedProperties) : $instance; + if ($properties) { + $privateProperties[$class] = isset($privateProperties[$class]) ? $properties + $privateProperties[$class] : $properties; + } + + foreach ($privateProperties as $class => $properties) { + if (!$properties) { + continue; + } + foreach ($properties as $name => $value) { + // because they're also used for "unserialization", hydrators + // deal with array of instances, so we need to wrap values + $properties[$name] = [$value]; + } + (Hydrator::$hydrators[$class] ?? Hydrator::getHydrator($class))($properties, $wrappedInstance); + } + + return $wrappedInstance[0]; } } diff --git a/vendor/symfony/var-exporter/Internal/Exporter.php b/vendor/symfony/var-exporter/Internal/Exporter.php index 13141a4..6ee3ee7 100644 --- a/vendor/symfony/var-exporter/Internal/Exporter.php +++ b/vendor/symfony/var-exporter/Internal/Exporter.php @@ -31,11 +31,9 @@ class Exporter * @param int &$objectsCount * @param bool &$valuesAreStatic * - * @return array - * * @throws NotInstantiableTypeException When a value cannot be serialized */ - public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic) + public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic): array { $refs = $values; foreach ($values as $k => $value) { @@ -73,26 +71,26 @@ class Exporter goto handle_value; } - $class = $value::class; - $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class); + $class = \get_class($value); + $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); + + if ($reflector->hasMethod('__serialize')) { + if (!$reflector->getMethod('__serialize')->isPublic()) { + throw new \Error(sprintf('Call to %s method "%s::__serialize()".', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class)); + } + + if (!\is_array($properties = $value->__serialize())) { + throw new \TypeError($class.'::__serialize() must return an array'); + } + + goto prepare_value; + } + $properties = []; $sleep = null; $proto = Registry::$prototypes[$class]; - if ($reflector->hasMethod('__serialize')) { - if (!$reflector->getMethod('__serialize')->isPublic()) { - throw new \Error(\sprintf('Call to %s method "%s::__serialize()".', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class)); - } - - if (!\is_array($arrayValue = $value->__serialize())) { - throw new \TypeError($class.'::__serialize() must return an array'); - } - - if ($reflector->hasMethod('__unserialize')) { - $properties = $arrayValue; - goto prepare_value; - } - } elseif (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) { + if (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) { // ArrayIterator and ArrayObject need special care because their "flags" // option changes the behavior of the (array) casting operator. [$arrayValue, $properties] = self::getArrayObjectProperties($value, $proto); @@ -108,7 +106,10 @@ class Exporter } $properties = ['SplObjectStorage' => ["\0" => $properties]]; $arrayValue = (array) $value; - } elseif ($value instanceof \Serializable || $value instanceof \__PHP_Incomplete_Class || \PHP_VERSION_ID < 80200 && $value instanceof \DatePeriod) { + } elseif ($value instanceof \Serializable + || $value instanceof \__PHP_Incomplete_Class + || \PHP_VERSION_ID < 80200 && $value instanceof \DatePeriod + ) { ++$objectsCount; $objectsPool[$value] = [$id = \count($objectsPool), serialize($value), [], 0]; $value = new Reference($id); @@ -132,40 +133,36 @@ class Exporter $i = 0; $n = (string) $name; if ('' === $n || "\0" !== $n[0]) { - $parent = $reflector; - do { - $p = $parent->hasProperty($n) ? $parent->getProperty($n) : null; - } while (!$p && $parent = $parent->getParentClass()); - - $c = $p && (!$p->isPublic() || (\PHP_VERSION_ID >= 80400 ? $p->isProtectedSet() || $p->isPrivateSet() : $p->isReadOnly())) ? $p->class : 'stdClass'; + $c = \PHP_VERSION_ID >= 80100 && $reflector->hasProperty($n) && ($p = $reflector->getProperty($n))->isReadOnly() ? $p->class : 'stdClass'; } elseif ('*' === $n[1]) { $n = substr($n, 3); $c = $reflector->getProperty($n)->class; + if ('Error' === $c) { + $c = 'TypeError'; + } elseif ('Exception' === $c) { + $c = 'ErrorException'; + } } else { $i = strpos($n, "\0", 2); $c = substr($n, 1, $i - 1); $n = substr($n, 1 + $i); } if (null !== $sleep) { - if (!isset($sleep[$name]) && (!isset($sleep[$n]) || ($i && $c !== $class))) { + if (!isset($sleep[$n]) || ($i && $c !== $class)) { unset($arrayValue[$name]); continue; } - unset($sleep[$name], $sleep[$n]); + $sleep[$n] = false; } - if ("\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) { + if (!\array_key_exists($name, $proto) || $proto[$name] !== $v || "\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) { $properties[$c][$n] = $v; - } elseif (!\array_key_exists($name, $proto) || $proto[$name] !== $v) { - $properties[match ($c) { - 'Error' => 'TypeError', - 'Exception' => 'ErrorException', - default => $c, - }][$n] = $v; } } if ($sleep) { foreach ($sleep as $n => $v) { - trigger_error(\sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), \E_USER_NOTICE); + if (false !== $v) { + trigger_error(sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), \E_USER_NOTICE); + } } } if (method_exists($class, '__unserialize')) { @@ -192,7 +189,7 @@ class Exporter return $values; } - public static function export($value, $indent = '') + public static function export($value, string $indent = '') { switch (true) { case \is_int($value) || \is_float($value): return var_export($value, true); @@ -218,10 +215,10 @@ class Exporter $subIndent = $indent.' '; if (\is_string($value)) { - $code = \sprintf("'%s'", addcslashes($value, "'\\")); + $code = sprintf("'%s'", addcslashes($value, "'\\")); $code = preg_replace_callback("/((?:[\\0\\r\\n]|\u{202A}|\u{202B}|\u{202D}|\u{202E}|\u{2066}|\u{2067}|\u{2068}|\u{202C}|\u{2069})++)(.)/", function ($m) use ($subIndent) { - $m[1] = \sprintf('\'."%s".\'', str_replace( + $m[1] = sprintf('\'."%s".\'', str_replace( ["\0", "\r", "\n", "\u{202A}", "\u{202B}", "\u{202D}", "\u{202E}", "\u{2066}", "\u{2067}", "\u{2068}", "\u{202C}", "\u{2069}", '\n\\'], ['\0', '\r', '\n', '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', '\u{202C}', '\u{2069}', '\n"'."\n".$subIndent.'."\\'], $m[1] @@ -231,7 +228,7 @@ class Exporter return substr($m[1], 0, -2); } - if (str_ends_with($m[1], 'n".\'')) { + if ('n".\'' === substr($m[1], -4)) { return substr_replace($m[1], "\n".$subIndent.".'".$m[2], -2); } @@ -279,7 +276,7 @@ class Exporter return self::exportHydrator($value, $indent, $subIndent); } - throw new \UnexpectedValueException(\sprintf('Cannot export value of type "%s".', get_debug_type($value))); + throw new \UnexpectedValueException(sprintf('Cannot export value of type "%s".', get_debug_type($value))); } private static function exportRegistry(Registry $value, string $indent, string $subIndent): string @@ -369,7 +366,7 @@ class Exporter self::export($value->wakeups, $subIndent), ]; - return '\\'.$value::class."::hydrate(\n".$subIndent.implode(",\n".$subIndent, $code)."\n".$indent.')'; + return '\\'.\get_class($value)."::hydrate(\n".$subIndent.implode(",\n".$subIndent, $code)."\n".$indent.')'; } /** @@ -379,7 +376,7 @@ class Exporter private static function getArrayObjectProperties($value, $proto): array { $reflector = $value instanceof \ArrayIterator ? 'ArrayIterator' : 'ArrayObject'; - $reflector = Registry::$reflectors[$reflector] ??= Registry::getClassReflector($reflector); + $reflector = Registry::$reflectors[$reflector] ?? Registry::getClassReflector($reflector); $properties = [ $arrayValue = (array) $value, diff --git a/vendor/symfony/var-exporter/Internal/Hydrator.php b/vendor/symfony/var-exporter/Internal/Hydrator.php index ebbceed..5ed6bdc 100644 --- a/vendor/symfony/var-exporter/Internal/Hydrator.php +++ b/vendor/symfony/var-exporter/Internal/Hydrator.php @@ -20,12 +20,7 @@ use Symfony\Component\VarExporter\Exception\ClassNotFoundException; */ class Hydrator { - public const PROPERTY_HAS_HOOKS = 1; - public const PROPERTY_NOT_BY_REF = 2; - - public static array $hydrators = []; - public static array $simpleHydrators = []; - public static array $propertyScopes = []; + public static $hydrators = []; public $registry; public $values; @@ -45,7 +40,7 @@ class Hydrator public static function hydrate($objects, $values, $properties, $value, $wakeups) { foreach ($properties as $class => $vars) { - (self::$hydrators[$class] ??= self::getHydrator($class))($vars, $objects); + (self::$hydrators[$class] ?? self::getHydrator($class))($vars, $objects); } foreach ($wakeups as $k => $v) { if (\is_array($v)) { @@ -60,33 +55,31 @@ class Hydrator public static function getHydrator($class) { - $baseHydrator = self::$hydrators['stdClass'] ??= static function ($properties, $objects) { - foreach ($properties as $name => $values) { - foreach ($values as $i => $v) { - $objects[$i]->$name = $v; - } - } - }; - switch ($class) { case 'stdClass': - return $baseHydrator; + return self::$hydrators[$class] = static function ($properties, $objects) { + foreach ($properties as $name => $values) { + foreach ($values as $i => $v) { + $objects[$i]->$name = $v; + } + } + }; case 'ErrorException': - return $baseHydrator->bindTo(null, new class extends \ErrorException { + return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \ErrorException { }); case 'TypeError': - return $baseHydrator->bindTo(null, new class extends \Error { + return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \Error { }); case 'SplObjectStorage': - return static function ($properties, $objects) { + return self::$hydrators[$class] = static function ($properties, $objects) { foreach ($properties as $name => $values) { if ("\0" === $name) { foreach ($values as $i => $v) { for ($j = 0; $j < \count($v); ++$j) { - $objects[$i][$v[$j]] = $v[++$j]; + $objects[$i]->attach($v[$j], $v[++$j]); } } continue; @@ -106,9 +99,9 @@ class Hydrator switch ($class) { case 'ArrayIterator': case 'ArrayObject': - $constructor = $classReflector->getConstructor()->invokeArgs(...); + $constructor = \Closure::fromCallable([$classReflector->getConstructor(), 'invokeArgs']); - return static function ($properties, $objects) use ($constructor) { + return self::$hydrators[$class] = static function ($properties, $objects) use ($constructor) { foreach ($properties as $name => $values) { if ("\0" !== $name) { foreach ($values as $i => $v) { @@ -123,25 +116,26 @@ class Hydrator } if (!$classReflector->isInternal()) { - return $baseHydrator->bindTo(null, $class); + return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, $class); } if ($classReflector->name !== $class) { - return self::$hydrators[$classReflector->name] ??= self::getHydrator($classReflector->name); + return self::$hydrators[$classReflector->name] ?? self::getHydrator($classReflector->name); } $propertySetters = []; foreach ($classReflector->getProperties() as $propertyReflector) { if (!$propertyReflector->isStatic()) { - $propertySetters[$propertyReflector->name] = $propertyReflector->setValue(...); + $propertyReflector->setAccessible(true); + $propertySetters[$propertyReflector->name] = \Closure::fromCallable([$propertyReflector, 'setValue']); } } if (!$propertySetters) { - return $baseHydrator; + return self::$hydrators[$class] = self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'); } - return static function ($properties, $objects) use ($propertySetters) { + return self::$hydrators[$class] = static function ($properties, $objects) use ($propertySetters) { foreach ($properties as $name => $values) { if ($setValue = $propertySetters[$name] ?? null) { foreach ($values as $i => $v) { @@ -155,175 +149,4 @@ class Hydrator } }; } - - public static function getSimpleHydrator($class) - { - $baseHydrator = self::$simpleHydrators['stdClass'] ??= (function ($properties, $object) { - $notByRef = (array) $this; - - foreach ($properties as $name => &$value) { - if (!$noRef = $notByRef[$name] ?? false) { - $object->$name = $value; - $object->$name = &$value; - } elseif (true !== $noRef) { - $noRef($object, $value); - } else { - $object->$name = $value; - } - } - })->bindTo(new \stdClass()); - - switch ($class) { - case 'stdClass': - return $baseHydrator; - - case 'ErrorException': - return $baseHydrator->bindTo(new \stdClass(), new class extends \ErrorException { - }); - - case 'TypeError': - return $baseHydrator->bindTo(new \stdClass(), new class extends \Error { - }); - - case 'SplObjectStorage': - return static function ($properties, $object) { - foreach ($properties as $name => &$value) { - if ("\0" !== $name) { - $object->$name = $value; - $object->$name = &$value; - continue; - } - for ($i = 0; $i < \count($value); ++$i) { - $object[$value[$i]] = $value[++$i]; - } - } - }; - } - - if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) { - throw new ClassNotFoundException($class); - } - $classReflector = new \ReflectionClass($class); - - switch ($class) { - case 'ArrayIterator': - case 'ArrayObject': - $constructor = $classReflector->getConstructor()->invokeArgs(...); - - return static function ($properties, $object) use ($constructor) { - foreach ($properties as $name => &$value) { - if ("\0" === $name) { - $constructor($object, $value); - } else { - $object->$name = $value; - $object->$name = &$value; - } - } - }; - } - - if (!$classReflector->isInternal()) { - $notByRef = new \stdClass(); - foreach ($classReflector->getProperties() as $propertyReflector) { - if ($propertyReflector->isStatic()) { - continue; - } - if (\PHP_VERSION_ID >= 80400 && !$propertyReflector->isAbstract() && $propertyReflector->getHooks()) { - $notByRef->{$propertyReflector->name} = $propertyReflector->setRawValue(...); - } elseif ($propertyReflector->isReadOnly()) { - $notByRef->{$propertyReflector->name} = true; - } - } - - return $baseHydrator->bindTo($notByRef, $class); - } - - if ($classReflector->name !== $class) { - return self::$simpleHydrators[$classReflector->name] ??= self::getSimpleHydrator($classReflector->name); - } - - $propertySetters = []; - foreach ($classReflector->getProperties() as $propertyReflector) { - if (!$propertyReflector->isStatic()) { - $propertySetters[$propertyReflector->name] = $propertyReflector->setValue(...); - } - } - - if (!$propertySetters) { - return $baseHydrator; - } - - return static function ($properties, $object) use ($propertySetters) { - foreach ($properties as $name => &$value) { - if ($setValue = $propertySetters[$name] ?? null) { - $setValue($object, $value); - } else { - $object->$name = $value; - $object->$name = &$value; - } - } - }; - } - - /** - * @return array - */ - public static function getPropertyScopes($class) - { - $propertyScopes = []; - $r = new \ReflectionClass($class); - - foreach ($r->getProperties() as $property) { - $flags = $property->getModifiers(); - - if (\ReflectionProperty::IS_STATIC & $flags) { - continue; - } - $name = $property->name; - $access = ($flags << 2) | ($flags & \ReflectionProperty::IS_READONLY ? self::PROPERTY_NOT_BY_REF : 0); - - if (\PHP_VERSION_ID >= 80400 && !$property->isAbstract() && $h = $property->getHooks()) { - $access |= self::PROPERTY_HAS_HOOKS | (isset($h['get']) && !$h['get']->returnsReference() ? self::PROPERTY_NOT_BY_REF : 0); - } - - if (\ReflectionProperty::IS_PRIVATE & $flags) { - $propertyScopes["\0$class\0$name"] = $propertyScopes[$name] = [$class, $name, null, $access, $property]; - - continue; - } - - $propertyScopes[$name] = [$class, $name, null, $access, $property]; - - if ($flags & (\PHP_VERSION_ID >= 80400 ? \ReflectionProperty::IS_PRIVATE_SET : \ReflectionProperty::IS_READONLY)) { - $propertyScopes[$name][2] = $property->class; - } - - if (\ReflectionProperty::IS_PROTECTED & $flags) { - $propertyScopes["\0*\0$name"] = $propertyScopes[$name]; - } - } - - while ($r = $r->getParentClass()) { - $class = $r->name; - - foreach ($r->getProperties(\ReflectionProperty::IS_PRIVATE) as $property) { - $flags = $property->getModifiers(); - - if (\ReflectionProperty::IS_STATIC & $flags) { - continue; - } - $name = $property->name; - $access = ($flags << 2) | ($flags & \ReflectionProperty::IS_READONLY ? self::PROPERTY_NOT_BY_REF : 0); - - if (\PHP_VERSION_ID >= 80400 && $h = $property->getHooks()) { - $access |= self::PROPERTY_HAS_HOOKS | (isset($h['get']) && !$h['get']->returnsReference() ? self::PROPERTY_NOT_BY_REF : 0); - } - - $propertyScopes["\0$class\0$name"] = [$class, $name, null, $access, $property]; - $propertyScopes[$name] ??= $propertyScopes["\0$class\0$name"]; - } - } - - return $propertyScopes; - } } diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php b/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php deleted file mode 100644 index d096be8..0000000 --- a/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php +++ /dev/null @@ -1,177 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -/** - * Stores the state of lazy objects and caches related reflection information. - * - * As a micro-optimization, this class uses no type declarations. - * - * @internal - */ -class LazyObjectRegistry -{ - /** - * @var array - */ - public static array $classReflectors = []; - - /** - * @var array> - */ - public static array $defaultProperties = []; - - /** - * @var array> - */ - public static array $classResetters = []; - - /** - * @var array - */ - public static array $classAccessors = []; - - /** - * @var array - */ - public static array $parentMethods = []; - - public static ?\Closure $noInitializerState = null; - - public static function getClassResetters($class) - { - $classProperties = []; - $hookedProperties = []; - - if ((self::$classReflectors[$class] ??= new \ReflectionClass($class))->isInternal()) { - $propertyScopes = []; - } else { - $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class); - } - - foreach ($propertyScopes as $key => [$scope, $name, $writeScope, $access]) { - $propertyScopes[$k = "\0$scope\0$name"] ?? $propertyScopes[$k = "\0*\0$name"] ?? $k = $name; - - if ($k !== $key || "\0$class\0lazyObjectState" === $k) { - continue; - } - - if ($access & Hydrator::PROPERTY_HAS_HOOKS) { - $hookedProperties[$k] = true; - } else { - $classProperties[$writeScope ?? $scope][$name] = $key; - } - } - - $resetters = []; - foreach ($classProperties as $scope => $properties) { - $resetters[] = \Closure::bind(static function ($instance, $skippedProperties, $onlyProperties = null) use ($properties) { - foreach ($properties as $name => $key) { - if (!\array_key_exists($key, $skippedProperties) && (null === $onlyProperties || \array_key_exists($key, $onlyProperties))) { - unset($instance->$name); - } - } - }, null, $scope); - } - - $resetters[] = static function ($instance, $skippedProperties, $onlyProperties = null) use ($hookedProperties) { - foreach ((array) $instance as $name => $value) { - if ("\0" !== ($name[0] ?? '') - && !\array_key_exists($name, $skippedProperties) - && (null === $onlyProperties || \array_key_exists($name, $onlyProperties)) - && !isset($hookedProperties[$name]) - ) { - unset($instance->$name); - } - } - }; - - return $resetters; - } - - public static function getClassAccessors($class) - { - return \Closure::bind(static fn () => [ - 'get' => static function &($instance, $name, $notByRef) { - if (!$notByRef) { - return $instance->$name; - } - $value = $instance->$name; - - return $value; - }, - 'set' => static function ($instance, $name, $value) { - $instance->$name = $value; - }, - 'isset' => static fn ($instance, $name) => isset($instance->$name), - 'unset' => static function ($instance, $name) { - unset($instance->$name); - }, - ], null, \Closure::class === $class ? null : $class)(); - } - - public static function getParentMethods($class) - { - $parent = get_parent_class($class); - $methods = []; - - foreach (['set', 'isset', 'unset', 'clone', 'serialize', 'unserialize', 'sleep', 'wakeup', 'destruct', 'get'] as $method) { - if (!$parent || !method_exists($parent, '__'.$method)) { - $methods[$method] = false; - } else { - $m = new \ReflectionMethod($parent, '__'.$method); - $methods[$method] = !$m->isAbstract() && !$m->isPrivate(); - } - } - - $methods['get'] = $methods['get'] ? ($m->returnsReference() ? 2 : 1) : 0; - - return $methods; - } - - public static function getScopeForRead($propertyScopes, $class, $property) - { - if (!isset($propertyScopes[$k = "\0$class\0$property"]) && !isset($propertyScopes[$k = "\0*\0$property"])) { - return null; - } - $frame = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]; - - if (\ReflectionProperty::class === $scope = $frame['class'] ?? \Closure::class) { - $scope = $frame['object']->class; - } - if ('*' === $k[1] && ($class === $scope || (is_subclass_of($class, $scope) && !isset($propertyScopes["\0$scope\0$property"])))) { - return null; - } - - return $scope; - } - - public static function getScopeForWrite($propertyScopes, $class, $property, $flags) - { - if (!($flags & (\ReflectionProperty::IS_PRIVATE | \ReflectionProperty::IS_PROTECTED | \ReflectionProperty::IS_READONLY | (\PHP_VERSION_ID >= 80400 ? \ReflectionProperty::IS_PRIVATE_SET | \ReflectionProperty::IS_PROTECTED_SET : 0)))) { - return null; - } - $frame = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]; - - if (\ReflectionProperty::class === $scope = $frame['class'] ?? \Closure::class) { - $scope = $frame['object']->class; - } - if ($flags & (\ReflectionProperty::IS_PRIVATE | (\PHP_VERSION_ID >= 80400 ? \ReflectionProperty::IS_PRIVATE_SET : \ReflectionProperty::IS_READONLY))) { - return $scope; - } - if ($flags & (\ReflectionProperty::IS_PROTECTED | (\PHP_VERSION_ID >= 80400 ? \ReflectionProperty::IS_PROTECTED_SET : 0)) && ($class === $scope || (is_subclass_of($class, $scope) && !isset($propertyScopes["\0$scope\0$property"])))) { - return null; - } - - return $scope; - } -} diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectState.php b/vendor/symfony/var-exporter/Internal/LazyObjectState.php deleted file mode 100644 index 619555e..0000000 --- a/vendor/symfony/var-exporter/Internal/LazyObjectState.php +++ /dev/null @@ -1,133 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -use Symfony\Component\VarExporter\Hydrator as PublicHydrator; - -/** - * Keeps the state of lazy objects. - * - * As a micro-optimization, this class uses no type declarations. - * - * @internal - */ -class LazyObjectState -{ - public const STATUS_UNINITIALIZED_FULL = 1; - public const STATUS_UNINITIALIZED_PARTIAL = 2; - public const STATUS_INITIALIZED_FULL = 3; - public const STATUS_INITIALIZED_PARTIAL = 4; - - /** - * @var array - */ - public readonly array $skippedProperties; - - /** - * @var self::STATUS_* - */ - public int $status = 0; - - public object $realInstance; - - public function __construct(public readonly \Closure|array $initializer, $skippedProperties = []) - { - $this->skippedProperties = $skippedProperties; - $this->status = \is_array($initializer) ? self::STATUS_UNINITIALIZED_PARTIAL : self::STATUS_UNINITIALIZED_FULL; - } - - public function initialize($instance, $propertyName, $writeScope) - { - if (self::STATUS_INITIALIZED_FULL === $this->status) { - return self::STATUS_INITIALIZED_FULL; - } - - if (\is_array($this->initializer)) { - $class = $instance::class; - $writeScope ??= $class; - $propertyScopes = Hydrator::$propertyScopes[$class]; - $propertyScopes[$k = "\0$writeScope\0$propertyName"] ?? $propertyScopes[$k = "\0*\0$propertyName"] ?? $k = $propertyName; - - if ($initializer = $this->initializer[$k] ?? null) { - $value = $initializer(...[$instance, $propertyName, $writeScope, LazyObjectRegistry::$defaultProperties[$class][$k] ?? null]); - $accessor = LazyObjectRegistry::$classAccessors[$writeScope] ??= LazyObjectRegistry::getClassAccessors($writeScope); - $accessor['set']($instance, $propertyName, $value); - - return $this->status = self::STATUS_INITIALIZED_PARTIAL; - } - - if ($initializer = $this->initializer["\0"] ?? null) { - if (!\is_array($values = $initializer($instance, LazyObjectRegistry::$defaultProperties[$class]))) { - throw new \TypeError(\sprintf('The lazy-initializer defined for instance of "%s" must return an array, got "%s".', $class, get_debug_type($values))); - } - $properties = (array) $instance; - foreach ($values as $key => $value) { - if (!\array_key_exists($key, $properties) && [$scope, $name, $writeScope] = $propertyScopes[$key] ?? null) { - $scope = $writeScope ?? $scope; - $accessor = LazyObjectRegistry::$classAccessors[$scope] ??= LazyObjectRegistry::getClassAccessors($scope); - $accessor['set']($instance, $name, $value); - - if ($k === $key) { - $this->status = self::STATUS_INITIALIZED_PARTIAL; - } - } - } - } - - return $this->status; - } - - if (self::STATUS_INITIALIZED_PARTIAL === $this->status) { - return self::STATUS_INITIALIZED_PARTIAL; - } - - $this->status = self::STATUS_INITIALIZED_PARTIAL; - - try { - if ($defaultProperties = array_diff_key(LazyObjectRegistry::$defaultProperties[$instance::class], $this->skippedProperties)) { - PublicHydrator::hydrate($instance, $defaultProperties); - } - - ($this->initializer)($instance); - } catch (\Throwable $e) { - $this->status = self::STATUS_UNINITIALIZED_FULL; - $this->reset($instance); - - throw $e; - } - - return $this->status = self::STATUS_INITIALIZED_FULL; - } - - public function reset($instance): void - { - $class = $instance::class; - $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class); - $skippedProperties = $this->skippedProperties; - $properties = (array) $instance; - $onlyProperties = \is_array($this->initializer) ? $this->initializer : null; - - foreach ($propertyScopes as $key => [$scope, $name, , $access]) { - $propertyScopes[$k = "\0$scope\0$name"] ?? $propertyScopes[$k = "\0*\0$name"] ?? $k = $name; - - if ($k === $key && ($access & Hydrator::PROPERTY_HAS_HOOKS || ($access >> 2) & \ReflectionProperty::IS_READONLY || !\array_key_exists($k, $properties))) { - $skippedProperties[$k] = true; - } - } - - foreach (LazyObjectRegistry::$classResetters[$class] as $reset) { - $reset($instance, $skippedProperties, $onlyProperties); - } - - $this->status = self::STATUS_INITIALIZED_FULL === $this->status ? self::STATUS_UNINITIALIZED_FULL : self::STATUS_UNINITIALIZED_PARTIAL; - } -} diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php b/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php deleted file mode 100644 index 4a6f232..0000000 --- a/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -use Symfony\Component\Serializer\Attribute\Ignore; - -if (\PHP_VERSION_ID >= 80300) { - /** - * @internal - */ - trait LazyObjectTrait - { - #[Ignore] - private readonly LazyObjectState $lazyObjectState; - } -} else { - /** - * @internal - */ - trait LazyObjectTrait - { - #[Ignore] - private LazyObjectState $lazyObjectState; - } -} diff --git a/vendor/symfony/var-exporter/Internal/Reference.php b/vendor/symfony/var-exporter/Internal/Reference.php index 2c7bd7b..e371c07 100644 --- a/vendor/symfony/var-exporter/Internal/Reference.php +++ b/vendor/symfony/var-exporter/Internal/Reference.php @@ -18,11 +18,13 @@ namespace Symfony\Component\VarExporter\Internal; */ class Reference { - public int $count = 0; + public $id; + public $value; + public $count = 0; - public function __construct( - public readonly int $id, - public readonly mixed $value = null, - ) { + public function __construct(int $id, $value = null) + { + $this->id = $id; + $this->value = $value; } } diff --git a/vendor/symfony/var-exporter/Internal/Registry.php b/vendor/symfony/var-exporter/Internal/Registry.php index db05bbb..a9fb061 100644 --- a/vendor/symfony/var-exporter/Internal/Registry.php +++ b/vendor/symfony/var-exporter/Internal/Registry.php @@ -21,11 +21,11 @@ use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; */ class Registry { - public static array $reflectors = []; - public static array $prototypes = []; - public static array $factories = []; - public static array $cloneable = []; - public static array $instantiableWithoutConstructor = []; + public static $reflectors = []; + public static $prototypes = []; + public static $factories = []; + public static $cloneable = []; + public static $instantiableWithoutConstructor = []; public $classes = []; @@ -58,9 +58,9 @@ class Registry public static function f($class) { - $reflector = self::$reflectors[$class] ??= self::getClassReflector($class, true, false); + $reflector = self::$reflectors[$class] ?? self::getClassReflector($class, true, false); - return self::$factories[$class] = [$reflector, 'newInstanceWithoutConstructor'](...); + return self::$factories[$class] = \Closure::fromCallable([$reflector, 'newInstanceWithoutConstructor']); } public static function getClassReflector($class, $instantiableWithoutConstructor = false, $cloneable = null) @@ -75,17 +75,17 @@ class Registry } elseif (!$isClass || $reflector->isAbstract()) { throw new NotInstantiableTypeException($class); } elseif ($reflector->name !== $class) { - $reflector = self::$reflectors[$name = $reflector->name] ??= self::getClassReflector($name, false, $cloneable); + $reflector = self::$reflectors[$name = $reflector->name] ?? self::getClassReflector($name, false, $cloneable); self::$cloneable[$class] = self::$cloneable[$name]; self::$instantiableWithoutConstructor[$class] = self::$instantiableWithoutConstructor[$name]; self::$prototypes[$class] = self::$prototypes[$name]; - return $reflector; + return self::$reflectors[$class] = $reflector; } else { try { $proto = $reflector->newInstanceWithoutConstructor(); $instantiableWithoutConstructor = true; - } catch (\ReflectionException) { + } catch (\ReflectionException $e) { $proto = $reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize') ? 'C:' : 'O:'; if ('C:' === $proto && !$reflector->getMethod('unserialize')->isInternal()) { $proto = null; @@ -132,13 +132,15 @@ class Registry new \ReflectionProperty(\Error::class, 'trace'), new \ReflectionProperty(\Exception::class, 'trace'), ]; - $setTrace[0] = $setTrace[0]->setValue(...); - $setTrace[1] = $setTrace[1]->setValue(...); + $setTrace[0]->setAccessible(true); + $setTrace[1]->setAccessible(true); + $setTrace[0] = \Closure::fromCallable([$setTrace[0], 'setValue']); + $setTrace[1] = \Closure::fromCallable([$setTrace[1], 'setValue']); } $setTrace[$proto instanceof \Exception]($proto, []); } - return $reflector; + return self::$reflectors[$class] = $reflector; } } diff --git a/vendor/symfony/var-exporter/LICENSE b/vendor/symfony/var-exporter/LICENSE index 7536cae..99757d5 100644 --- a/vendor/symfony/var-exporter/LICENSE +++ b/vendor/symfony/var-exporter/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2023 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/var-exporter/LazyGhostTrait.php b/vendor/symfony/var-exporter/LazyGhostTrait.php deleted file mode 100644 index 79d8a0f..0000000 --- a/vendor/symfony/var-exporter/LazyGhostTrait.php +++ /dev/null @@ -1,409 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\Serializer\Attribute\Ignore; -use Symfony\Component\VarExporter\Internal\Hydrator; -use Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry; -use Symfony\Component\VarExporter\Internal\LazyObjectState; -use Symfony\Component\VarExporter\Internal\LazyObjectTrait; - -trait LazyGhostTrait -{ - use LazyObjectTrait; - - /** - * Creates a lazy-loading ghost instance. - * - * Skipped properties should be indexed by their array-cast identifier, see - * https://php.net/manual/language.types.array#language.types.array.casting - * - * @param (\Closure(static):void $initializer The closure should initialize the object it receives as argument - * @param array|null $skippedProperties An array indexed by the properties to skip, a.k.a. the ones - * that the initializer doesn't initialize, if any - * @param static|null $instance - */ - public static function createLazyGhost(\Closure|array $initializer, ?array $skippedProperties = null, ?object $instance = null): static - { - if (\is_array($initializer)) { - trigger_deprecation('symfony/var-exporter', '6.4', 'Per-property lazy-initializers are deprecated and won\'t be supported anymore in 7.0, use an object initializer instead.'); - } - - $onlyProperties = null === $skippedProperties && \is_array($initializer) ? $initializer : null; - - if (self::class !== $class = $instance ? $instance::class : static::class) { - $skippedProperties["\0".self::class."\0lazyObjectState"] = true; - } elseif (\defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) { - Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES; - } - - $instance ??= (Registry::$classReflectors[$class] ??= new \ReflectionClass($class))->newInstanceWithoutConstructor(); - Registry::$defaultProperties[$class] ??= (array) $instance; - $instance->lazyObjectState = new LazyObjectState($initializer, $skippedProperties ??= []); - - foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) { - $reset($instance, $skippedProperties, $onlyProperties); - } - - return $instance; - } - - /** - * Returns whether the object is initialized. - * - * @param $partial Whether partially initialized objects should be considered as initialized - */ - #[Ignore] - public function isLazyObjectInitialized(bool $partial = false): bool - { - if (!$state = $this->lazyObjectState ?? null) { - return true; - } - - if (!\is_array($state->initializer)) { - return LazyObjectState::STATUS_INITIALIZED_FULL === $state->status; - } - - $class = $this::class; - $properties = (array) $this; - - if ($partial) { - return (bool) array_intersect_key($state->initializer, $properties); - } - - $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class); - foreach ($state->initializer as $key => $initializer) { - if (!\array_key_exists($key, $properties) && isset($propertyScopes[$key])) { - return false; - } - } - - return true; - } - - /** - * Forces initialization of a lazy object and returns it. - */ - public function initializeLazyObject(): static - { - if (!$state = $this->lazyObjectState ?? null) { - return $this; - } - - if (!\is_array($state->initializer)) { - if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) { - $state->initialize($this, '', null); - } - - return $this; - } - - $values = isset($state->initializer["\0"]) ? null : []; - - $class = $this::class; - $properties = (array) $this; - $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class); - foreach ($state->initializer as $key => $initializer) { - if (\array_key_exists($key, $properties) || ![$scope, $name, $writeScope] = $propertyScopes[$key] ?? null) { - continue; - } - $scope = $writeScope ?? $scope; - - if (null === $values) { - if (!\is_array($values = ($state->initializer["\0"])($this, Registry::$defaultProperties[$class]))) { - throw new \TypeError(\sprintf('The lazy-initializer defined for instance of "%s" must return an array, got "%s".', $class, get_debug_type($values))); - } - - if (\array_key_exists($key, $properties = (array) $this)) { - continue; - } - } - - if (\array_key_exists($key, $values)) { - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - $accessor['set']($this, $name, $properties[$key] = $values[$key]); - } else { - $state->initialize($this, $name, $scope); - $properties = (array) $this; - } - } - - return $this; - } - - /** - * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object - */ - public function resetLazyObject(): bool - { - if (!$state = $this->lazyObjectState ?? null) { - return false; - } - - if (LazyObjectState::STATUS_UNINITIALIZED_FULL !== $state->status) { - $state->reset($this); - } - - return true; - } - - public function &__get($name): mixed - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - $notByRef = 0; - - if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScopeForRead($propertyScopes, $class, $name); - $state = $this->lazyObjectState ?? null; - - if ($state && (null === $scope || isset($propertyScopes["\0$scope\0$name"]))) { - $notByRef = $access & Hydrator::PROPERTY_NOT_BY_REF; - - if (LazyObjectState::STATUS_INITIALIZED_FULL === $state->status) { - // Work around php/php-src#12695 - $property = null === $scope ? $name : "\0$scope\0$name"; - $property = $propertyScopes[$property][4] - ?? Hydrator::$propertyScopes[$this::class][$property][4] = new \ReflectionProperty($scope ?? $class, $name); - } else { - $property = null; - } - if (\PHP_VERSION_ID >= 80400 && !$notByRef && ($access >> 2) & \ReflectionProperty::IS_PRIVATE_SET) { - $scope ??= $writeScope; - } - - if ($property?->isInitialized($this) ?? LazyObjectState::STATUS_UNINITIALIZED_PARTIAL !== $state->initialize($this, $name, $writeScope ?? $scope)) { - goto get_in_scope; - } - } - } - - if ($parent = (Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['get']) { - if (2 === $parent) { - return parent::__get($name); - } - $value = parent::__get($name); - - return $value; - } - - if (null === $class) { - $frame = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]; - trigger_error(\sprintf('Undefined property: %s::$%s in %s on line %s', $this::class, $name, $frame['file'], $frame['line']), \E_USER_NOTICE); - } - - get_in_scope: - - try { - if (null === $scope) { - if (!$notByRef) { - return $this->$name; - } - $value = $this->$name; - - return $value; - } - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - - return $accessor['get']($this, $name, $notByRef); - } catch (\Error $e) { - if (\Error::class !== $e::class || !str_starts_with($e->getMessage(), 'Cannot access uninitialized non-nullable property')) { - throw $e; - } - - try { - if (null === $scope) { - $this->$name = []; - - return $this->$name; - } - - $accessor['set']($this, $name, []); - - return $accessor['get']($this, $name, $notByRef); - } catch (\Error) { - if (preg_match('/^Cannot access uninitialized non-nullable property ([^ ]++) by reference$/', $e->getMessage(), $matches)) { - throw new \Error('Typed property '.$matches[1].' must not be accessed before initialization', $e->getCode(), $e->getPrevious()); - } - - throw $e; - } - } - } - - public function __set($name, $value): void - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - - if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScopeForWrite($propertyScopes, $class, $name, $access >> 2); - $state = $this->lazyObjectState ?? null; - - if ($state && ($writeScope === $scope || isset($propertyScopes["\0$scope\0$name"])) - && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status - ) { - if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) { - $state->initialize($this, $name, $writeScope ?? $scope); - } - goto set_in_scope; - } - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['set']) { - parent::__set($name, $value); - - return; - } - - set_in_scope: - - if (null === $scope) { - $this->$name = $value; - } else { - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - $accessor['set']($this, $name, $value); - } - } - - public function __isset($name): bool - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - - if ([$class, , $writeScope] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScopeForRead($propertyScopes, $class, $name); - $state = $this->lazyObjectState ?? null; - - if ($state && (null === $scope || isset($propertyScopes["\0$scope\0$name"])) - && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status - && LazyObjectState::STATUS_UNINITIALIZED_PARTIAL !== $state->initialize($this, $name, $writeScope ?? $scope) - ) { - goto isset_in_scope; - } - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['isset']) { - return parent::__isset($name); - } - - isset_in_scope: - - if (null === $scope) { - return isset($this->$name); - } - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - - return $accessor['isset']($this, $name); - } - - public function __unset($name): void - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - - if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScopeForWrite($propertyScopes, $class, $name, $access >> 2); - $state = $this->lazyObjectState ?? null; - - if ($state && ($writeScope === $scope || isset($propertyScopes["\0$scope\0$name"])) - && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status - ) { - if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) { - $state->initialize($this, $name, $writeScope ?? $scope); - } - goto unset_in_scope; - } - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['unset']) { - parent::__unset($name); - - return; - } - - unset_in_scope: - - if (null === $scope) { - unset($this->$name); - } else { - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - $accessor['unset']($this, $name); - } - } - - public function __clone(): void - { - if ($state = $this->lazyObjectState ?? null) { - $this->lazyObjectState = clone $state; - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['clone']) { - parent::__clone(); - } - } - - public function __serialize(): array - { - $class = self::class; - - if ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) { - $properties = parent::__serialize(); - } else { - $this->initializeLazyObject(); - $properties = (array) $this; - } - unset($properties["\0$class\0lazyObjectState"]); - - if (Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) { - return $properties; - } - - $scope = get_parent_class($class); - $data = []; - - foreach (parent::__sleep() as $name) { - $value = $properties[$k = $name] ?? $properties[$k = "\0*\0$name"] ?? $properties[$k = "\0$class\0$name"] ?? $properties[$k = "\0$scope\0$name"] ?? $k = null; - - if (null === $k) { - trigger_error(\sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $name), \E_USER_NOTICE); - } else { - $data[$k] = $value; - } - } - - return $data; - } - - public function __destruct() - { - $state = $this->lazyObjectState ?? null; - - if ($state && \in_array($state->status, [LazyObjectState::STATUS_UNINITIALIZED_FULL, LazyObjectState::STATUS_UNINITIALIZED_PARTIAL], true)) { - return; - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['destruct']) { - parent::__destruct(); - } - } - - #[Ignore] - private function setLazyObjectAsInitialized(bool $initialized): void - { - $state = $this->lazyObjectState ?? null; - - if ($state && !\is_array($state->initializer)) { - $state->status = $initialized ? LazyObjectState::STATUS_INITIALIZED_FULL : LazyObjectState::STATUS_UNINITIALIZED_FULL; - } - } -} diff --git a/vendor/symfony/var-exporter/LazyObjectInterface.php b/vendor/symfony/var-exporter/LazyObjectInterface.php deleted file mode 100644 index 3670884..0000000 --- a/vendor/symfony/var-exporter/LazyObjectInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -interface LazyObjectInterface -{ - /** - * Returns whether the object is initialized. - * - * @param $partial Whether partially initialized objects should be considered as initialized - */ - public function isLazyObjectInitialized(bool $partial = false): bool; - - /** - * Forces initialization of a lazy object and returns it. - */ - public function initializeLazyObject(): object; - - /** - * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object - */ - public function resetLazyObject(): bool; -} diff --git a/vendor/symfony/var-exporter/LazyProxyTrait.php b/vendor/symfony/var-exporter/LazyProxyTrait.php deleted file mode 100644 index af009ae..0000000 --- a/vendor/symfony/var-exporter/LazyProxyTrait.php +++ /dev/null @@ -1,355 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\Serializer\Attribute\Ignore; -use Symfony\Component\VarExporter\Hydrator as PublicHydrator; -use Symfony\Component\VarExporter\Internal\Hydrator; -use Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry; -use Symfony\Component\VarExporter\Internal\LazyObjectState; -use Symfony\Component\VarExporter\Internal\LazyObjectTrait; - -trait LazyProxyTrait -{ - use LazyObjectTrait; - - /** - * Creates a lazy-loading virtual proxy. - * - * @param \Closure():object $initializer Returns the proxied object - * @param static|null $instance - */ - public static function createLazyProxy(\Closure $initializer, ?object $instance = null): static - { - if (self::class !== $class = $instance ? $instance::class : static::class) { - $skippedProperties = ["\0".self::class."\0lazyObjectState" => true]; - } elseif (\defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) { - Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES; - } - - $instance ??= (Registry::$classReflectors[$class] ??= new \ReflectionClass($class))->newInstanceWithoutConstructor(); - $instance->lazyObjectState = new LazyObjectState($initializer); - - foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) { - $reset($instance, $skippedProperties ??= []); - } - - return $instance; - } - - /** - * Returns whether the object is initialized. - * - * @param $partial Whether partially initialized objects should be considered as initialized - */ - #[Ignore] - public function isLazyObjectInitialized(bool $partial = false): bool - { - return !isset($this->lazyObjectState) || isset($this->lazyObjectState->realInstance) || Registry::$noInitializerState === $this->lazyObjectState->initializer; - } - - /** - * Forces initialization of a lazy object and returns it. - */ - public function initializeLazyObject(): parent - { - if ($state = $this->lazyObjectState ?? null) { - return $state->realInstance ??= ($state->initializer)(); - } - - return $this; - } - - /** - * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object - */ - public function resetLazyObject(): bool - { - if (!isset($this->lazyObjectState) || Registry::$noInitializerState === $this->lazyObjectState->initializer) { - return false; - } - - unset($this->lazyObjectState->realInstance); - - return true; - } - - public function &__get($name): mixed - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - $instance = $this; - $notByRef = 0; - - if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) { - $notByRef = $access & Hydrator::PROPERTY_NOT_BY_REF; - $scope = Registry::getScopeForRead($propertyScopes, $class, $name); - - if (null === $scope || isset($propertyScopes["\0$scope\0$name"])) { - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } - if (\PHP_VERSION_ID >= 80400 && !$notByRef && ($access >> 2) & \ReflectionProperty::IS_PRIVATE_SET) { - $scope ??= $writeScope; - } - $parent = 2; - goto get_in_scope; - } - } - $parent = (Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['get']; - - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } else { - if (2 === $parent) { - return parent::__get($name); - } - $value = parent::__get($name); - - return $value; - } - - if (!$parent && null === $class && !\array_key_exists($name, (array) $instance)) { - $frame = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]; - trigger_error(\sprintf('Undefined property: %s::$%s in %s on line %s', $instance::class, $name, $frame['file'], $frame['line']), \E_USER_NOTICE); - } - - get_in_scope: - $notByRef = $notByRef || 1 === $parent; - - try { - if (null === $scope) { - if (!$notByRef) { - return $instance->$name; - } - $value = $instance->$name; - - return $value; - } - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - - return $accessor['get']($instance, $name, $notByRef); - } catch (\Error $e) { - if (\Error::class !== $e::class || !str_starts_with($e->getMessage(), 'Cannot access uninitialized non-nullable property')) { - throw $e; - } - - try { - if (null === $scope) { - $instance->$name = []; - - return $instance->$name; - } - - $accessor['set']($instance, $name, []); - - return $accessor['get']($instance, $name, $notByRef); - } catch (\Error) { - throw $e; - } - } - } - - public function __set($name, $value): void - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - $instance = $this; - - if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScopeForWrite($propertyScopes, $class, $name, $access >> 2); - - if ($writeScope === $scope || isset($propertyScopes["\0$scope\0$name"])) { - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } - goto set_in_scope; - } - } - - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['set']) { - parent::__set($name, $value); - - return; - } - - set_in_scope: - - if (null === $scope) { - $instance->$name = $value; - } else { - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - $accessor['set']($instance, $name, $value); - } - } - - public function __isset($name): bool - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - $instance = $this; - - if ([$class] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScopeForRead($propertyScopes, $class, $name); - - if (null === $scope || isset($propertyScopes["\0$scope\0$name"])) { - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } - goto isset_in_scope; - } - } - - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['isset']) { - return parent::__isset($name); - } - - isset_in_scope: - - if (null === $scope) { - return isset($instance->$name); - } - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - - return $accessor['isset']($instance, $name); - } - - public function __unset($name): void - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - $instance = $this; - - if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScopeForWrite($propertyScopes, $class, $name, $access >> 2); - - if ($writeScope === $scope || isset($propertyScopes["\0$scope\0$name"])) { - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } - goto unset_in_scope; - } - } - - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['unset']) { - parent::__unset($name); - - return; - } - - unset_in_scope: - - if (null === $scope) { - unset($instance->$name); - } else { - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - $accessor['unset']($instance, $name); - } - } - - public function __clone(): void - { - if (!isset($this->lazyObjectState)) { - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['clone']) { - parent::__clone(); - } - - return; - } - - $this->lazyObjectState = clone $this->lazyObjectState; - - if (isset($this->lazyObjectState->realInstance)) { - $this->lazyObjectState->realInstance = clone $this->lazyObjectState->realInstance; - } - } - - public function __serialize(): array - { - $class = self::class; - $state = $this->lazyObjectState ?? null; - - if (!$state && (Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) { - $properties = parent::__serialize(); - } else { - $properties = (array) $this; - - if ($state) { - unset($properties["\0$class\0lazyObjectState"]); - $properties["\0$class\0lazyObjectReal"] = $state->realInstance ??= ($state->initializer)(); - } - } - - if ($state || Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) { - return $properties; - } - - $scope = get_parent_class($class); - $data = []; - - foreach (parent::__sleep() as $name) { - $value = $properties[$k = $name] ?? $properties[$k = "\0*\0$name"] ?? $properties[$k = "\0$class\0$name"] ?? $properties[$k = "\0$scope\0$name"] ?? $k = null; - - if (null === $k) { - trigger_error(\sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $name), \E_USER_NOTICE); - } else { - $data[$k] = $value; - } - } - - return $data; - } - - public function __unserialize(array $data): void - { - $class = self::class; - - if ($instance = $data["\0$class\0lazyObjectReal"] ?? null) { - unset($data["\0$class\0lazyObjectReal"]); - - foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) { - $reset($this, $data); - } - - if ($data) { - PublicHydrator::hydrate($this, $data); - } - $this->lazyObjectState = new LazyObjectState(Registry::$noInitializerState ??= static fn () => throw new \LogicException('Lazy proxy has no initializer.')); - $this->lazyObjectState->realInstance = $instance; - } elseif ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['unserialize']) { - parent::__unserialize($data); - } else { - PublicHydrator::hydrate($this, $data); - - if (Registry::$parentMethods[$class]['wakeup']) { - parent::__wakeup(); - } - } - } - - public function __destruct() - { - if (isset($this->lazyObjectState)) { - return; - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['destruct']) { - parent::__destruct(); - } - } -} diff --git a/vendor/symfony/var-exporter/ProxyHelper.php b/vendor/symfony/var-exporter/ProxyHelper.php deleted file mode 100644 index 56fd00e..0000000 --- a/vendor/symfony/var-exporter/ProxyHelper.php +++ /dev/null @@ -1,553 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\VarExporter\Exception\LogicException; -use Symfony\Component\VarExporter\Internal\Hydrator; -use Symfony\Component\VarExporter\Internal\LazyObjectRegistry; - -/** - * @author Nicolas Grekas - */ -final class ProxyHelper -{ - /** - * Helps generate lazy-loading ghost objects. - * - * @throws LogicException When the class is incompatible with ghost objects - */ - public static function generateLazyGhost(\ReflectionClass $class): string - { - if (\PHP_VERSION_ID >= 80200 && \PHP_VERSION_ID < 80300 && $class->isReadOnly()) { - throw new LogicException(\sprintf('Cannot generate lazy ghost with PHP < 8.3: class "%s" is readonly.', $class->name)); - } - if ($class->isFinal()) { - throw new LogicException(\sprintf('Cannot generate lazy ghost: class "%s" is final.', $class->name)); - } - if ($class->isInterface() || $class->isAbstract() || $class->isTrait()) { - throw new LogicException(\sprintf('Cannot generate lazy ghost: "%s" is not a concrete class.', $class->name)); - } - if (\stdClass::class !== $class->name && $class->isInternal()) { - throw new LogicException(\sprintf('Cannot generate lazy ghost: class "%s" is internal.', $class->name)); - } - if ($class->hasMethod('__get') && 'mixed' !== (self::exportType($class->getMethod('__get')) ?? 'mixed')) { - throw new LogicException(\sprintf('Cannot generate lazy ghost: return type of method "%s::__get()" should be "mixed".', $class->name)); - } - - static $traitMethods; - $traitMethods ??= (new \ReflectionClass(LazyGhostTrait::class))->getMethods(); - - foreach ($traitMethods as $method) { - if ($class->hasMethod($method->name) && $class->getMethod($method->name)->isFinal()) { - throw new LogicException(\sprintf('Cannot generate lazy ghost: method "%s::%s()" is final.', $class->name, $method->name)); - } - } - - $parent = $class; - while ($parent = $parent->getParentClass()) { - if (\stdClass::class !== $parent->name && $parent->isInternal()) { - throw new LogicException(\sprintf('Cannot generate lazy ghost: class "%s" extends "%s" which is internal.', $class->name, $parent->name)); - } - } - - $hooks = ''; - $propertyScopes = Hydrator::$propertyScopes[$class->name] ??= Hydrator::getPropertyScopes($class->name); - foreach ($propertyScopes as $key => [$scope, $name, , $access]) { - $propertyScopes[$k = "\0$scope\0$name"] ?? $propertyScopes[$k = "\0*\0$name"] ?? $k = $name; - $flags = $access >> 2; - - if ($k !== $key || !($access & Hydrator::PROPERTY_HAS_HOOKS) || $flags & \ReflectionProperty::IS_VIRTUAL) { - continue; - } - - if ($flags & (\ReflectionProperty::IS_FINAL | \ReflectionProperty::IS_PRIVATE)) { - throw new LogicException(\sprintf('Cannot generate lazy ghost: property "%s::$%s" is final or private(set).', $class->name, $name)); - } - - $p = $propertyScopes[$k][4] ?? Hydrator::$propertyScopes[$class->name][$k][4] = new \ReflectionProperty($scope, $name); - - $type = self::exportType($p); - $hooks .= "\n " - .($p->isProtected() ? 'protected' : 'public') - .($p->isProtectedSet() ? ' protected(set)' : '') - ." {$type} \${$name}" - .($p->hasDefaultValue() ? ' = '.VarExporter::export($p->getDefaultValue()) : '') - ." {\n"; - - foreach ($p->getHooks() as $hook => $method) { - if ('get' === $hook) { - $ref = ($method->returnsReference() ? '&' : ''); - $hooks .= " {$ref}get { \$this->initializeLazyObject(); return parent::\${$name}::get(); }\n"; - } elseif ('set' === $hook) { - $parameters = self::exportParameters($method, true); - $arg = '$'.$method->getParameters()[0]->name; - $hooks .= " set({$parameters}) { \$this->initializeLazyObject(); parent::\${$name}::set({$arg}); }\n"; - } else { - throw new LogicException(\sprintf('Cannot generate lazy ghost: hook "%s::%s()" is not supported.', $class->name, $method->name)); - } - } - - $hooks .= " }\n"; - } - - $propertyScopes = self::exportPropertyScopes($class->name, $propertyScopes); - - return <<name} implements \Symfony\Component\VarExporter\LazyObjectInterface - { - use \Symfony\Component\VarExporter\LazyGhostTrait; - - private const LAZY_OBJECT_PROPERTY_SCOPES = {$propertyScopes}; - {$hooks}} - - // Help opcache.preload discover always-needed symbols - class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); - class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); - class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); - - EOPHP; - } - - /** - * Helps generate lazy-loading virtual proxies. - * - * @param \ReflectionClass[] $interfaces - * - * @throws LogicException When the class is incompatible with virtual proxies - */ - public static function generateLazyProxy(?\ReflectionClass $class, array $interfaces = []): string - { - if (!class_exists($class?->name ?? \stdClass::class, false)) { - throw new LogicException(\sprintf('Cannot generate lazy proxy: "%s" is not a class.', $class->name)); - } - if ($class?->isFinal()) { - throw new LogicException(\sprintf('Cannot generate lazy proxy: class "%s" is final.', $class->name)); - } - if (\PHP_VERSION_ID >= 80200 && \PHP_VERSION_ID < 80300 && $class?->isReadOnly()) { - throw new LogicException(\sprintf('Cannot generate lazy proxy with PHP < 8.3: class "%s" is readonly.', $class->name)); - } - - $propertyScopes = $class ? Hydrator::$propertyScopes[$class->name] ??= Hydrator::getPropertyScopes($class->name) : []; - $abstractProperties = []; - $hookedProperties = []; - if (\PHP_VERSION_ID >= 80400 && $class) { - foreach ($propertyScopes as $key => [$scope, $name, , $access]) { - $propertyScopes[$k = "\0$scope\0$name"] ?? $propertyScopes[$k = "\0*\0$name"] ?? $k = $name; - $flags = $access >> 2; - - if ($k !== $key) { - continue; - } - - if ($flags & \ReflectionProperty::IS_ABSTRACT) { - $abstractProperties[$name] = $propertyScopes[$k][4] ?? Hydrator::$propertyScopes[$class->name][$k][4] = new \ReflectionProperty($scope, $name); - continue; - } - $abstractProperties[$name] = false; - - if (!($access & Hydrator::PROPERTY_HAS_HOOKS) || $flags & \ReflectionProperty::IS_VIRTUAL) { - continue; - } - - if ($flags & (\ReflectionProperty::IS_FINAL | \ReflectionProperty::IS_PRIVATE)) { - throw new LogicException(\sprintf('Cannot generate lazy proxy: property "%s::$%s" is final or private(set).', $class->name, $name)); - } - - $p = $propertyScopes[$k][4] ?? Hydrator::$propertyScopes[$class->name][$k][4] = new \ReflectionProperty($scope, $name); - $hookedProperties[$name] = [$p, $p->getHooks()]; - } - } - - $methodReflectors = [$class?->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) ?? []]; - foreach ($interfaces as $interface) { - if (!$interface->isInterface()) { - throw new LogicException(\sprintf('Cannot generate lazy proxy: "%s" is not an interface.', $interface->name)); - } - $methodReflectors[] = $interface->getMethods(); - - if (\PHP_VERSION_ID >= 80400) { - foreach ($interface->getProperties() as $p) { - $abstractProperties[$p->name] ??= $p; - $hookedProperties[$p->name] ??= [$p, []]; - $hookedProperties[$p->name][1] += $p->getHooks(); - } - } - } - - $hooks = ''; - - foreach (array_filter($abstractProperties) as $name => $p) { - $type = self::exportType($p); - $hooks .= "\n " - .($p->isProtected() ? 'protected' : 'public') - .($p->isProtectedSet() ? ' protected(set)' : '') - ." {$type} \${$name};\n"; - } - - foreach ($hookedProperties as $name => [$p, $methods]) { - $type = self::exportType($p); - $hooks .= "\n " - .($p->isProtected() ? 'protected' : 'public') - .($p->isProtectedSet() ? ' protected(set)' : '') - ." {$type} \${$name} {\n"; - - foreach ($methods as $hook => $method) { - if ('get' === $hook) { - $ref = ($method->returnsReference() ? '&' : ''); - $hooks .= <<lazyObjectState)) { - return (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$p->name}; - } - - return parent::\${$p->name}::get(); - } - - EOPHP; - } elseif ('set' === $hook) { - $parameters = self::exportParameters($method, true); - $arg = '$'.$method->getParameters()[0]->name; - $hooks .= <<lazyObjectState)) { - \$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)(); - \$this->lazyObjectState->realInstance->{$p->name} = {$arg}; - } - - parent::\${$p->name}::set({$arg}); - } - - EOPHP; - } else { - throw new LogicException(\sprintf('Cannot generate lazy proxy: hook "%s::%s()" is not supported.', $class->name, $method->name)); - } - } - - $hooks .= " }\n"; - } - - $extendsInternalClass = false; - if ($parent = $class) { - do { - $extendsInternalClass = \stdClass::class !== $parent->name && $parent->isInternal(); - } while (!$extendsInternalClass && $parent = $parent->getParentClass()); - } - $methodsHaveToBeProxied = $extendsInternalClass; - $methods = []; - $methodReflectors = array_merge(...$methodReflectors); - - foreach ($methodReflectors as $method) { - if ('__get' !== strtolower($method->name) || 'mixed' === ($type = self::exportType($method) ?? 'mixed')) { - continue; - } - $methodsHaveToBeProxied = true; - $trait = new \ReflectionMethod(LazyProxyTrait::class, '__get'); - $body = \array_slice(file($trait->getFileName()), $trait->getStartLine() - 1, $trait->getEndLine() - $trait->getStartLine()); - $body[0] = str_replace('): mixed', '): '.$type, $body[0]); - $methods['__get'] = strtr(implode('', $body).' }', [ - 'Hydrator' => '\\'.Hydrator::class, - 'Registry' => '\\'.LazyObjectRegistry::class, - ]); - break; - } - - foreach ($methodReflectors as $method) { - if (($method->isStatic() && !$method->isAbstract()) || isset($methods[$lcName = strtolower($method->name)])) { - continue; - } - if ($method->isFinal()) { - if ($extendsInternalClass || $methodsHaveToBeProxied || method_exists(LazyProxyTrait::class, $method->name)) { - throw new LogicException(\sprintf('Cannot generate lazy proxy: method "%s::%s()" is final.', $class->name, $method->name)); - } - continue; - } - if (method_exists(LazyProxyTrait::class, $method->name) || ($method->isProtected() && !$method->isAbstract())) { - continue; - } - - $signature = self::exportSignature($method, true, $args); - $parentCall = $method->isAbstract() ? "throw new \BadMethodCallException('Cannot forward abstract method \"{$method->class}::{$method->name}()\".')" : "parent::{$method->name}({$args})"; - - if ($method->isStatic()) { - $body = " $parentCall;"; - } elseif (str_ends_with($signature, '): never') || str_ends_with($signature, '): void')) { - $body = <<lazyObjectState)) { - (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args}); - } else { - {$parentCall}; - } - EOPHP; - } else { - if (!$methodsHaveToBeProxied && !$method->isAbstract()) { - // Skip proxying methods that might return $this - foreach (preg_split('/[()|&]++/', self::exportType($method) ?? 'static') as $type) { - if (\in_array($type = ltrim($type, '?'), ['static', 'object'], true)) { - continue 2; - } - foreach ([$class, ...$interfaces] as $r) { - if ($r && is_a($r->name, $type, true)) { - continue 3; - } - } - } - } - - $body = <<lazyObjectState)) { - return (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args}); - } - - return {$parentCall}; - EOPHP; - } - $methods[$lcName] = " {$signature}\n {\n{$body}\n }"; - } - - $types = $interfaces = array_unique(array_column($interfaces, 'name')); - $interfaces[] = LazyObjectInterface::class; - $interfaces = implode(', \\', $interfaces); - $parent = $class ? ' extends \\'.$class->name : ''; - array_unshift($types, $class ? 'parent' : ''); - $type = ltrim(implode('&\\', $types), '&'); - - if (!$class) { - $trait = new \ReflectionMethod(LazyProxyTrait::class, 'initializeLazyObject'); - $body = \array_slice(file($trait->getFileName()), $trait->getStartLine() - 1, $trait->getEndLine() - $trait->getStartLine()); - $body[0] = str_replace('): parent', '): '.$type, $body[0]); - $methods = ['initializeLazyObject' => implode('', $body).' }'] + $methods; - } - $body = $methods ? "\n".implode("\n\n", $methods)."\n" : ''; - $propertyScopes = $class ? self::exportPropertyScopes($class->name, $propertyScopes) : '[]'; - - if ( - $class?->hasMethod('__unserialize') - && !$class->getMethod('__unserialize')->getParameters()[0]->getType() - ) { - // fix contravariance type problem when $class declares a `__unserialize()` method without typehint. - $lazyProxyTraitStatement = <<__doUnserialize(\$data); - } - - EOPHP; - } else { - $lazyProxyTraitStatement = <<class : $function->getNamespaceName().'\\'; - $namespace = substr($namespace, 0, strrpos($namespace, '\\') ?: 0); - foreach ($function->getParameters() as $param) { - $parameters[] = ($param->getAttributes(\SensitiveParameter::class) ? '#[\SensitiveParameter] ' : '') - .($withParameterTypes && $param->hasType() ? self::exportType($param).' ' : '') - .($param->isPassedByReference() ? '&' : '') - .($param->isVariadic() ? '...' : '').'$'.$param->name - .($param->isOptional() && !$param->isVariadic() ? ' = '.self::exportDefault($param, $namespace) : ''); - if ($param->isPassedByReference()) { - $byRefIndex = 1 + $param->getPosition(); - } - $args .= ($param->isVariadic() ? '...$' : '$').$param->name.', '; - } - - if (!$param || !$byRefIndex) { - $args = '...\func_get_args()'; - } elseif ($param->isVariadic()) { - $args = substr($args, 0, -2); - } else { - $args = explode(', ', $args, 1 + $byRefIndex); - $args[$byRefIndex] = \sprintf('...\array_slice(\func_get_args(), %d)', $byRefIndex); - $args = implode(', ', $args); - } - - return implode(', ', $parameters); - } - - public static function exportSignature(\ReflectionFunctionAbstract $function, bool $withParameterTypes = true, ?string &$args = null): string - { - $parameters = self::exportParameters($function, $withParameterTypes, $args); - - $signature = 'function '.($function->returnsReference() ? '&' : '') - .($function->isClosure() ? '' : $function->name).'('.$parameters.')'; - - if ($function instanceof \ReflectionMethod) { - $signature = ($function->isPublic() ? 'public ' : ($function->isProtected() ? 'protected ' : 'private ')) - .($function->isStatic() ? 'static ' : '').$signature; - } - if ($function->hasReturnType()) { - $signature .= ': '.self::exportType($function); - } - - static $getPrototype; - $getPrototype ??= (new \ReflectionMethod(\ReflectionMethod::class, 'getPrototype'))->invoke(...); - - while ($function) { - if ($function->hasTentativeReturnType()) { - return '#[\ReturnTypeWillChange] '.$signature; - } - - try { - $function = $function instanceof \ReflectionMethod && $function->isAbstract() ? false : $getPrototype($function); - } catch (\ReflectionException) { - break; - } - } - - return $signature; - } - - public static function exportType(\ReflectionFunctionAbstract|\ReflectionProperty|\ReflectionParameter $owner, bool $noBuiltin = false, ?\ReflectionType $type = null): ?string - { - if (!$type ??= $owner instanceof \ReflectionFunctionAbstract ? $owner->getReturnType() : $owner->getType()) { - return null; - } - $class = null; - $types = []; - if ($type instanceof \ReflectionUnionType) { - $reflectionTypes = $type->getTypes(); - $glue = '|'; - } elseif ($type instanceof \ReflectionIntersectionType) { - $reflectionTypes = $type->getTypes(); - $glue = '&'; - } else { - $reflectionTypes = [$type]; - $glue = null; - } - - foreach ($reflectionTypes as $type) { - if ($type instanceof \ReflectionIntersectionType) { - if ('' !== $name = '('.self::exportType($owner, $noBuiltin, $type).')') { - $types[] = $name; - } - continue; - } - $name = $type->getName(); - - if ($noBuiltin && $type->isBuiltin()) { - continue; - } - if (\in_array($name, ['parent', 'self'], true) && $class ??= $owner->getDeclaringClass()) { - $name = 'parent' === $name ? ($class->getParentClass() ?: null)?->name ?? 'parent' : $class->name; - } - - $types[] = ($noBuiltin || $type->isBuiltin() || 'static' === $name ? '' : '\\').$name; - } - - if (!$types) { - return ''; - } - if (null === $glue) { - $defaultNull = $owner instanceof \ReflectionParameter && 'NULL' === rtrim(substr(explode('$'.$owner->name.' = ', (string) $owner, 2)[1] ?? '', 0, -2)); - - return (!$noBuiltin && ($type->allowsNull() || $defaultNull) && !\in_array($name, ['mixed', 'null'], true) ? '?' : '').$types[0]; - } - sort($types); - - return implode($glue, $types); - } - - private static function exportPropertyScopes(string $parent, array $propertyScopes): string - { - uksort($propertyScopes, 'strnatcmp'); - foreach ($propertyScopes as $k => $v) { - unset($propertyScopes[$k][4]); - } - $propertyScopes = VarExporter::export($propertyScopes); - $propertyScopes = str_replace(VarExporter::export($parent), 'parent::class', $propertyScopes); - $propertyScopes = preg_replace("/(?|(,)\n( ) |\n |,\n (\]))/", '$1$2', $propertyScopes); - $propertyScopes = str_replace("\n", "\n ", $propertyScopes); - - return $propertyScopes; - } - - private static function exportDefault(\ReflectionParameter $param, $namespace): string - { - $default = rtrim(substr(explode('$'.$param->name.' = ', (string) $param, 2)[1] ?? '', 0, -2)); - - if (\in_array($default, ['', 'NULL'], true)) { - return 'null'; - } - if (str_ends_with($default, "...'") && preg_match("/^'(?:[^'\\\\]*+(?:\\\\.)*+)*+'$/", $default)) { - return VarExporter::export($param->getDefaultValue()); - } - - $regexp = "/(\"(?:[^\"\\\\]*+(?:\\\\.)*+)*+\"|'(?:[^'\\\\]*+(?:\\\\.)*+)*+')/"; - $parts = preg_split($regexp, $default, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); - - $regexp = '/([\[\( ]|^)([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z0-9_\x7f-\xff]++)*+)(\(?)(?!: )/'; - $callback = (false !== strpbrk($default, "\\:('") && $class = $param->getDeclaringClass()) - ? fn ($m) => $m[1].match ($m[2]) { - 'new', 'false', 'true', 'null' => $m[2], - 'NULL' => 'null', - 'self' => '\\'.$class->name, - 'namespace\\parent', - 'parent' => ($parent = $class->getParentClass()) ? '\\'.$parent->name : 'parent', - default => self::exportSymbol($m[2], '(' !== $m[3], $namespace), - }.$m[3] - : fn ($m) => $m[1].match ($m[2]) { - 'new', 'false', 'true', 'null', 'self', 'parent' => $m[2], - 'NULL' => 'null', - default => self::exportSymbol($m[2], '(' !== $m[3], $namespace), - }.$m[3]; - - return implode('', array_map(fn ($part) => match ($part[0]) { - '"' => $part, // for internal classes only - "'" => false !== strpbrk($part, "\\\0\r\n") ? '"'.substr(str_replace(['$', "\0", "\r", "\n"], ['\$', '\0', '\r', '\n'], $part), 1, -1).'"' : $part, - default => preg_replace_callback($regexp, $callback, $part), - }, $parts)); - } - - private static function exportSymbol(string $symbol, bool $mightBeRootConst, string $namespace): string - { - if (!$mightBeRootConst - || false === ($ns = strrpos($symbol, '\\')) - || substr($symbol, 0, $ns) !== $namespace - || \defined($symbol) - || !\defined(substr($symbol, $ns + 1)) - ) { - return '\\'.$symbol; - } - - return '\\'.substr($symbol, $ns + 1); - } -} diff --git a/vendor/symfony/var-exporter/README.md b/vendor/symfony/var-exporter/README.md index 7195270..a34e4c2 100644 --- a/vendor/symfony/var-exporter/README.md +++ b/vendor/symfony/var-exporter/README.md @@ -1,22 +1,15 @@ VarExporter Component ===================== -The VarExporter component provides various tools to deal with the internal state -of objects: +The VarExporter component allows exporting any serializable PHP data structure to +plain PHP code. While doing so, it preserves all the semantics associated with +the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`, +`__serialize`, `__unserialize`). -- `VarExporter::export()` allows exporting any serializable PHP data structure to - plain PHP code. While doing so, it preserves all the semantics associated with - the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`, - `__serialize`, `__unserialize`); -- `Instantiator::instantiate()` creates an object and sets its properties without - calling its constructor nor any other methods; -- `Hydrator::hydrate()` can set the properties of an existing object; -- `Lazy*Trait` can make a class behave as a lazy-loading ghost or virtual proxy. +It also provides an instantiator that allows creating and populating objects +without calling their constructor nor any other methods. -VarExporter::export() ---------------------- - -The reason to use `VarExporter::export()` *vs* `serialize()` or +The reason to use this component *vs* `serialize()` or [igbinary](https://github.com/igbinary/igbinary) is performance: thanks to OPcache, the resulting code is significantly faster and more memory efficient than using `unserialize()` or `igbinary_unserialize()`. @@ -26,107 +19,15 @@ Unlike `var_export()`, this works on any serializable PHP value. It also provides a few improvements over `var_export()`/`serialize()`: * the output is PSR-2 compatible; - * the output can be re-indented without messing up with `\r` or `\n` in the data; - * missing classes throw a `ClassNotFoundException` instead of being unserialized - to `PHP_Incomplete_Class` objects; + * the output can be re-indented without messing up with `\r` or `\n` in the data + * missing classes throw a `ClassNotFoundException` instead of being unserialized to + `PHP_Incomplete_Class` objects; * references involving `SplObjectStorage`, `ArrayObject` or `ArrayIterator` instances are preserved; * `Reflection*`, `IteratorIterator` and `RecursiveIteratorIterator` classes throw an exception when being serialized (their unserialized version is broken anyway, see https://bugs.php.net/76737). -Instantiator and Hydrator -------------------------- - -`Instantiator::instantiate($class)` creates an object of the given class without -calling its constructor nor any other methods. - -`Hydrator::hydrate()` sets the properties of an existing object, including -private and protected ones. For example: - -```php -// Sets the public or protected $object->propertyName property -Hydrator::hydrate($object, ['propertyName' => $propertyValue]); - -// Sets a private property defined on its parent Bar class: -Hydrator::hydrate($object, ["\0Bar\0privateBarProperty" => $propertyValue]); - -// Alternative way to set the private $object->privateBarProperty property -Hydrator::hydrate($object, [], [ - Bar::class => ['privateBarProperty' => $propertyValue], -]); -``` - -`Lazy*Trait` ------------- - -The component provides two lazy-loading patterns: ghost objects and virtual -proxies (see https://martinfowler.com/eaaCatalog/lazyLoad.html for reference). - -Ghost objects work only with concrete and non-internal classes. In the generic -case, they are not compatible with using factories in their initializer. - -Virtual proxies work with concrete, abstract or internal classes. They provide an -API that looks like the actual objects and forward calls to them. They can cause -identity problems because proxies might not be seen as equivalents to the actual -objects they proxy. - -Because of this identity problem, ghost objects should be preferred when -possible. Exceptions thrown by the `ProxyHelper` class can help decide when it -can be used or not. - -Ghost objects and virtual proxies both provide implementations for the -`LazyObjectInterface` which allows resetting them to their initial state or to -forcibly initialize them when needed. Note that resetting a ghost object skips -its read-only properties. You should use a virtual proxy to reset read-only -properties. - -### `LazyGhostTrait` - -By using `LazyGhostTrait` either directly in your classes or by using -`ProxyHelper::generateLazyGhost()`, you can make their instances lazy-loadable. -This works by creating these instances empty and by computing their state only -when accessing a property. - -```php -class FooLazyGhost extends Foo -{ - use LazyGhostTrait; -} - -$foo = FooLazyGhost::createLazyGhost(initializer: function (Foo $instance): void { - // [...] Use whatever heavy logic you need here - // to compute the $dependencies of the $instance - $instance->__construct(...$dependencies); - // [...] Call setters, etc. if needed -}); - -// $foo is now a lazy-loading ghost object. The initializer will -// be called only when and if a *property* is accessed. -``` - -### `LazyProxyTrait` - -Alternatively, `LazyProxyTrait` can be used to create virtual proxies: - -```php -$proxyCode = ProxyHelper::generateLazyProxy(new ReflectionClass(Foo::class)); -// $proxyCode contains the reference to LazyProxyTrait -// and should be dumped into a file in production envs -eval('class FooLazyProxy'.$proxyCode); - -$foo = FooLazyProxy::createLazyProxy(initializer: function (): Foo { - // [...] Use whatever heavy logic you need here - // to compute the $dependencies of the $instance - $instance = new Foo(...$dependencies); - // [...] Call setters, etc. if needed - - return $instance; -}); -// $foo is now a lazy-loading virtual proxy object. The initializer will -// be called only when and if a *method* is called. -``` - Resources --------- diff --git a/vendor/symfony/var-exporter/VarExporter.php b/vendor/symfony/var-exporter/VarExporter.php index 22e9b51..3e2a4cc 100644 --- a/vendor/symfony/var-exporter/VarExporter.php +++ b/vendor/symfony/var-exporter/VarExporter.php @@ -32,12 +32,12 @@ final class VarExporter /** * Exports a serializable PHP value to PHP code. * - * @param bool &$isStaticValue Set to true after execution if the provided value is static, false otherwise - * @param array &$foundClasses Classes found in the value are added to this list as both keys and values + * @param bool &$isStaticValue Set to true after execution if the provided value is static, false otherwise + * @param bool &$classes Classes found in the value are added to this list as both keys and values * * @throws ExceptionInterface When the provided value cannot be serialized */ - public static function export(mixed $value, ?bool &$isStaticValue = null, array &$foundClasses = []): string + public static function export(mixed $value, bool &$isStaticValue = null, array &$foundClasses = []): string { $isStaticValue = true; @@ -82,7 +82,7 @@ final class VarExporter ksort($states); $wakeups = [null]; - foreach ($states as $v) { + foreach ($states as $k => $v) { if (\is_array($v)) { $wakeups[-$v[0]] = $v[1]; } else { diff --git a/vendor/symfony/var-exporter/composer.json b/vendor/symfony/var-exporter/composer.json index e7b0fb0..3bf21a6 100644 --- a/vendor/symfony/var-exporter/composer.json +++ b/vendor/symfony/var-exporter/composer.json @@ -2,7 +2,7 @@ "name": "symfony/var-exporter", "type": "library", "description": "Allows exporting any serializable PHP data structure to plain PHP code", - "keywords": ["export", "serialize", "instantiate", "hydrate", "construct", "clone", "lazy-loading", "proxy"], + "keywords": ["export", "serialize", "instantiate", "hydrate", "construct", "clone"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ @@ -16,13 +16,10 @@ } ], "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.0.2" }, "require-dev": { - "symfony/property-access": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/var-dumper": "^5.4|^6.0" }, "autoload": { "psr-4": { "Symfony\\Component\\VarExporter\\": "" }, diff --git a/vendor/workerman/phpsocket.io/src/Engine/Transport.php b/vendor/workerman/phpsocket.io/src/Engine/Transport.php index d5320b5..09f07a5 100644 --- a/vendor/workerman/phpsocket.io/src/Engine/Transport.php +++ b/vendor/workerman/phpsocket.io/src/Engine/Transport.php @@ -41,7 +41,11 @@ class Transport extends Emitter public function onError(string $msg, string $desc = '') { if ($this->listeners('error')) { - $this->emit('error', "TransportError: {$desc}"); + $err = [ + 'type' => 'TransportError', + 'description' => $desc, + ]; + $this->emit('error', $err); } else { echo("ignored transport error $msg $desc\n"); } diff --git a/vendor/workerman/phpsocket.io/src/SocketIO.php b/vendor/workerman/phpsocket.io/src/SocketIO.php index 0bcb612..94c6687 100644 --- a/vendor/workerman/phpsocket.io/src/SocketIO.php +++ b/vendor/workerman/phpsocket.io/src/SocketIO.php @@ -39,13 +39,7 @@ class SocketIO class_alias('PHPSocketIO\Engine\Protocols\SocketIO', 'Protocols\SocketIO'); } if ($port) { - $host = '0.0.0.0'; - if (isset($opts['host'])) { - $ip = trim($opts['host'], '[]'); - if (filter_var($ip, FILTER_VALIDATE_IP)) { - $host = (strpos($ip, ':') !== false) ? "[$ip]" : $ip; - } - } + $host = filter_var(trim($opts['host'] ?? '0.0.0.0', '[]'), FILTER_VALIDATE_IP) ?: '0.0.0.0'; $worker = new Worker('SocketIO://' . $host . ':' . $port, $opts); $worker->name = 'PHPSocketIO'; diff --git a/vendor/yansongda/artful/CHANGELOG.md b/vendor/yansongda/artful/CHANGELOG.md index 3bf3b4f..b95395a 100644 --- a/vendor/yansongda/artful/CHANGELOG.md +++ b/vendor/yansongda/artful/CHANGELOG.md @@ -2,7 +2,7 @@ ### added -- feat: EventInterface 增加更多常用方法(#28, #29) +- feat: EventInterface 增加更多常用方法(#28) ## v1.1.2 diff --git a/vendor/yansongda/artful/src/Event.php b/vendor/yansongda/artful/src/Event.php index 1e82cb6..2c76c14 100644 --- a/vendor/yansongda/artful/src/Event.php +++ b/vendor/yansongda/artful/src/Event.php @@ -12,7 +12,6 @@ use Yansongda\Artful\Exception\ServiceNotFoundException; /** * @method static Event\Event dispatch(object $event) - * @method static void addListener(string $eventName, callable $listener, int $priority = 0) */ class Event { diff --git a/vendor/yansongda/pay/CHANGELOG.md b/vendor/yansongda/pay/CHANGELOG.md index 76d0cd3..7f6f622 100644 --- a/vendor/yansongda/pay/CHANGELOG.md +++ b/vendor/yansongda/pay/CHANGELOG.md @@ -1,15 +1,3 @@ -## v3.7.18 - -### fixed - -- fix: 微信分账参数可能丢失的问题 (#1108) - -## v3.7.17 - -### fixed - -- fix: 事件缺失与不生效的问题 (#1106) - ## v3.7.16 ### added diff --git a/vendor/yansongda/pay/composer.json b/vendor/yansongda/pay/composer.json index 114a3aa..311d5a3 100644 --- a/vendor/yansongda/pay/composer.json +++ b/vendor/yansongda/pay/composer.json @@ -22,7 +22,7 @@ "ext-libxml": "*", "ext-json": "*", "ext-bcmath": "*", - "yansongda/artful": "~1.1.3", + "yansongda/artful": "~1.1.1", "yansongda/supports": "~4.0.10" }, "require-dev": { diff --git a/vendor/yansongda/pay/src/Event.php b/vendor/yansongda/pay/src/Event.php deleted file mode 100644 index 05fe77c..0000000 --- a/vendor/yansongda/pay/src/Event.php +++ /dev/null @@ -1,7 +0,0 @@ -plugins, $event->params)); - } - - public static function artfulEnd(ArtfulEnd $event): void - { - Event::dispatch(new PayEnd($event->rocket)); - } - - public static function httpStart(HttpStart $event): void - { - Event::dispatch(new Event\HttpStart($event->rocket)); - } - - public static function httpEnd(HttpEnd $event): void - { - Event::dispatch(new Event\HttpEnd($event->rocket)); - } -} diff --git a/vendor/yansongda/pay/src/Plugin/Wechat/V3/Extend/ProfitSharing/CreatePlugin.php b/vendor/yansongda/pay/src/Plugin/Wechat/V3/Extend/ProfitSharing/CreatePlugin.php index 07f9da7..1b3e346 100644 --- a/vendor/yansongda/pay/src/Plugin/Wechat/V3/Extend/ProfitSharing/CreatePlugin.php +++ b/vendor/yansongda/pay/src/Plugin/Wechat/V3/Extend/ProfitSharing/CreatePlugin.php @@ -83,7 +83,7 @@ class CreatePlugin implements PluginInterface return $data; } - return array_merge($data, $this->encryptSensitiveData($params, $payload)); + return array_merge($data, $this->encryptSensitiveData($params, $config, $payload)); } /** @@ -110,7 +110,7 @@ class CreatePlugin implements PluginInterface return $data; } - return array_merge($data, $this->encryptSensitiveData($params, $payload)); + return array_merge($data, $this->encryptSensitiveData($params, $config, $payload)); } /** @@ -120,15 +120,14 @@ class CreatePlugin implements PluginInterface * @throws InvalidParamsException * @throws ServiceNotFoundException */ - protected function encryptSensitiveData(array $params, Collection $payload): array + protected function encryptSensitiveData(array $params, array $config, Collection $payload): array { - $data['receivers'] = $payload->get('receivers', []); $data['_serial_no'] = get_wechat_serial_no($params); $config = get_provider_config('wechat', $params); $publicKey = get_wechat_public_key($config, $data['_serial_no']); - foreach ($data['receivers'] as $key => $list) { + foreach ($payload->get('receivers', []) as $key => $list) { $data['receivers'][$key]['name'] = encrypt_wechat_contents($list['name'], $publicKey); } diff --git a/vendor/yansongda/pay/src/Provider/Alipay.php b/vendor/yansongda/pay/src/Provider/Alipay.php index 44500ae..c93004e 100644 --- a/vendor/yansongda/pay/src/Provider/Alipay.php +++ b/vendor/yansongda/pay/src/Provider/Alipay.php @@ -10,13 +10,13 @@ use Psr\Http\Message\MessageInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Yansongda\Artful\Artful; +use Yansongda\Artful\Event; use Yansongda\Artful\Exception\ContainerException; use Yansongda\Artful\Exception\InvalidParamsException; use Yansongda\Artful\Exception\ServiceNotFoundException; use Yansongda\Artful\Plugin\ParserPlugin; use Yansongda\Artful\Rocket; use Yansongda\Pay\Contract\ProviderInterface; -use Yansongda\Pay\Event; use Yansongda\Pay\Event\CallbackReceived; use Yansongda\Pay\Event\MethodCalled; use Yansongda\Pay\Pay; diff --git a/vendor/yansongda/pay/src/Provider/Douyin.php b/vendor/yansongda/pay/src/Provider/Douyin.php index 87a0112..dfe77c1 100644 --- a/vendor/yansongda/pay/src/Provider/Douyin.php +++ b/vendor/yansongda/pay/src/Provider/Douyin.php @@ -10,6 +10,7 @@ use Psr\Http\Message\MessageInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Yansongda\Artful\Artful; +use Yansongda\Artful\Event; use Yansongda\Artful\Exception\ContainerException; use Yansongda\Artful\Exception\InvalidParamsException; use Yansongda\Artful\Exception\ServiceNotFoundException; @@ -19,7 +20,6 @@ use Yansongda\Artful\Plugin\ParserPlugin; use Yansongda\Artful\Plugin\StartPlugin; use Yansongda\Artful\Rocket; use Yansongda\Pay\Contract\ProviderInterface; -use Yansongda\Pay\Event; use Yansongda\Pay\Event\CallbackReceived; use Yansongda\Pay\Event\MethodCalled; use Yansongda\Pay\Exception\Exception; diff --git a/vendor/yansongda/pay/src/Provider/Jsb.php b/vendor/yansongda/pay/src/Provider/Jsb.php index d23a2c4..1190846 100644 --- a/vendor/yansongda/pay/src/Provider/Jsb.php +++ b/vendor/yansongda/pay/src/Provider/Jsb.php @@ -10,13 +10,13 @@ use Psr\Http\Message\MessageInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Yansongda\Artful\Artful; +use Yansongda\Artful\Event; use Yansongda\Artful\Exception\ContainerException; use Yansongda\Artful\Exception\InvalidParamsException; use Yansongda\Artful\Exception\ServiceNotFoundException; use Yansongda\Artful\Plugin\ParserPlugin; use Yansongda\Artful\Rocket; use Yansongda\Pay\Contract\ProviderInterface; -use Yansongda\Pay\Event; use Yansongda\Pay\Event\CallbackReceived; use Yansongda\Pay\Event\MethodCalled; use Yansongda\Pay\Exception\Exception; @@ -41,11 +41,14 @@ class Jsb implements ProviderInterface ]; /** + * @param mixed $name + * @param mixed $params + * * @throws ContainerException * @throws InvalidParamsException * @throws ServiceNotFoundException */ - public function __call(string $name, array $params): null|Collection|MessageInterface|Rocket + public function __call($name, $params): null|Collection|MessageInterface|Rocket { $plugin = '\Yansongda\Pay\Shortcut\Jsb\\'.Str::studly($name).'Shortcut'; diff --git a/vendor/yansongda/pay/src/Provider/Unipay.php b/vendor/yansongda/pay/src/Provider/Unipay.php index e28703f..08d7cce 100644 --- a/vendor/yansongda/pay/src/Provider/Unipay.php +++ b/vendor/yansongda/pay/src/Provider/Unipay.php @@ -10,6 +10,7 @@ use Psr\Http\Message\MessageInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Yansongda\Artful\Artful; +use Yansongda\Artful\Event; use Yansongda\Artful\Exception\ContainerException; use Yansongda\Artful\Exception\InvalidParamsException; use Yansongda\Artful\Exception\ServiceNotFoundException; @@ -17,7 +18,6 @@ use Yansongda\Artful\Plugin\AddPayloadBodyPlugin; use Yansongda\Artful\Plugin\ParserPlugin; use Yansongda\Artful\Rocket; use Yansongda\Pay\Contract\ProviderInterface; -use Yansongda\Pay\Event; use Yansongda\Pay\Event\CallbackReceived; use Yansongda\Pay\Event\MethodCalled; use Yansongda\Pay\Exception\Exception; diff --git a/vendor/yansongda/pay/src/Provider/Wechat.php b/vendor/yansongda/pay/src/Provider/Wechat.php index cfb464e..c2a027b 100644 --- a/vendor/yansongda/pay/src/Provider/Wechat.php +++ b/vendor/yansongda/pay/src/Provider/Wechat.php @@ -10,6 +10,7 @@ use Psr\Http\Message\MessageInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Yansongda\Artful\Artful; +use Yansongda\Artful\Event; use Yansongda\Artful\Exception\ContainerException; use Yansongda\Artful\Exception\InvalidParamsException; use Yansongda\Artful\Exception\ServiceNotFoundException; @@ -18,7 +19,6 @@ use Yansongda\Artful\Plugin\ParserPlugin; use Yansongda\Artful\Plugin\StartPlugin; use Yansongda\Artful\Rocket; use Yansongda\Pay\Contract\ProviderInterface; -use Yansongda\Pay\Event; use Yansongda\Pay\Event\CallbackReceived; use Yansongda\Pay\Event\MethodCalled; use Yansongda\Pay\Pay; @@ -84,9 +84,7 @@ class Wechat implements ProviderInterface } /** - * @throws ContainerException * @throws InvalidParamsException - * @throws ServiceNotFoundException */ public function cancel(array $order): Collection|Rocket { diff --git a/vendor/yansongda/supports/composer.json b/vendor/yansongda/supports/composer.json index 355560f..7f3e385 100644 --- a/vendor/yansongda/supports/composer.json +++ b/vendor/yansongda/supports/composer.json @@ -13,9 +13,7 @@ } ], "require": { - "php": ">=8.0", - "ext-mbstring": "*", - "ext-ctype": "*" + "php": ">=8.0" }, "require-dev": { "phpunit/phpunit": "^9.0", diff --git a/vendor/yansongda/supports/src/Str.php b/vendor/yansongda/supports/src/Str.php index 2abad72..7749192 100644 --- a/vendor/yansongda/supports/src/Str.php +++ b/vendor/yansongda/supports/src/Str.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace Yansongda\Supports; +use Random\RandomException; + /** * Most of the methods in this file come from illuminate/support. * thanks provide such a useful class. @@ -144,6 +146,9 @@ class Str return static::contains($callback, '@') ? explode('@', $callback, 2) : [$callback, $default]; } + /** + * @throws RandomException + */ public static function random(int $length = 16): string { $string = ''; @@ -270,10 +275,10 @@ class Str return $value; } - public static function startsWith(int|string $haystack, array|string $needles): bool + public static function startsWith(string $haystack, array|string $needles): bool { foreach ((array) $needles as $needle) { - if (str_starts_with(strval($haystack), $needle)) { + if (str_starts_with($haystack, $needle)) { return true; } } diff --git a/vendor/yansongda/supports/src/Traits/Serializable.php b/vendor/yansongda/supports/src/Traits/Serializable.php index 9735dcd..7ba952e 100644 --- a/vendor/yansongda/supports/src/Traits/Serializable.php +++ b/vendor/yansongda/supports/src/Traits/Serializable.php @@ -49,7 +49,7 @@ trait Serializable { foreach ($data as $key => $item) { if (method_exists($this, 'set')) { - $this->set(strval($key), $item); + $this->set($key, $item); } }