@@ -25,71 +25,71 @@ discard block |
||
25 | 25 | use Test\TestCase; |
26 | 26 | |
27 | 27 | class AppFetcherTest extends TestCase { |
28 | - /** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */ |
|
29 | - protected $appData; |
|
30 | - /** @var IClientService|\PHPUnit\Framework\MockObject\MockObject */ |
|
31 | - protected $clientService; |
|
32 | - /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ |
|
33 | - protected $timeFactory; |
|
34 | - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ |
|
35 | - protected $config; |
|
36 | - /** @var CompareVersion|\PHPUnit\Framework\MockObject\MockObject */ |
|
37 | - protected $compareVersion; |
|
38 | - /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ |
|
39 | - protected $logger; |
|
40 | - /** @var IRegistry|\PHPUnit\Framework\MockObject\MockObject */ |
|
41 | - protected $registry; |
|
42 | - /** @var AppFetcher */ |
|
43 | - protected $fetcher; |
|
44 | - /** @var string */ |
|
45 | - public static $responseJson = <<<'EOD' |
|
28 | + /** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */ |
|
29 | + protected $appData; |
|
30 | + /** @var IClientService|\PHPUnit\Framework\MockObject\MockObject */ |
|
31 | + protected $clientService; |
|
32 | + /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ |
|
33 | + protected $timeFactory; |
|
34 | + /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ |
|
35 | + protected $config; |
|
36 | + /** @var CompareVersion|\PHPUnit\Framework\MockObject\MockObject */ |
|
37 | + protected $compareVersion; |
|
38 | + /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ |
|
39 | + protected $logger; |
|
40 | + /** @var IRegistry|\PHPUnit\Framework\MockObject\MockObject */ |
|
41 | + protected $registry; |
|
42 | + /** @var AppFetcher */ |
|
43 | + protected $fetcher; |
|
44 | + /** @var string */ |
|
45 | + public static $responseJson = <<<'EOD' |
|
46 | 46 | [{"id":"direct_menu","categories":["customization"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/juliushaertl/direct_menu/issues","website":"","created":"2016-10-01T09:16:06.030994Z","lastModified":"2016-10-06T14:01:05.584192Z","releases":[{"version":"0.9.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/juliushaertl/direct_menu/releases/download/v0.9.2/direct_menu.tar.gz","created":"2016-10-06T14:01:05.578297Z","licenses":["agpl"],"lastModified":"2016-10-06T14:01:05.643813Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"ERBS9G5bZ3vwCizz2Ht5DehsVJmb63bzF3aYcH7xjbDVMPagOFWdUAiLDwTeZR1n\ni4gdZ73J/IjHQQJoOPwtCjgbZgLPFqL5x13CLUO9mb/33dZe/+gqEDc/3AuJ4TlA\nXUdLxHRb1bwIlJOwuSr/E24452VG20WUhLXBoM0Zm7WcMxvJWo2zAWnuqnLX3dy9\ncPB4PX+6JU2lUMINj8OYQmM1QnqvjG8YV0cYHbBbnSicOGwXEnni7mojsC8T0cn7\nYEJ2O2iO9hh3fvFEXUzDcL7tDQ5bZqm63Oa991bsAJxFo/RbzeJRh//DcOrd8Ufn\nu2SqRhwybS8j4YvfjAL9RPdRfPLwf6X2gx/Y6QFrKHH0QMI/9J/ZFyoUQcqKbsHV\n85O+yuWoqVmza71tkp4n9PuMdprCinaVvHbHbNGUf2SIh9BWuEQuVvvnvB+ZW8XY\n+Cl+unzk3WgOgT0iY3uEmsQcrLIo4DSKhcNgD1NS13fR/JTSavvmOqBarUMFZfVC\nbkR1DTBCyDjdpNBidpa3/26675dz5IT5Zedp4BBBREQzX08cIhJx5mgqDdX3CU09\nuWtzoaLi71/1BWTFAN+Y9VyfZ8/Z3Pg3vKedRJ565mztIj0geL3riEsC5YnPS0+C\n+a3B9sDiiOa101EORzX3lrPqL7reEPdCxrIwN+hKFBQ=","translations":{}}],"screenshots":[{"url":"https://bitgrid.net/~jus/direct_menu_nc.png"}],"translations":{"en":{"name":"Direct Menu","summary":"Provide easy access to all apps in the header.","description":"Provide easy access to all apps in the header."}},"isFeatured":false,"authors":[{"name":"Julius Härtl","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEBjCCAu4CAhADMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwOTE0MTI1MDU0WhcNMjYxMjIxMTI1MDU0WjAWMRQwEgYD\r\nVQQDDAtkaXJlY3RfbWVudTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\r\nAMkzWsAkKP/40ktvJMpnr0IJNVoPOR0hvh24igcDskL1WKiD2eiRUenj5LE0Nvn+\r\nsiGmWsAqRVpdiz+Y8ghQqQMzKi43IrRN0AxlCrHWrSqBZT3wIAUcFz4RzEoFxc1N\r\nUZzWma6ljukGnvt4V1ZyT+H/cjqxUkBhh/y9SS0jUen1a1grND6Rw54X46V2dlCu\r\nFH+pLsfPJJGw+QLeTGHn7dqdv18cYMAlWDCzPixVnNiCXHZcUtKMmstU2xU4R2e6\r\nzimp2rgkE4TNHrafpjH8xGdNi2FG5Dmokob/L5Q2r8jyNaW7UsFfrvLTRj371b3/\r\n2FhhxoGUvDzaG2An02Exwm52LJfdTVMHAMPZub5poHfy5vAEdZGPQ/m02l8ZK/Y2\r\n7yT807GlfPMXfdfjCxR6wNtmv7rvBDdrUZmIRNJfpFSdvlH/+MOTWnabyfQv2K4Q\r\nBIwltX6Elh0lh4ntvt1ZVtvFv+PL1Dc7QLV+w19+/LJA0mnsh7GIFYKFlbA65gA0\r\nc/w+uqDy0+5MxkR9WGPpd79KRA1tKWTis4Ny1lApK5y3zIsVGa3DfBHXcwqkWHbV\r\nwIpyuyyDsFtC1b9LTFONX7iU9cbNk5C5GTM331MdA2kLcD/D5k42GNTBSca7MkPx\r\nFx/ETSn0Ct167el30symf2AxvXjw+mBYPN71rVTMDwe9AgMBAAEwDQYJKoZIhvcN\r\nAQELBQADggEBAC0fJKnbEhXA8M283jA9GxABxLyTBcQyVVNnz2L/bYYNi81Y9iZv\r\n+U0S3qaIfoqNcV9FTKAutbsKvWyolnI7MRRK6feNuFfoP2jKubM1CnawpyT/RF2Q\r\ne/zxnB1EmeI2X5D2xceJDLB7Fy5W0EGrLixRIdFaSUommWFUm9E2hSIaNlziSBdc\r\n1J/mOQeNYO5zg5ouEt1rzQW4Mhh1I2uNQmGe4ip+Jl/2LAv3FZuu4NrSEcoXH3ro\r\nG2dF9Gtu4GiQ5fuaJknaxlgXHovfqeZwZJX9o4M+Ug81AqiY7XjdiaCPdh0Tthcx\r\n2OmWZo7UBREWenjKyFZZ/iKoqH5sdenBtpo=\r\n-----END CERTIFICATE-----"},{"id":"apporder","categories":["customization"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/juliushaertl/apporder/issues","website":"","created":"2016-10-01T09:16:47.111889Z","lastModified":"2016-10-12T19:50:16.038821Z","releases":[{"version":"0.3.3","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/juliushaertl/apporder/releases/download/0.3.3/apporder.tar.gz","created":"2016-10-12T19:14:10.802359Z","licenses":["agpl"],"lastModified":"2016-10-12T19:50:16.104357Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"nhlT9lhrmBxIsqh/e3RLm2NDw/U8ZvvoMyYQTLMM3H19DQmVcPYPYC9QWVTsowUzXblVaOXVGylbpKma9yOlOAqJtF3qyXecLl4+tA/Awb6BBhKPgHFdcLDAL5yy1K7/uei3SgEojMlJoI9vEK5I1C5YTh43yNH+//Im6MAuNYFUTlMXK426zdOe6ogpCI5GlYdXopqYANxcpT+WXWET6DDSM5Ev+MYwMcSAY4r8+tvARRU4ZAenRgjkBT6R5z6cD76emRax14tbV6vkjjwRcO+dQtM0tFPbd+5fsNInbauv50VzIMgjA6RnKTOI17gRsSdGlsV4vZn2aIxEPWauu6T/UohMvAE9HMn13vtbpPBSFwJAktj6yHASYGzupNQLprA0+OdyALoLZPpQAKNEXA42a4EVISBKu0EmduHJlUPeqhnIGkkGgVNWS8AWqzP2nFoPdXBgUWateiMcBTHxgEKDac5YmNc9lsXpzf1OxBaXHBhGYKuXPwIfyH3jTWb1OdwixJEuRe9dl63T9qOTRre8QWns/bMqKLibGfMtFhVB21ARJayBuX70eVvabG/2N7Y5t1zUlFygIKu51tvo3AVCRDdRrFWDvkAjxzIz5FIdALVZ+DReFYu/r4WF/w3V9rInFuEDSwb/OH4r8sQycs07tSlMyA74Y3FpjKTBxso=","translations":{}},{"version":"0.3.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/juliushaertl/apporder/releases/download/0.3.2/apporder.tar.gz","created":"2016-10-06T14:00:51.532409Z","licenses":["agpl"],"lastModified":"2016-10-06T14:00:51.598455Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"gRVFOtj9414ZNSdRH/qNB2SwVZUQh+gaFnNLFjjXjJ1MdRMCISzvwb+QU1qYuK/y\nuL8K0pn1+fFQf8A3VsC2pb6yaLQ5U9C3Guf886Flf4qtYw1P8UWRA9yOJ+6Md+PH\n6pTEiDIdm4xbmM0KkBhsE5kL8dvLIq4EwwcAh2Qq8fjytzAk1YiP+KrTaYrVwskM\nDmm0lgP4NVnjRBTX9myW6tr6N3w0tq2jJ/+a/vEDJv+5ozKJx8N5gbJNdrtI4k7I\nyaQNWJ7cngtAHmUREeoBggV5uJayDceu83PPQR6N9/WVyNyZjw1Q8/Q6e/NyiXT2\no8mGv5tHl3DBOVuv8v7gBQgDh6ppp12M81aiCZymn2XIgjw50VQ+K15KHnLHuFFw\nwuHZVcoQ7b6oR4K4TURSfPFUeNgGS4R9v6gjg1RUcSm1Pnryc6pYnh10AUY8dk6q\n1CZ6Upt6SScP2ZEGWsFwVjjQhY/ZJmNfnhaGoFOZ5L9CnzyNCkGXFg0rL36i6djb\naqFy/z+Brnklng5ct6XWoP7uDt5BaHznQj1NHSfHn0GUQ0N968zWm9vQvy+dyXyC\nxR7vKeu2ppZ2ydoeQ9CVwfhOEsGs5OvrpapQdh9KbUHcX7b7ql01J7/P6dFuNuHe\n+7/y4ex3sEVg5YBmDtF8iZ6d7zsHd6peL1s1EsLnenQ=","translations":{}}],"screenshots":[{"url":"https://bitgrid.net/~jus/apporder-nc.gif"}],"translations":{"en":{"name":"AppOrder","summary":"Sort apps in the menu with drag and drop","description":"\nEnable sorting for icons inside the app menu. The order will be saved for each\nuser individually. Administrators can define a custom default order.\nAppOrder works with the default owncloud menu as well as with the direct_menu\napp.\n\n## Set a default order for all new users\n\nGo to the Admin settings > Additional settings and drag the icons under App order.\n\n## Use first app as default app\n\nYou can easily let Nextcloud redirect your user to the first app in their\npersonal order by changing the following parameter in your config/config.php:\n\n'defaultapp' => 'apporder',\n\nUsers will now get redirected to the first app of the default order or to the\nfirst app of the user order.\n "}},"isFeatured":false,"authors":[{"name":"Julius Härtl","mail":"[email protected]","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEAzCCAusCAhAEMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwOTE0MTI1MjQ4WhcNMjYxMjIxMTI1MjQ4WjATMREwDwYD\r\nVQQDDAhhcHBvcmRlcjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKVK\r\nKn5jivCu+eRfe5BECjDOzNaGHlpiegb49Hf4nh0W7DqcoLHip5c1O2BcEYdH6rkw\r\n20WclvjoQpgavG5aFXzXzur6eKTT5TpgY5oZTLoWjbx4e+fKdhyDPTpqNZzs1pxz\r\nsZLDL/ElpbSErE0s+QK/pzP11WNPylAkI9AKSyDMO3Mbllg8I8Bt+bT7LJKYOO/T\r\nLhv9m0anLZ4HrdfimhVIoMiu3RpyRigk8titXZA94+F8Fbf7ZQ9f14Y/v3+rfJFQ\r\nii9cDoox5uUrjplH2LrMr5BodfCfydLu4uVpPWYkdccgvcZ1sugjvNXyCQgdzQDK\r\npOpiwVkkiQFaQJYbGSDblFWPl/cLtA/P/qS7s8tWyTQuc1rYlEpCHG/fG8ZFkSVK\r\n9eCMGxK908VB4IU2DHZHOHi7JvtOz8X/Ak6pIIFdARoW3rfKlrz6DD4T9jEgYq0n\r\nRe7YwCKEIU3liZJ+qG6LCa+rMlp/7sCzAmqBhaaaJyX4nnZCa2Q2cNZpItEAdwVc\r\nqxLYL1FiNFMSeeYhzJJoq5iMC3vp2LScUJJNoXZj9zv+uqTNGHr+bimchR2rHUBo\r\nPzDLFJmat03KdWcMYxcK5mxJNGHpgyqM7gySlbppY/cgAospE8/ygU2FlFWIC9N0\r\neDaY+T8QA1msnzsfMhYuOI8CRYigan1agGOMDgGxAgMBAAEwDQYJKoZIhvcNAQEL\r\nBQADggEBAGsECd+meXHg1rr8Wb6qrkDz/uxkY1J+pa5WxnkVcB6QrF3+HDtLMvYm\r\nTTS02ffLLyATNTOALZFSy4fh4At4SrNzl8dUaapgqk1T8f+y1FhfpZrEBsarrq+2\r\nCSKtBro2jcnxzI3BvHdQcx4RAGo8sUzaqKBmsy+JmAqpCSk8f1zHR94x4Akp7n44\r\n8Ha7u1GcHMPzSeScRMGJX/x06B45cLVGHH5GF2Bu/8JaCSEAsgETCMkc/XFMYrRd\r\nTu+WGOL2Ee5U4k4XFdzeSLODWby08iU+Gx3bXTR6WIvXCYeIVsCPKK/luvfGkiSR\r\nCpW1GUIA1cyulT4uyHf9g6BMdYVOsFQ=\r\n-----END CERTIFICATE-----"},{"id":"twofactor_totp","categories":["tools"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"","website":"","created":"2016-10-08T14:13:54.356716Z","lastModified":"2016-10-12T14:38:56.186269Z","releases":[{"version":"0.4.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0 <7.1.0","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/ChristophWurst/twofactor_totp/releases/download/0.4.1/twofactor_totp.tar.gz","created":"2016-10-12T14:38:56.174612Z","licenses":["agpl"],"lastModified":"2016-10-12T14:38:56.248223Z","isNightly":false,"rawPhpVersionSpec":">=5.4 <=7.0","rawPlatformVersionSpec":">=10 <=11","signature":"bnwWxmHEn8xkoWbtwhC1kIrJ0dQfAI3PUtU62k+Tru/BHt1G2aVxqO8bCdghojZ7\nzdFMlIJw4kekYFsVfLk8jzjUTZKVbNVKCdkHrVTQ0bUUryMAMLqGQ3PSRI5NX6D5\nFpkvwO1coYwU0XVWF8KAS0meX0ztSkT3Mv96LLrxr8F8SrB/MGmKIE4WTjt1fAIa\nZLAVEUo/3sNFTGLYBtL3wjctrkZvJltP8abeRfls9FkRHu+rN7R3uLFzk42uZn3X\nWpt5BBmlYm5ORbnJ2ApsxEkMNK+rOy8GIePaz5277ozTNrOnO04id1FXnS9mIsKD\n20nRzjekZH+nneQYoCTfnEFg2QXpW+a+zINbqCD5hivEU8utdpDAHFpNjIJdjXcS\n8MiCA/yvtwRnfqJ5Fy9BxJ6Gt05/GPUqT8DS7P1I1N+qxhsvFEdxhrm2yIOhif8o\nh7ro5ls+d3OQ8i3i4vdZm821Ytxdu/DQBHiVoOBarvFWwWAv2zd2VAvpTmk6J5yv\n3y+csRqpEJYd9fcVMPsTu7WBRRrpBsAqdAHJcZEwak2kz1kdOgSf8FIzP1z6Q71d\nMl2RKcPeutMHHSLiGIN/h7fM5aSs49wGgGZmfz28fHVd7/U0HFSMYmkT/GMq5tMP\nIyc+QZAN4qbX8G0k/QSTkK/L4lOT2hQiQqiSqmWItMk=","translations":{}}],"screenshots":[],"translations":{"en":{"name":"Two Factor TOTP Provider","summary":"A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)","description":"A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)"}},"isFeatured":true,"authors":[{"name":"Christoph Wurst","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIECTCCAvECAhASMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYxMDEyMDkzNDMxWhcNMjcwMTE4MDkzNDMxWjAZMRcwFQYD\r\nVQQDDA50d29mYWN0b3JfdG90cDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC\r\nggIBALC1K94104L/nOtmTygx7QNjUcnHs3yrn71mw4pMxTlonXOnMTpwxsfL1Hhu\r\n/5GMSgupTbQPlevSl6J86UMs455/sPShd6ifmAuhb8VFaAsjpizjs0RMaUg1sjmF\r\nuV18PD9FXLourx51V/c4MG5kpavlV+bLUrVMAjbsJY2+k30tCC/XkP5u8jUWmM/T\r\n5REChn7/obPgaeddhuJoILYhKEW3VNrR8Fm9SYiviB3FLhM7URDZ97IBnXYqbvbT\r\nZnvq+E74Zc7HgYwQwrjU/AqQAInhNpAR4ZM6CkWWWWaL96O1q3lCfKJNaxqC0Kg/\r\nkGn/pxYkl9062jtMUz60s9OPDyuisfyl68UyM68Ozyz4SMRLmDVbewOqQAwmAbtz\r\n8p9AQrX3Pr9tXhARR4pDSsQz1z+8ExEd6EKbhMyiTtHtZQ1Vm9qfoR52snpznb5N\r\ne4TcT2qHAkOWV9+a9ESXmQz2bNjgThxEl5edTVY9m4t248lK5aBTGq5ZKGULNHSQ\r\nGGpr/ftMFpII45tSvadexUvzcR/BHt3QwBAlPmA4rWtjmOMuJGDGk+mKw4pUgtT8\r\nKvUMPQpnrbXSjKctxb3V5Ppg0UGntlSG71aVdxY1raLvKSmYeoMxUTnNeS6UYAF6\r\nI3FiuPnrjVFsZa2gwZfG8NmUPVPdv1O/IvLbToXvyieo8MbZAgMBAAEwDQYJKoZI\r\nhvcNAQELBQADggEBAEb6ajdng0bnNRuqL/GbmDC2hyy3exqPoZB/P5u0nZZzDZ18\r\nLFgiWr8DOYvS+9i6kdwWscMwNJsLEUQ2rdrAi+fGr6dlazn3sCCXrskLURKn5qCU\r\nfIFZbr2bGjSg93JGnvNorfsdJkwpFW2Z9gOwMwa9tAzSkR9CsSdOeYrmdtBdodAR\r\ndIu2MkhxAZk9FZfnFkjTaAXcBHafJce7H/IEjHDEoIkFp5KnAQLHsJb4n8JeXmi9\r\nVMgQ6yUWNuzOQMZpMIV7RMOUZHvxiX/ZWUFzXNYX0GYub6p4O2uh3LJE+xXyDf77\r\nRBO7PLY3m4TXCeKesxZlkoGke+lnq7B8tkADdPI=\r\n-----END CERTIFICATE-----"},{"id":"contacts","categories":["office","organization","social"],"userDocs":"https://docs.nextcloud.com/server/11/user_manual/pim/contacts.html","adminDocs":"https://docs.nextcloud.com/server/11/admin_manual/configuration_server/occ_command.html?highlight=occ%20commands#dav-label","developerDocs":"https://github.com/nextcloud/contacts#building-the-app","issueTracker":"https://github.com/nextcloud/contacts/issues","website":"https://github.com/nextcloud/contacts#readme","created":"2016-10-30T14:00:58.922766Z","lastModified":"2016-11-22T22:08:01.904319Z","releases":[{"version":"1.5.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/contacts/releases/download/v1.5.0/contacts.tar.gz","created":"2016-11-22T22:08:01.861942Z","licenses":["agpl"],"lastModified":"2016-11-22T22:08:02.306939Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"ZqqhqtbHcNB+rzGCQ7FDIjjvHjit+dhAE1UhFgiXApkx3tmPP4nJOBAGNjHe+2Ao\nVcTIX2SrWEfieRrA4Gp+0k7pUPWag1Z0T1OVOwO4cmS1AVFyGIOE1bRvDhMfsWTU\n4CI4oXaKBFAY6mtnf7VJ7EeIdNqhImkohyWDQ88NiPRLM1XNkJJk6AvZBcT0fvCv\no145X4dLpbixSXsN99QFNJ/oXvK+9tBGwTd5i/WnNFY90vcNRLia8aRo7SA0YJRx\nLnxnj2HMqwTTDQEKE+1elYKWsqQ2DeqwScP97UIKe5bZXnrwOi9kH9PDmR4abtzd\nlHL8E1Wgw25ePDeHG7APrx0tVOJy1bP+g8vcarpGynWZoizDkBvYZD+xtxizpBXC\nJsDOSzczApptY6dnOtv0Vat8oh/Z/F99gBUahEu4WZ16ZgR1nj40PDK1Snl18Cgk\nMe1EZcde8SLEpTbCWYIfIw/O9Fkp5cWD/dAqoiO6g+gNxSZ/gGp57qoGfFxn7d/x\nH3aH8GljatAFjrwItw1JzR0THt0ukkOK+bw/pfCslk10sjHMitmz/GXa4qMS91DZ\nBKLUd0dSfQUQzkfwcojImbzJRvca4/DYe3mfG7+RCH0tDL6t72dKL9joB++u5R1u\nVZPgkToexlXcKWpiDB8H2/SEShKr4udAOjR5de9CYWM=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/nextcloud/screenshots/master/apps/Contacts/contacts.png"}],"translations":{"en":{"name":"Contacts","summary":"The new and improved app for your Contacts.","description":"The new and improved app for your Contacts."}},"isFeatured":true,"authors":[{"name":"Alexander Weidinger","mail":"","homepage":""},{"name":"Jan-Christoph Borchardt","mail":"","homepage":""},{"name":"Hendrik Leppelsack","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEAzCCAusCAhATMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYxMDEyMjAzNzIyWhcNMjcwMTE4MjAzNzIyWjATMREwDwYD\r\nVQQDDAhjb250YWN0czCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANzx\r\n/zJF+5/s4lOJLWIlfKQgTy+UpvIpiUXCgrsHsDZTx+hjQAhIWukH88a+7NVAL7Ys\r\nkQNC0Tlm755FJi/T6EdR7edOwIRdo2ZwakOWLZXd209+6cCd2UloHL0bgnbWepTl\r\nR/4YgbLg/G+FVKCfkEiYc3PuDZ3EVrcwQFcg7h74X9ne6CHH0Z1WQLydxJuVEb2n\r\nX9I+nIRpPHcVostkSiUmzHR7C5TjTIo2PzzgnCU6GC0iBa6z6dDYfz24QEp/b8UA\r\nZaLhjkyKghVGMnoF/s9KPgH4NM8pvvtadQN8pxlOPju4wbmKPUrsXo4ujurDXbbc\r\nYkzNt8ojobGwdTXoyDogAsGZLQd2FQksWpRvY+I3zVPokBfPMdUPLllG5VcV0VA5\r\nDRK+h2ms+XmspdBvGonjF+XdbFm9hEmDoFmoi9aU6C6AdofjmG/e9+pw/20dXUWk\r\nmMorWwXQ5yLmIn5LnpRXrOuK7CS28VRhBYuVNMlsyKhzU0rophbsD9OFXxYLjr6s\r\n7UPNwZ5h+kjXZDBKD89QctBSViT8RhLe8nulRIm0iJn1sb9hca/CF63KmsFzENfK\r\nQeM6MO0H34PB84iNyz5AX1OIy+1wHD4Wrzt9O/i2LkWK6tBhL69aZiBqdLXWKffj\r\nARDCxxIfews51EZFyHzwsw65I97y46aBKxY382q7AgMBAAEwDQYJKoZIhvcNAQEL\r\nBQADggEBACLypX0spxAVAwQIS9dlC9bh1X/XdW2nAvSju2taUTBzbp074SnW6niI\r\nbnY4ihYs4yOuGvzXxnp/OlvWH7qhOIchJUq/XPcEFMa7P03XjVpcNnD3k0zQWlZb\r\ntGonX9EUOeLZKdqI4fkrCkMLScfjgJzoHGYQrm8vlIg0IVuRLCKd5+x4bS7KagbG\r\niuPit2pjkw3nWz0JRHneRXz/BNoAWBnJiV7JMF2xwBAHN4ghTM8NSJzrGTurmpMI\r\nGld7yCP47xNPaAZEC66odcClvNtJ2Clgp8739jD6uJJCqcKDejeef0VU1PG7AXId\r\n52bVrGMxJwOuL1393vKxGH0PHDzcB1M=\r\n-----END CERTIFICATE-----"},{"id":"mail","categories":["tools"],"userDocs":"","adminDocs":"https://github.com/nextcloud/mail#readme","developerDocs":"","issueTracker":"","website":"","created":"2016-10-19T19:41:41.710285Z","lastModified":"2016-10-19T19:57:33.689238Z","releases":[{"version":"0.6.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0 <7.1.0","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/mail/releases/download/v0.6.0/mail.tar.gz","created":"2016-10-19T19:57:33.676730Z","licenses":["agpl"],"lastModified":"2016-10-19T19:57:33.834580Z","isNightly":false,"rawPhpVersionSpec":">=5.4 <=7.0","rawPlatformVersionSpec":">=10 <=11","signature":"VbMsvDpt+gSPeFM8LrZXEK10rk8kkLlgCcblgqNdCSeGZeVpwDAYv3CccVSLa0+l\nlTSqQ0VIoH+OIU6vIQNBKHmSCzTplk7OrY0+L5FajXx8LnBaOh892GfGSlEt1neN\nKyM0i0uOjO/xpCP/NoUlgkz6hnmYY5XEdN6DTsJtJ/XZhDQ45IYuIkMkHE/eFehS\n0JnOagIz+PSipeBY2Ry+tV8YbRa7bC1JAvZzlod0dyI015AHZESeitRUY+MwMWkt\nN/me7g7/Kev0wggIQQZm9aYcw63GMk/1VHUPB7Y0ESW9tx2nR5+KwTDn/Jy4DGf1\nrg8h0t5I+aPhHOBLrpczH0qaZWY2lsVZWq8KWjJI9aR9P0v2f2aXixXzD/Cuz1cK\nhvhKWkOSla4D+/FxeyHGjQvdXMG8gXm0ZmTimKChCoVuCbncDd8pzkdyNoGXcvuk\nsP8OrkQFooL4E7S4BWfdSiN/a8jUITJQkuXp/OVrVGeCupLWJh7qegUw6DvoqyGy\nD4c6b+qYn68kx3CLaPPiz+tFAZQZQdj7+Kx/lohso8yTnVSiGYrMj4IvvCbpsQjg\nWF3WSqF/K/tTnPYTWb9NUPSihTbVNv6AXOfTsPEp/ba2YSS5DjvjVjkr5vhR9eg1\nikQ3Cw6lW3vaA4LVCC+hFkMRnI4N0bo5qQavP3PnZPc=","translations":{"en":{"changelog":"### Added\n- Alias support\n [#1523](https://github.com/owncloud/mail/pull/1523) @tahaalibra\n- New incoming messages are prefetched\n [#1631](https://github.com/owncloud/mail/pull/1631) @ChristophWurst\n- Custom app folder support\n [#1627](https://github.com/owncloud/mail/pull/1627) @juliushaertl\n- Improved search\n [#1609](https://github.com/owncloud/mail/pull/1609) @ChristophWurst\n- Scroll to refresh\n [#1595](https://github.com/owncloud/mail/pull/1593) @ChristophWurst\n- Shortcuts to star and mark messages as unread\n [#1590](https://github.com/owncloud/mail/pull/1590) @ChristophWurst\n- Shortcuts to select previous/next messsage\n [#1557](https://github.com/owncloud/mail/pull/1557) @ChristophWurst\n\n## Changed\n- Minimum server is Nextcloud 10/ownCloud 9.1\n [#84](https://github.com/nextcloud/mail/pull/84) @ChristophWurst\n- Use session storage instead of local storage for client-side cache\n [#1612](https://github.com/owncloud/mail/pull/1612) @ChristophWurst\n- When deleting the current message, the next one is selected immediatelly\n [#1585](https://github.com/owncloud/mail/pull/1585) @ChristophWurst\n\n## Fixed\n- Client error while composing a new message\n [#1609](https://github.com/owncloud/mail/pull/1609) @ChristophWurst\n- Delay app start until page has finished loading\n [#1634](https://github.com/owncloud/mail/pull/1634) @ChristophWurst\n- Auto-redirection of HTML mail links\n [#1603](https://github.com/owncloud/mail/pull/1603) @ChristophWurst\n- Update folder counters when reading/deleting messages\n [#1585](https://github.com/owncloud/mail/pull/1585)"}}}],"screenshots":[],"translations":{"en":{"name":"Mail","summary":"Easy to use email client which connects to your mail server via IMAP and SMTP.","description":"Easy to use email client which connects to your mail server via IMAP and SMTP."}},"isFeatured":false,"authors":[{"name":"Christoph Wurst, Thomas Müller, Jan-Christoph Borchardt, Steffen Lindner & many more …","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIID/zCCAucCAhAVMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYxMDE5MTkzMDM0WhcNMjcwMTI1MTkzMDM0WjAPMQ0wCwYD\nVQQDDARtYWlsMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp++RuliQ\nlBeeiPtP0ecBn00OaU1UCpft/NVI5pnSiT9nU4l2kc5IvKjA8UxDB3gWfYTOeBFh\ntUHQ2P6UKCmHZT9sApHhqLu2n0V+YhlFIViuaxndSID/M414cl56xOYQusV3Pcae\no2dOSeRRzLab3tEaVHlkBSFkGmAwPZItsmTklvV3h1sUysDicYgfXPCkf7K+JgWA\nBP7vsWC8B7MDRhcB3enYv5tTcpsyvtGX7bb1oTIWVypcmKsGYfTX12VNBxKzNBIG\n8pwdb8Xo0o14TytWsWN7mSHf1XbwfwYMjDWOlMqiRc+mcoKMBH41TfM/CXslSivI\nsyvxasEaFdlj8lmKPENdzw1OfYRs43usIf4szwyt4rb8ocXfDipnY3P2hccN6YcZ\nl8y8Vsr69ASluDj2A2Pl5vH6xp6tNybZRnN5G6sghhaYaLNDU/TdMyYzz4AY33Ra\nHSaMypfcXjd76Aj8jZvcwk1BH+ZsvFqNK7ZKCb7WVcMH8KRcU1sxZ4rp9vviM2fL\nL7EVtznm3bSI9jjHXbiwq7RvNRRy+F6YRpAdWGwTU8uUkDabPFi41FikYyzNWauK\nJhlDJXl514XjKyMVBjAZYVr5gZZkO1J7C4XzLFbC5UzYNSzW5Iwx/1j5OeYJRxh6\n5rhiUwR+COT1wdVsl6khMC8MfBR4unSd338CAwEAATANBgkqhkiG9w0BAQsFAAOC\nAQEATBvpqz75PUOFPy7Tsj9bJPaKOlvBSklHH7s43fDDmQbJwswXarZi3gNdKf8D\nyO/ACZvO8ANWAWL/WahkOyQtKOYzffaABGcEIP7636jzBdKtgwSGzW3fMwDghG10\nqBr2dE6ruOEdSpuZxgMgh2EulgknZUXaHAMI2HjjtAMOBScLQVjOgUqiOHmICrXy\nZETmzhx0BXDt5enJYs8R2KMYJNIme1easQRYmWKliXogNY09W7ifT9FHtVW1HX+K\nxRS4JXbapjolkxyGSpP+iYSgItVnYzl6o9KZResR4yDsBv7G/8fpV4GQU9IS3zLD\nPiZOosVHWJdpUKCw9V4P1prGTQ==\n-----END CERTIFICATE-----"},{"id":"audioplayer","categories":["multimedia"],"userDocs":"https://github.com/rello/audioplayer/wiki#user-documentation","adminDocs":"https://github.com/rello/audioplayer/wiki#admin-documentation","developerDocs":"","issueTracker":"https://github.com/rello/audioplayer/issues","website":"https://github.com/rello/audioplayer","created":"2016-09-16T05:44:24.857567Z","lastModified":"2016-11-17T22:34:34.637028Z","releases":[{"version":"1.3.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/Rello/audioplayer/releases/download/1.3.1/audioplayer-1.3.1.tar.gz","created":"2016-11-17T22:34:34.215350Z","licenses":["agpl"],"lastModified":"2016-11-17T22:34:34.867778Z","isNightly":false,"rawPhpVersionSpec":">=5.4","rawPlatformVersionSpec":">=9 <=11","signature":"p6Zz0IEFrxvw6y/3jHgGWWCxR6qpMzvU2HKfxcIVsK6sJnoRUhWLeAXwZ432fH2a S2llj+IGS9OvW+5VQElrXgPtEjDK1BT00DRJnp5RFCRlUv0LNoedJMzx6B6AHqPP JBufk3cG1O/CO0M0L1ITGSmSOzfKvWTRo3lxVGF792NyBaP/SyZCkH1N1TzBQzUi Ywl3+HiglPcXbHjtJm/arnKorbJWVKoaN93xFuaBapd2ozQSpi0fE0uGRsici+U7 HNa1M5WFE1rzUJoufE0E9246At07rFY1e+TdNEq8IlLgCXg5vGCKkEyuWpWno6aX LfRaIiT9x39UTAwNvuDKS0c+n4uWDYPsGfKhDx9N7CXpUrthfXVEWRzZEXG7as10 6ANvrRPJemSZH8FUSrdJhD7k12qa9R825y7mIG68Li8P71V92EOxFfo9tNXqXwBt VuDGxBqByFVPqSCj5I8hrzJzQl2Xt40g8+8ZcSF96RMg/pM+bwRMTv+mz0V+vQQ4 DWjqnWVPalaJ1PPD5/QFFErtXuNRbyxKZ6BMWxfJlLM9Kz66P75K+8fYaSwz+2KG NxY7I3svzS2K9LGH3fBLUy1t3Hl+c3zGFq/ll1MJrf9NswV4yxt2WmISfM/KDww8 yELkGs2cRzbw2tCvnmYlJJhIqRLkyFAbDzWRH/XdVx4=","translations":{"en":{"changelog":"2016-11-17\n- fix: one-click-play for wav not working\n- fix: wrong sql statement for PostgreSQL [#90](https://github.com/rello/audioplayer/issues/90)"}}},{"version":"1.3.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/Rello/audioplayer/releases/download/1.3.0/audioplayer-1.3.0.tar.gz","created":"2016-11-15T18:11:19.539636Z","licenses":["agpl"],"lastModified":"2016-11-15T18:11:19.592881Z","isNightly":false,"rawPhpVersionSpec":">=5.4","rawPlatformVersionSpec":">=9 <=11","signature":"lbp7wd3JhMHW5mC8kVnQFvcwzf3aTIhYhq3ak/C/vfDXJDIPFuQ1odVRWtaHXEKQ XmKYIoTobV1TAU5q9G0O0Kds73T/XtHG4ATLxMZE8RsUWNSj5v3H4YDub6A0uoX6 rzyLEYV6SGEtdPFMwLcUjDExKpzAzKpgxcd9uyz2NhcHJEO8FJmirn34bm69//TO vjjiMW4zpL+dho+7LQbOX+L1SmwmdBqwypE9zzeuIuhUWDEQtImHAvjIO6Temajm lX0H5JaowJa8kvP6Jkh3KAvsHQ4sJklvWTPGcv0gboN+o6CmjWNOb+3LeSH0nhe6 BmiPloUDJcPQwq2gQejH2pY+qJEdRcULSKS09/dRbE3gOSlG36FThN0INpv6uNP4 qVIiYs3/SEHMmlS5CHvJDt2S2XN9LT9IX7QPeuS/0CMcuopaG/+cdC4KscVCq4D4 bllgew9asiBqix8iV8C4oerYOiC5vWcgBrZhGShoJT1Qq+NKz+H10dFgjFCAZuPj nVagJkbXmf2NdcvpSC7qsufhyEZyCSp+I7QEYsbo1PW3aUU35Syt47lgeVFX0hVQ jC1wMIhEW5Rm2nCkRSZkRupKDQ+N6uWuB0lykeMV2ShcDvvUZrhN3c49sooWgigB yIqKryzM4fLErjjNHdYgwCq6bbgPDLK3ic9b3B4rF3E=","translations":{"en":{"changelog":"2016-11-15\n- fix: handling of temporary scanner files [#68](https://github.com/rello/audioplayer/issues/68)\n- fix: simpler analysis of incorrect files in scanner [#57](https://github.com/rello/audioplayer/issues/57)\n- fix: album sorted correctly by artist and album [#80](https://github.com/rello/audioplayer/issues/80)\n- fix: neutral cover for unknown album [#16](https://github.com/rello/audioplayer/issues/16)\n- fix: error message from ID3 editor shown in front-end [#77](https://github.com/rello/audioplayer/issues/77)\n- enhancement: occ support for library scan and reset [#72](https://github.com/rello/audioplayer/issues/72)\n- enhancement: select a dedicated folder for scanning in personal settings [#79](https://github.com/rello/audioplayer/issues/79)\n- enhancement: exclude folders from scanning via .noaudio file [#79](https://github.com/rello/audioplayer/issues/79)\n- enhancement: significantly reduce database reads during scanning [#79](https://github.com/rello/audioplayer/issues/79)\n- enhancement: cleanup of classes; move from \\OC\\Files\\View to \\OCP\\Files\\IRootFolder [#72](https://github.com/rello/audioplayer/issues/72)"}}},{"version":"1.2.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/Rello/audioplayer/releases/download/1.2.2/audioplayer-1.2.2.tar.gz","created":"2016-10-06T21:21:05.414691Z","licenses":["agpl"],"lastModified":"2016-10-06T21:21:05.483224Z","isNightly":false,"rawPhpVersionSpec":">=5.4","rawPlatformVersionSpec":">=9 <=11","signature":"toeS45z50Lm0djgrQokOTN7gA8a113IZtiKKiLsGUKWrCV/6AKJBmEFcSun6rhLH\nbz/RtIdFKwQql6O3E0m1Zch2y1A8aLWHzFTO+5orLCVi7y15SshrJYbb9aI5Pj3i\nSR7+kMHGS8uNx2uIn3B4mO6UYF8AzCfp+ule18DOjnpu86KWvEOGtFXsQkLtgepp\nbJhOGWW/uOVIos/T1xPP4GCmtVmgn7U3b9q0pMYRH7ONXEiNsfQxDrR66EZH3Jfo\nlVyM9UvQmMKoDSdBUlvLlhCEGJGqFOD7hFntLYloI4oXv9uGqcagaJVh3TkEysY2\nMbBZpVhch5zRJ/HGlZOvmEzZ8Inxkk3iap+JmJ5/gZTefwfKUyYHALsILlh820U2\nNA/1B5A015XH5a5uflGE/tnlPtrOeecIN4mg+1njo2RG89HJWJNHM2ZDO4SkXjSR\njgygmAS5aR5+KKifiA/pwjhLozDWPU4lNzsj3Foz3bx3Okopy7eq83LORqieT4Jp\nFvP64q/45LOSRBWIWLitYzRzZp7HYywMsnz12WpxtqxIjO7+7y/ByeWWOBNU1IJC\nK2D+035ZGWZr0CxDJte33WOISwjVoSwrcov++O3BQW8lM5IkcDNcJFyzNPKAXcQU\nPUXmQpYurHoIw6odAYcbrG6iOiSesuNOf2kQWbjV3/c=","translations":{"en":{"changelog":"2016-09-18\n- fix: icon issues with alternative apps folder [#65](https://github.com/rello/audioplayer/issues/65)"}}}],"screenshots":[{"url":"https://github.com/rello/screenshots/raw/master/audioplayer_main.png"},{"url":"https://github.com/rello/screenshots/raw/master/audioplayer_lists.png"},{"url":"https://github.com/rello/screenshots/raw/master/audioplayer_share.png"}],"translations":{"en":{"name":"Audio Player","summary":"Audio Player for ownCloud and Nextcloud","description":"Audio Player for MP3, MP4, Ogg, and Wave with a lot of flexibility for all your needs."}},"isFeatured":false,"authors":[{"name":"Marcel Scherello","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEBjCCAu4CAhAIMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwOTE1MjExMjA4WhcNMjYxMjIyMjExMjA4WjAWMRQwEgYD\r\nVQQDDAthdWRpb3BsYXllcjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\r\nALyC+iLscLs62NeNmUXEBmg+xMuUtDmZKr+xzJWtl6SSNRz+8K1JygvUIXFJ3RIL\r\nCYA3xyq8/wyZH1gNrLKyz5eTeYawG+eT3ges/FT6MWGUbZoRrBrikVcLC94QzxTH\r\nxOl8Dn+SCV/2bhcvPTQdhK+dqtvGilOtjHa40iMrk9gSdlKVys5CK/xdlEp8uiMa\r\nkz1WENn8MVCCJV58bAUbaCupDWXR9CCoSsw8XinNsCenZ2B2XlnmbM44280w0ojs\r\n72rfQRgj3yDG+ZUUyUOuxIuodu8liXYciLf0ph6t/f/qoSmctbBdsR5Fl1Upj1Ac\r\nqeHb5Yf/B3Vi6Mn3XfDx0H2EHk1v9Dhzxay+v9BHUzyIX2iH/q+7TE0/Jzo5AwBW\r\nvFKWXvG7wXaALcHYZf5v/M93IE0iCHsv2EsZKQPBnzXVGmp4DwFSP4po1B7hcog1\r\ngAMaellAzzvUAizgCovN6Qct3qDEANYniPlvtnlcaQGonajW4N019kFQRHLIzPFR\r\njab5iUMMwSnT8FhZO2ZOWuWhJven+gXjxC8mfMVgBfZnAVgydNfx9rN+KzTc88ke\r\nobUdZ0OOeBzA7pIxGEFg9V6KTEEWZ+qH048vxXz4HI9B1I+2wQLBrZl8CvweEZ5U\r\n5ID8XrrE/UaNZ1CvLKtCgB24gj/m1Elkh7wA3gEcEo2JAgMBAAEwDQYJKoZIhvcN\r\nAQELBQADggEBACtgUp+FCmjWIkQUuWSdzKWdO+IH4v9wBIrF9mo0OLIakFyDYyM5\r\nLlkYZXbplGXd4cfn3ruIqJNzlIb4xa5CU0bM4TMbD4oOSlLMKM/EamKPHI3bzr++\r\nzi7mQDFxmAE6FWSMBgKKUb4tqLc5oBap8e12tPEZl/UR6d9iUB2ltvrm3T3vrjjl\r\n2Worm0eYBNqnagXmX5+wS11AQqeJemGqRy5e1yXRlTgB0IJhH0dCsFNwifEigutp\r\nFNvGFVBn4r5qCiChEoq+rCXHRjPi/eCfbW21XeLFDiLxapcZyc85JIcA7znUYoFe\r\nP7Y/ekMscwWhLbF91OaQlcWpRtEMyde/DaI=\r\n-----END CERTIFICATE-----"},{"id":"calendar","categories":["organization"],"userDocs":"https://docs.nextcloud.com/server/10/user_manual/pim/calendar.html","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/nextcloud/calendar/issues","website":"https://github.com/nextcloud/calendar/","created":"2016-10-01T12:40:39.060903Z","lastModified":"2016-11-22T20:31:13.029921Z","releases":[{"version":"1.4.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/calendar/releases/download/v1.4.1/calendar.tar.gz","created":"2016-11-22T20:31:13.020268Z","licenses":["agpl"],"lastModified":"2016-11-22T20:31:13.087340Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"nThwe9CJBCan9nuDLdhfBiQyPhmum6Aa0UcYsIDdhGMw+C2acf81KhEmBJuTTWxo\nWGby6WcrcJJmeuCW+ePU91ju7Pd76RirprhVXIEceIDzSCxin+K0oZCZ1IGVIJjP\nIkVehTsLuCeTBbjvz1b3k5QFyhUhvd32Xt7k5d7VARyI4OqnqYYNBtH9vvgeRrFw\nAxsQr4o4axof6i3iykLg6WfWarYArY4dIuu5DkPuGPWf2bbgjwWEra4sQejhOs7G\nsk1xcsfYv2NpArIbpw/wnATdjiax+Gjz1URMD3NgL5ky0ecuZmNvN25QErg3nlVr\nhh1FBfA5pvCJbkJ6nr5bU4bKaffwDX1nr5h77FS5zzn0Pyd7ZIExmVmNtaeJfnfV\n5vnclapzXMNU+R6t/ATJQd1srvSJhyljQapzsqnrjNMEUojOEvqqygJp0KwNVPqs\n3g9XGSoOnO+WULWBeISW7UVOg8BOF8pwvHIU2++bSzOdpypW0Eq6p2DPWO6qL/H1\neFLKrUg3EvnTjvknbBxMB55h9jNJr0SAlkrmyEVm6+CE3BwRWpKB+cJMBuGiwPwv\nr/ASRiJrkDThbNWAUtX70rUmCqDV6/MujLXViqOc/Q2OHvcXd1oGDccJSQT92/1z\n7nonnedyYQIDqUt7u68WL8JRxp7pFsEqKLVuWSgxW3c=","translations":{}},{"version":"1.4.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/calendar/releases/download/v1.4.0/calendar.tar.gz","created":"2016-10-06T19:58:12.724588Z","licenses":["agpl"],"lastModified":"2016-10-06T19:58:12.790604Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"b//hJbICFMLR0Va1BGMzpLpaPREOo9QhjgfrHvDOfXVpddhvCM8ocz74X1s5hKyy\nGg67EE0pOp0dBf6RyJjduI+Dz1wQX55My7J9G1vXGCN30C/8zAcKSJoA218IWcub\nICavLkz2PkiitIOSZyBCAfEiSAeHPop/JGkq3KxQDC7QwFC78BnE9/adD9tO55c/\nDGLhvP/uTJIeH8RUifikTqVMmPH+aP3uPbZzl+AxhUezRiNCpEtZPA5QGqtQdJU4\nFc6x3d9y4IWbJV4TEIAP8jdfqtLVUQ6szFVnN8Oi1wtN9e8LIylBSYbmIZRj0+qh\nZcgntzEq6U843ZwXcAnL5jNYV0m+KNI+EkXFeWHkjvbwfCdvGPBvgFVbhc0YPzXU\nqHOe4Lvcx9X20ALG/MacV9zX69GzNnWgbBp9RnIHuaSRPFEKrNXUeXl2THuKsTyQ\nF9QtTwS5U5DcMyTO2RAN45NrRxIh8IL4stoIg5rmF7/ZaOm/Jza2gnUquOTarDE/\ntiWnNW5kWUAWyYYHvQgQix/of9qXvc2hhZaw0y623WDNrEwA+rngnjDMLA/vNv3B\nhgwQ6NbCOuHWsRK3S8DcJFpB9Kj/i7CDvDLEuJYnjSTvQ/q1XqawbJPDoRlydX43\n3/L0LvHvKVakYybv2OE5gy6bQ2Dw8e7D27DtZ6XTaBY=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/1.png"},{"url":"https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/2.png"},{"url":"https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/3.png"},{"url":"https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/4.png"}],"translations":{"en":{"name":"Calendar","summary":"Calendar GUI for Nextcloud's CalDAV server","description":"The Nextcloud calendar app is a user interface for Nextcloud's CalDAV server.\n\nIt integrates with other apps, allows you to manage calendars and events, display external calendars and invite attendees to your events"}},"isFeatured":true,"authors":[{"name":"Georg Ehrke","mail":"","homepage":"https://georg.coffee"},{"name":"Raghu Nayyar","mail":"","homepage":"http://raghunayyar.com"},{"name":"Thomas Citharel","mail":"","homepage":"https://tcit.fr"}],"ratingRecent":0.944444444444444,"ratingOverall":0.944444444444444,"ratingNumRecent":9,"ratingNumOverall":9,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEAzCCAusCAhARMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYxMDAzMTMyNjQwWhcNMjcwMTA5MTMyNjQwWjATMREwDwYD\r\nVQQDEwhjYWxlbmRhcjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMm6\r\nFTeqgzCXprkU83VM4/DrZWn3kqtfaR/edkC4gYT3ug7RHa/Uv1C/S++vr7pvgpnk\r\nYzQoavl/0Qlh5sKEYX+0ud/LQDoiidwBRDckFUQ1bRfVLxAD9UAVvDRHxDqJMOx2\r\ngZArbeQ3ztdSHZp4ThzBFWq2FILsJD86weG7LwHjzhW6SWgLb/YTLbuuW6tRCDVV\r\nbtB0I/a0vCwj2u91Chw3u6pWWjPakc9DQrIDH4HCIBKQ4zVrYDxAmJDRFGDvVVWx\r\nuIAeux8sd8drqSMqAhX+XMcZPRD71NQTWbCupSwWO8kgjmZnBpIiBNpzvMQzJf3A\r\nQloZtjZ2RDXAQG88eTeT8pp8yEOCEoDLpGdraKxJrh/z2Dsk30JP3lOiNYJ9vBaB\r\nC8NJbJ3oAlG7THwUaFF9fsdAKoTwzs5Xms04TI7W/v4Z/GClOzMymnR1T4sR72Oy\r\n3WaMNHv/1QGffvQn2/TtZt23Ou3P083xWx2vn5FgTcac8+x85vRgWsVCA4hq9v6m\r\nAlktB0+UWDEXpDTKD9BdFNWM8Ig9jQf7EJrvTLNnS7FIJZMB4GK8lpvPxyvACWnh\r\nR2hQOe987Zvl3B1JZNO5RvtSeYld9Y9UfMgW1aPRweDNjSuZYAKlugx1ZoyI5HyA\r\nQjfzAwicIMwZsCJDV/P5ZO8FE+23rdWaoJczpBqDAgMBAAEwDQYJKoZIhvcNAQEL\r\nBQADggEBAHQXwvj8q5khWR/ilg3JGYpmMNBYHE9OeDaOcNArkKaGMd478SDPOXeu\r\nyW7hCvNEpiTk5g0h3g3yleZFws0xH8fPsQgZANgvQXb3RCcD61NL77d0cMTr7Xzr\r\nN3Lq/ML1YLc/WwL4uV1XvpMQMwALFL1p63BU2c0ysO31zbLOjMKAJi0hHFDYz5ZQ\r\nD3xxtc17ll3B5IqrMnMHRqmOQ39Sbe56Y7T4agaIz/sUWpseo85D5kt7UAIOR+Mr\r\nQ0Bl/QinETk72afGR46Qvc7tC1t9JjQQD3AUbEGuJdGvXjJJ9GREYu01XoODmPdT\r\njXXOI8XIOK6kxXhPHUc3iWu9b4KqGm0=\r\n-----END CERTIFICATE-----"},{"id":"gpxpod","categories":["multimedia","tools"],"userDocs":"https://gitlab.com/eneiluj/gpxpod-oc/wikis/userdoc","adminDocs":"https://gitlab.com/eneiluj/gpxpod-oc/wikis/admindoc","developerDocs":"https://gitlab.com/eneiluj/gpxpod-oc/wikis/devdoc","issueTracker":"https://gitlab.com/eneiluj/gpxpod-oc/issues","website":"https://gitlab.com/eneiluj/gpxpod-oc","created":"2016-10-31T10:57:44.387319Z","lastModified":"2016-11-23T17:27:37.793159Z","releases":[{"version":"1.0.8","phpExtensions":[],"databases":[{"id":"pgsql","versionSpec":">=9.4.0","rawVersionSpec":">=9.4"},{"id":"sqlite","versionSpec":"*","rawVersionSpec":"*"},{"id":"mysql","versionSpec":">=5.5.0","rawVersionSpec":">=5.5"}],"shellCommands":[],"phpVersionSpec":">=5.6.0","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://gitlab.com/eneiluj/gpxpod-oc/uploads/963bbf246412bcbe8979bccadb3b8d03/gpxpod-1.0.8.tar.gz","created":"2016-11-23T17:27:37.783365Z","licenses":["agpl"],"lastModified":"2016-11-23T17:27:37.862469Z","isNightly":false,"rawPhpVersionSpec":">=5.6","rawPlatformVersionSpec":">=9.0","signature":"hqhMh1l/mnwbYf4uPzEjjLFtZWHidzgR57X471OuXv2K/s87T5WhIkTSKk+2r8sp\nS7CtrF5+Pc5AgCCHvwzawN3e2+4eO4cK0+HD9CCzygzzHZEbSjufNHMMQucVoSD8\nPqR6MV9azzUpwHa/5d8fp3cFLVAle+aG0o4v5eHky9c7eaKxVJcgfjw3pjDE73N6\ngJVdtw1jf1kOFYk5pZQxDfBKFDrO5BRo5ZfZGuOuP2u/SmTwj42oTZiT7oTVWhqd\nLvJw+2TPv7B8s0Gin+J5e9K1Rs6CEWQ6WBxM+NhS5KgWB5Ig3pwm0QvMgza2cvoh\nlwVobOotfKLUBJzg0+wR7B2YH9Ao+m94h93vg7H0OKPReoTKhlDj2UExoTyeurV8\nhJdQv8sKVAxjC7/xrVaGSjM4YxFdBpzq8Zl8z4zq1o2voH5+u4ko3c62C1loDpsC\n8KrL1t6A7QpMk/XAMrPqwEPmFqlLEdv6FhzpOGyt4IEVnv6vdMTShcYw3tPvU/mD\njPtiVwpo8gWbGVIfpmwBg4wPaTrWK8V3+/1iTahIQHZfu4Lebb5mzht80HLQIcd8\n+oB4cGDEX4Rix1WxnCmE5ZzURY8xQXcvqYN+mTrUDh/3OtxQPSm5yC945SGoFNpr\nBYxfEyQcwulZrOMBdY0Ssj1AB5NOeC9OHwjJrnVe7dQ=","translations":{"en":{"changelog":"### Added\n- save/restore options for logged user\n- option to choose picture style (popup/small/big marker)\n [#25](https://gitlab.com/eneiluj/gpxpod-oc/issues/25) @eneiluj\n- add average speed and average moving speed in comparison table\n\n### Changed\n\n### Fixed\n- bug when python PIL is not available\n- deletion of bad parameter given to getGeoPicsFromFolder() in controller\n [#20](https://gitlab.com/eneiluj/gpxpod-oc/issues/20) @eneiluj\n- bug in file cleaning, bad use of array\\_unique\n [#22](https://gitlab.com/eneiluj/gpxpod-oc/issues/22) @eneiluj\n- python script do not need to be exectuable now\n [#23](https://gitlab.com/eneiluj/gpxpod-oc/issues/23) @eneiluj\n- jquery.colorbox was brought by \"First run wizard\" app, now included\n [#21](https://gitlab.com/eneiluj/gpxpod-oc/issues/21) @eneiluj\n- avoid JS error when failed to get options values by ajax"}}},{"version":"1.0.8","phpExtensions":[],"databases":[{"id":"pgsql","versionSpec":">=9.4.0","rawVersionSpec":">=9.4"},{"id":"sqlite","versionSpec":"*","rawVersionSpec":"*"},{"id":"mysql","versionSpec":">=5.5.0","rawVersionSpec":">=5.5"}],"shellCommands":[],"phpVersionSpec":">=5.6.0","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://pluton.cassio.pe/~julien/gpxpod-nightly.tar.gz","created":"2016-11-16T14:06:33.937534Z","licenses":["agpl"],"lastModified":"2016-11-16T14:06:33.971502Z","isNightly":true,"rawPhpVersionSpec":">=5.6","rawPlatformVersionSpec":">=9.0","signature":"JtUhKRDFGYDx9xtHjdfEUFOb0O4idexUYw6ixlBhKPP8Dn7NfyBfV6KH6MJTIVLU\nQ5Jw6tv/Nr1YDOvVikcWPG0p23mQdn1+7w8DzzIGKmknxCat9/vKr83oJZdWYxS7\nTJ4I7qTvWNlbMfK8OEdl13VJXgc6ftX+1isluLYqLjEm3aBFCS+/awYNMmXO55a1\nyG0NgJRu3pw1CBCMhDaRLsunhpRNDVLsamZj1SPmeT8qy0I/arFaG6hQnAo6JosE\ndi1XkvK6TEt9g16L6eizd+JpGE7xiWFP9ZEmMmmQSOLQYwU5Sk1YWcrW3EX4vtz5\nWnEIC0SENyyAyzBO6YJfu/EP2lLnlbNJiuc4zzKLqRw/zyz3j+imJLcXHIA78ZkQ\nuyUOBkkk3xeyBGeUcYfDuBqYQOQs+F/7+cNMsIBKJhx9ef3OPURBc7X16upk3mxV\n6GsOktbHkgUwWk3WiXRriBIqbAZocvDp0+PN++PAEZVWFEZEJzztd4Fxaeo+QSN5\n5Pz/9yXYRsoSPZv82Tlh7dx5tIPUvYb+UsANh5eGWUGufTSwgYBN0H2KT/iO35D7\nkDzNyh1qNakfBhAgPjrC2p4mBKBJJjlM0D9erDwr5D4GSTW2fp92vlRHeD0X8sqo\n3kBbwGuWnmhdJhbd7zYy0jVM6tVX/zgbhycimNALG0I=","translations":{"en":{"changelog":"### Added\n- save/restore options for logged user\n- option to choose picture style (popup/small/big marker)\n [#25](https://gitlab.com/eneiluj/gpxpod-oc/issues/25) @eneiluj\n\n### Changed\n\n### Fixed\n- bug when python PIL is not available\n- deletion of bad parameter given to getGeoPicsFromFolder() in controller\n [#20](https://gitlab.com/eneiluj/gpxpod-oc/issues/20) @eneiluj\n- bug in file cleaning, bad use of array\\_unique\n [#22](https://gitlab.com/eneiluj/gpxpod-oc/issues/22) @eneiluj\n- python script do not need to be exectuable now\n [#23](https://gitlab.com/eneiluj/gpxpod-oc/issues/23) @eneiluj\n- jquery.colorbox was brought by \"First run wizard\" app, now included\n [#21](https://gitlab.com/eneiluj/gpxpod-oc/issues/21) @eneiluj"}}},{"version":"1.0.7","phpExtensions":[],"databases":[{"id":"pgsql","versionSpec":">=9.4.0","rawVersionSpec":">=9.4"},{"id":"sqlite","versionSpec":"*","rawVersionSpec":"*"},{"id":"mysql","versionSpec":">=5.5.0","rawVersionSpec":">=5.5"}],"shellCommands":[],"phpVersionSpec":">=5.6.0","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://pluton.cassio.pe/~julien/gpxpod-1.0.7.tar.gz","created":"2016-11-14T00:57:37.521001Z","licenses":["agpl"],"lastModified":"2016-11-14T20:35:45.363487Z","isNightly":false,"rawPhpVersionSpec":">=5.6","rawPlatformVersionSpec":">=9.0","signature":"SigBof6QJZ9IMZyFgc+B3LO2+EXaAPvnxUHjJQjIl3jLzomocpDGR6WjO6gtvB81\nzXUHjJ8+huc+P9TvgjUGRTmn9a/29HZ4IKTXnYBKIUY7wSLcJNMbJSp2Zd3OFHAG\nJwRaEdh/cIRk2X6NE1VT6dFCxB+LhTM4BXOEwuNYQvU1lZDVQgTz/r68zFLWBt6R\nqhBCNJHrVp87ecS4+XaGq/CfT4k1ihiOv+f4eX9iaPzUhxBJ71iYKF7wHpDoVmIk\nNrzWFUJH3BLBuW9oiC0PApli6Xu5RXrWUsOV7OAmxXgylRCPuTFwe09hw16JMbiS\nii8WFiUtp4qW53+7eoS7Fllm7CRi/Dg6Jvjtp3msrf1m+OiYM7dLyoKw22/S4P/a\nBIErZpSCHaCfrZ+DBXrAYcas27GWE7HizzG3yXk3aDJMa0Otcsq56bSPo01JDfNx\nm1y9iuwmlon8zKKoxsJCwxaFDnQpqazaLcUO0ATHUk8LdomTA7MCXVvNFPaO86Ea\n16iyw7Cfs0k3GrvN71+SdpvWss359CEEwBMpDwJZqwSFbLRyHtogUgbRWLIJqR4n\n5uVvJqirxWkr/EtXw6UkDWAI3ZoMhMRtjn4H4ekANP5mC8R0yp+UuFs2RkEC5uA0\nKzzh73WmxmpeUl6jcMZ49gXn3PTCC2fJNrdmSYch5Dc=","translations":{"en":{"changelog":"### Added\n- option to choose waypoint style\n- show elevation, lat, lng in waypoint popup\n- ability to display geotagged jpg pictures on the map\n- pictures slideshow with colorbox\n- pictures work in public dir link\n- use NC/OC thumbnails to display pictures on the map\n- options block hidden by default\n\n### Fixed\n- fix bug in geojson generation for waypoint-only files"}}},{"version":"1.0.6","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.6.0","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://pluton.cassio.pe/~julien/gpxpod-1.0.6.tar.gz","created":"2016-11-07T12:11:00.619161Z","licenses":["agpl"],"lastModified":"2016-11-07T12:11:00.699921Z","isNightly":false,"rawPhpVersionSpec":">=5.6","rawPlatformVersionSpec":">=9.0","signature":"WBts2fm2rW/7LMHYjcx9a0k0WTXV6PnGRxTl+158cjfV7ruMpNvhK58iTjrox69k\nFWAoIi1wNAlLBu9Xet1j7HKi4TC9q61IEN+lPlnwBCu0uHawiqS2gqB4i8A019Ei\noLsgAPWh8ndy6+gyUtPhVLVduLH76aT6KTwAiHPknV0zPtxsUy1P6nbbNOS5A5rG\nSQBqljy0TbcjOctTudEPp1IqjJIwcd12eZ9MLG4CEIO13n53pMAsuXJf4jnKSCm0\ngimvsFOwFRjBab3ZPwtOqeVw6aIh/lYF3U3/k8YBpaDN74m30nDtkp8teXBgshSY\nVYvX3yOAYe0PIR419IX0eoHb61K0VfZYvPT4FsOqjDr0zlVB8Rjq+6SiK4vMD2+6\neGE0aHbjR9HV5jymUnFYdm/hlhcZGaKrAiQKfBY6Vh0SWKfIv7bdGfQYauePAdZt\njlsV8lIwOy7FGAeP81CcjzWWfDeBgYr+MSzfoDNoTi41MvUaT14iWPIU/s5P1/Qv\nALGxgsbmB19wEgNbdh1UtTUY3xARLpWPYdUqU7yDcsddX9vCoCG2G5wCcbYJRj8o\nC+H7wdgPJoiMY/p4Go/lyWkvmzhfXrOeXytZIFXjb3ERVd1vD9WSt1DSy/7gsFYt\nxzzOPgqMvL3BbeluNuzNv366oT872s3OuFKa1ZOYY7A=","translations":{}},{"version":"1.0.5","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.6.0","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://pluton.cassio.pe/~julien/gpxpod-1.0.5.tar.gz","created":"2016-10-31T11:08:41.017766Z","licenses":["agpl"],"lastModified":"2016-10-31T11:08:41.068782Z","isNightly":false,"rawPhpVersionSpec":">=5.6","rawPlatformVersionSpec":">=9.0","signature":"UXeZVh5f0/WZE+r/dHWc1pu9q4qr/zACX6XraMhhIuKIp7vNCwUESeqJtVc99QZw\nw9kJp0isvib6l0zbQBRS1vI7xwKKBQyeaEhIciEs1JjsaCiato1Gyi26N+fY2N0Z\nFWlTwCsF3DdlwERXTYfeCpsOWCoxLxHKhnJIjUc0PVme/Ste4zxYj+5Su1RpadSw\n4vGnkW8zy/0tzua50NQCrOg+B4jXzH9kMWAP47w3sdP5CYalHSHl8EX0D1RjgGU5\n7vZYX3wF853FvQDbL4JXXCJupj3wZe8py8McWpQIcgz1p3KmE7A7d/rdNWExT+T+\nDxtStJ56qTRMz4aFwoSFxJrrEfgHIsE9Gv+Vo7nshCUYA8gkfHeckiaUtH1EiFTh\nVNeO6mTIqGpRosFvfUrZMKcuF5j74vGQjNM1o+M5N31gtLoPSkU605f/U4v+j2oC\n3/N1rYF2SEDFO0EgAGXaXVhB0ltSDkHJw6vZJ1L8Qz6tooUMDxaMri8vycA6LHvE\nqN+z+S6TXMfLvN/6ATYPGhicrWmkMT/k7v1az/hcnfH+zRyLZyFx94s88JWF7Jf+\nI+tgDbfqTMAIcytJUC+KfdQW1ueXh5F0owrOYM6jgBRvhqj1T8s+Twgw8orGmRPe\n9h8G9Z3wZAooQvmC0KdVhLuOeIkqt/S5krELNFFBRnk=","translations":{}}],"screenshots":[{"url":"https://gitlab.com/eneiluj/gpxpod-oc/uploads/db5af6ba7ae1cd4d22ea81d418f5c762/screen1.jpg"},{"url":"https://gitlab.com/eneiluj/gpxpod-oc/uploads/123588561a8067185572a8d1887ef906/screen2.jpg"},{"url":"https://gitlab.com/eneiluj/gpxpod-oc/uploads/427688b80bf8428dd45bd15d69b19075/screen3.jpg"}],"translations":{"en":{"name":"GpxPod","summary":"Display, analyse, compare and share gpx tracks","description":"\n# GpxPod owncloud/nextcloud application\n\nIf you want to help to translate this app in your language, take the english=>french files in \"l10n\" directory as examples.\n\nThis app's purpose is to display gpx, kml and tcx files collections,\nview elevation profiles and tracks stats, filter tracks,\n color tracks by speed, slope, elevation and compare divergent parts of similar tracks.\n\nIt's compatible with SQLite, MySQL and PostgreSQL databases.\n\nIt works with gpx/kml/tcx files anywhere in your files, files shared with you, files in folders shared with you.\nkml and tcx files will be displayed only if GpsBabel is found on the server system.\nElevations can be corrected for entire folders or specific track if SRTM.py (gpxelevations) is found.\nPersonal map tile servers can be added.\nIt works with encrypted data folder (server side encryption).\nA public link pointing to a specific track/folder can be shared if the corresponding gpx file/folder is already shared by public link.\n!!! GpxPod now uses the owncloud database to store meta-information. If you want to get rid of the .geojson, .geojson.colored and .markers produced by previous gpxpod versions, there are two buttons at the bottom of the \"Settings\" tab in user interface. !!!\nGeolocated pictures can be displayed if python PIL is installed on the server.\n\nGpxPod proudly uses Leaflet with lots of plugins to display the map.\n\nThis app is tested under Owncloud/Nextcloud 9.0/10 with Firefox and Chromium.\nThis app is under development.\n\nLink to Owncloud application website : https://apps.owncloud.com/content/show.php/GpxPod?content=174248\n\n## Install\n\nNo special installation instruction except :\n!! Server needs python2.x or 3.x \"gpxpy\" and \"geojson\" module to work !!\nThey may be installed with pip.\n\nFor example, on Debian-like systems :\n\n```\nsudo apt-get install python-pip\nsudo pip install gpxpy geojson\n```\nor on Redhat-like systems :\n```\nsudo yum install python-pip\nsudo pip install gpxpy geojson\n```\n\nThen put gpxpod directory in the Owncloud/Nextcloud apps to install.\nThere are several ways to do that.\n\n### Clone the git repository\n\n```\ncd /path/to/owncloud/apps\ngit clone https://gitlab.com/eneiluj/gpxpod-oc.git gpxpod\n```\n\n### Download from apps.owncloud.org\n\nExtract gpxpod archive you just downloaded from apps.owncloud.org :\n```\ncd /path/to/owncloud/apps\ntar xvf 174733-gpxpod-1.0.0.tar.gz\n```\n\n### Post install precautions\n\nJust in case, make python scripts executables :\n```\ncd /path/to/owncloud/apps\nchmod +x gpxpod/*.py\n```\n\n## Known issues\n\n* bad management of file names including simple or double quotes\n* _WARNING_, kml conversion will NOT work with recent kml files using the proprietary \"gx:track\" extension tag.\n\nAny feedback will be appreciated.\n\n "}},"isFeatured":false,"authors":[{"name":"Julien Veyssier","mail":"","homepage":""},{"name":"Fritz Kleinschroth","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIIEATCCAukCAhAaMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYxMDMxMTA1MTI2WhcNMjcwMjA2MTA1MTI2WjARMQ8wDQYD\nVQQDDAZncHhwb2QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCq9p5l\nzNzR98l/xPgrplWrGQBhF6aQSLpnIyCdLAYKk+CmXn47W1pHh5CRYyCCyB8YPBBG\nTwbpP69pP1updfK2vUt+ShYmCXLxOLB3qEdhnwgqFfwpC48Ocev9d6XcacYp7jwu\nRNtv0ocMkm5o0TWWupcutQWkmqzCVq+OkrqM0xrf3mfPymuM6edEREshukoL86Ei\ngTuMMGT0XO99LikszvdceNQYEATix1MHzSVhkE7jHCNBXb95H6nQGr0v7R1MIbrI\nGFlgqxwwNNKwBFNfPMWZVnKwz9hoIwW6WOuu7ntwVcPqwB/gUsRZJTu7EjIW0trX\nnhA6xLlc4X66W1sdUCkJOxsV+Y21akz6wynI0SzIfjALLI2Ls4QWrPM8GOX8nPVM\nm+Y5WXzqLJScdWYoefFJKS7kxwUJRewREB9ykCG5OdDubV+Iu/6jh6HWx3h4p3ih\nqkDypPWoxpfLgA8VZkLD1RRKGkRa858QBGdF/RHbYT3JfLEp9l9gJVKZE/yw7HKk\nwsZ/T6CMpLyorpd1XWtp2wLX8lr3pp9ecVDOdAMSqD2thDMDsZA82JrJ/vITwkCF\nBlqtDZmT0UnpxYNYTfYBam5Cd00jsqCt+Hr+QkODNe8Yae9c/D0zE3h2Vt7g9H+W\n7Ei+rF5nDYTBAApoETxK7+aUZpycBf3THAJOcwIDAQABMA0GCSqGSIb3DQEBCwUA\nA4IBAQBbCGAEwg3M5QJDMnZgu0zNOH2f9bamAS9ksyCZqzLoeQic1W7GYYe9NqAi\n7lO5jXRZpTN4L133IUQPtxCxuDooD2vFmCne92tLxJbc7uqlSVfhL8uMVOlnrA99\nKTAhySTZU5so8/OibrngnBmcdWwbhaWoCQ671M8aXM1wg2FVYDqB2GP3RvbpW11L\nOc+4tfh4mO4TwXygf7KYMOJyJW8mNNY7PZ+XW2Qe3vSXR3DuN8H8fgMh5wppXPJf\nE0+yNs42hwFjSojtI8BCb0s5DTleaakpDo8HQGNzEXP8tBlUYudtjzdP0jxFXbFa\nsT9pcMdeJ0/t5HqJSx1EjUCLYS4y\n-----END CERTIFICATE-----"},{"id":"ownpad","categories":["tools"],"userDocs":"https://github.com/otetard/ownpad/blob/master/README.md#mimetype-detection","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/otetard/ownpad/issues","website":"","created":"2016-09-29T15:58:52.814912Z","lastModified":"2016-11-19T17:37:52.278497Z","releases":[{"version":"0.5.6","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/otetard/ownpad/releases/download/v0.5.6/ownpad.tar.gz","created":"2016-11-19T17:37:52.234684Z","licenses":["agpl"],"lastModified":"2016-11-19T17:37:52.423930Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"dh+Txg1iVfqXr8+cxplNQuBZGErSnXUo0ewGwnybNMJqp8/EjEo72+zPpW3dVnhY\n67YCvhrm2bo+VRdFFymEfymzSJu9nWVFkGJhEwvTxPyIdAtuD5YAVrzmnR6L+H7m\n7Q1nXE63ICPCAQpHkxIfIXLh25OhWeyofBB8AVsjDUNn58FEYJ8fFkr6dCgPriZS\nsM2J+xtZMDYufy+xFMsVf/Q3WopjFuBjMC3qOecW76ZTwtREaswOC2RtpzUku2r1\nsogrfFlFer3Ii9/CWgOktnLfjB1DzbTwdEkM2xNVBRJgdMXt2VLA9FsxFFkjmr5A\nl7x9cNLWA8RLpOIpIMBbaef75u5HgRBvSvq114UsA9GCu/EYbIgD8YxEt7xuKd4t\nenksJB5gJ2IQNdHrPbsil59AsJ/dismDN6ktYgWQEk5dINzvm9EAvucueW0Gt+Jr\nqEC5WBgJucsFxSvkHh52v43M8jgPYBfHWEL/M/+377z3+mbuIh+BcQ+vcDdiqxTF\no3n0+gw3QYIhLEe75sUhxG6ynVUdW25AKKju1kVj3KJnZTBH1R8t8/zy4DnJG8d4\nuRGqyU4BXpZjEC3nVlsC7vCncWWhxl0WZQ/MWKqsfjVAU4I88E518D6NioqMnPEJ\niCZ2x+69UCDEQyfCSKajgAYT17r3OhZei8F9KSCH8Vw=","translations":{}},{"version":"0.5.5","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <11.0.0","minIntSize":32,"download":"https://github.com/otetard/ownpad/releases/download/v0.5.5/ownpad.tar.gz","created":"2016-10-06T07:51:05.278637Z","licenses":["agpl"],"lastModified":"2016-10-06T07:51:05.348825Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=10","signature":"nYsQ9U5r7uXwtcquaWGm2XMJBNYCcA95aUx9gLZ/wEmjCHqId7+MzcCdBnom33+j\nat2XR2a4R96UAUP78bfSC4Yb7nPepFT51Y8CSpV3mDT85/+SgJdq500fXldq+qGY\nffXLneadAztyOfZO9TXljaCLdREYI0LJIGVENsxBQVKM/eyGIuZO7fF70cH5vbfS\ns37+BXB+fxcDTlP2Xuulra8HsNoS81bzjsdVMLM7B7QwwO6rZ1zd5c3UzQ1LmY5g\npQUBNd0KjfHfZ6+Fd64XZO6NGfgucGNmL3lgxdsfUqKiLtikvFxK39dYW5MckV8p\nvLoS2nZ7cgETQmAW9Ahn3ro7gXWcPxzL41oWtZOOHRRC2Yz5zlZ3Bky1o+bF9g5a\nYdDF13zV6utUkhlplZhWbjKaXa04rzOvmut8Iqhx/tmDtZRYtaQXJZWutVJYtPC3\nH86uJJnUHHNFHeoT560mp1Hq0dTeR+G+yWsPacPD1rTYgZOUVEtj3Y+YdbTODR2o\nOdGzeYFl+6CL/OcY4wPGRUCTFwvc31lIUd4DK5SPfN+IGtuuXhAqVhwy6lpkcKRs\ncj8sBoVXbMvEtMnt5uARBvA4tyVffUL4oyoIsUnvXz4u+q4WVt3T17swLm6HjGVC\nNVqU0srHN7EeBRhHlXP1CrKQWGQlS4k9j9Li4Iw+X8s=","translations":{}}],"screenshots":[],"translations":{"en":{"name":"Ownpad","summary":"\n Create and open Etherpad and Ethercalc documents.\n ","description":"\n Ownpad is an ownCloud application that allows to create and open\n Etherpad and Ethercalc documents.\n\n This application requires to have access to an instance of\n Etherpad and/or Ethercalc to work properly.\n "}},"isFeatured":false,"authors":[{"name":"Olivier Tétard","mail":"[email protected]","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIIEATCCAukCAhAPMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYwOTI5MTU1NDA3WhcNMjcwMTA1MTU1NDA3WjARMQ8wDQYD\nVQQDDAZvd25wYWQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC6CY7I\nHRJTaqDu376vt+kruX+QOL864joScxRuh3IOVcQktCvxasuA0EtrX7TCAQrV1tBK\nfkqJxU9uOV54RTgyh30yH/ZtnF2bYQwViGM06Snc0riqWydFrN5fxK52dpZWs63o\nUFCNhHxrX4aUGyfXu5nQMISLm4QHoZ3LDLofk1ZsiK62fM/Jz8N2PM8qeHzf1ATo\nSKcAOd3UeaS9C8bv2DuiZM7unkSO/tjrBzkMiq8ds9sIzBBsyk6BRh2HQjHPOtmO\ned+pS9mIZmc2xhssXoHL4IfZwTqwhktpsaTl7v0ROw2dwDATz/QoKMkUpboQ5lkz\nwgLQhoIZw6uAZ1R/Qjze59I3iU8zIo9quDarHBotZNXboYCmg9FRfE4mHtegVaa8\nv1a1JvFQ5gvsWEsKSV6Bzb65GTp4KG4q7YnUrzh6HJyDCGLvLlWm5OWsFj6sNzXX\nwLOv6JLORMbF4ZIo2iybb3x7gdfCu9JxMZ4JtOUC8KSJ6+ub15C1Aia3lN68dNts\nY6KwUF1Ted0o4OQPAulq5pUc+g6dTYmIKsavIiPKhMtl86AbUK50vRTeuGdFsT7X\nav73IanPdFI9bKth+tajgvB6dxcVnvBXbrsLUyEcsxsxtBJvQcMYS4aZ6ZJYLTep\n7AdK0Zt1iMdXB8+4PCps4rcG6bYB/uJeEAVm7QIDAQABMA0GCSqGSIb3DQEBCwUA\nA4IBAQCM10O+sCYhIExnx01vGzKlnRS7MSQNx8ZMmbR5Elfz4AVJAEJ96ytS2DXH\n2c+hcD0wAenXQEFk920AEqFQBT8DP34p0FmF83aMHW08ovzFiu4MdlhcqrLnko0h\ncZTXHVyS/8JZh+o6SVm8R0/BBLF1MQQ5TqRkJehbmk6gL0+MSYxehUDKWTjJITkR\nifneTw/Ba1d0AXBOq0c0HFyGxMPIlWe4qn5LtxH5t0wyVGeSj4jyv4nvd3ZGuAgY\nEUa2uYht/z475k4+vf0YhV98iQH07GnmlfD2TDZgmOCQGKlNfJh1v88OZyLLa3dz\ngRHzGwKbAiJ8T8bbpZ3e2ozXxADr\n-----END CERTIFICATE-----"},{"id":"announcementcenter","categories":["organization"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/nextcloud/announcementcenter/issues","website":"https://github.com/nextcloud/announcementcenter","created":"2016-09-14T10:38:53.939634Z","lastModified":"2016-11-24T11:21:50.324839Z","releases":[{"version":"2.0.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=10.0.0 <11.0.0","minIntSize":32,"download":"https://github.com/nextcloud/announcementcenter/releases/download/v2.0.1/announcementcenter-2.0.1.tar.gz","created":"2016-11-24T11:21:50.317635Z","licenses":["agpl"],"lastModified":"2016-11-24T11:21:50.386203Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=10 <=10","signature":"lmqeE6xBqUJfhuXPbjCfuWiIP0FEB4V/SsF/OvYar6rLpvDpJVf3DJoeIoxXurRP\nE9/xCcNN44P8PreRRDnFLCa0XsKOtwoGa56Lxk7IKvtiQG6xu4J6PKM+q/tIeF9K\nakw0LQXtjZB5InPhnCDDbY5YS9jgGEBylSHsgNgrElipcW+BzOBu1Amw4FECVlQw\ncQ83bio+YPZvsnE5+v3/bAx0m6QNxfyN9Sn6rMEqRkY3jfA3vejXGQH/XkputfV+\n5hOz48KbOVg7cKxg+ieJlSwC0aYjb+RXiopjc3icCoIF1llltOOeSsVYSflOb080\nupociPgQ6qIab/VNNXa2YQ==","translations":{}},{"version":"2.0.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/announcementcenter/releases/download/v2.0.0/announcementcenter-2.0.0.tar.gz","created":"2016-10-06T12:41:56.195206Z","licenses":["agpl"],"lastModified":"2016-10-06T12:41:56.263124Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=10 <=11","signature":"NVWYz73KtuoZ7ti2sluztJO5aFUc7PzhlDcg0VWyAQd1H7sk5wjw7i0bhrjw8O7M\nLsrb+PegnsL9eMlYM2WrRom+RF1PDP482xymZf1T8vh8qcTCm3TK89xSuiSm8yoA\niWUb/Uv/ODj74wVDWqWxAFKaAG/FestCB3InOOZQqQZLzlAV0U9ziYDGNzBjFqof\n9rLNxJ2IOqZOA7hhMIKhSrpA0KkSfNhBsVf8CWClYnVkZQiq0LoYkHkHIlXmXUr3\nOfQFKEjtsx+bNLa6CkAaocHGHJXAofX3GQZ9cjBsjZqiTfbXfcVk0kRfz7pwL92L\nI1McfJYvgMxDQG5bjRpNJw==","translations":{}}],"screenshots":[{"url":"https://github.com/nextcloud/announcementcenter/raw/stable10/docs/AnnouncementCenterFrontpage.png"}],"translations":{"en":{"name":"Announcement Center","summary":"An announcement center for Nextcloud","description":"An announcement center for Nextcloud"}},"isFeatured":true,"authors":[{"name":"Joas Schilling","mail":"","homepage":""}],"ratingRecent":0.75,"ratingOverall":0.75,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIDDTCCAfUCAhABMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwODIzMDkyNTQ0WhcNMjYxMTI5MDkyNTQ0WjAdMRswGQYD\r\nVQQDDBJhbm5vdW5jZW1lbnRjZW50ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\r\nggEKAoIBAQDPx4Hp1HdBo5v7bDEiVcv2UrVjNW+fPPKS/5rwbagtPcE/1v3WDcwX\r\nvFwaXk8qCn2UpPSQ2b1rTuTDm51G1ZmEZhNiio+rBfEe9F+3tLsq9lElqIPKhkAq\r\nEUVI6dcN+jSqvLmLhuwloEoQQSYaLrX75mY3lGqTb83h1l2Pk/brVixuVf4vJW31\r\nTgeieuGKnC+keLzKOrvTHffJakU8ktwB2Nuu1o+jN5a7u1bxKkP3LjEWPjq236hk\r\nAoOcW/wi1dUEyUKUZsZQeJyvTJh1UXdLHKwYywtUu1/VLZ1IUtNyPBfiQ8ukPp3T\r\nTnSSmG3ZnvsfM6DmAvLZ8bBQkMBzEcTLAgMBAAEwDQYJKoZIhvcNAQELBQADggEB\r\nAAB3i2NgiZ4rpNag7cXYdaFxAxdDWnke1+LX2V2R3hzGmx73/W6cKLpo3JBn9+zT\r\n1aEjlqkt0yHu4aAPVYQzOa5zIV8mjP84p3ODSyV9J8lfjFNXT7wdA8+9PVx3lVki\r\n2ONoCNBh1kOxnxI4+BsMlQfF00ZbBSuGcMm3Ep3lTFWXzuUn3MQITzPwkL5LkW6a\r\nsli/yAYQRTVDsXD8A3ACYT7BG31jGxyXtIHzqCci0MhZFdKKayMYkwfjZchIUtGN\r\nJJoU8LQoHwGRtp3wutk0GlFzpEQEvSsn/Lsvvot5IfIe46tnzA6MVj5s64s5G8+Q\r\nphhXFlzXqO/VxquPdbfYjvU=\r\n-----END CERTIFICATE-----"},{"id":"ocsms","categories":["tools"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/nerzhul/ocsms/issues","website":"https://github.com/nerzhul/ocsms","created":"2016-09-19T21:56:04.745481Z","lastModified":"2016-11-11T16:29:55.864273Z","releases":[{"version":"1.10.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://ftp.unix-experience.fr/owncloud-sms/v1.10.1.tar.gz","created":"2016-11-11T16:29:55.856768Z","licenses":["agpl"],"lastModified":"2016-11-11T16:29:55.947926Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9.0","signature":"hVzbkmmtJCtiOkZGe1mkWElqS3IPQ8wLtSzikVvoKmcg+Zq3YLQjpQWzy0t3UVjo\n9I/BfnL0bF+kjtGc9xF6M8IQaFqPrfJmN+lNT8WYIKLI97TTsLmJGg8Q8PAux3nY\n8/NxMjWdByMw9nVBClKo0o9eSW4+EnaUSJ62Gl/XWjq728kbB16WZm+iesk8LjJJ\nqqAgczWGwz6lkZTCN5o9n0a/YoLJTf4iT+OItHZyS609Cqaxx9CAmZPj/Xn5g1fm\n8hqO2ITAXLoBj4rYS/QsZTMcubtGkJ8fq3XYKVSv2UXZfvGsNWbbGV7puKN33uWJ\n5MrdoMlJ8XnJRPDlCBcb00LY+AB+hAMooLnNy765/Ew6ztp4KNLEPWGG+Ut8/Lkk\n0jIULl1RF/FjlW8P26NfwH36K30RCJFY06OFcWnxGBkkQaNFORDIsKcqTAxkl4x5\nnfKBkNdQZppCVfOSKOZj4NkWfWx75Ouq1S0QksmOsMZoOcjy1TbBKR8h6dt9DQub\nWpYBL0QwyQShGp0Vb1qCKkP69ZQAHVUJNzIFPz9LyoguvFyv8iZmAPLYDnFBvlf2\nnSHtA19rnJmZ4H7RJ02r6BdkstxISvEiHU7RLjNQxcb+DptIWX5C03wH87HTNIhr\nvptPorEoSY1KwW9fqUvvLE/c+vfkr5cvIEwZlyVKVXU=","translations":{}}],"screenshots":[],"translations":{"en":{"name":"ownCloud SMS","summary":"A app to sync SMS with your ownCloud","description":"A app to sync SMS with your ownCloud"}},"isFeatured":false,"authors":[{"name":"Loic Blot","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEADCCAugCAhALMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwOTE5MjE1MzU5WhcNMjYxMjI2MjE1MzU5WjAQMQ4wDAYD\r\nVQQDDAVvY3NtczCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANqZVIzM\r\nwBJuacuvgYKr2KnXuYhjKjZ58nfspSebsaGLr0ifBbo8L+NH5eaynnLCNhpegmu0\r\nO8D+KrbM1LtIkcdg1/eFpN5dTc6G2OAc9H9stmHs9nroF6MNhszgdZCz8Q8xkSoD\r\nGdSm8hdPg5GcfLrH27UilGtzdQlWJ1DralLMt3l+SfGJo152c/dc+e6SuT8+EbY2\r\nCeLdH5ImasXNpUgY+tAoEt2ZvhBrUghykBJTJVOjwL1jGLT37ybMtV4FBKo6hpeg\r\ntq/YzEk1ijBAC4pmoNWixDKCdolpVJVz0fijI9mlda3llurcp8eMhxfYJ9soXLHp\r\njvLX02YY6RfPcyy48uWVk4IEt9BvZWEVAAp7hCGA2yXrVSsR37E6sDbLsBcKav9A\r\n6dkGAgfmGkr2WT6O1/EhK/MakmnYO4WD1B+E7PnxtP/wOa+aQBmntQcd7igDiwzG\r\n6h05NYAWcRhqfZ4KWYsq0t0SezMbuHOhwzzi22q8wijC5YZbmhKSh+b3N8XwYKDi\r\nZaw+fSahPbRWaLyR3wn9zh7vKCwqrG3ugrNo6CtyoACAnmxKZ97ROFJIQTe3ndLL\r\nmv7Wy8iCZLhRYUaW/GKrF11AFwBVec9xmvkgU+PIKq2HSjwi9sCF+pFyhVjmq29C\r\nmZEPKUV7ySIpNHXpsXm8kTJJfqjSdb2ECbLfAgMBAAEwDQYJKoZIhvcNAQELBQAD\r\nggEBABvn97e8Nw8KAscf6FX/nZ99rEX+3IrZxTC8fmBgNwAvlbF2A+QZQcFI4G9/\r\n85nHK117+u7XDuwWl4QG3flWlI0hDE59Ud9Bd4AiTQ12VoXlNdYoTg/mXARxVozb\r\nKYqZ+1xRQclZKb2AqW8YiGo18okIKovn9VVRAFYPYx4O3Ve1FjgfsaMlIZLiXUFm\r\nkk+2qWo6kYsdU9FABLo6izx7RFOMbnYNre5FmDrWP1Dga/U7ErK/Dilh8g9b3HrP\r\nwP8OIZhdtFWw21wDTfyqrb9EhC/tsjPVP9u+bqyognHeiMhjbVYRbSvz5o8T7Mhj\r\nbxalCt4/LnMIfMwVyIvye7Uy2GY=\r\n-----END CERTIFICATE-----"},{"id":"rainloop","categories":["social","tools"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/RainLoop/rainloop-webmail/issues","website":"http://www.rainloop.net/","created":"2016-10-20T04:17:37.217555Z","lastModified":"2016-11-18T11:36:04.309739Z","releases":[{"version":"4.26.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/pierre-alain-b/rainloop-nextcloud/releases/download/v4.26.0/rainloop-4.26.0.tar.gz","created":"2016-10-20T04:28:21.491747Z","licenses":["agpl"],"lastModified":"2016-11-18T11:36:04.619927Z","isNightly":false,"rawPhpVersionSpec":">=5.4","rawPlatformVersionSpec":">=10 <=11","signature":"nTYIVSB6mIwKtXIrKoVGsOGFflpLjed8jFem1VLQNtXQj4bztnNrdc4YaPIn0yzM\nyLpMSqRDNzdYNFuOeDiyKLPJPTA++MotLCNjEe7kxUekek+m+qzgnGBdcT7RQT6R\np9xWGecnVx94d6aA55uiRhgQRyHpdDMMLCOz1be+HvpwHy69DRFZ1+SPmGUt6eW0\nu5yS0vHCu1K22cbrVNXFKjxAOlGcIDm61oQuz7ycl3uAujZO4rZbWt55jilgKGak\new559A5gTp9W+j+TWKIcg6LIZ9zLRlGjcQrWJrsc+OBZQcqiYimSFyO6HhfT9TPS\nPof//I+dSsd+H0SRGGeL8DvSnK+NKZL1q5EX5pziqsv6nZFITpCDwmAN+I8AnXXL\nSNkFi53M8RZTOABpD2x7YPYP1cEvwrRweqV/C/oHcYnpfh7D2DjFeWwXsjeAXrHY\nhgFhPrg+7rf7g6UmJFOCp0dC9sBdyQ3KtJkv7bGqPr854r2cdA7xW0QHWQ2in9qQ\nLhIczc32ECi3ZVVgyF8zyT4Y/3MRS05oX3FHvHyt88mjni6bVaO78F7ZRSha8gHh\nNOAkku7AMXPvUCHaZP2iVCCoAViEso8GeR3O8xh2G42Ai61RLYwx8LB1+23EoJTr\nmfFuRYNSg+qAKCokXNnh+lDlwu4AkaQo3vtKGPXvU7A=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/pierre-alain-b/rainloop-nextcloud/master/screenshots/2016.10.20-screenshot.jpg"}],"translations":{"en":{"name":"RainLoop","summary":"RainLoop Webmail","description":"Simple, modern and fast web-based email client."}},"isFeatured":false,"authors":[{"name":"RainLoop Team","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIIEAzCCAusCAhAXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYxMDE5MTkzNDEwWhcNMjcwMTI1MTkzNDEwWjATMREwDwYD\nVQQDDAhyYWlubG9vcDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANqB\n5jnF9qZ/qjckt0kRjpHCOMtJumW/KiQoMeNP5nGv4ad0DS3KemOapUef8Zn7qCYb\nMnODhK7HBwPifFzI1j8bnT2hP6E0geFLb0MdN59d2NF0n4CCs1+BnepQPJ1kFbPK\n35wQRi0RDeTf/GQ+/owEVCU9a9W1P/VUXk8Z0vMoQxCXEdRqnB63SgsKl7DB9G/C\n4SYrgGor+OHVGl4ntMZhJujiM996DttrNK3iZRGkQ07L+lfUIwQ52XOhQNRdic4p\nB03lw7PpChwPGMv/EEvdR5HpCJQBJniqJbbu3Jh8bMBKTE/8fCzN3vMXICB2g3Bq\nlKkZW6fnJRGsrZ79fsQnl+WBPNSrWRLOxOfe1fyCFV1ljFB4nTH7uF3pC8ZRgJes\nkHIESHz3GJm28hn4+17ESMGHBCbs7L9FK2GY31cobU0VRntLxpSG+d9njbIAgMG1\nS7U+oKVFQhSVpdXNOaUNqhcQ3HkbQTLEP0k53A/lhLQb2+KPd8nntaELjwNyrmZg\nsVMgHj/zdlvrbguZjZFzUzDBFvkuv/5M58lNT/D1C6ufVp/R6eLsYI+nnk1ojAjz\nl7N6U8X5SXpD+Bm7+Kn1PH+bHl7cViCx8oXJXO2RhP+COXckw7BDZKtjItYHNG7M\npFwgYqWpvCu9LN6IN5a/eLqSI76dOOP3iYbaTH+NAgMBAAEwDQYJKoZIhvcNAQEL\nBQADggEBAGB0Vq0l6ndGTgNbZxSEFyBR3u3tiR3pWK81DYjsui7qBoO6P/BaGmf+\nraSwHPaBOwA9XNS8jcGLh5xdqY2p/m0dTS64xNjVL9nweWsG+FwVnPANo8C4nXdm\n9ajJ4cdg54stQK8qn1uh/xPcd23GKfYJazjYSwYmZ3pXXdzlGN9NxkeYJQxJ6B+5\npzAeVGiABI/e5URpxzz2UayRX7EE+vtpe3B84hzkLqsq0N39ZN6KLfaTyEBGLzqE\niLYeXQTV0XSRs8xVt+iyGlj7nPkv2DR0oCqRpWUFWeSBI//niDG5WxS3qg8kacSW\nfDSYhSN+IjrnIkwNtc8V9t7/GeQB5FE=\n-----END CERTIFICATE-----"},{"id":"richdocuments","categories":["integration","office"],"userDocs":"https://nextcloud.com/collaboraonline/","adminDocs":"https://nextcloud.com/collaboraonline/","developerDocs":"","issueTracker":"https://github.com/owncloud/richdocuments/issues","website":"","created":"2016-10-31T08:55:45.631429Z","lastModified":"2016-11-24T12:13:53.905352Z","releases":[{"version":"1.1.3","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=8.2.0 <9.3.0","minIntSize":32,"download":"https://github.com/owncloud/richdocuments/releases/download/1.1.3/richdocuments.tar.gz","created":"2016-10-31T09:03:40.389355Z","licenses":["agpl"],"lastModified":"2016-10-31T09:03:40.439510Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=8.2 <=9.2","signature":"s5giQeiU2zwV5X6FmxWXiG9LtNDeKBlFqK+hfvGNbGZ+nic77Y+AnXHodV4lb3Ko\n0C0ThFLuafaZRdp9rBIN2K/acCfCYKJewGuYErb7FlEl+P9J4OQbb9pva0htZJw6\niuG5eyeTufi5MKB4vuj4+jo9zhepOFAtZMa7o+ZCfJkt8vDBuq5AXxomEiZRtW+n\nf9PPUnq0z7DJVwINhHvvBZJlSLjkpJ6VIHAr+/ElWr8O/mDKq5S5ohbvpDcPqR7b\njnsBckFDLFUz1FX9dA0JCJEKMMfkcfGqZcjH17NdjKAxRW2soN5cEKluu5MkOhz9\nFEPKfshzbrfUIm5MaFGv6w==","translations":{}},{"version":"1.1.14","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/owncloud/richdocuments/releases/download/1.1.14/richdocuments.tar.gz","created":"2016-11-24T12:10:13.337165Z","licenses":["agpl"],"lastModified":"2016-11-24T12:13:53.963638Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"prDGlfRPxqT6LP0BsAFPwGww7P4Bngha2N4u5B6+F02N+RVOjGtTcXKqvM1KjZb1\nCo7qJvgJmjpvIvDmB+rup02i8ObfwP2ct6UdsD7ouzOWJG2sJANXK31bHyvOmQ2h\nvKu5eNcOkf+WFyFKYi51TbsfWn2+1Wge3WWujKAVcEvqtcOOz+uMWNtqzBptEupk\nE1aaRnQfTx488YB8Ubul06LIY0PNCHgGCWPgy817tOVT7JA+V0P0FFonl/PXE0dr\nWgtxRJmvGaNiFzYq+kQmdKMfayZTm3kdVgP0W52t5wp878K0i4s2KPg5lANvjTz7\nDCT+VV2IGIE52o4RpMUGyQ==","translations":{}}],"screenshots":[{"url":"https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-document.png"},{"url":"https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-app.png"},{"url":"https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-presentation.png"},{"url":"https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-spreadsheet.png"}],"translations":{"en":{"name":"Collabora Online","summary":"Edit office documents directly in your browser.","description":"Collabora Online allows you to to work with all kinds of office documents directly in your browser. This application requires Collabora Cloudsuite to be installed on one of your servers, please read the documentation to learn more about that."}},"isFeatured":false,"authors":[{"name":"Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIIDCDCCAfACAhAZMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYxMDMxMDg1NDExWhcNMjcwMjA2MDg1NDExWjAYMRYwFAYD\nVQQDEw1yaWNoZG9jdW1lbnRzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\nAQEA1jk29m6JykcJ2Ld0YEpjPMYh6kwxY6GysNJnfkA/th7tPWL3+vBJ9oTYyVnZ\njwAE1Cqwfa9MyBKMZ2IdfIqtT8PeWzuFP7Ib942EdxUpwwh9F3lykeGsj0h4zQwX\nF9OooiS99PfLX+JpkKm15Ujb00iLB6xQmq0+3NeOT1CTD1ziJ1ueOcxBKMwaFp2a\nPuz3F5ywqCvpmxG/OBuOs0LI3/zStXhBNbUMxBrWblr7zaVNJXl/I2JCKj8Wah/H\nXUEEGbW15fAUP1f+90eQSxpEoCZDBHXOQCTJYzySGv+BjU+qlI9/gS0QbrsiyzUf\nO5lyvi8LvUZBzpBw+yg1U75rqQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQA9jU3m\nZmD0ywO3MUsG/GLigFtcWi/p7zp2BliR+NpuY2qNFYDcsIb8ZUudmUc/cJRRctzy\nAPaLLj/d+h5RFaxjTVvim1PSe6M7urK/IMSvyUVYCeQRYpG8ZJixKTCOVIBaWHMz\nxTfc51tm9EPlpJpK6JtaWrYYoWGE3k9sINdJ4JkvKkE2CBAqVhX6ZGyEQ0bnEhtk\nRu1DXn+LW7TJ4NZ8VtLWvmW/6Kfmi7dQ1V++Kmn0lO5ntRt5altePbStCHC8bhGp\nmyBOrjhrJgLIwvgH26MYZhdiSkFzoE38nMPZdrUmUDxcPCwucWJqgzDPudguFthj\nWCVZ3TTG/2z3+tWM\n-----END CERTIFICATE-----"},{"id":"ocr","categories":["files","tools"],"userDocs":"https://janis91.github.io/ocr/","adminDocs":"https://github.com/janis91/ocr/wiki","developerDocs":"https://github.com/janis91/ocr/wiki","issueTracker":"https://github.com/janis91/ocr/issues","website":"https://janis91.github.io/ocr/","created":"2016-09-19T12:07:49.220376Z","lastModified":"2016-11-21T11:22:21.024501Z","releases":[{"version":"1.0.0","phpExtensions":[],"databases":[{"id":"pgsql","versionSpec":"*","rawVersionSpec":"*"},{"id":"mysql","versionSpec":"*","rawVersionSpec":"*"},{"id":"sqlite","versionSpec":"*","rawVersionSpec":"*"}],"shellCommands":["ocrmypdf","tesseract"],"phpVersionSpec":">=5.6.0 <8.0.0","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/janis91/ocr/releases/download/v1.0.0/ocr.tar.gz","created":"2016-10-24T06:50:43.283900Z","licenses":["agpl"],"lastModified":"2016-11-21T11:22:21.269108Z","isNightly":false,"rawPhpVersionSpec":">=5.6 <=7","rawPlatformVersionSpec":">=10 <=11","signature":"CBJkCIiUKyf2NuWfz2zJ3grhf8p7wJes7DPV/OxUzhlxIH0Fh7K54+U5A9JOOi6f\nWPhjXG1ylkyIVY1glr/B8svWNsD4jAclpnUi1/9ZW5UPT8LnRBfTbtF9Uoj0OgNs\ntsGQYbpuREoHnjbJWTRe0kq1OsOfX44xuf8PuX43B+lpQPW4iRSSz3ZIhdPcDGq1\n7pyqQM7gdKhBQ6/tOiwd7Enyt5Hi4V6jhwhUOCYeTNiLD2V3yKL+qA9DzpXUfNNw\nLGTjcaMrifibHQIZBZWbPPMmCfMJZ7GO9oR4gWHwkhWqt0yVWAJXAHJBLd5vXC5I\njtRTXRpHO/k6Dtqem8tZCVoDE5MAC7fDZ/0XzoFiXHciP6MenVasVcXo6xJOJc5y\nGsrecNftUEhP/ngxA6lMBVkLmmdpiexVisvsavPi64i34OUA6qOuxjgNVBDwg56i\n2lOEVvHa3nn0UX7ZZoQ/Nu6Mz7J3Hx/VDlttPuWe42eeJAphyDGubT1M62gW8dVB\nD3tJOF7spnK6I3BhVLviou/zs30AIRVBDTU0Orzx78cbInwy6/vyJib2a1olAaHz\nv05SzlQRnBWM4jYBe0mA/2ds9AO6VrXGrT/iLlHemj6JYoGBM185TGewA7OJyX3a\nHSlSDqaremmi+aS3onx3AKhXykDxTRkMVarePwTzzFs=","translations":{}},{"version":"0.8.8","phpExtensions":[],"databases":[{"id":"pgsql","versionSpec":"*","rawVersionSpec":"*"},{"id":"mysql","versionSpec":"*","rawVersionSpec":"*"},{"id":"sqlite","versionSpec":"*","rawVersionSpec":"*"}],"shellCommands":["ocrmypdf","tesseract"],"phpVersionSpec":">=5.6.0 <8.0.0","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/janis91/ocr/releases/download/v0.8.8-beta/ocr-0.8.8-beta.tar.gz","created":"2016-10-10T18:01:16.076330Z","licenses":["agpl"],"lastModified":"2016-10-10T18:01:16.169733Z","isNightly":false,"rawPhpVersionSpec":">=5.6 <=7","rawPlatformVersionSpec":">=10 <=11","signature":"uEvhHfQCrzb6z+QuOoO8rYXiMsZFkrFWEqDvTyOTSgFKvo7dVoj3EfDfaApgcKEB\nIM/SqjLSO0lNhrp8F2mST3twbvLDprKsfrDWKFE6eiH0yKl2aNB+cHWE27utARaX\n/QZBD114vbWeDnbaBa4b9OwtBXDqKJrnO1LmqSLFP8guAlVTkU1jSPkRTpmwAcAZ\nJA/aiN/D2LSGfiNp/YdeTuzU+gPINIs9dCb6+PPkyam8PCBaXUSSaW+c0lAQHln+\ntb3EXxZ5YXdjPWrpEyHvFLk1N8s/w615QoMxr5fEs1M8D29aGbcL/wu7LXH4X0Yn\noiWwIFbpfrpJQlrIFumxWZR74JXiNr9J7ijnQ7SjxdHCcrLxMdnZ2cwq4iD6PnYm\nnIojhlhPOqUIzsWYCYutLWDQbUQz9eyWbj/+7XL+5KjetUUr/MnCu6xJ27IqFbAX\nHc8KRCO+9I0/qMQ2/rCZXBMeo39MGhhkgkVl5YAKwC1IEN/jlfyVNXZwYlfcHLKj\n6aNQ4zN6gGOerWWZ8qXtOeNJN+qv0nmXUKrZdnZUAhxOdB4G9Ym+JujxJZ9yNIWV\nsiqAI9J+OIzCwv/dzZhaHadONoo/RTF+Fl6Hy56HyBtMehb8w9p8ksVediqf33yt\nFAE/tzKtNK5NiRd+8MZkq/GbocaFUv3C7Y6pLMpTE1c=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc1.png"},{"url":"https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc2.png"},{"url":"https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc3.png"}],"translations":{"en":{"name":"OCR","summary":"Character recoginition for your images and pdf files.","description":"# Description\n\nNextcloud OCR (optical character recoginition) processing for images and PDF with tesseract-ocr and OCRmyPDF brings OCR capability to your Nextcloud 10.\nThe app uses tesseract-ocr, OCRmyPDF and a php internal message queueing service in order to process images (png, jpeg, tiff) and PDF (currently not all PDF-types are supported, for more information see [here](https://github.com/jbarlow83/OCRmyPDF)) asynchronously and save the output file to the same folder in nextcloud, so you are able to search in it.\nThe source data won't get lost. Instead:\n - in case of a PDF a copy will be saved with an extra layer of the processed text, so that you are able to search in it.\n - in case of a image the result of the OCR processing will be saved in a .txt file next to the image (same folder).\n\n**One big feature is the asynchronous ocr processing brought by the internal php message queueing system (Semaphore functions), which supports workers to handle tasks asynchronous from the rest of nextcloud.**\n\n## Prerequisites, Requirements and Dependencies\nThe OCR app has some prerequisites:\n - **[Nextcloud 10](https://nextcloud.com/)** or higher\n - **Linux** server as environment. (tested with Debian 8, Raspbian and Ubuntu 14.04 (Trusty))\n - **[OCRmyPDF](https://github.com/jbarlow83/OCRmyPDF)** >v2.x (tested with v4.1.3 (v4 is recommended))\n - **[tesseract-ocr](https://github.com/tesseract-ocr/tesseract)** >v3.02.02 with corresponding language files (e.g. tesseract-ocr-eng)\n\nFor further information see the homepage or the appropriate documentation."},"de":{"name":"OCR","summary":"Schrifterkennung für Bilder (mit Text) und PDF Dateien.","description":"# Beschreibung\n\nOCR (Automatische Texterkennung) für Bilder (mit Text) und PDF Dateien mithilfe von tesseract-ocr und OCRmyPDF ermöglicht Ihnen automatische Schrifterkennung direkt in Ihrer Nextcloud 10.\nDie App nutzt Tesseract-ocr, OCRmyPDF und den internen Message Queueing Service von PHP, um so asynchron (im Hintegrund) Bilder (PNG, JPEG, TIFF) und PDFs (aktuell werden nicht alle Typen unterstützt, näheres [hier](https://github.com/jbarlow83/OCRmyPDF)) zu verarbeiten. Das Ergebnis, welches jetzt durchsuchbar, kopierbar und ähnliches ist, wird anschließend im selben Ordner gespeichert, wie die Ursprungsdatei.\nDie Ursuprungsdatei geht dabei nicht verloren:\n - im Falle einer PDF wird eine Kopie mit einer zusätzlichen Textebene gespeichert, damit sie durchsuchbar und kopierbar wird.\n - im Falle eines Bildes wird das Resultat in einer txt-Datei gespeichert.\n\n**Ein großer Vorteil ist, dass das Ausführen und Verarbeiten asynchron im Hintergrund stattfindet. Dies geschieht mithilfe der PHP internernen Unterstützung einer Message Queue (Semaphore Funktionen). Die Aufgaben werden somit getrennt von der Nextcloud in einem eigenen Arbeits-Prozess (Worker) abgearbeitet.**\n\n## Anforderungen und Abhängigkeiten\nFür die OCR App müssen folgende Anforderungen erfüllt sein:\n - **[Nextcloud 10](https://nextcloud.com/)** oder höher\n - **Linux** server als Betriebssystem. (getestet mit Debian 8, Raspbian und Ubuntu 14.04 (Trusty))\n - **[OCRmyPDF](https://github.com/jbarlow83/OCRmyPDF)** >v2.x (getestet mit v4.1.3 (v4 empfohlen))\n - **[tesseract-ocr](https://github.com/tesseract-ocr/tesseract)** >v3.02.02 mit den dazugehörigen Übersetzungs- und Sprachdateien (z. B. tesseract-ocr-deu)\n\nFür weiter Informationen besuchen Sie die Homepage oder lesen Sie die zutreffende Dokumentation."}},"isFeatured":false,"authors":[{"name":"Janis Koehr","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIID/jCCAuYCAhAKMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYwOTE5MTEzNTAxWhcNMjYxMjI2MTEzNTAxWjAOMQwwCgYD\nVQQDDANvY3IwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDDpXiwec4f\nXAT//7YBPSb4z6ZsBJSMfBq0VTL/HagjJnQ7BL+WagzWlS69IStNDqlIlenamYRX\n4B40heJIUinzYKjTRbr5UAw6MX29HibZccm/qgrk36o1XTgIsoRhmvSxbXDVIo1k\nbDOJN8gc2Gvswa8X+uOe9pfcDgAdqGxOvFnoKW89GnB01pCNT+xakNErGAFqVLsr\n2AeademAZnbxJ1cB54tQn2Bygb/7DKKY8EmFfIq6/27n9Jbph1FG9HIlWRT4/M2H\nU2pG3cCScWMEBPsW7kpfpnzLk7Q30Oj6k/rEYjJgmNYgg6oVnn0D9uRmhBYBnGyx\nMab1ilsK53lyuzQY0pmU8V5ULqpnNFAK6DVFfofEamDUhBPO+TZXEA5cZmuULRpf\nQQXmGpUQSyV6pS9WirMIqXFp9wmQ4vtjMdhu/6CP7cmtYZdq9uOhWEHbQM0mZUkb\n8hMjeItPx9XITI7Cge1JUOI8ZIwiB3USnQXcMd3v82l++/VgqHB7s5OaKPhygsWI\nM6RCoBcGiuQB5/fEUOg5ACOpGVyJiBda0Mi57AdoxdJmfnr7Bxcf2tAWIJL9Y7T3\nE1+V2BMxJOWwvVz26Cq83F41yXK2hJS+SbfQTqNUR8Cfh50CS9POvgRxNrJK9yvI\nkKle3ITRtGVM1XU0njWjnsdGg3D3O2mmjQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB\nAQAbFddMbgfPI1szT57V1FKZrOrdYqQ7qjewlIQOzshGydbMtqS/9XL5hYocJCMt\nY6w+C/i6iEzO2Jx8D/k4rcZMXoVR6y3ZvO0Ke0gzSRsU+5eYj2FK1VV+cNIQW5Iu\nCYYIVa7pVPVHdeQH2Bba680bLV0HMF6b1fI9IwkfdCAinvCYZLjyEXZlmB7YjyA8\nHR7qPCNz4uG2Va7mlUHE3UYUYnlv8JFOV3YdbVL0nxhWwIdzSri5sxFIhdlabpzY\nyA1z/MCBEyTRo80jxFmL+MpwbsdbUJi7Qxlnd56zb6HHDGrLHXZTh9LXgyVbnhWL\nkxomWjIXQh4aMHQL4QF7U4EK\n-----END CERTIFICATE-----"},{"id":"spreedme","categories":["tools"],"userDocs":"https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md","adminDocs":"https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md","developerDocs":"","issueTracker":"https://github.com/strukturag/nextcloud-spreedme/issues","website":"","created":"2016-09-27T08:43:07.835196Z","lastModified":"2016-11-21T16:51:23.703819Z","releases":[{"version":"0.3.4","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://apps.owncloud.com/CONTENT/content-files/174436-spreedme.tar.gz","created":"2016-11-21T16:51:23.689599Z","licenses":["agpl"],"lastModified":"2016-11-21T16:51:23.826509Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"Mhy3hXeGWlIujx1Op39MMRdqHYOo360BCwr4FPWoTNNggH3aS0gWlh48DAfGYK9W\netNiOqIuRyA0NrVlsqR2vDILgFtODJSbKPyHd3PQn3hcGsjogjQ+dkKciLNLinw7\nOhbv6aDdRFLBeRHpX/7wOnWL5W3ko/gyn0Awvi88M9+nC5aARtqncQqPy2SxDGzH\nKlOZHSNDnEQCGMhA8hNWWKdVwNUJHod/wmBWpW5QVNSJq5DqrKZcNwpGM2UUJoql\nEqUMwDXk5uVH5r5k62Tr9kguDWoUEG1OqQSyeMY24AmA64tq/HSlAdZ+CX32bc4E\nZvm+n8poJBrdSVmWEaa4ZfYaLFdOc6Kcuid1B1Sv9kPhD9WD6T1sicdzjDzcorBK\n/MLReCuSb2E8aPTnFWRoAZ4xCUGs1IXzX5fmxI8VdzwR42R6RhGJ/rqMuZRFenZF\nbOks45K5gE1da4QpkYOUQa3GVMNPqPiT3CqjmJ8tjxq7bGpb6v+YoCLACjjPpPZL\n2Y28qLxwHVaINDFUUxD75WWdrlulRbqHwiSw8jolP9qrpXhDuLAqYam9tRwV5K5R\n8uNawnFwWkicBEYkN/WtBTouWzehOPn38tHXov6SyEyD6lkuxUBZrsGQ2ru+t33U\nk0kKCbV0GFw43I+3Ji5DiB4TUVNZYVoPG1B7Qve+UfA=","translations":{}},{"version":"0.3.3","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <11.0.0","minIntSize":32,"download":"https://apps.owncloud.com/CONTENT/content-files/174436-spreedme.tar.gz","created":"2016-10-20T09:09:26.520692Z","licenses":["agpl"],"lastModified":"2016-10-20T09:09:26.666738Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=10","signature":"D62Ck7JUnrYbrfFlX7xXVaYUMZIh2acmykIKapqfemD/tuX5Bvb08GYGTeFG61MA\nQzsqcIylDfGnC1UJbf8yWEX7PbyJD5w/R4WlbFv34njDvM8rBs4HpzSjkqQoykOF\nZpYAjH2ydfKqtZadgoIRm7et5B8X2AeoGg11ec52DId5t1wAEBcDIv824CDBUt8t\n0pVY8Z8n1MUYwU7DCjCbPy23br2+EBODFCHp+cFfMBLg3F0BJI5nY3Q8ku+0tqMR\n0NDxQcscNZ2Ck/wpVDWylfhpS+ICIxSMiyq7urP593mRrK3399SUyaMqDfgl/pxo\nqTzdBxHLaAqcnKZYglbqp+Gxbyj4teqCod8TiSMlp90VaxhC72ACuVQQRWQKuTNI\nZeW3YweWB5d7VErqBNmQR1tGnX5YFFHiKo41fVDQFsrOqHx4zP6AeU3nkl2ol/r/\n3pg553so1MOxMkyLEhGYGMfrdQqVEtajNWHUdj3B73LS+M3jcjBFIdOD+AGXPtDX\njCRymt07c1znhkL+aT8yY5SHMVbKBZj9mExL49hcLjAYYc4U++60uq9MFH5r9g4T\ndph+yT6VVEM/UH2HjvKsHv2wm937sNgG3EXQdh79JU8nCXIz7cVrJ8f5/9r6n1VP\nBbjtfDAPEjmfVCXX2gmgLuZHV+GMhLBS9bTh+61AhhE=","translations":{}},{"version":"0.3.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <11.0.0","minIntSize":32,"download":"https://apps.owncloud.com/CONTENT/content-files/174436-spreedme.tar.gz","created":"2016-10-06T08:14:05.212553Z","licenses":["agpl"],"lastModified":"2016-10-06T08:14:05.278533Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=10","signature":"X9zXDyMBPoXPMpZ+XXWK3MLufjY2MG8lJ+93LiW3rv0iq9yd8PafK4IvP9czO6o9\nf/vNilq+1mfl6mjTvL6QF5+sySlzbRGbT3uTBwYXyYL07HVYgl1ZLrwe0kxvxqaW\nxTvPem7+HzwClI3VnWc7ylQfzGrcYIaSIg7nNq1GOHocsgZVNyj/nVW/eQx24MjZ\nuLzZs9SJqYoBGq+mo63vRswhqv5OzGebo+G6dHm0hvRSOw9qsWCDWBugiSRU8zU4\nD9PQ0e8WbyrIrQhBoUvvkuijO3zCySx606S1HUyaHmbJzMc4Fbpwz6ggmi6IRBbT\nFBKB1DWJDwN/7mY4fhS4KhircVnAHDqiBVCTu5i3pSfMPrwFymcmbn9OBuFHAFuZ\nd9PZvWQg4v32w+Q/NNvZVW5lRi+l0w5DEqNREaj79hljk2reZMaB65lvtV9NCYw+\nHmwWqsGqZ1SgGZuhYkOzEIkCfJ2fF/VpyavJ4X6bHP9yYdkt1pxnSSoZ2HC8mkG4\nBnPf28mEXRcY8EJv0rEePqKSBIhAt8yfEW+joH/8nupe1qOdfPvP08ifLad5m76s\nt23UzlSljzq9kVO+d16z2uagKomN9USZaNnJcUDVblfjvCPpdiHLfRPEJnRsDZCm\nNffFWEMcz+TWmwBboZgTRO9v0bPDEuwfCCEW0zy8rT0=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/conference.gif"},{"url":"https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/presentation.png"},{"url":"https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/import.png"},{"url":"https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/users.png"}],"translations":{"en":{"name":"Spreed.ME","summary":"Audio-, video- and text chat for your Nextcloud","description":"Securely communicate with your friends and family using rich audio-, video- and text chat, and much more right from your Nextcloud – in your browser"}},"isFeatured":false,"authors":[{"name":"struktur AG","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEAzCCAusCAhANMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwOTI2MTYxNzMzWhcNMjcwMTAyMTYxNzMzWjATMREwDwYD\r\nVQQDEwhzcHJlZWRtZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKLx\r\n2dCPBLIgX948BnOdLij0YyI2+FKD6uZOvzxMaoi3rlxNf8MJgraNMzTBWEXtxT5b\r\n7ZISNp89WEXhaQ1dwwCocodd/xow4Ek63m5nUvTZXsm+YSbMgrFbxzsBhYU7KuIE\r\nT/jhKdzYgemzErwwN/gtwkLMfPo3jkgg6c8NPPohYv6k7V4VnsqtJ0JS0kX19FqM\r\nMiNz9XkcncBHy9x0BSxy4+YnwbFcgIx/MtYKlBL8NkPuuJaB/6C1O+IPYhdEdnpX\r\n+RaIue71nSStOYOqT4YDqHAIw7EmqgA1my09mmK+0Pn92GJVEAEN7JGBSQ+F32RI\r\ndB3ivGAOVtUtVvJlepWdbHxj1xqeP+LCjWzHMLQjm0TyH8VqU4Cg/wxwAEFnBATH\r\naOaWwrggzY2d9KBo1mp0k71NArLbBdlHykFU4bgiSDWrXXMz0fZzLQVwGI0Eqcxc\r\nouf6t0kvrK8oKjrnso+FjBoT7lHV/H6ny4ufxIEDAJ/FEBV/gMizt5fDZ+DvmMw4\r\nq+a088/lXoiI/vWPoGfOa77H5BQOt3y70Pmwv2uVYp46dtU8oat+ZvyW9iMmgP1h\r\nJSEHj1WGGGlp45d10l4OghwfTB0OSuPUYwWR+lZnV8sukGvQzC9iRV1DGl/rREMC\r\ncQ5ajRAtO5NPnThvN5/Zuh4n8JoDc0GK4jEZsIivAgMBAAEwDQYJKoZIhvcNAQEL\r\nBQADggEBAGHMRbPV0WTI9r1w6m2iJRrMbZtbBb+mQr8NtOoXQwvSXWT1lXMP2N8u\r\nLQ1a8U5UaUjeg7TnoUWTEOqU05HpwA8GZtdWZqPPQpe691kMNvfqF64g0le2kzOL\r\nhuMP9kpDGzSD8pEKf1ihxvEWNUBmwewrZTC3+b4gM+MJ3BBCfb5SCzMURLirfFST\r\naxCNzc7veb2M98hS73w5ZE6vO+C/wz0GTsxuK0AoLitApT5naQnjvxSvSsjFPEGD\r\nsUNUEU2Decyp0jxLVnrrpz6Y5UupfBR0V8yAv1t5Od/mCKLc5DxHsDWiKOpsob9U\r\nJN+bdzJil2NNftihD4Dm7Ha7OS3O8W0=\r\n-----END CERTIFICATE-----"},{"id":"nextant","categories":["files","tools"],"userDocs":"","adminDocs":"https://github.com/nextcloud/nextant/wiki","developerDocs":"","issueTracker":"https://github.com/nextcloud/nextant/issues","website":"https://github.com/nextcloud/nextant/wiki","created":"2016-09-14T14:34:35.977699Z","lastModified":"2016-11-22T16:02:57.758477Z","releases":[{"version":"0.6.6","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.6/nextant-0.6.6.tar.gz","created":"2016-11-16T15:11:14.344704Z","licenses":["agpl"],"lastModified":"2016-11-16T20:39:59.030384Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"aOZeEeThyZ0V/vXBcn6c+Z0vyCsZcN6nfSJ8oWEea4zXh4g705Si+MFZESqix3M2\nOPCnA/U8eASwdRTAEwQJrW5ECmu1THXSIsrzQzc9kFycvyOGzCgAWtuu0ayzZD2/\nU5aDWlzpLHC1Czg9QJ5UnfZR0AfChWQ402N1YzGqMShdJv6AHXFrVE+uYnIyxuYI\noPJQBUYbQwthVUjpYwFwSxw50YU17gmx5RZ0Y0OPz3i/EiuEUrxopXtfDVYAuCML\npDw37LOTRQ2JqxSU3teALh8LcrwJbTeOP0n4bTeV+vU3jvtiaEoRrwfVrK41F701\nQymGXy1/EFG0kxPGS2dRNPBAXYLZfeoWlROl3D5BWlbsCcXKU1S+22yn0TEdS7x1\nY44x8jRKnBddDE7qkn+QoQYHNNcxOREsFFLmIoyCUpdNOdDX2PvTFUYkIqdnXaJy\noAKv2GkvWPQ0aiiBtA1i4oXuzvHW/M2wOrK7v7DCpNfILrD/sjxpljxcX082nRCd\n9P3iPd2hQ6yOM9fG21LVN74b6wggI81BzFf/xJPd4ZqYLjfeG/yqd0zaiMOzMm1W\nse+kc/a4iB3BoCNX3E942pBBzew4ya8LkCXdCHUUsuelDf1va1ikTh/G7D84ll9/\n2avNqQnUh3hgOnxFCLI/5VrbqxfSTVdO6O/LTuAmwgw=","translations":{}},{"version":"0.6.5","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.5/nextant-0.6.5.tar.gz","created":"2016-11-09T16:58:06.856332Z","licenses":["agpl"],"lastModified":"2016-11-09T16:58:07.139404Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"DVOIbLEVggiLkNkuPW+pXqu8WYT15unUsMoqHSw81NiU6HF0Nuf3XiwnHJJDDqo5\nyX+QyHADO4ZiQpvXhGigvwD2eS1jVLatAztyxE0tEQv5eBU/7R0jQYxI8YCnC/jE\nZDa0qs+TI58EkDek0LBzueVQqrLubKgGU9P+E9H8gbWi1JHvl/2LdY7CplPqaJ+J\nMRokobPntzgx9m4DZC1RsCoXzSON7o2gp2cmunPJiXVHPhMUfIfolGEbNGJ1/xdp\nra7Y7XkPnDx4po98a38UpUh1x/2m5goOV54em35bWbh4ShNDykiE5ttz6tOywlYN\ngxceSsStTKyqscVaOV2Xu6Ive0pY9CInvrSfRnRktIWBYDyWdbK9sJuqs/s69kqn\nKQ/SjzE2smw0zwOUMnSaz0Jzr1vdPFgNu2xDYAVQO5G03V+wQ5AhxuhBz5Xp5Fll\nLaOhymZLCC7lq0DUqkeTeQ2QCfiG23hvG2VUPsIqW7xFe2YzKHZVXi9JuH//Gwym\nDmJmcyZDMvNwNiObx3ZRKsZNH2XwbldFZ9nTpb9AafyoSR/qbwd473NewaDLRTiY\nLrOP5Wx1xx6DOkRmDF2l2iT1bSJ6eoAoWQU2I0aYRH9NAr2Ugd4f2Um4o61EJaL+\nRHT9cERRySEloU/NdgmZEOi+CG0rEu+9LC5G/jGlHE8=","translations":{}},{"version":"0.6.4","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.4/nextant-0.6.4.tar.gz","created":"2016-11-05T18:17:47.622023Z","licenses":["agpl"],"lastModified":"2016-11-05T18:17:47.678445Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"RdkvnhNjw+kAnT6Or3+N9FzAv9DjJ9BAlmgANMwZZcaqo1gZRFewsGD2Rx1KEb9X\numSC28tl2B5/3r/+dprVJmOnYJny/7+kDmI/d+vigKfnaQJOUZ0ya5+f72pFgow7\nth8fw9rX/3+zIBs2IeEN66cis8ioFq97BJDsnDMBDr7wl7CnFJjYe6eviWuiFTnC\n4sBXlYjHoaIRRu561nwAooV+WXmWsparYPVhj2cXdyP/CnWo5HSF5jA51WCsz7Up\n7a0URXdh85xmxEbZtnjUymTW2BIegdxj9Erbfiuy/m3ApgnP+DiEQRcM13J7pXqg\n4cgFOBSzKDZgim599WBW2uNO1ztnDYOzz47GXDfJhcdvKiZZoQpUF9W4LMRtheMz\nxD9YArO3j3d+VOInSYU2Rpvhugwo1LExhwnRdT4+cOZfEeq0VojiM7yBZLDdEjIb\nGdYUJtNWSU0F6cPab2Au8FgZymLrHL9EpGvxuA1oAwtRxHAgMElJG2O6Jp89gGl9\nh/AptypeTvzNEc9/Kg24ueBKqmSUd5a45pZ3gM2pNATJhUK7fzLb/K6cq/kEzZtj\nOPra1ZfP0/20u8VP32Rgw1cFmIjqt8DFzUmOMpMfyoJkdldtTwQtGk+yIvtN1zp6\nT2zDknAKA2N/rZ/0SJl8KxVVNLhQWtYBJ+rFAdapuxI=","translations":{}},{"version":"0.6.3","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.3/nextant-0.6.3.tar.gz","created":"2016-11-03T21:51:27.654342Z","licenses":["agpl"],"lastModified":"2016-11-04T18:25:35.697130Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"Hf5GB4xd+rVXzWvVpGbbF5tqmnI+DGHlNHdLYPImFLS/Z4K5wKeNp80E5sd/RkAi\nhyuEsdWHlGDVMT6s7oeCmH/ClyWqLNSz9VH4KYqyFgD4+usHZp9PrEeEKbvPDPKv\nD3eB7Ats34cWcpf4E1oR5wsPicgmdgIgb2uMXzc/1G9xUBRWzocwCstzjEEAB/VJ\nvJuHvhDTGG294P4gOb82MxKCQ8LZ4i1QXzOf/mLETOubiUbZtJgTReYvpdAo2Wct\nbdfDFw13LYZkCf71r9jIQ3PSPlIpD+0BwAlE1fi0Br9dP2JjIfiKN6CGVaki6O0v\nKR42jtcE9xXiAop0Ym1FYMWJvQUy5PFLMwYDfEd6CvfEFJl+fi+RjXNDNZcTyw00\nHa48sACoGzxwts2JknWMU57mwvi0Z4uwpE0cFp/PRzBsXmSlCzWHjJhu7+2qambE\nAabdP9nH2NvqJHUJyPsxtDSrSWCBY4CoL3wYu36UrIA4NepyudMPNe9fhKTEU0bg\n8DLclw6hYdj5p9Zj3OUuwOZLz6r85KwnooTsUjOYkBXvdUuHWkgONqqZlPMApS4i\nChRQ7ysHAinPyyzsvr0PR9g6J52CSCO/7qwSJy6yqSzuSWrbZUa4FVTcKIwWJJPu\nJ2XzB4rWVG1wWjzMM6MIvFbO2HY9upzh651OdOwsYvk=","translations":{}},{"version":"0.6.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.2/nextant-0.6.2.tar.gz","created":"2016-11-01T11:24:58.054892Z","licenses":["agpl"],"lastModified":"2016-11-01T11:24:58.151609Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"h8KgwMh2RGGIp7q/II23VSfE5Ibkha7p/C1kvIfG6QIIc2Zu/Mm3Oekynnysh5ZJ\nZuMTaeWbejbBAmlnxW+AwBWa/s2PoMhv7foVvdtg76l9/qr+9jGvUM7D1LbbBvAy\n/XW6JSrhhBZHOohdU7kwV5Xnwsn/NC/zUe0G4eZ+9fc9uSntkob9wnWvUs2daAeD\nY6Mi7Xt/XAIX65OIVTKfC6ah1SlbXgtJ2i2j4G32I9jRhmbkpt/UJEangn90fHnY\nQXNJ85OyV0aNMafNHoMSL3uLscdvjp0Hy8w4iBeavsRlCs0GiUoG1+YdwTwmC9EM\n4CjbMfRJ0DYK7u697TOmS8MQzk8O7f5THtjeokZlrom2YnV9t6gLvjnxl/+gXPdJ\nmgLixnA8P6tPsff9pquHKQZsvxjv6vVa2DVJc8VpcqJRih7yj/3V7rxesEP7MUnP\nznIOcwzTsKXHuAnvujpCwyQj3QtpQK2XJPQ5WkKgwbTdvriVJfnzPironhcHo1vC\nbuUDOdhL59aySChw2cZGD9lCWaxYR7I1BDDzWKNl9Qg0AZ2auyGUGTv8P2vi5qUB\n0CmnkzkZurR5ju6Nb9/2lcZvda7QJdIdMtm2Wnn+Ak/Z3Y4IehB5PPDP5/MMAhQY\nXE8Jqe0mGtiU/O2346L5IThkS58JlRmep4kYv+II9zE=","translations":{}},{"version":"0.6.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.1/nextant-0.6.1.tar.gz","created":"2016-10-27T21:16:47.066097Z","licenses":["agpl"],"lastModified":"2016-10-27T21:16:47.125641Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"axSX4Kz2P4PbKU676DibjPZsxk8hCIG3lLOmeMXoiBhp3ka4wJ8u5tNwTzgY8/MV\n3mjXe5DNttD66SqmiRNSPKbotYHVFFW3wFK+Dgh/++n/KTomGYUeIwt88Z9ecbuG\nNT6U46jFrfZBYzRHWzbgiJ4c7MCoid9cfmoB7HDuQSyw+E0S2vbLL8+jzMcIzF+5\nTh/sJEterXCyrWSciw/9x98F+4svNbskdEIvrOox3+K6UIhpsojqJR2+bQhG3rsM\nPerOb6J+bzHdLV1ZL/4nWEz1F30T7B08QxY/4pHD68JFQcdtzmHMIhXfCoRvWhN2\nVRnizx3IXBALY4F49Ql6bjsnr6BCp+LroM5RSQ3eupDcqejDJLbjPz8xfOMOwlx7\nz84Xd0MUyqaEkxg1ihsWLbPlYACUZ2aoDkSQUIbfZTTiov7eqTM8UBc/UqVID/LU\nyEW4gjFZzQy6kX76XRAGq1vebKFjCU63asCnVyJhF/YQVTu1hPGbFslkRKnYuh8W\ne4MeaNfbdjcSEX+7oTcPJz6V09pOPvukXL0M1m7lS9PhTisI6oGj8c33GPYp/DSK\n6SGk+ukbt1mwFuFKdTvAMxo1lk96D+pKUv4MX/ralaaoIAmwPTGsSQ04RyL454ae\nU6q8PApwrVyPHYwMBPtXGoQMyb2ZV9rylazYbKCQ8I0=","translations":{}},{"version":"0.6.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.0/nextant-0.6.0.tar.gz","created":"2016-10-26T01:46:48.419025Z","licenses":["agpl"],"lastModified":"2016-10-26T01:46:48.521063Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"W2TmbX/NbbfPPjIJLalO0kCDhhQF1pEohH/CxO9bY+yR+a5NKiTbpAhG2McqpTSj\nmgC4J8/thmwGlWGC+VW+KlpXzzjc7wCgMGMKViOpGD3pIy8p8U5MXTqVgjjrEb9g\nKgr9uErXzxJ5oDfkx8Uh1bUeBJTsAAivGJqMlhBYFGxw8BSB09sfOZytNxo4wbwZ\nNAcYP1qvkUQ8CVR0nInSTRfLvAp5+e/8xxyYZwJIWrdNgpoP0CxiwzKP/VSjBk/U\nsPU4R72UQnVZB0InRCeh/KNTwu1YiPkUKm+mNmt2hCfN7Fm6bY2rUMH7oa8KTkqn\nh52FhbaYRSAR1OPdC5RnHiQWlPh71gq+4Xqgp19Eawnl/QiVteVifSjNQZ+Ban8M\nRyw/PxHnzIWg/OAjx81Jx9mXjUIHSeUxMTJTKTp+lEqIAzjku0iHeU5UPGCfE+VM\nwmopZfnlfk2nLkUwjQXLCIcnZD1ME1m0h/H4Ad0Q/qXpBScUp47npkxg2b8zPIhk\n3aXUmNPLgwyXPWvAuaBK/WwpNefUnqWFns8t2Alpzg/EpC2PrZqciCNDcRFEycoa\nX+JsFyD7eYA7Dc9iIf09gXZX+tZ+Jinb+iPDwYrl1u/7IIBoBlUGCgo+cF7/dL9S\nc3vYeWw6MCH8Sv+ckgS2g726BfdN5EjB/8cb071b4lE=","translations":{}},{"version":"0.5.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/daita/nextant/releases/download/0.5.1/nextant-0.5.1.tar.gz","created":"2016-10-17T15:23:04.515057Z","licenses":["agpl"],"lastModified":"2016-10-17T15:23:04.576640Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"Pp3rC/9RmAYURneGpGit4HZ2t1qH9A9nwsUnGDgRuJ0akIii7CtJC+n8l1b9k73/\nhxMYnp2JOBu2HWKgFp9a3yeo1xphI5hOUdVQ1UZAWxIQyDI1FZVYDr81l7GCdkqm\n2lMxgviFADSYURCgEnAsj9Nt0NZ6LDcJZiJg3iPAjkDI0U+KnEBjtx/XRFqGUnfp\nCUZ/XLHh/hvoEitSHepTBDCMKkTNjbDEwBYfA2rAoz4zbMR5zKLU+1r1DIUgWSRe\nbk2i8TaTDVL4cbb6MhkGKwkujb+Atikvkpi45o7+fyQMs84c6fjjh/TZJaC+dMyG\n1GCikMPwwtEPjXtnLzynERAxJOd5mP4Ee4sD8ZrnzNUehpyFR88pwWU6r+dmiebb\nnsYlGkhIu2aIO2O4HZ4sUTsO5sfjZ9me7jsafhgJl6iG4IBeHa/L1MsSbhsh6mvH\nYsz4Xsluwr0QcFLmSDDQQYynyogKfJZG2xQsadM0GETWgXE44dVeRvMUsILfB4uZ\nmfKgd23SgaOhYC8m4bg5Hxnkl+xHJnyGZ6jhqg7bhuKwsoLymc18Vmjmb7a45HGV\nXbL5CTmw9yaPOBS3v7v91TnlB+0lhlzbKzZ0xIhY55qsTC76uScbTLwndPqNGaF7\n2koxRbJ3jcmf/Z2MLymdRi2BTZbZkPkxgVrSf9plaR0=","translations":{}},{"version":"0.5.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/daita/nextant/releases/download/0.5.0/nextant-0.5.0.tar.gz","created":"2016-10-11T11:47:46.191539Z","licenses":["agpl"],"lastModified":"2016-10-11T11:55:40.393000Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"qzQJSLK8nkrQedwwxUdhxL8bq3aXyppAlWJo+n3GqSvqA8uNTzl3Wsci0LsnBV0E\nDvDNW8K0enhl563F/bywQrDhgKl8jTX/CA5KCxqO9P+tvE80zAfMqiRnQayVcWuY\nSWX6RqfI/kqiWyN1SsFp2EDlas6eb+xfIoiJamlfsN0qzHYOFt5W77wmw2Bn9dB5\n9nwHHyC0z60Pf2pPduc/KuZ/971WrDFaIapL7Gm+z9XoaKSwUT575VtS+RNJkOKy\niBrwnHdc8x/62HPFOXsUYjCt2aEmLzPCQN8Ke5pd3596hm5wbAVzTHuxf2H35tb3\nljfGqAZ5AJX2Xd13d4aHXFdSEILwv6IFq2fx0hO3vkvFEoKF5oQ2t3hi++Mw/h8R\n15OKZCOC1bFH3gTwdshmnHSTSr3LxDeTF60aH16wpXcehQuJHagpb/aG8mPD1w+v\n759/mekqa4LYlqT9TLWTqX3UPeQXYIwcPijG84IvW1BDK1M4Mj2Vqsld4jXwG6CP\nORIL8xoQbA52dQI1Y19JXcU9zxIb6GaHYgpV0wejatsZRfhPv2Yd0CBShF4HY7aw\nnfcm88pqzOKNvjnLZjTFQwuJ0AUUSOsWhgZzYt8tATJ2KDZ+lxz+WAMGXJAC/ciY\ntrrglY7YxwJNLbYp+arE0sowZx+IOVaSZBvmUGHiEBY=","translations":{}},{"version":"0.4.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/daita/nextant/releases/download/0.4.2/nextant-0.4.2.tar.gz","created":"2016-10-06T10:31:12.482416Z","licenses":["agpl"],"lastModified":"2016-10-06T10:31:12.551117Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"QHJhYcBMi5HyPofshZ7EdcXsOfRrl7o48Y3BBBq8CkmYtFDbekghdJqjFbwwZa5u\n8FtgMVwssql/RSDNP6M2Zc/MpQ3K9gDm+DyxE5KRmtMEpzHB+oD+1DxP7kAoyW8/\nnBr5iiQSdLCelddMcTwbdxskLFUXIs3cFuLGhMvr8pdQOAgfxte5lolrj4/8EsJ0\n0yUImgIYG4NlgmvCygGApdpVaOcK7XVtv4oH+x43JmX9YZ3Ce0DQPYPUbFTCf4ZS\nS075j1vcnPx2cRFGxc+YpKzYVVYoy7ZdB75Hq+kaei/atxrTyV5+gcCrVPnH1RkX\n6G8rgu5l8FoGJYopi8/9dd8LsGLFx53CHMdEVob3tFR0WeK4TJAGJa403zE6S3hM\nxr86WCedmjuti0uOhSQr5AEVAoXZ/JUWQMMsPAUMuKEYVjKfmve6TlcNMC2oM5XT\nXcOf4OP3pcQq4ViN53o4Pj6NGSci6IzD6xLeAxKZUoTX37ArVKH6RHS5Najc193H\nRhYRnfE7D5YOr1u10HaZCFCVJif2MgMP0/uH2759NoRjXFowrh7Z6dW7JQG5lbHN\ne0jjJH1Y8m8H1peGGcmM0YxFiOVZ0ER7P+AxT4Cbau/cVhaS8vnPF2a2a6YFRiFS\nVH4aqazvvXrtifDr3lfvlyPCrP/570nwvOJgZGk+K/Y=","translations":{}},{"version":"0.10.0-alpha","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/0.10.0/nextant-master-0.10.0.tar.gz","created":"2016-11-22T16:02:57.740378Z","licenses":["agpl"],"lastModified":"2016-11-22T16:02:57.900805Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"kDO3xbPpoUdl2qo362tXfJIqKeiKE12M8FkMXbdKiRNzuQyvDOehQq3dErALZDOr\nLG47Tpez/Kn9Fsx1y4dQDx0w9SD3pyoqvjj1O6KkTYN6srpitQcj9EzEItCY+MZd\ngRSc7Px9MzxpFpgwtuThGVlSt5kLMd0vjWFLVcv7k07rZfWEsTwXd24INIDtlr1A\nC7hyLB777nEOGa7oAzx8nr+FJcIbmu9opVZk8AL40FOFDNBgfAy2AS9hGZreUmRV\ndV9Zh7UAR+RsEeO51xcU/CKqC8Jb0jL1gkYyUaQy16oe1HF9bRs1PWuNL5mYwsmy\nZNn0ay/a7mb7hxJbza1F3lbgBtodvbgUm7+So/QvaR29CSAqqoUXeQy6FfSBVWhZ\nYlTxdQfKcBcUPFO14BBk/O5p5iQaG8JCLJ/EZGDPDIVDMn7crGQ4oLZJv80eqTeB\n7ueDmWaD3gQ9j2XKsMk1uLSyY4unt9AaTofBylsKD1SjLhyxofGZym4jc2+M1GnQ\nyLcoEMSexnKuextu4nzrA0y5k3z9tvO07R29lwT1GFp6oGAakMLob/6XrGsm3YQY\nRQXgfXKFw8XmXBumqG8ayEIyvQ/O8nO6r4R1H8a7ooj6oWa3PhPsen+gLE0SpJPZ\nz3e2TLliwC4VtZp69H7u3px5Qn1Fc6RMDTh571edCr8=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/displayResult.jpg"},{"url":"https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/admin.jpg"}],"translations":{"en":{"name":"Nextant","summary":"Navigate through your cloud using Solr","description":"\n\t Navigate through your cloud using Solr\n\n\n**Nextant** performs fast and concise _Full-Text Search_ within:\n\n- your own files,\n- shared files,\n- external storage,\n- bookmarks\n\n\n### Recognized file format:\n- plain text,\n- rtf,\n- pdf,\n- html,\n- openoffice,\n- microsoft office,\n- image JPEG and TIFF (will requiert Tesseract installed)\n- pdf with no text layer (will also requiert Tesseract) _[work in progress]_\n\n\n\n## Installation\n\n- [You first need to install a Solr servlet](https://github.com/nextcloud/nextant/wiki)\n- Download the .zip from the appstore, unzip and place this app in **nextcloud/apps/** (or clone the github and build the app yourself)\n- Enable the app in the app list,\n- Edit the settings in the administration page.\n- Extract the current files from your cloud using the **./occ nextant:index** commands\n- Have a look to this [explanation on how Nextant works](https://github.com/nextcloud/nextant/wiki/Extracting,-Live-Update)\n- _(Optional)_ [Installing Tesseract](https://github.com/tesseract-ocr/tesseract/wiki) ([Optical Character Recognition](https://en.wikipedia.org/wiki/Optical_character_recognition) (OCR) Engine) will allow Nextant to extract text from images and pdfs without text layer.\n\n\n\t"}},"isFeatured":false,"authors":[{"name":"Maxence Lange","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIIEAjCCAuoCAhAFMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYwOTE0MTI1NDQwWhcNMjYxMjIxMTI1NDQwWjASMRAwDgYD\nVQQDDAduZXh0YW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsbnQ\n+9acjKHfcrUj4yqBpD++GmQ5z2Sp8C8uOz4ZbLyM9bUXEYHo4a4u3CdC49kGUkb3\np5MkEAEzslTWDi1eh5MZgPWpbPgItsDsXY1o55O3jtxNkzSG5/yYcPQcuKtIOm9S\n7DY0K+UQt3nK+RrXEZfARMNrzFbEzpE3b7w901Yl5n+m/B8rhW4pqg8uSfx3u04J\nwduV1fHwoHUB0Ox5HyWib4Pq1XppNh7xdc2Fg93JxshwuCPJyOOzrFTnxC7s1yzQ\nUvaqkjPW5QeQRunQjZ2XtpYH8f8v01W18bNEiHwqtFwuDEyCVx1rvEMgUDVXdPkP\ngZrlB5TzGmz0U3HzYvf6205WuzfHxz7kPj502wP51PoZBKpniggKzmuXkx6BpsZC\nZX45VpDHdiATLwRj1t2bMs3C01nzpIWO5ZwFtkepH3Y+mvwX5lDh/XDsqJC2Yo8o\nWMmniWNW7dspufYOsBUqqYGP7rkailgVT4oYk6D1j6oFZ5SSpfPF5lsyYedDSM6y\nbIGVkSF+sjLK6R9BenBijKceAKsS//WwRYCBPC+JHlsYpXKW12bL+C47Kj2/N6d4\nrYryzV6ofVSF6pwIq0oEjoyfBfNpYavf3xrRkSSmIIlPSnMY7DT1xkGD5retxSm6\n+WIfkWKRZpv2S6PhMHGLspYc4H5Dj8c48rG5Co8CAwEAATANBgkqhkiG9w0BAQsF\nAAOCAQEAOZUwyPaUi+1BOUgQJMWqYRoTVZUyBshTXSC7jSwa97b7qADV9ooA6TYF\nzgsPcE41k7jRkUbnjcY45RGtL3vqsgZbx5TjPa5fGMxlqJ6eYBOY61Q6VIHEVm3u\nxnPEO9dsMoDBijvo5D7KtE+Ccs907Rq70kCsbrdgPHkyb5tDSnCKogN1LiQrg1EP\nmy7Z1C7jG9/h57vx0+QBMDCYnTmqLsvMKqo27uHskzAiB7VXLEdSZ2FtMGHkLUQO\n0bfhnvTZ2VhMmK83t7ovo71An4ycmsolGD/MA0vNI78VrVISrdI8rRh2WntUnCBU\nEJL3BaQAQaASSsvFrcozYxrQG4VzEg==\n-----END CERTIFICATE-----"}] |
47 | 47 | EOD; |
48 | - public static $expectedResponse = [ |
|
49 | - 'data' |
|
50 | - => [ |
|
51 | - 0 |
|
52 | - => [ |
|
53 | - 'id' => 'direct_menu', |
|
54 | - 'categories' |
|
55 | - => [ |
|
56 | - 0 => 'customization', |
|
57 | - ], |
|
58 | - 'userDocs' => '', |
|
59 | - 'adminDocs' => '', |
|
60 | - 'developerDocs' => '', |
|
61 | - 'issueTracker' => 'https://github.com/juliushaertl/direct_menu/issues', |
|
62 | - 'website' => '', |
|
63 | - 'created' => '2016-10-01T09:16:06.030994Z', |
|
64 | - 'lastModified' => '2016-10-06T14:01:05.584192Z', |
|
65 | - 'releases' |
|
66 | - => [ |
|
67 | - 0 |
|
68 | - => [ |
|
69 | - 'version' => '0.9.2', |
|
70 | - 'phpExtensions' |
|
71 | - => [ |
|
72 | - ], |
|
73 | - 'databases' |
|
74 | - => [ |
|
75 | - ], |
|
76 | - 'shellCommands' |
|
77 | - => [ |
|
78 | - ], |
|
79 | - 'phpVersionSpec' => '*', |
|
80 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
81 | - 'minIntSize' => 32, |
|
82 | - 'download' => 'https://github.com/juliushaertl/direct_menu/releases/download/v0.9.2/direct_menu.tar.gz', |
|
83 | - 'created' => '2016-10-06T14:01:05.578297Z', |
|
84 | - 'licenses' |
|
85 | - => [ |
|
86 | - 0 => 'agpl', |
|
87 | - ], |
|
88 | - 'lastModified' => '2016-10-06T14:01:05.643813Z', |
|
89 | - 'isNightly' => false, |
|
90 | - 'rawPhpVersionSpec' => '*', |
|
91 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
92 | - 'signature' => 'ERBS9G5bZ3vwCizz2Ht5DehsVJmb63bzF3aYcH7xjbDVMPagOFWdUAiLDwTeZR1n |
|
48 | + public static $expectedResponse = [ |
|
49 | + 'data' |
|
50 | + => [ |
|
51 | + 0 |
|
52 | + => [ |
|
53 | + 'id' => 'direct_menu', |
|
54 | + 'categories' |
|
55 | + => [ |
|
56 | + 0 => 'customization', |
|
57 | + ], |
|
58 | + 'userDocs' => '', |
|
59 | + 'adminDocs' => '', |
|
60 | + 'developerDocs' => '', |
|
61 | + 'issueTracker' => 'https://github.com/juliushaertl/direct_menu/issues', |
|
62 | + 'website' => '', |
|
63 | + 'created' => '2016-10-01T09:16:06.030994Z', |
|
64 | + 'lastModified' => '2016-10-06T14:01:05.584192Z', |
|
65 | + 'releases' |
|
66 | + => [ |
|
67 | + 0 |
|
68 | + => [ |
|
69 | + 'version' => '0.9.2', |
|
70 | + 'phpExtensions' |
|
71 | + => [ |
|
72 | + ], |
|
73 | + 'databases' |
|
74 | + => [ |
|
75 | + ], |
|
76 | + 'shellCommands' |
|
77 | + => [ |
|
78 | + ], |
|
79 | + 'phpVersionSpec' => '*', |
|
80 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
81 | + 'minIntSize' => 32, |
|
82 | + 'download' => 'https://github.com/juliushaertl/direct_menu/releases/download/v0.9.2/direct_menu.tar.gz', |
|
83 | + 'created' => '2016-10-06T14:01:05.578297Z', |
|
84 | + 'licenses' |
|
85 | + => [ |
|
86 | + 0 => 'agpl', |
|
87 | + ], |
|
88 | + 'lastModified' => '2016-10-06T14:01:05.643813Z', |
|
89 | + 'isNightly' => false, |
|
90 | + 'rawPhpVersionSpec' => '*', |
|
91 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
92 | + 'signature' => 'ERBS9G5bZ3vwCizz2Ht5DehsVJmb63bzF3aYcH7xjbDVMPagOFWdUAiLDwTeZR1n |
|
93 | 93 | i4gdZ73J/IjHQQJoOPwtCjgbZgLPFqL5x13CLUO9mb/33dZe/+gqEDc/3AuJ4TlA |
94 | 94 | XUdLxHRb1bwIlJOwuSr/E24452VG20WUhLXBoM0Zm7WcMxvJWo2zAWnuqnLX3dy9 |
95 | 95 | cPB4PX+6JU2lUMINj8OYQmM1QnqvjG8YV0cYHbBbnSicOGwXEnni7mojsC8T0cn7 |
@@ -100,42 +100,42 @@ discard block |
||
100 | 100 | bkR1DTBCyDjdpNBidpa3/26675dz5IT5Zedp4BBBREQzX08cIhJx5mgqDdX3CU09 |
101 | 101 | uWtzoaLi71/1BWTFAN+Y9VyfZ8/Z3Pg3vKedRJ565mztIj0geL3riEsC5YnPS0+C |
102 | 102 | +a3B9sDiiOa101EORzX3lrPqL7reEPdCxrIwN+hKFBQ=', |
103 | - 'translations' |
|
104 | - => [ |
|
105 | - ], |
|
106 | - ], |
|
107 | - ], |
|
108 | - 'screenshots' |
|
109 | - => [ |
|
110 | - 0 |
|
111 | - => [ |
|
112 | - 'url' => 'https://bitgrid.net/~jus/direct_menu_nc.png', |
|
113 | - ], |
|
114 | - ], |
|
115 | - 'translations' |
|
116 | - => [ |
|
117 | - 'en' |
|
118 | - => [ |
|
119 | - 'name' => 'Direct Menu', |
|
120 | - 'summary' => 'Provide easy access to all apps in the header.', |
|
121 | - 'description' => 'Provide easy access to all apps in the header.', |
|
122 | - ], |
|
123 | - ], |
|
124 | - 'isFeatured' => false, |
|
125 | - 'authors' |
|
126 | - => [ |
|
127 | - 0 |
|
128 | - => [ |
|
129 | - 'name' => 'Julius Härtl', |
|
130 | - 'mail' => '', |
|
131 | - 'homepage' => '', |
|
132 | - ], |
|
133 | - ], |
|
134 | - 'ratingRecent' => 0.5, |
|
135 | - 'ratingOverall' => 0.5, |
|
136 | - 'ratingNumRecent' => 0, |
|
137 | - 'ratingNumOverall' => 0, |
|
138 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
103 | + 'translations' |
|
104 | + => [ |
|
105 | + ], |
|
106 | + ], |
|
107 | + ], |
|
108 | + 'screenshots' |
|
109 | + => [ |
|
110 | + 0 |
|
111 | + => [ |
|
112 | + 'url' => 'https://bitgrid.net/~jus/direct_menu_nc.png', |
|
113 | + ], |
|
114 | + ], |
|
115 | + 'translations' |
|
116 | + => [ |
|
117 | + 'en' |
|
118 | + => [ |
|
119 | + 'name' => 'Direct Menu', |
|
120 | + 'summary' => 'Provide easy access to all apps in the header.', |
|
121 | + 'description' => 'Provide easy access to all apps in the header.', |
|
122 | + ], |
|
123 | + ], |
|
124 | + 'isFeatured' => false, |
|
125 | + 'authors' |
|
126 | + => [ |
|
127 | + 0 |
|
128 | + => [ |
|
129 | + 'name' => 'Julius Härtl', |
|
130 | + 'mail' => '', |
|
131 | + 'homepage' => '', |
|
132 | + ], |
|
133 | + ], |
|
134 | + 'ratingRecent' => 0.5, |
|
135 | + 'ratingOverall' => 0.5, |
|
136 | + 'ratingNumRecent' => 0, |
|
137 | + 'ratingNumOverall' => 0, |
|
138 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
139 | 139 | MIIEBjCCAu4CAhADMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
140 | 140 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
141 | 141 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -159,68 +159,68 @@ discard block |
||
159 | 159 | G2dF9Gtu4GiQ5fuaJknaxlgXHovfqeZwZJX9o4M+Ug81AqiY7XjdiaCPdh0Tthcx |
160 | 160 | 2OmWZo7UBREWenjKyFZZ/iKoqH5sdenBtpo= |
161 | 161 | -----END CERTIFICATE-----', |
162 | - ], |
|
163 | - 1 |
|
164 | - => [ |
|
165 | - 'id' => 'apporder', |
|
166 | - 'categories' |
|
167 | - => [ |
|
168 | - 0 => 'customization', |
|
169 | - ], |
|
170 | - 'userDocs' => '', |
|
171 | - 'adminDocs' => '', |
|
172 | - 'developerDocs' => '', |
|
173 | - 'issueTracker' => 'https://github.com/juliushaertl/apporder/issues', |
|
174 | - 'website' => '', |
|
175 | - 'created' => '2016-10-01T09:16:47.111889Z', |
|
176 | - 'lastModified' => '2016-10-12T19:50:16.038821Z', |
|
177 | - 'releases' |
|
178 | - => [ |
|
179 | - 0 |
|
180 | - => [ |
|
181 | - 'version' => '0.3.3', |
|
182 | - 'phpExtensions' |
|
183 | - => [ |
|
184 | - ], |
|
185 | - 'databases' |
|
186 | - => [ |
|
187 | - ], |
|
188 | - 'shellCommands' |
|
189 | - => [ |
|
190 | - ], |
|
191 | - 'phpVersionSpec' => '*', |
|
192 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
193 | - 'minIntSize' => 32, |
|
194 | - 'download' => 'https://github.com/juliushaertl/apporder/releases/download/0.3.3/apporder.tar.gz', |
|
195 | - 'created' => '2016-10-12T19:14:10.802359Z', |
|
196 | - 'licenses' |
|
197 | - => [ |
|
198 | - 0 => 'agpl', |
|
199 | - ], |
|
200 | - 'lastModified' => '2016-10-12T19:50:16.104357Z', |
|
201 | - 'isNightly' => false, |
|
202 | - 'rawPhpVersionSpec' => '*', |
|
203 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
204 | - 'signature' => 'nhlT9lhrmBxIsqh/e3RLm2NDw/U8ZvvoMyYQTLMM3H19DQmVcPYPYC9QWVTsowUzXblVaOXVGylbpKma9yOlOAqJtF3qyXecLl4+tA/Awb6BBhKPgHFdcLDAL5yy1K7/uei3SgEojMlJoI9vEK5I1C5YTh43yNH+//Im6MAuNYFUTlMXK426zdOe6ogpCI5GlYdXopqYANxcpT+WXWET6DDSM5Ev+MYwMcSAY4r8+tvARRU4ZAenRgjkBT6R5z6cD76emRax14tbV6vkjjwRcO+dQtM0tFPbd+5fsNInbauv50VzIMgjA6RnKTOI17gRsSdGlsV4vZn2aIxEPWauu6T/UohMvAE9HMn13vtbpPBSFwJAktj6yHASYGzupNQLprA0+OdyALoLZPpQAKNEXA42a4EVISBKu0EmduHJlUPeqhnIGkkGgVNWS8AWqzP2nFoPdXBgUWateiMcBTHxgEKDac5YmNc9lsXpzf1OxBaXHBhGYKuXPwIfyH3jTWb1OdwixJEuRe9dl63T9qOTRre8QWns/bMqKLibGfMtFhVB21ARJayBuX70eVvabG/2N7Y5t1zUlFygIKu51tvo3AVCRDdRrFWDvkAjxzIz5FIdALVZ+DReFYu/r4WF/w3V9rInFuEDSwb/OH4r8sQycs07tSlMyA74Y3FpjKTBxso=', |
|
205 | - 'translations' |
|
206 | - => [ |
|
207 | - ], |
|
208 | - ], |
|
209 | - ], |
|
210 | - 'screenshots' |
|
211 | - => [ |
|
212 | - 0 |
|
213 | - => [ |
|
214 | - 'url' => 'https://bitgrid.net/~jus/apporder-nc.gif', |
|
215 | - ], |
|
216 | - ], |
|
217 | - 'translations' |
|
218 | - => [ |
|
219 | - 'en' |
|
220 | - => [ |
|
221 | - 'name' => 'AppOrder', |
|
222 | - 'summary' => 'Sort apps in the menu with drag and drop', |
|
223 | - 'description' => ' |
|
162 | + ], |
|
163 | + 1 |
|
164 | + => [ |
|
165 | + 'id' => 'apporder', |
|
166 | + 'categories' |
|
167 | + => [ |
|
168 | + 0 => 'customization', |
|
169 | + ], |
|
170 | + 'userDocs' => '', |
|
171 | + 'adminDocs' => '', |
|
172 | + 'developerDocs' => '', |
|
173 | + 'issueTracker' => 'https://github.com/juliushaertl/apporder/issues', |
|
174 | + 'website' => '', |
|
175 | + 'created' => '2016-10-01T09:16:47.111889Z', |
|
176 | + 'lastModified' => '2016-10-12T19:50:16.038821Z', |
|
177 | + 'releases' |
|
178 | + => [ |
|
179 | + 0 |
|
180 | + => [ |
|
181 | + 'version' => '0.3.3', |
|
182 | + 'phpExtensions' |
|
183 | + => [ |
|
184 | + ], |
|
185 | + 'databases' |
|
186 | + => [ |
|
187 | + ], |
|
188 | + 'shellCommands' |
|
189 | + => [ |
|
190 | + ], |
|
191 | + 'phpVersionSpec' => '*', |
|
192 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
193 | + 'minIntSize' => 32, |
|
194 | + 'download' => 'https://github.com/juliushaertl/apporder/releases/download/0.3.3/apporder.tar.gz', |
|
195 | + 'created' => '2016-10-12T19:14:10.802359Z', |
|
196 | + 'licenses' |
|
197 | + => [ |
|
198 | + 0 => 'agpl', |
|
199 | + ], |
|
200 | + 'lastModified' => '2016-10-12T19:50:16.104357Z', |
|
201 | + 'isNightly' => false, |
|
202 | + 'rawPhpVersionSpec' => '*', |
|
203 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
204 | + 'signature' => 'nhlT9lhrmBxIsqh/e3RLm2NDw/U8ZvvoMyYQTLMM3H19DQmVcPYPYC9QWVTsowUzXblVaOXVGylbpKma9yOlOAqJtF3qyXecLl4+tA/Awb6BBhKPgHFdcLDAL5yy1K7/uei3SgEojMlJoI9vEK5I1C5YTh43yNH+//Im6MAuNYFUTlMXK426zdOe6ogpCI5GlYdXopqYANxcpT+WXWET6DDSM5Ev+MYwMcSAY4r8+tvARRU4ZAenRgjkBT6R5z6cD76emRax14tbV6vkjjwRcO+dQtM0tFPbd+5fsNInbauv50VzIMgjA6RnKTOI17gRsSdGlsV4vZn2aIxEPWauu6T/UohMvAE9HMn13vtbpPBSFwJAktj6yHASYGzupNQLprA0+OdyALoLZPpQAKNEXA42a4EVISBKu0EmduHJlUPeqhnIGkkGgVNWS8AWqzP2nFoPdXBgUWateiMcBTHxgEKDac5YmNc9lsXpzf1OxBaXHBhGYKuXPwIfyH3jTWb1OdwixJEuRe9dl63T9qOTRre8QWns/bMqKLibGfMtFhVB21ARJayBuX70eVvabG/2N7Y5t1zUlFygIKu51tvo3AVCRDdRrFWDvkAjxzIz5FIdALVZ+DReFYu/r4WF/w3V9rInFuEDSwb/OH4r8sQycs07tSlMyA74Y3FpjKTBxso=', |
|
205 | + 'translations' |
|
206 | + => [ |
|
207 | + ], |
|
208 | + ], |
|
209 | + ], |
|
210 | + 'screenshots' |
|
211 | + => [ |
|
212 | + 0 |
|
213 | + => [ |
|
214 | + 'url' => 'https://bitgrid.net/~jus/apporder-nc.gif', |
|
215 | + ], |
|
216 | + ], |
|
217 | + 'translations' |
|
218 | + => [ |
|
219 | + 'en' |
|
220 | + => [ |
|
221 | + 'name' => 'AppOrder', |
|
222 | + 'summary' => 'Sort apps in the menu with drag and drop', |
|
223 | + 'description' => ' |
|
224 | 224 | Enable sorting for icons inside the app menu. The order will be saved for each |
225 | 225 | user individually. Administrators can define a custom default order. |
226 | 226 | AppOrder works with the default owncloud menu as well as with the direct_menu |
@@ -240,23 +240,23 @@ discard block |
||
240 | 240 | Users will now get redirected to the first app of the default order or to the |
241 | 241 | first app of the user order. |
242 | 242 | ', |
243 | - ], |
|
244 | - ], |
|
245 | - 'isFeatured' => false, |
|
246 | - 'authors' |
|
247 | - => [ |
|
248 | - 0 |
|
249 | - => [ |
|
250 | - 'name' => 'Julius Härtl', |
|
251 | - 'mail' => '[email protected]', |
|
252 | - 'homepage' => '', |
|
253 | - ], |
|
254 | - ], |
|
255 | - 'ratingRecent' => 0.5, |
|
256 | - 'ratingOverall' => 0.5, |
|
257 | - 'ratingNumRecent' => 0, |
|
258 | - 'ratingNumOverall' => 0, |
|
259 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
243 | + ], |
|
244 | + ], |
|
245 | + 'isFeatured' => false, |
|
246 | + 'authors' |
|
247 | + => [ |
|
248 | + 0 |
|
249 | + => [ |
|
250 | + 'name' => 'Julius Härtl', |
|
251 | + 'mail' => '[email protected]', |
|
252 | + 'homepage' => '', |
|
253 | + ], |
|
254 | + ], |
|
255 | + 'ratingRecent' => 0.5, |
|
256 | + 'ratingOverall' => 0.5, |
|
257 | + 'ratingNumRecent' => 0, |
|
258 | + 'ratingNumOverall' => 0, |
|
259 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
260 | 260 | MIIEAzCCAusCAhAEMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
261 | 261 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
262 | 262 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -280,49 +280,49 @@ discard block |
||
280 | 280 | Tu+WGOL2Ee5U4k4XFdzeSLODWby08iU+Gx3bXTR6WIvXCYeIVsCPKK/luvfGkiSR |
281 | 281 | CpW1GUIA1cyulT4uyHf9g6BMdYVOsFQ= |
282 | 282 | -----END CERTIFICATE-----', |
283 | - ], |
|
284 | - 2 |
|
285 | - => [ |
|
286 | - 'id' => 'twofactor_totp', |
|
287 | - 'categories' |
|
288 | - => [ |
|
289 | - 0 => 'tools', |
|
290 | - ], |
|
291 | - 'userDocs' => '', |
|
292 | - 'adminDocs' => '', |
|
293 | - 'developerDocs' => '', |
|
294 | - 'issueTracker' => '', |
|
295 | - 'website' => '', |
|
296 | - 'created' => '2016-10-08T14:13:54.356716Z', |
|
297 | - 'lastModified' => '2016-10-12T14:38:56.186269Z', |
|
298 | - 'releases' |
|
299 | - => [ |
|
300 | - 0 |
|
301 | - => [ |
|
302 | - 'version' => '0.4.1', |
|
303 | - 'phpExtensions' |
|
304 | - => [ |
|
305 | - ], |
|
306 | - 'databases' |
|
307 | - => [ |
|
308 | - ], |
|
309 | - 'shellCommands' |
|
310 | - => [ |
|
311 | - ], |
|
312 | - 'phpVersionSpec' => '>=5.4.0 <7.1.0', |
|
313 | - 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
314 | - 'minIntSize' => 32, |
|
315 | - 'download' => 'https://github.com/ChristophWurst/twofactor_totp/releases/download/0.4.1/twofactor_totp.tar.gz', |
|
316 | - 'created' => '2016-10-12T14:38:56.174612Z', |
|
317 | - 'licenses' |
|
318 | - => [ |
|
319 | - 0 => 'agpl', |
|
320 | - ], |
|
321 | - 'lastModified' => '2016-10-12T14:38:56.248223Z', |
|
322 | - 'isNightly' => false, |
|
323 | - 'rawPhpVersionSpec' => '>=5.4 <=7.0', |
|
324 | - 'rawPlatformVersionSpec' => '>=10 <=11', |
|
325 | - 'signature' => 'bnwWxmHEn8xkoWbtwhC1kIrJ0dQfAI3PUtU62k+Tru/BHt1G2aVxqO8bCdghojZ7 |
|
283 | + ], |
|
284 | + 2 |
|
285 | + => [ |
|
286 | + 'id' => 'twofactor_totp', |
|
287 | + 'categories' |
|
288 | + => [ |
|
289 | + 0 => 'tools', |
|
290 | + ], |
|
291 | + 'userDocs' => '', |
|
292 | + 'adminDocs' => '', |
|
293 | + 'developerDocs' => '', |
|
294 | + 'issueTracker' => '', |
|
295 | + 'website' => '', |
|
296 | + 'created' => '2016-10-08T14:13:54.356716Z', |
|
297 | + 'lastModified' => '2016-10-12T14:38:56.186269Z', |
|
298 | + 'releases' |
|
299 | + => [ |
|
300 | + 0 |
|
301 | + => [ |
|
302 | + 'version' => '0.4.1', |
|
303 | + 'phpExtensions' |
|
304 | + => [ |
|
305 | + ], |
|
306 | + 'databases' |
|
307 | + => [ |
|
308 | + ], |
|
309 | + 'shellCommands' |
|
310 | + => [ |
|
311 | + ], |
|
312 | + 'phpVersionSpec' => '>=5.4.0 <7.1.0', |
|
313 | + 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
314 | + 'minIntSize' => 32, |
|
315 | + 'download' => 'https://github.com/ChristophWurst/twofactor_totp/releases/download/0.4.1/twofactor_totp.tar.gz', |
|
316 | + 'created' => '2016-10-12T14:38:56.174612Z', |
|
317 | + 'licenses' |
|
318 | + => [ |
|
319 | + 0 => 'agpl', |
|
320 | + ], |
|
321 | + 'lastModified' => '2016-10-12T14:38:56.248223Z', |
|
322 | + 'isNightly' => false, |
|
323 | + 'rawPhpVersionSpec' => '>=5.4 <=7.0', |
|
324 | + 'rawPlatformVersionSpec' => '>=10 <=11', |
|
325 | + 'signature' => 'bnwWxmHEn8xkoWbtwhC1kIrJ0dQfAI3PUtU62k+Tru/BHt1G2aVxqO8bCdghojZ7 |
|
326 | 326 | zdFMlIJw4kekYFsVfLk8jzjUTZKVbNVKCdkHrVTQ0bUUryMAMLqGQ3PSRI5NX6D5 |
327 | 327 | FpkvwO1coYwU0XVWF8KAS0meX0ztSkT3Mv96LLrxr8F8SrB/MGmKIE4WTjt1fAIa |
328 | 328 | ZLAVEUo/3sNFTGLYBtL3wjctrkZvJltP8abeRfls9FkRHu+rN7R3uLFzk42uZn3X |
@@ -333,38 +333,38 @@ discard block |
||
333 | 333 | 3y+csRqpEJYd9fcVMPsTu7WBRRrpBsAqdAHJcZEwak2kz1kdOgSf8FIzP1z6Q71d |
334 | 334 | Ml2RKcPeutMHHSLiGIN/h7fM5aSs49wGgGZmfz28fHVd7/U0HFSMYmkT/GMq5tMP |
335 | 335 | Iyc+QZAN4qbX8G0k/QSTkK/L4lOT2hQiQqiSqmWItMk=', |
336 | - 'translations' |
|
337 | - => [ |
|
338 | - ], |
|
339 | - ], |
|
340 | - ], |
|
341 | - 'screenshots' |
|
342 | - => [ |
|
343 | - ], |
|
344 | - 'translations' |
|
345 | - => [ |
|
346 | - 'en' |
|
347 | - => [ |
|
348 | - 'name' => 'Two Factor TOTP Provider', |
|
349 | - 'summary' => 'A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)', |
|
350 | - 'description' => 'A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)', |
|
351 | - ], |
|
352 | - ], |
|
353 | - 'isFeatured' => true, |
|
354 | - 'authors' |
|
355 | - => [ |
|
356 | - 0 |
|
357 | - => [ |
|
358 | - 'name' => 'Christoph Wurst', |
|
359 | - 'mail' => '', |
|
360 | - 'homepage' => '', |
|
361 | - ], |
|
362 | - ], |
|
363 | - 'ratingRecent' => 0.5, |
|
364 | - 'ratingOverall' => 0.5, |
|
365 | - 'ratingNumRecent' => 0, |
|
366 | - 'ratingNumOverall' => 0, |
|
367 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
336 | + 'translations' |
|
337 | + => [ |
|
338 | + ], |
|
339 | + ], |
|
340 | + ], |
|
341 | + 'screenshots' |
|
342 | + => [ |
|
343 | + ], |
|
344 | + 'translations' |
|
345 | + => [ |
|
346 | + 'en' |
|
347 | + => [ |
|
348 | + 'name' => 'Two Factor TOTP Provider', |
|
349 | + 'summary' => 'A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)', |
|
350 | + 'description' => 'A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)', |
|
351 | + ], |
|
352 | + ], |
|
353 | + 'isFeatured' => true, |
|
354 | + 'authors' |
|
355 | + => [ |
|
356 | + 0 |
|
357 | + => [ |
|
358 | + 'name' => 'Christoph Wurst', |
|
359 | + 'mail' => '', |
|
360 | + 'homepage' => '', |
|
361 | + ], |
|
362 | + ], |
|
363 | + 'ratingRecent' => 0.5, |
|
364 | + 'ratingOverall' => 0.5, |
|
365 | + 'ratingNumRecent' => 0, |
|
366 | + 'ratingNumOverall' => 0, |
|
367 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
368 | 368 | MIIECTCCAvECAhASMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
369 | 369 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
370 | 370 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -388,51 +388,51 @@ discard block |
||
388 | 388 | VMgQ6yUWNuzOQMZpMIV7RMOUZHvxiX/ZWUFzXNYX0GYub6p4O2uh3LJE+xXyDf77 |
389 | 389 | RBO7PLY3m4TXCeKesxZlkoGke+lnq7B8tkADdPI= |
390 | 390 | -----END CERTIFICATE-----', |
391 | - ], |
|
392 | - 3 |
|
393 | - => [ |
|
394 | - 'id' => 'contacts', |
|
395 | - 'categories' |
|
396 | - => [ |
|
397 | - 0 => 'office', |
|
398 | - 1 => 'organization', |
|
399 | - 2 => 'social', |
|
400 | - ], |
|
401 | - 'userDocs' => 'https://docs.nextcloud.com/server/11/user_manual/pim/contacts.html', |
|
402 | - 'adminDocs' => 'https://docs.nextcloud.com/server/11/admin_manual/configuration_server/occ_command.html?highlight=occ%20commands#dav-label', |
|
403 | - 'developerDocs' => 'https://github.com/nextcloud/contacts#building-the-app', |
|
404 | - 'issueTracker' => 'https://github.com/nextcloud/contacts/issues', |
|
405 | - 'website' => 'https://github.com/nextcloud/contacts#readme', |
|
406 | - 'created' => '2016-10-30T14:00:58.922766Z', |
|
407 | - 'lastModified' => '2016-11-22T22:08:01.904319Z', |
|
408 | - 'releases' |
|
409 | - => [ |
|
410 | - 0 |
|
411 | - => [ |
|
412 | - 'version' => '1.5.0', |
|
413 | - 'phpExtensions' |
|
414 | - => [ |
|
415 | - ], |
|
416 | - 'databases' |
|
417 | - => [ |
|
418 | - ], |
|
419 | - 'shellCommands' |
|
420 | - => [ |
|
421 | - ], |
|
422 | - 'phpVersionSpec' => '*', |
|
423 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
424 | - 'minIntSize' => 32, |
|
425 | - 'download' => 'https://github.com/nextcloud/contacts/releases/download/v1.5.0/contacts.tar.gz', |
|
426 | - 'created' => '2016-11-22T22:08:01.861942Z', |
|
427 | - 'licenses' |
|
428 | - => [ |
|
429 | - 0 => 'agpl', |
|
430 | - ], |
|
431 | - 'lastModified' => '2016-11-22T22:08:02.306939Z', |
|
432 | - 'isNightly' => false, |
|
433 | - 'rawPhpVersionSpec' => '*', |
|
434 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
435 | - 'signature' => 'ZqqhqtbHcNB+rzGCQ7FDIjjvHjit+dhAE1UhFgiXApkx3tmPP4nJOBAGNjHe+2Ao |
|
391 | + ], |
|
392 | + 3 |
|
393 | + => [ |
|
394 | + 'id' => 'contacts', |
|
395 | + 'categories' |
|
396 | + => [ |
|
397 | + 0 => 'office', |
|
398 | + 1 => 'organization', |
|
399 | + 2 => 'social', |
|
400 | + ], |
|
401 | + 'userDocs' => 'https://docs.nextcloud.com/server/11/user_manual/pim/contacts.html', |
|
402 | + 'adminDocs' => 'https://docs.nextcloud.com/server/11/admin_manual/configuration_server/occ_command.html?highlight=occ%20commands#dav-label', |
|
403 | + 'developerDocs' => 'https://github.com/nextcloud/contacts#building-the-app', |
|
404 | + 'issueTracker' => 'https://github.com/nextcloud/contacts/issues', |
|
405 | + 'website' => 'https://github.com/nextcloud/contacts#readme', |
|
406 | + 'created' => '2016-10-30T14:00:58.922766Z', |
|
407 | + 'lastModified' => '2016-11-22T22:08:01.904319Z', |
|
408 | + 'releases' |
|
409 | + => [ |
|
410 | + 0 |
|
411 | + => [ |
|
412 | + 'version' => '1.5.0', |
|
413 | + 'phpExtensions' |
|
414 | + => [ |
|
415 | + ], |
|
416 | + 'databases' |
|
417 | + => [ |
|
418 | + ], |
|
419 | + 'shellCommands' |
|
420 | + => [ |
|
421 | + ], |
|
422 | + 'phpVersionSpec' => '*', |
|
423 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
424 | + 'minIntSize' => 32, |
|
425 | + 'download' => 'https://github.com/nextcloud/contacts/releases/download/v1.5.0/contacts.tar.gz', |
|
426 | + 'created' => '2016-11-22T22:08:01.861942Z', |
|
427 | + 'licenses' |
|
428 | + => [ |
|
429 | + 0 => 'agpl', |
|
430 | + ], |
|
431 | + 'lastModified' => '2016-11-22T22:08:02.306939Z', |
|
432 | + 'isNightly' => false, |
|
433 | + 'rawPhpVersionSpec' => '*', |
|
434 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
435 | + 'signature' => 'ZqqhqtbHcNB+rzGCQ7FDIjjvHjit+dhAE1UhFgiXApkx3tmPP4nJOBAGNjHe+2Ao |
|
436 | 436 | VcTIX2SrWEfieRrA4Gp+0k7pUPWag1Z0T1OVOwO4cmS1AVFyGIOE1bRvDhMfsWTU |
437 | 437 | 4CI4oXaKBFAY6mtnf7VJ7EeIdNqhImkohyWDQ88NiPRLM1XNkJJk6AvZBcT0fvCv |
438 | 438 | o145X4dLpbixSXsN99QFNJ/oXvK+9tBGwTd5i/WnNFY90vcNRLia8aRo7SA0YJRx |
@@ -443,54 +443,54 @@ discard block |
||
443 | 443 | H3aH8GljatAFjrwItw1JzR0THt0ukkOK+bw/pfCslk10sjHMitmz/GXa4qMS91DZ |
444 | 444 | BKLUd0dSfQUQzkfwcojImbzJRvca4/DYe3mfG7+RCH0tDL6t72dKL9joB++u5R1u |
445 | 445 | VZPgkToexlXcKWpiDB8H2/SEShKr4udAOjR5de9CYWM=', |
446 | - 'translations' |
|
447 | - => [ |
|
448 | - ], |
|
449 | - ], |
|
450 | - ], |
|
451 | - 'screenshots' |
|
452 | - => [ |
|
453 | - 0 |
|
454 | - => [ |
|
455 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/screenshots/master/apps/Contacts/contacts.png', |
|
456 | - ], |
|
457 | - ], |
|
458 | - 'translations' |
|
459 | - => [ |
|
460 | - 'en' |
|
461 | - => [ |
|
462 | - 'name' => 'Contacts', |
|
463 | - 'summary' => 'The new and improved app for your Contacts.', |
|
464 | - 'description' => 'The new and improved app for your Contacts.', |
|
465 | - ], |
|
466 | - ], |
|
467 | - 'isFeatured' => true, |
|
468 | - 'authors' |
|
469 | - => [ |
|
470 | - 0 |
|
471 | - => [ |
|
472 | - 'name' => 'Alexander Weidinger', |
|
473 | - 'mail' => '', |
|
474 | - 'homepage' => '', |
|
475 | - ], |
|
476 | - 1 |
|
477 | - => [ |
|
478 | - 'name' => 'Jan-Christoph Borchardt', |
|
479 | - 'mail' => '', |
|
480 | - 'homepage' => '', |
|
481 | - ], |
|
482 | - 2 |
|
483 | - => [ |
|
484 | - 'name' => 'Hendrik Leppelsack', |
|
485 | - 'mail' => '', |
|
486 | - 'homepage' => '', |
|
487 | - ], |
|
488 | - ], |
|
489 | - 'ratingRecent' => 0.5, |
|
490 | - 'ratingOverall' => 0.5, |
|
491 | - 'ratingNumRecent' => 0, |
|
492 | - 'ratingNumOverall' => 0, |
|
493 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
446 | + 'translations' |
|
447 | + => [ |
|
448 | + ], |
|
449 | + ], |
|
450 | + ], |
|
451 | + 'screenshots' |
|
452 | + => [ |
|
453 | + 0 |
|
454 | + => [ |
|
455 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/screenshots/master/apps/Contacts/contacts.png', |
|
456 | + ], |
|
457 | + ], |
|
458 | + 'translations' |
|
459 | + => [ |
|
460 | + 'en' |
|
461 | + => [ |
|
462 | + 'name' => 'Contacts', |
|
463 | + 'summary' => 'The new and improved app for your Contacts.', |
|
464 | + 'description' => 'The new and improved app for your Contacts.', |
|
465 | + ], |
|
466 | + ], |
|
467 | + 'isFeatured' => true, |
|
468 | + 'authors' |
|
469 | + => [ |
|
470 | + 0 |
|
471 | + => [ |
|
472 | + 'name' => 'Alexander Weidinger', |
|
473 | + 'mail' => '', |
|
474 | + 'homepage' => '', |
|
475 | + ], |
|
476 | + 1 |
|
477 | + => [ |
|
478 | + 'name' => 'Jan-Christoph Borchardt', |
|
479 | + 'mail' => '', |
|
480 | + 'homepage' => '', |
|
481 | + ], |
|
482 | + 2 |
|
483 | + => [ |
|
484 | + 'name' => 'Hendrik Leppelsack', |
|
485 | + 'mail' => '', |
|
486 | + 'homepage' => '', |
|
487 | + ], |
|
488 | + ], |
|
489 | + 'ratingRecent' => 0.5, |
|
490 | + 'ratingOverall' => 0.5, |
|
491 | + 'ratingNumRecent' => 0, |
|
492 | + 'ratingNumOverall' => 0, |
|
493 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
494 | 494 | MIIEAzCCAusCAhATMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
495 | 495 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
496 | 496 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -514,49 +514,49 @@ discard block |
||
514 | 514 | Gld7yCP47xNPaAZEC66odcClvNtJ2Clgp8739jD6uJJCqcKDejeef0VU1PG7AXId |
515 | 515 | 52bVrGMxJwOuL1393vKxGH0PHDzcB1M= |
516 | 516 | -----END CERTIFICATE-----', |
517 | - ], |
|
518 | - 4 |
|
519 | - => [ |
|
520 | - 'id' => 'mail', |
|
521 | - 'categories' |
|
522 | - => [ |
|
523 | - 0 => 'tools', |
|
524 | - ], |
|
525 | - 'userDocs' => '', |
|
526 | - 'adminDocs' => 'https://github.com/nextcloud/mail#readme', |
|
527 | - 'developerDocs' => '', |
|
528 | - 'issueTracker' => '', |
|
529 | - 'website' => '', |
|
530 | - 'created' => '2016-10-19T19:41:41.710285Z', |
|
531 | - 'lastModified' => '2016-10-19T19:57:33.689238Z', |
|
532 | - 'releases' |
|
533 | - => [ |
|
534 | - 0 |
|
535 | - => [ |
|
536 | - 'version' => '0.6.0', |
|
537 | - 'phpExtensions' |
|
538 | - => [ |
|
539 | - ], |
|
540 | - 'databases' |
|
541 | - => [ |
|
542 | - ], |
|
543 | - 'shellCommands' |
|
544 | - => [ |
|
545 | - ], |
|
546 | - 'phpVersionSpec' => '>=5.4.0 <7.1.0', |
|
547 | - 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
548 | - 'minIntSize' => 32, |
|
549 | - 'download' => 'https://github.com/nextcloud/mail/releases/download/v0.6.0/mail.tar.gz', |
|
550 | - 'created' => '2016-10-19T19:57:33.676730Z', |
|
551 | - 'licenses' |
|
552 | - => [ |
|
553 | - 0 => 'agpl', |
|
554 | - ], |
|
555 | - 'lastModified' => '2016-10-19T19:57:33.834580Z', |
|
556 | - 'isNightly' => false, |
|
557 | - 'rawPhpVersionSpec' => '>=5.4 <=7.0', |
|
558 | - 'rawPlatformVersionSpec' => '>=10 <=11', |
|
559 | - 'signature' => 'VbMsvDpt+gSPeFM8LrZXEK10rk8kkLlgCcblgqNdCSeGZeVpwDAYv3CccVSLa0+l |
|
517 | + ], |
|
518 | + 4 |
|
519 | + => [ |
|
520 | + 'id' => 'mail', |
|
521 | + 'categories' |
|
522 | + => [ |
|
523 | + 0 => 'tools', |
|
524 | + ], |
|
525 | + 'userDocs' => '', |
|
526 | + 'adminDocs' => 'https://github.com/nextcloud/mail#readme', |
|
527 | + 'developerDocs' => '', |
|
528 | + 'issueTracker' => '', |
|
529 | + 'website' => '', |
|
530 | + 'created' => '2016-10-19T19:41:41.710285Z', |
|
531 | + 'lastModified' => '2016-10-19T19:57:33.689238Z', |
|
532 | + 'releases' |
|
533 | + => [ |
|
534 | + 0 |
|
535 | + => [ |
|
536 | + 'version' => '0.6.0', |
|
537 | + 'phpExtensions' |
|
538 | + => [ |
|
539 | + ], |
|
540 | + 'databases' |
|
541 | + => [ |
|
542 | + ], |
|
543 | + 'shellCommands' |
|
544 | + => [ |
|
545 | + ], |
|
546 | + 'phpVersionSpec' => '>=5.4.0 <7.1.0', |
|
547 | + 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
548 | + 'minIntSize' => 32, |
|
549 | + 'download' => 'https://github.com/nextcloud/mail/releases/download/v0.6.0/mail.tar.gz', |
|
550 | + 'created' => '2016-10-19T19:57:33.676730Z', |
|
551 | + 'licenses' |
|
552 | + => [ |
|
553 | + 0 => 'agpl', |
|
554 | + ], |
|
555 | + 'lastModified' => '2016-10-19T19:57:33.834580Z', |
|
556 | + 'isNightly' => false, |
|
557 | + 'rawPhpVersionSpec' => '>=5.4 <=7.0', |
|
558 | + 'rawPlatformVersionSpec' => '>=10 <=11', |
|
559 | + 'signature' => 'VbMsvDpt+gSPeFM8LrZXEK10rk8kkLlgCcblgqNdCSeGZeVpwDAYv3CccVSLa0+l |
|
560 | 560 | lTSqQ0VIoH+OIU6vIQNBKHmSCzTplk7OrY0+L5FajXx8LnBaOh892GfGSlEt1neN |
561 | 561 | KyM0i0uOjO/xpCP/NoUlgkz6hnmYY5XEdN6DTsJtJ/XZhDQ45IYuIkMkHE/eFehS |
562 | 562 | 0JnOagIz+PSipeBY2Ry+tV8YbRa7bC1JAvZzlod0dyI015AHZESeitRUY+MwMWkt |
@@ -567,11 +567,11 @@ discard block |
||
567 | 567 | D4c6b+qYn68kx3CLaPPiz+tFAZQZQdj7+Kx/lohso8yTnVSiGYrMj4IvvCbpsQjg |
568 | 568 | WF3WSqF/K/tTnPYTWb9NUPSihTbVNv6AXOfTsPEp/ba2YSS5DjvjVjkr5vhR9eg1 |
569 | 569 | ikQ3Cw6lW3vaA4LVCC+hFkMRnI4N0bo5qQavP3PnZPc=', |
570 | - 'translations' |
|
571 | - => [ |
|
572 | - 'en' |
|
573 | - => [ |
|
574 | - 'changelog' => '### Added |
|
570 | + 'translations' |
|
571 | + => [ |
|
572 | + 'en' |
|
573 | + => [ |
|
574 | + 'changelog' => '### Added |
|
575 | 575 | - Alias support |
576 | 576 | [#1523](https://github.com/owncloud/mail/pull/1523) @tahaalibra |
577 | 577 | - New incoming messages are prefetched |
@@ -604,37 +604,37 @@ discard block |
||
604 | 604 | [#1603](https://github.com/owncloud/mail/pull/1603) @ChristophWurst |
605 | 605 | - Update folder counters when reading/deleting messages |
606 | 606 | [#1585](https://github.com/owncloud/mail/pull/1585)', |
607 | - ], |
|
608 | - ], |
|
609 | - ], |
|
610 | - ], |
|
611 | - 'screenshots' |
|
612 | - => [ |
|
613 | - ], |
|
614 | - 'translations' |
|
615 | - => [ |
|
616 | - 'en' |
|
617 | - => [ |
|
618 | - 'name' => 'Mail', |
|
619 | - 'summary' => 'Easy to use email client which connects to your mail server via IMAP and SMTP.', |
|
620 | - 'description' => 'Easy to use email client which connects to your mail server via IMAP and SMTP.', |
|
621 | - ], |
|
622 | - ], |
|
623 | - 'isFeatured' => false, |
|
624 | - 'authors' |
|
625 | - => [ |
|
626 | - 0 |
|
627 | - => [ |
|
628 | - 'name' => 'Christoph Wurst, Thomas Müller, Jan-Christoph Borchardt, Steffen Lindner & many more …', |
|
629 | - 'mail' => '', |
|
630 | - 'homepage' => '', |
|
631 | - ], |
|
632 | - ], |
|
633 | - 'ratingRecent' => 0.5, |
|
634 | - 'ratingOverall' => 0.5, |
|
635 | - 'ratingNumRecent' => 0, |
|
636 | - 'ratingNumOverall' => 0, |
|
637 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
607 | + ], |
|
608 | + ], |
|
609 | + ], |
|
610 | + ], |
|
611 | + 'screenshots' |
|
612 | + => [ |
|
613 | + ], |
|
614 | + 'translations' |
|
615 | + => [ |
|
616 | + 'en' |
|
617 | + => [ |
|
618 | + 'name' => 'Mail', |
|
619 | + 'summary' => 'Easy to use email client which connects to your mail server via IMAP and SMTP.', |
|
620 | + 'description' => 'Easy to use email client which connects to your mail server via IMAP and SMTP.', |
|
621 | + ], |
|
622 | + ], |
|
623 | + 'isFeatured' => false, |
|
624 | + 'authors' |
|
625 | + => [ |
|
626 | + 0 |
|
627 | + => [ |
|
628 | + 'name' => 'Christoph Wurst, Thomas Müller, Jan-Christoph Borchardt, Steffen Lindner & many more …', |
|
629 | + 'mail' => '', |
|
630 | + 'homepage' => '', |
|
631 | + ], |
|
632 | + ], |
|
633 | + 'ratingRecent' => 0.5, |
|
634 | + 'ratingOverall' => 0.5, |
|
635 | + 'ratingNumRecent' => 0, |
|
636 | + 'ratingNumOverall' => 0, |
|
637 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
638 | 638 | MIID/zCCAucCAhAVMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
639 | 639 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
640 | 640 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -658,99 +658,99 @@ discard block |
||
658 | 658 | xRS4JXbapjolkxyGSpP+iYSgItVnYzl6o9KZResR4yDsBv7G/8fpV4GQU9IS3zLD |
659 | 659 | PiZOosVHWJdpUKCw9V4P1prGTQ== |
660 | 660 | -----END CERTIFICATE-----', |
661 | - ], |
|
662 | - 5 |
|
663 | - => [ |
|
664 | - 'id' => 'audioplayer', |
|
665 | - 'categories' |
|
666 | - => [ |
|
667 | - 0 => 'multimedia', |
|
668 | - ], |
|
669 | - 'userDocs' => 'https://github.com/rello/audioplayer/wiki#user-documentation', |
|
670 | - 'adminDocs' => 'https://github.com/rello/audioplayer/wiki#admin-documentation', |
|
671 | - 'developerDocs' => '', |
|
672 | - 'issueTracker' => 'https://github.com/rello/audioplayer/issues', |
|
673 | - 'website' => 'https://github.com/rello/audioplayer', |
|
674 | - 'created' => '2016-09-16T05:44:24.857567Z', |
|
675 | - 'lastModified' => '2016-11-17T22:34:34.637028Z', |
|
676 | - 'releases' |
|
677 | - => [ |
|
678 | - 0 |
|
679 | - => [ |
|
680 | - 'version' => '1.3.1', |
|
681 | - 'phpExtensions' |
|
682 | - => [ |
|
683 | - ], |
|
684 | - 'databases' |
|
685 | - => [ |
|
686 | - ], |
|
687 | - 'shellCommands' |
|
688 | - => [ |
|
689 | - ], |
|
690 | - 'phpVersionSpec' => '>=5.4.0', |
|
691 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
692 | - 'minIntSize' => 32, |
|
693 | - 'download' => 'https://github.com/Rello/audioplayer/releases/download/1.3.1/audioplayer-1.3.1.tar.gz', |
|
694 | - 'created' => '2016-11-17T22:34:34.215350Z', |
|
695 | - 'licenses' |
|
696 | - => [ |
|
697 | - 0 => 'agpl', |
|
698 | - ], |
|
699 | - 'lastModified' => '2016-11-17T22:34:34.867778Z', |
|
700 | - 'isNightly' => false, |
|
701 | - 'rawPhpVersionSpec' => '>=5.4', |
|
702 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
703 | - 'signature' => 'p6Zz0IEFrxvw6y/3jHgGWWCxR6qpMzvU2HKfxcIVsK6sJnoRUhWLeAXwZ432fH2a S2llj+IGS9OvW+5VQElrXgPtEjDK1BT00DRJnp5RFCRlUv0LNoedJMzx6B6AHqPP JBufk3cG1O/CO0M0L1ITGSmSOzfKvWTRo3lxVGF792NyBaP/SyZCkH1N1TzBQzUi Ywl3+HiglPcXbHjtJm/arnKorbJWVKoaN93xFuaBapd2ozQSpi0fE0uGRsici+U7 HNa1M5WFE1rzUJoufE0E9246At07rFY1e+TdNEq8IlLgCXg5vGCKkEyuWpWno6aX LfRaIiT9x39UTAwNvuDKS0c+n4uWDYPsGfKhDx9N7CXpUrthfXVEWRzZEXG7as10 6ANvrRPJemSZH8FUSrdJhD7k12qa9R825y7mIG68Li8P71V92EOxFfo9tNXqXwBt VuDGxBqByFVPqSCj5I8hrzJzQl2Xt40g8+8ZcSF96RMg/pM+bwRMTv+mz0V+vQQ4 DWjqnWVPalaJ1PPD5/QFFErtXuNRbyxKZ6BMWxfJlLM9Kz66P75K+8fYaSwz+2KG NxY7I3svzS2K9LGH3fBLUy1t3Hl+c3zGFq/ll1MJrf9NswV4yxt2WmISfM/KDww8 yELkGs2cRzbw2tCvnmYlJJhIqRLkyFAbDzWRH/XdVx4=', |
|
704 | - 'translations' |
|
705 | - => [ |
|
706 | - 'en' |
|
707 | - => [ |
|
708 | - 'changelog' => '2016-11-17 |
|
661 | + ], |
|
662 | + 5 |
|
663 | + => [ |
|
664 | + 'id' => 'audioplayer', |
|
665 | + 'categories' |
|
666 | + => [ |
|
667 | + 0 => 'multimedia', |
|
668 | + ], |
|
669 | + 'userDocs' => 'https://github.com/rello/audioplayer/wiki#user-documentation', |
|
670 | + 'adminDocs' => 'https://github.com/rello/audioplayer/wiki#admin-documentation', |
|
671 | + 'developerDocs' => '', |
|
672 | + 'issueTracker' => 'https://github.com/rello/audioplayer/issues', |
|
673 | + 'website' => 'https://github.com/rello/audioplayer', |
|
674 | + 'created' => '2016-09-16T05:44:24.857567Z', |
|
675 | + 'lastModified' => '2016-11-17T22:34:34.637028Z', |
|
676 | + 'releases' |
|
677 | + => [ |
|
678 | + 0 |
|
679 | + => [ |
|
680 | + 'version' => '1.3.1', |
|
681 | + 'phpExtensions' |
|
682 | + => [ |
|
683 | + ], |
|
684 | + 'databases' |
|
685 | + => [ |
|
686 | + ], |
|
687 | + 'shellCommands' |
|
688 | + => [ |
|
689 | + ], |
|
690 | + 'phpVersionSpec' => '>=5.4.0', |
|
691 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
692 | + 'minIntSize' => 32, |
|
693 | + 'download' => 'https://github.com/Rello/audioplayer/releases/download/1.3.1/audioplayer-1.3.1.tar.gz', |
|
694 | + 'created' => '2016-11-17T22:34:34.215350Z', |
|
695 | + 'licenses' |
|
696 | + => [ |
|
697 | + 0 => 'agpl', |
|
698 | + ], |
|
699 | + 'lastModified' => '2016-11-17T22:34:34.867778Z', |
|
700 | + 'isNightly' => false, |
|
701 | + 'rawPhpVersionSpec' => '>=5.4', |
|
702 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
703 | + 'signature' => 'p6Zz0IEFrxvw6y/3jHgGWWCxR6qpMzvU2HKfxcIVsK6sJnoRUhWLeAXwZ432fH2a S2llj+IGS9OvW+5VQElrXgPtEjDK1BT00DRJnp5RFCRlUv0LNoedJMzx6B6AHqPP JBufk3cG1O/CO0M0L1ITGSmSOzfKvWTRo3lxVGF792NyBaP/SyZCkH1N1TzBQzUi Ywl3+HiglPcXbHjtJm/arnKorbJWVKoaN93xFuaBapd2ozQSpi0fE0uGRsici+U7 HNa1M5WFE1rzUJoufE0E9246At07rFY1e+TdNEq8IlLgCXg5vGCKkEyuWpWno6aX LfRaIiT9x39UTAwNvuDKS0c+n4uWDYPsGfKhDx9N7CXpUrthfXVEWRzZEXG7as10 6ANvrRPJemSZH8FUSrdJhD7k12qa9R825y7mIG68Li8P71V92EOxFfo9tNXqXwBt VuDGxBqByFVPqSCj5I8hrzJzQl2Xt40g8+8ZcSF96RMg/pM+bwRMTv+mz0V+vQQ4 DWjqnWVPalaJ1PPD5/QFFErtXuNRbyxKZ6BMWxfJlLM9Kz66P75K+8fYaSwz+2KG NxY7I3svzS2K9LGH3fBLUy1t3Hl+c3zGFq/ll1MJrf9NswV4yxt2WmISfM/KDww8 yELkGs2cRzbw2tCvnmYlJJhIqRLkyFAbDzWRH/XdVx4=', |
|
704 | + 'translations' |
|
705 | + => [ |
|
706 | + 'en' |
|
707 | + => [ |
|
708 | + 'changelog' => '2016-11-17 |
|
709 | 709 | - fix: one-click-play for wav not working |
710 | 710 | - fix: wrong sql statement for PostgreSQL [#90](https://github.com/rello/audioplayer/issues/90)', |
711 | - ], |
|
712 | - ], |
|
713 | - ], |
|
714 | - ], |
|
715 | - 'screenshots' |
|
716 | - => [ |
|
717 | - 0 |
|
718 | - => [ |
|
719 | - 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_main.png', |
|
720 | - ], |
|
721 | - 1 |
|
722 | - => [ |
|
723 | - 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_lists.png', |
|
724 | - ], |
|
725 | - 2 |
|
726 | - => [ |
|
727 | - 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_share.png', |
|
728 | - ], |
|
729 | - ], |
|
730 | - 'translations' |
|
731 | - => [ |
|
732 | - 'en' |
|
733 | - => [ |
|
734 | - 'name' => 'Audio Player', |
|
735 | - 'summary' => 'Audio Player for ownCloud and Nextcloud', |
|
736 | - 'description' => 'Audio Player for MP3, MP4, Ogg, and Wave with a lot of flexibility for all your needs.', |
|
737 | - ], |
|
738 | - ], |
|
739 | - 'isFeatured' => false, |
|
740 | - 'authors' |
|
741 | - => [ |
|
742 | - 0 |
|
743 | - => [ |
|
744 | - 'name' => 'Marcel Scherello', |
|
745 | - 'mail' => '', |
|
746 | - 'homepage' => '', |
|
747 | - ], |
|
748 | - ], |
|
749 | - 'ratingRecent' => 0.5, |
|
750 | - 'ratingOverall' => 0.5, |
|
751 | - 'ratingNumRecent' => 0, |
|
752 | - 'ratingNumOverall' => 0, |
|
753 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
711 | + ], |
|
712 | + ], |
|
713 | + ], |
|
714 | + ], |
|
715 | + 'screenshots' |
|
716 | + => [ |
|
717 | + 0 |
|
718 | + => [ |
|
719 | + 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_main.png', |
|
720 | + ], |
|
721 | + 1 |
|
722 | + => [ |
|
723 | + 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_lists.png', |
|
724 | + ], |
|
725 | + 2 |
|
726 | + => [ |
|
727 | + 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_share.png', |
|
728 | + ], |
|
729 | + ], |
|
730 | + 'translations' |
|
731 | + => [ |
|
732 | + 'en' |
|
733 | + => [ |
|
734 | + 'name' => 'Audio Player', |
|
735 | + 'summary' => 'Audio Player for ownCloud and Nextcloud', |
|
736 | + 'description' => 'Audio Player for MP3, MP4, Ogg, and Wave with a lot of flexibility for all your needs.', |
|
737 | + ], |
|
738 | + ], |
|
739 | + 'isFeatured' => false, |
|
740 | + 'authors' |
|
741 | + => [ |
|
742 | + 0 |
|
743 | + => [ |
|
744 | + 'name' => 'Marcel Scherello', |
|
745 | + 'mail' => '', |
|
746 | + 'homepage' => '', |
|
747 | + ], |
|
748 | + ], |
|
749 | + 'ratingRecent' => 0.5, |
|
750 | + 'ratingOverall' => 0.5, |
|
751 | + 'ratingNumRecent' => 0, |
|
752 | + 'ratingNumOverall' => 0, |
|
753 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
754 | 754 | MIIEBjCCAu4CAhAIMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
755 | 755 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
756 | 756 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -774,49 +774,49 @@ discard block |
||
774 | 774 | FNvGFVBn4r5qCiChEoq+rCXHRjPi/eCfbW21XeLFDiLxapcZyc85JIcA7znUYoFe |
775 | 775 | P7Y/ekMscwWhLbF91OaQlcWpRtEMyde/DaI= |
776 | 776 | -----END CERTIFICATE-----', |
777 | - ], |
|
778 | - 6 |
|
779 | - => [ |
|
780 | - 'id' => 'calendar', |
|
781 | - 'categories' |
|
782 | - => [ |
|
783 | - 0 => 'organization', |
|
784 | - ], |
|
785 | - 'userDocs' => 'https://docs.nextcloud.com/server/10/user_manual/pim/calendar.html', |
|
786 | - 'adminDocs' => '', |
|
787 | - 'developerDocs' => '', |
|
788 | - 'issueTracker' => 'https://github.com/nextcloud/calendar/issues', |
|
789 | - 'website' => 'https://github.com/nextcloud/calendar/', |
|
790 | - 'created' => '2016-10-01T12:40:39.060903Z', |
|
791 | - 'lastModified' => '2016-11-22T20:31:13.029921Z', |
|
792 | - 'releases' |
|
793 | - => [ |
|
794 | - 0 |
|
795 | - => [ |
|
796 | - 'version' => '1.4.1', |
|
797 | - 'phpExtensions' |
|
798 | - => [ |
|
799 | - ], |
|
800 | - 'databases' |
|
801 | - => [ |
|
802 | - ], |
|
803 | - 'shellCommands' |
|
804 | - => [ |
|
805 | - ], |
|
806 | - 'phpVersionSpec' => '*', |
|
807 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
808 | - 'minIntSize' => 32, |
|
809 | - 'download' => 'https://github.com/nextcloud/calendar/releases/download/v1.4.1/calendar.tar.gz', |
|
810 | - 'created' => '2016-11-22T20:31:13.020268Z', |
|
811 | - 'licenses' |
|
812 | - => [ |
|
813 | - 0 => 'agpl', |
|
814 | - ], |
|
815 | - 'lastModified' => '2016-11-22T20:31:13.087340Z', |
|
816 | - 'isNightly' => false, |
|
817 | - 'rawPhpVersionSpec' => '*', |
|
818 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
819 | - 'signature' => 'nThwe9CJBCan9nuDLdhfBiQyPhmum6Aa0UcYsIDdhGMw+C2acf81KhEmBJuTTWxo |
|
777 | + ], |
|
778 | + 6 |
|
779 | + => [ |
|
780 | + 'id' => 'calendar', |
|
781 | + 'categories' |
|
782 | + => [ |
|
783 | + 0 => 'organization', |
|
784 | + ], |
|
785 | + 'userDocs' => 'https://docs.nextcloud.com/server/10/user_manual/pim/calendar.html', |
|
786 | + 'adminDocs' => '', |
|
787 | + 'developerDocs' => '', |
|
788 | + 'issueTracker' => 'https://github.com/nextcloud/calendar/issues', |
|
789 | + 'website' => 'https://github.com/nextcloud/calendar/', |
|
790 | + 'created' => '2016-10-01T12:40:39.060903Z', |
|
791 | + 'lastModified' => '2016-11-22T20:31:13.029921Z', |
|
792 | + 'releases' |
|
793 | + => [ |
|
794 | + 0 |
|
795 | + => [ |
|
796 | + 'version' => '1.4.1', |
|
797 | + 'phpExtensions' |
|
798 | + => [ |
|
799 | + ], |
|
800 | + 'databases' |
|
801 | + => [ |
|
802 | + ], |
|
803 | + 'shellCommands' |
|
804 | + => [ |
|
805 | + ], |
|
806 | + 'phpVersionSpec' => '*', |
|
807 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
808 | + 'minIntSize' => 32, |
|
809 | + 'download' => 'https://github.com/nextcloud/calendar/releases/download/v1.4.1/calendar.tar.gz', |
|
810 | + 'created' => '2016-11-22T20:31:13.020268Z', |
|
811 | + 'licenses' |
|
812 | + => [ |
|
813 | + 0 => 'agpl', |
|
814 | + ], |
|
815 | + 'lastModified' => '2016-11-22T20:31:13.087340Z', |
|
816 | + 'isNightly' => false, |
|
817 | + 'rawPhpVersionSpec' => '*', |
|
818 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
819 | + 'signature' => 'nThwe9CJBCan9nuDLdhfBiQyPhmum6Aa0UcYsIDdhGMw+C2acf81KhEmBJuTTWxo |
|
820 | 820 | WGby6WcrcJJmeuCW+ePU91ju7Pd76RirprhVXIEceIDzSCxin+K0oZCZ1IGVIJjP |
821 | 821 | IkVehTsLuCeTBbjvz1b3k5QFyhUhvd32Xt7k5d7VARyI4OqnqYYNBtH9vvgeRrFw |
822 | 822 | AxsQr4o4axof6i3iykLg6WfWarYArY4dIuu5DkPuGPWf2bbgjwWEra4sQejhOs7G |
@@ -827,68 +827,68 @@ discard block |
||
827 | 827 | eFLKrUg3EvnTjvknbBxMB55h9jNJr0SAlkrmyEVm6+CE3BwRWpKB+cJMBuGiwPwv |
828 | 828 | r/ASRiJrkDThbNWAUtX70rUmCqDV6/MujLXViqOc/Q2OHvcXd1oGDccJSQT92/1z |
829 | 829 | 7nonnedyYQIDqUt7u68WL8JRxp7pFsEqKLVuWSgxW3c=', |
830 | - 'translations' |
|
831 | - => [ |
|
832 | - ], |
|
833 | - ], |
|
834 | - ], |
|
835 | - 'screenshots' |
|
836 | - => [ |
|
837 | - 0 |
|
838 | - => [ |
|
839 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/1.png', |
|
840 | - ], |
|
841 | - 1 |
|
842 | - => [ |
|
843 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/2.png', |
|
844 | - ], |
|
845 | - 2 |
|
846 | - => [ |
|
847 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/3.png', |
|
848 | - ], |
|
849 | - 3 |
|
850 | - => [ |
|
851 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/4.png', |
|
852 | - ], |
|
853 | - ], |
|
854 | - 'translations' |
|
855 | - => [ |
|
856 | - 'en' |
|
857 | - => [ |
|
858 | - 'name' => 'Calendar', |
|
859 | - 'summary' => 'Calendar GUI for Nextcloud\'s CalDAV server', |
|
860 | - 'description' => 'The Nextcloud calendar app is a user interface for Nextcloud\'s CalDAV server. |
|
830 | + 'translations' |
|
831 | + => [ |
|
832 | + ], |
|
833 | + ], |
|
834 | + ], |
|
835 | + 'screenshots' |
|
836 | + => [ |
|
837 | + 0 |
|
838 | + => [ |
|
839 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/1.png', |
|
840 | + ], |
|
841 | + 1 |
|
842 | + => [ |
|
843 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/2.png', |
|
844 | + ], |
|
845 | + 2 |
|
846 | + => [ |
|
847 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/3.png', |
|
848 | + ], |
|
849 | + 3 |
|
850 | + => [ |
|
851 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/4.png', |
|
852 | + ], |
|
853 | + ], |
|
854 | + 'translations' |
|
855 | + => [ |
|
856 | + 'en' |
|
857 | + => [ |
|
858 | + 'name' => 'Calendar', |
|
859 | + 'summary' => 'Calendar GUI for Nextcloud\'s CalDAV server', |
|
860 | + 'description' => 'The Nextcloud calendar app is a user interface for Nextcloud\'s CalDAV server. |
|
861 | 861 | |
862 | 862 | It integrates with other apps, allows you to manage calendars and events, display external calendars and invite attendees to your events', |
863 | - ], |
|
864 | - ], |
|
865 | - 'isFeatured' => true, |
|
866 | - 'authors' |
|
867 | - => [ |
|
868 | - 0 |
|
869 | - => [ |
|
870 | - 'name' => 'Georg Ehrke', |
|
871 | - 'mail' => '', |
|
872 | - 'homepage' => 'https://georg.coffee', |
|
873 | - ], |
|
874 | - 1 |
|
875 | - => [ |
|
876 | - 'name' => 'Raghu Nayyar', |
|
877 | - 'mail' => '', |
|
878 | - 'homepage' => 'http://raghunayyar.com', |
|
879 | - ], |
|
880 | - 2 |
|
881 | - => [ |
|
882 | - 'name' => 'Thomas Citharel', |
|
883 | - 'mail' => '', |
|
884 | - 'homepage' => 'https://tcit.fr', |
|
885 | - ], |
|
886 | - ], |
|
887 | - 'ratingRecent' => 0.94444444444444398, |
|
888 | - 'ratingOverall' => 0.94444444444444398, |
|
889 | - 'ratingNumRecent' => 9, |
|
890 | - 'ratingNumOverall' => 9, |
|
891 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
863 | + ], |
|
864 | + ], |
|
865 | + 'isFeatured' => true, |
|
866 | + 'authors' |
|
867 | + => [ |
|
868 | + 0 |
|
869 | + => [ |
|
870 | + 'name' => 'Georg Ehrke', |
|
871 | + 'mail' => '', |
|
872 | + 'homepage' => 'https://georg.coffee', |
|
873 | + ], |
|
874 | + 1 |
|
875 | + => [ |
|
876 | + 'name' => 'Raghu Nayyar', |
|
877 | + 'mail' => '', |
|
878 | + 'homepage' => 'http://raghunayyar.com', |
|
879 | + ], |
|
880 | + 2 |
|
881 | + => [ |
|
882 | + 'name' => 'Thomas Citharel', |
|
883 | + 'mail' => '', |
|
884 | + 'homepage' => 'https://tcit.fr', |
|
885 | + ], |
|
886 | + ], |
|
887 | + 'ratingRecent' => 0.94444444444444398, |
|
888 | + 'ratingOverall' => 0.94444444444444398, |
|
889 | + 'ratingNumRecent' => 9, |
|
890 | + 'ratingNumOverall' => 9, |
|
891 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
892 | 892 | MIIEAzCCAusCAhARMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
893 | 893 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
894 | 894 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -912,49 +912,49 @@ discard block |
||
912 | 912 | Q0Bl/QinETk72afGR46Qvc7tC1t9JjQQD3AUbEGuJdGvXjJJ9GREYu01XoODmPdT |
913 | 913 | jXXOI8XIOK6kxXhPHUc3iWu9b4KqGm0= |
914 | 914 | -----END CERTIFICATE-----', |
915 | - ], |
|
916 | - 8 |
|
917 | - => [ |
|
918 | - 'id' => 'ownpad', |
|
919 | - 'categories' |
|
920 | - => [ |
|
921 | - 0 => 'tools', |
|
922 | - ], |
|
923 | - 'userDocs' => 'https://github.com/otetard/ownpad/blob/master/README.md#mimetype-detection', |
|
924 | - 'adminDocs' => '', |
|
925 | - 'developerDocs' => '', |
|
926 | - 'issueTracker' => 'https://github.com/otetard/ownpad/issues', |
|
927 | - 'website' => '', |
|
928 | - 'created' => '2016-09-29T15:58:52.814912Z', |
|
929 | - 'lastModified' => '2016-11-19T17:37:52.278497Z', |
|
930 | - 'releases' |
|
931 | - => [ |
|
932 | - 0 |
|
933 | - => [ |
|
934 | - 'version' => '0.5.6', |
|
935 | - 'phpExtensions' |
|
936 | - => [ |
|
937 | - ], |
|
938 | - 'databases' |
|
939 | - => [ |
|
940 | - ], |
|
941 | - 'shellCommands' |
|
942 | - => [ |
|
943 | - ], |
|
944 | - 'phpVersionSpec' => '*', |
|
945 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
946 | - 'minIntSize' => 32, |
|
947 | - 'download' => 'https://github.com/otetard/ownpad/releases/download/v0.5.6/ownpad.tar.gz', |
|
948 | - 'created' => '2016-11-19T17:37:52.234684Z', |
|
949 | - 'licenses' |
|
950 | - => [ |
|
951 | - 0 => 'agpl', |
|
952 | - ], |
|
953 | - 'lastModified' => '2016-11-19T17:37:52.423930Z', |
|
954 | - 'isNightly' => false, |
|
955 | - 'rawPhpVersionSpec' => '*', |
|
956 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
957 | - 'signature' => 'dh+Txg1iVfqXr8+cxplNQuBZGErSnXUo0ewGwnybNMJqp8/EjEo72+zPpW3dVnhY |
|
915 | + ], |
|
916 | + 8 |
|
917 | + => [ |
|
918 | + 'id' => 'ownpad', |
|
919 | + 'categories' |
|
920 | + => [ |
|
921 | + 0 => 'tools', |
|
922 | + ], |
|
923 | + 'userDocs' => 'https://github.com/otetard/ownpad/blob/master/README.md#mimetype-detection', |
|
924 | + 'adminDocs' => '', |
|
925 | + 'developerDocs' => '', |
|
926 | + 'issueTracker' => 'https://github.com/otetard/ownpad/issues', |
|
927 | + 'website' => '', |
|
928 | + 'created' => '2016-09-29T15:58:52.814912Z', |
|
929 | + 'lastModified' => '2016-11-19T17:37:52.278497Z', |
|
930 | + 'releases' |
|
931 | + => [ |
|
932 | + 0 |
|
933 | + => [ |
|
934 | + 'version' => '0.5.6', |
|
935 | + 'phpExtensions' |
|
936 | + => [ |
|
937 | + ], |
|
938 | + 'databases' |
|
939 | + => [ |
|
940 | + ], |
|
941 | + 'shellCommands' |
|
942 | + => [ |
|
943 | + ], |
|
944 | + 'phpVersionSpec' => '*', |
|
945 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
946 | + 'minIntSize' => 32, |
|
947 | + 'download' => 'https://github.com/otetard/ownpad/releases/download/v0.5.6/ownpad.tar.gz', |
|
948 | + 'created' => '2016-11-19T17:37:52.234684Z', |
|
949 | + 'licenses' |
|
950 | + => [ |
|
951 | + 0 => 'agpl', |
|
952 | + ], |
|
953 | + 'lastModified' => '2016-11-19T17:37:52.423930Z', |
|
954 | + 'isNightly' => false, |
|
955 | + 'rawPhpVersionSpec' => '*', |
|
956 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
957 | + 'signature' => 'dh+Txg1iVfqXr8+cxplNQuBZGErSnXUo0ewGwnybNMJqp8/EjEo72+zPpW3dVnhY |
|
958 | 958 | 67YCvhrm2bo+VRdFFymEfymzSJu9nWVFkGJhEwvTxPyIdAtuD5YAVrzmnR6L+H7m |
959 | 959 | 7Q1nXE63ICPCAQpHkxIfIXLh25OhWeyofBB8AVsjDUNn58FEYJ8fFkr6dCgPriZS |
960 | 960 | sM2J+xtZMDYufy+xFMsVf/Q3WopjFuBjMC3qOecW76ZTwtREaswOC2RtpzUku2r1 |
@@ -965,46 +965,46 @@ discard block |
||
965 | 965 | o3n0+gw3QYIhLEe75sUhxG6ynVUdW25AKKju1kVj3KJnZTBH1R8t8/zy4DnJG8d4 |
966 | 966 | uRGqyU4BXpZjEC3nVlsC7vCncWWhxl0WZQ/MWKqsfjVAU4I88E518D6NioqMnPEJ |
967 | 967 | iCZ2x+69UCDEQyfCSKajgAYT17r3OhZei8F9KSCH8Vw=', |
968 | - 'translations' |
|
969 | - => [ |
|
970 | - ], |
|
971 | - ], |
|
972 | - ], |
|
973 | - 'screenshots' |
|
974 | - => [ |
|
975 | - ], |
|
976 | - 'translations' |
|
977 | - => [ |
|
978 | - 'en' |
|
979 | - => [ |
|
980 | - 'name' => 'Ownpad', |
|
981 | - 'summary' => ' |
|
968 | + 'translations' |
|
969 | + => [ |
|
970 | + ], |
|
971 | + ], |
|
972 | + ], |
|
973 | + 'screenshots' |
|
974 | + => [ |
|
975 | + ], |
|
976 | + 'translations' |
|
977 | + => [ |
|
978 | + 'en' |
|
979 | + => [ |
|
980 | + 'name' => 'Ownpad', |
|
981 | + 'summary' => ' |
|
982 | 982 | Create and open Etherpad and Ethercalc documents. |
983 | 983 | ', |
984 | - 'description' => ' |
|
984 | + 'description' => ' |
|
985 | 985 | Ownpad is an ownCloud application that allows to create and open |
986 | 986 | Etherpad and Ethercalc documents. |
987 | 987 | |
988 | 988 | This application requires to have access to an instance of |
989 | 989 | Etherpad and/or Ethercalc to work properly. |
990 | 990 | ', |
991 | - ], |
|
992 | - ], |
|
993 | - 'isFeatured' => false, |
|
994 | - 'authors' |
|
995 | - => [ |
|
996 | - 0 |
|
997 | - => [ |
|
998 | - 'name' => 'Olivier Tétard', |
|
999 | - 'mail' => '[email protected]', |
|
1000 | - 'homepage' => '', |
|
1001 | - ], |
|
1002 | - ], |
|
1003 | - 'ratingRecent' => 0.5, |
|
1004 | - 'ratingOverall' => 0.5, |
|
1005 | - 'ratingNumRecent' => 0, |
|
1006 | - 'ratingNumOverall' => 0, |
|
1007 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
991 | + ], |
|
992 | + ], |
|
993 | + 'isFeatured' => false, |
|
994 | + 'authors' |
|
995 | + => [ |
|
996 | + 0 |
|
997 | + => [ |
|
998 | + 'name' => 'Olivier Tétard', |
|
999 | + 'mail' => '[email protected]', |
|
1000 | + 'homepage' => '', |
|
1001 | + ], |
|
1002 | + ], |
|
1003 | + 'ratingRecent' => 0.5, |
|
1004 | + 'ratingOverall' => 0.5, |
|
1005 | + 'ratingNumRecent' => 0, |
|
1006 | + 'ratingNumOverall' => 0, |
|
1007 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1008 | 1008 | MIIEATCCAukCAhAPMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
1009 | 1009 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
1010 | 1010 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1028,90 +1028,90 @@ discard block |
||
1028 | 1028 | EUa2uYht/z475k4+vf0YhV98iQH07GnmlfD2TDZgmOCQGKlNfJh1v88OZyLLa3dz |
1029 | 1029 | gRHzGwKbAiJ8T8bbpZ3e2ozXxADr |
1030 | 1030 | -----END CERTIFICATE-----', |
1031 | - ], |
|
1032 | - 9 |
|
1033 | - => [ |
|
1034 | - 'id' => 'announcementcenter', |
|
1035 | - 'categories' |
|
1036 | - => [ |
|
1037 | - 0 => 'organization', |
|
1038 | - ], |
|
1039 | - 'userDocs' => '', |
|
1040 | - 'adminDocs' => '', |
|
1041 | - 'developerDocs' => '', |
|
1042 | - 'issueTracker' => 'https://github.com/nextcloud/announcementcenter/issues', |
|
1043 | - 'website' => 'https://github.com/nextcloud/announcementcenter', |
|
1044 | - 'created' => '2016-09-14T10:38:53.939634Z', |
|
1045 | - 'lastModified' => '2016-11-24T11:21:50.324839Z', |
|
1046 | - 'releases' |
|
1047 | - => [ |
|
1048 | - 0 |
|
1049 | - => [ |
|
1050 | - 'version' => '2.0.0', |
|
1051 | - 'phpExtensions' |
|
1052 | - => [ |
|
1053 | - ], |
|
1054 | - 'databases' |
|
1055 | - => [ |
|
1056 | - ], |
|
1057 | - 'shellCommands' |
|
1058 | - => [ |
|
1059 | - ], |
|
1060 | - 'phpVersionSpec' => '*', |
|
1061 | - 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
1062 | - 'minIntSize' => 32, |
|
1063 | - 'download' => 'https://github.com/nextcloud/announcementcenter/releases/download/v2.0.0/announcementcenter-2.0.0.tar.gz', |
|
1064 | - 'created' => '2016-10-06T12:41:56.195206Z', |
|
1065 | - 'licenses' |
|
1066 | - => [ |
|
1067 | - 0 => 'agpl', |
|
1068 | - ], |
|
1069 | - 'lastModified' => '2016-10-06T12:41:56.263124Z', |
|
1070 | - 'isNightly' => false, |
|
1071 | - 'rawPhpVersionSpec' => '*', |
|
1072 | - 'rawPlatformVersionSpec' => '>=10 <=11', |
|
1073 | - 'signature' => 'NVWYz73KtuoZ7ti2sluztJO5aFUc7PzhlDcg0VWyAQd1H7sk5wjw7i0bhrjw8O7M |
|
1031 | + ], |
|
1032 | + 9 |
|
1033 | + => [ |
|
1034 | + 'id' => 'announcementcenter', |
|
1035 | + 'categories' |
|
1036 | + => [ |
|
1037 | + 0 => 'organization', |
|
1038 | + ], |
|
1039 | + 'userDocs' => '', |
|
1040 | + 'adminDocs' => '', |
|
1041 | + 'developerDocs' => '', |
|
1042 | + 'issueTracker' => 'https://github.com/nextcloud/announcementcenter/issues', |
|
1043 | + 'website' => 'https://github.com/nextcloud/announcementcenter', |
|
1044 | + 'created' => '2016-09-14T10:38:53.939634Z', |
|
1045 | + 'lastModified' => '2016-11-24T11:21:50.324839Z', |
|
1046 | + 'releases' |
|
1047 | + => [ |
|
1048 | + 0 |
|
1049 | + => [ |
|
1050 | + 'version' => '2.0.0', |
|
1051 | + 'phpExtensions' |
|
1052 | + => [ |
|
1053 | + ], |
|
1054 | + 'databases' |
|
1055 | + => [ |
|
1056 | + ], |
|
1057 | + 'shellCommands' |
|
1058 | + => [ |
|
1059 | + ], |
|
1060 | + 'phpVersionSpec' => '*', |
|
1061 | + 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
1062 | + 'minIntSize' => 32, |
|
1063 | + 'download' => 'https://github.com/nextcloud/announcementcenter/releases/download/v2.0.0/announcementcenter-2.0.0.tar.gz', |
|
1064 | + 'created' => '2016-10-06T12:41:56.195206Z', |
|
1065 | + 'licenses' |
|
1066 | + => [ |
|
1067 | + 0 => 'agpl', |
|
1068 | + ], |
|
1069 | + 'lastModified' => '2016-10-06T12:41:56.263124Z', |
|
1070 | + 'isNightly' => false, |
|
1071 | + 'rawPhpVersionSpec' => '*', |
|
1072 | + 'rawPlatformVersionSpec' => '>=10 <=11', |
|
1073 | + 'signature' => 'NVWYz73KtuoZ7ti2sluztJO5aFUc7PzhlDcg0VWyAQd1H7sk5wjw7i0bhrjw8O7M |
|
1074 | 1074 | Lsrb+PegnsL9eMlYM2WrRom+RF1PDP482xymZf1T8vh8qcTCm3TK89xSuiSm8yoA |
1075 | 1075 | iWUb/Uv/ODj74wVDWqWxAFKaAG/FestCB3InOOZQqQZLzlAV0U9ziYDGNzBjFqof |
1076 | 1076 | 9rLNxJ2IOqZOA7hhMIKhSrpA0KkSfNhBsVf8CWClYnVkZQiq0LoYkHkHIlXmXUr3 |
1077 | 1077 | OfQFKEjtsx+bNLa6CkAaocHGHJXAofX3GQZ9cjBsjZqiTfbXfcVk0kRfz7pwL92L |
1078 | 1078 | I1McfJYvgMxDQG5bjRpNJw==', |
1079 | - 'translations' |
|
1080 | - => [ |
|
1081 | - ], |
|
1082 | - ], |
|
1083 | - ], |
|
1084 | - 'screenshots' |
|
1085 | - => [ |
|
1086 | - 0 |
|
1087 | - => [ |
|
1088 | - 'url' => 'https://github.com/nextcloud/announcementcenter/raw/stable10/docs/AnnouncementCenterFrontpage.png', |
|
1089 | - ], |
|
1090 | - ], |
|
1091 | - 'translations' |
|
1092 | - => [ |
|
1093 | - 'en' |
|
1094 | - => [ |
|
1095 | - 'name' => 'Announcement Center', |
|
1096 | - 'summary' => 'An announcement center for Nextcloud', |
|
1097 | - 'description' => 'An announcement center for Nextcloud', |
|
1098 | - ], |
|
1099 | - ], |
|
1100 | - 'isFeatured' => true, |
|
1101 | - 'authors' |
|
1102 | - => [ |
|
1103 | - 0 |
|
1104 | - => [ |
|
1105 | - 'name' => 'Joas Schilling', |
|
1106 | - 'mail' => '', |
|
1107 | - 'homepage' => '', |
|
1108 | - ], |
|
1109 | - ], |
|
1110 | - 'ratingRecent' => 0.75, |
|
1111 | - 'ratingOverall' => 0.75, |
|
1112 | - 'ratingNumRecent' => 0, |
|
1113 | - 'ratingNumOverall' => 0, |
|
1114 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1079 | + 'translations' |
|
1080 | + => [ |
|
1081 | + ], |
|
1082 | + ], |
|
1083 | + ], |
|
1084 | + 'screenshots' |
|
1085 | + => [ |
|
1086 | + 0 |
|
1087 | + => [ |
|
1088 | + 'url' => 'https://github.com/nextcloud/announcementcenter/raw/stable10/docs/AnnouncementCenterFrontpage.png', |
|
1089 | + ], |
|
1090 | + ], |
|
1091 | + 'translations' |
|
1092 | + => [ |
|
1093 | + 'en' |
|
1094 | + => [ |
|
1095 | + 'name' => 'Announcement Center', |
|
1096 | + 'summary' => 'An announcement center for Nextcloud', |
|
1097 | + 'description' => 'An announcement center for Nextcloud', |
|
1098 | + ], |
|
1099 | + ], |
|
1100 | + 'isFeatured' => true, |
|
1101 | + 'authors' |
|
1102 | + => [ |
|
1103 | + 0 |
|
1104 | + => [ |
|
1105 | + 'name' => 'Joas Schilling', |
|
1106 | + 'mail' => '', |
|
1107 | + 'homepage' => '', |
|
1108 | + ], |
|
1109 | + ], |
|
1110 | + 'ratingRecent' => 0.75, |
|
1111 | + 'ratingOverall' => 0.75, |
|
1112 | + 'ratingNumRecent' => 0, |
|
1113 | + 'ratingNumOverall' => 0, |
|
1114 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1115 | 1115 | MIIDDTCCAfUCAhABMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
1116 | 1116 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
1117 | 1117 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1130,50 +1130,50 @@ discard block |
||
1130 | 1130 | JJoU8LQoHwGRtp3wutk0GlFzpEQEvSsn/Lsvvot5IfIe46tnzA6MVj5s64s5G8+Q |
1131 | 1131 | phhXFlzXqO/VxquPdbfYjvU= |
1132 | 1132 | -----END CERTIFICATE-----', |
1133 | - ], |
|
1134 | - 11 |
|
1135 | - => [ |
|
1136 | - 'id' => 'rainloop', |
|
1137 | - 'categories' |
|
1138 | - => [ |
|
1139 | - 0 => 'social', |
|
1140 | - 1 => 'tools', |
|
1141 | - ], |
|
1142 | - 'userDocs' => '', |
|
1143 | - 'adminDocs' => '', |
|
1144 | - 'developerDocs' => '', |
|
1145 | - 'issueTracker' => 'https://github.com/RainLoop/rainloop-webmail/issues', |
|
1146 | - 'website' => 'http://www.rainloop.net/', |
|
1147 | - 'created' => '2016-10-20T04:17:37.217555Z', |
|
1148 | - 'lastModified' => '2016-11-18T11:36:04.309739Z', |
|
1149 | - 'releases' |
|
1150 | - => [ |
|
1151 | - 0 |
|
1152 | - => [ |
|
1153 | - 'version' => '4.26.0', |
|
1154 | - 'phpExtensions' |
|
1155 | - => [ |
|
1156 | - ], |
|
1157 | - 'databases' |
|
1158 | - => [ |
|
1159 | - ], |
|
1160 | - 'shellCommands' |
|
1161 | - => [ |
|
1162 | - ], |
|
1163 | - 'phpVersionSpec' => '>=5.4.0', |
|
1164 | - 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
1165 | - 'minIntSize' => 32, |
|
1166 | - 'download' => 'https://github.com/pierre-alain-b/rainloop-nextcloud/releases/download/v4.26.0/rainloop-4.26.0.tar.gz', |
|
1167 | - 'created' => '2016-10-20T04:28:21.491747Z', |
|
1168 | - 'licenses' |
|
1169 | - => [ |
|
1170 | - 0 => 'agpl', |
|
1171 | - ], |
|
1172 | - 'lastModified' => '2016-11-18T11:36:04.619927Z', |
|
1173 | - 'isNightly' => false, |
|
1174 | - 'rawPhpVersionSpec' => '>=5.4', |
|
1175 | - 'rawPlatformVersionSpec' => '>=10 <=11', |
|
1176 | - 'signature' => 'nTYIVSB6mIwKtXIrKoVGsOGFflpLjed8jFem1VLQNtXQj4bztnNrdc4YaPIn0yzM |
|
1133 | + ], |
|
1134 | + 11 |
|
1135 | + => [ |
|
1136 | + 'id' => 'rainloop', |
|
1137 | + 'categories' |
|
1138 | + => [ |
|
1139 | + 0 => 'social', |
|
1140 | + 1 => 'tools', |
|
1141 | + ], |
|
1142 | + 'userDocs' => '', |
|
1143 | + 'adminDocs' => '', |
|
1144 | + 'developerDocs' => '', |
|
1145 | + 'issueTracker' => 'https://github.com/RainLoop/rainloop-webmail/issues', |
|
1146 | + 'website' => 'http://www.rainloop.net/', |
|
1147 | + 'created' => '2016-10-20T04:17:37.217555Z', |
|
1148 | + 'lastModified' => '2016-11-18T11:36:04.309739Z', |
|
1149 | + 'releases' |
|
1150 | + => [ |
|
1151 | + 0 |
|
1152 | + => [ |
|
1153 | + 'version' => '4.26.0', |
|
1154 | + 'phpExtensions' |
|
1155 | + => [ |
|
1156 | + ], |
|
1157 | + 'databases' |
|
1158 | + => [ |
|
1159 | + ], |
|
1160 | + 'shellCommands' |
|
1161 | + => [ |
|
1162 | + ], |
|
1163 | + 'phpVersionSpec' => '>=5.4.0', |
|
1164 | + 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
1165 | + 'minIntSize' => 32, |
|
1166 | + 'download' => 'https://github.com/pierre-alain-b/rainloop-nextcloud/releases/download/v4.26.0/rainloop-4.26.0.tar.gz', |
|
1167 | + 'created' => '2016-10-20T04:28:21.491747Z', |
|
1168 | + 'licenses' |
|
1169 | + => [ |
|
1170 | + 0 => 'agpl', |
|
1171 | + ], |
|
1172 | + 'lastModified' => '2016-11-18T11:36:04.619927Z', |
|
1173 | + 'isNightly' => false, |
|
1174 | + 'rawPhpVersionSpec' => '>=5.4', |
|
1175 | + 'rawPlatformVersionSpec' => '>=10 <=11', |
|
1176 | + 'signature' => 'nTYIVSB6mIwKtXIrKoVGsOGFflpLjed8jFem1VLQNtXQj4bztnNrdc4YaPIn0yzM |
|
1177 | 1177 | yLpMSqRDNzdYNFuOeDiyKLPJPTA++MotLCNjEe7kxUekek+m+qzgnGBdcT7RQT6R |
1178 | 1178 | p9xWGecnVx94d6aA55uiRhgQRyHpdDMMLCOz1be+HvpwHy69DRFZ1+SPmGUt6eW0 |
1179 | 1179 | u5yS0vHCu1K22cbrVNXFKjxAOlGcIDm61oQuz7ycl3uAujZO4rZbWt55jilgKGak |
@@ -1184,42 +1184,42 @@ discard block |
||
1184 | 1184 | LhIczc32ECi3ZVVgyF8zyT4Y/3MRS05oX3FHvHyt88mjni6bVaO78F7ZRSha8gHh |
1185 | 1185 | NOAkku7AMXPvUCHaZP2iVCCoAViEso8GeR3O8xh2G42Ai61RLYwx8LB1+23EoJTr |
1186 | 1186 | mfFuRYNSg+qAKCokXNnh+lDlwu4AkaQo3vtKGPXvU7A=', |
1187 | - 'translations' |
|
1188 | - => [ |
|
1189 | - ], |
|
1190 | - ], |
|
1191 | - ], |
|
1192 | - 'screenshots' |
|
1193 | - => [ |
|
1194 | - 0 |
|
1195 | - => [ |
|
1196 | - 'url' => 'https://raw.githubusercontent.com/pierre-alain-b/rainloop-nextcloud/master/screenshots/2016.10.20-screenshot.jpg', |
|
1197 | - ], |
|
1198 | - ], |
|
1199 | - 'translations' |
|
1200 | - => [ |
|
1201 | - 'en' |
|
1202 | - => [ |
|
1203 | - 'name' => 'RainLoop', |
|
1204 | - 'summary' => 'RainLoop Webmail', |
|
1205 | - 'description' => 'Simple, modern and fast web-based email client.', |
|
1206 | - ], |
|
1207 | - ], |
|
1208 | - 'isFeatured' => false, |
|
1209 | - 'authors' |
|
1210 | - => [ |
|
1211 | - 0 |
|
1212 | - => [ |
|
1213 | - 'name' => 'RainLoop Team', |
|
1214 | - 'mail' => '', |
|
1215 | - 'homepage' => '', |
|
1216 | - ], |
|
1217 | - ], |
|
1218 | - 'ratingRecent' => 0.5, |
|
1219 | - 'ratingOverall' => 0.5, |
|
1220 | - 'ratingNumRecent' => 0, |
|
1221 | - 'ratingNumOverall' => 0, |
|
1222 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1187 | + 'translations' |
|
1188 | + => [ |
|
1189 | + ], |
|
1190 | + ], |
|
1191 | + ], |
|
1192 | + 'screenshots' |
|
1193 | + => [ |
|
1194 | + 0 |
|
1195 | + => [ |
|
1196 | + 'url' => 'https://raw.githubusercontent.com/pierre-alain-b/rainloop-nextcloud/master/screenshots/2016.10.20-screenshot.jpg', |
|
1197 | + ], |
|
1198 | + ], |
|
1199 | + 'translations' |
|
1200 | + => [ |
|
1201 | + 'en' |
|
1202 | + => [ |
|
1203 | + 'name' => 'RainLoop', |
|
1204 | + 'summary' => 'RainLoop Webmail', |
|
1205 | + 'description' => 'Simple, modern and fast web-based email client.', |
|
1206 | + ], |
|
1207 | + ], |
|
1208 | + 'isFeatured' => false, |
|
1209 | + 'authors' |
|
1210 | + => [ |
|
1211 | + 0 |
|
1212 | + => [ |
|
1213 | + 'name' => 'RainLoop Team', |
|
1214 | + 'mail' => '', |
|
1215 | + 'homepage' => '', |
|
1216 | + ], |
|
1217 | + ], |
|
1218 | + 'ratingRecent' => 0.5, |
|
1219 | + 'ratingOverall' => 0.5, |
|
1220 | + 'ratingNumRecent' => 0, |
|
1221 | + 'ratingNumOverall' => 0, |
|
1222 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1223 | 1223 | MIIEAzCCAusCAhAXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
1224 | 1224 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
1225 | 1225 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1243,103 +1243,103 @@ discard block |
||
1243 | 1243 | iLYeXQTV0XSRs8xVt+iyGlj7nPkv2DR0oCqRpWUFWeSBI//niDG5WxS3qg8kacSW |
1244 | 1244 | fDSYhSN+IjrnIkwNtc8V9t7/GeQB5FE= |
1245 | 1245 | -----END CERTIFICATE-----', |
1246 | - ], |
|
1247 | - 12 |
|
1248 | - => [ |
|
1249 | - 'id' => 'richdocuments', |
|
1250 | - 'categories' |
|
1251 | - => [ |
|
1252 | - 0 => 'integration', |
|
1253 | - 1 => 'office', |
|
1254 | - ], |
|
1255 | - 'userDocs' => 'https://nextcloud.com/collaboraonline/', |
|
1256 | - 'adminDocs' => 'https://nextcloud.com/collaboraonline/', |
|
1257 | - 'developerDocs' => '', |
|
1258 | - 'issueTracker' => 'https://github.com/owncloud/richdocuments/issues', |
|
1259 | - 'website' => '', |
|
1260 | - 'created' => '2016-10-31T08:55:45.631429Z', |
|
1261 | - 'lastModified' => '2016-11-24T12:13:53.905352Z', |
|
1262 | - 'releases' |
|
1263 | - => [ |
|
1264 | - 0 |
|
1265 | - => [ |
|
1266 | - 'version' => '1.1.14', |
|
1267 | - 'phpExtensions' |
|
1268 | - => [ |
|
1269 | - ], |
|
1270 | - 'databases' |
|
1271 | - => [ |
|
1272 | - ], |
|
1273 | - 'shellCommands' |
|
1274 | - => [ |
|
1275 | - ], |
|
1276 | - 'phpVersionSpec' => '*', |
|
1277 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
1278 | - 'minIntSize' => 32, |
|
1279 | - 'download' => 'https://github.com/owncloud/richdocuments/releases/download/1.1.14/richdocuments.tar.gz', |
|
1280 | - 'created' => '2016-11-24T12:10:13.337165Z', |
|
1281 | - 'licenses' |
|
1282 | - => [ |
|
1283 | - 0 => 'agpl', |
|
1284 | - ], |
|
1285 | - 'lastModified' => '2016-11-24T12:13:53.963638Z', |
|
1286 | - 'isNightly' => false, |
|
1287 | - 'rawPhpVersionSpec' => '*', |
|
1288 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
1289 | - 'signature' => 'prDGlfRPxqT6LP0BsAFPwGww7P4Bngha2N4u5B6+F02N+RVOjGtTcXKqvM1KjZb1 |
|
1246 | + ], |
|
1247 | + 12 |
|
1248 | + => [ |
|
1249 | + 'id' => 'richdocuments', |
|
1250 | + 'categories' |
|
1251 | + => [ |
|
1252 | + 0 => 'integration', |
|
1253 | + 1 => 'office', |
|
1254 | + ], |
|
1255 | + 'userDocs' => 'https://nextcloud.com/collaboraonline/', |
|
1256 | + 'adminDocs' => 'https://nextcloud.com/collaboraonline/', |
|
1257 | + 'developerDocs' => '', |
|
1258 | + 'issueTracker' => 'https://github.com/owncloud/richdocuments/issues', |
|
1259 | + 'website' => '', |
|
1260 | + 'created' => '2016-10-31T08:55:45.631429Z', |
|
1261 | + 'lastModified' => '2016-11-24T12:13:53.905352Z', |
|
1262 | + 'releases' |
|
1263 | + => [ |
|
1264 | + 0 |
|
1265 | + => [ |
|
1266 | + 'version' => '1.1.14', |
|
1267 | + 'phpExtensions' |
|
1268 | + => [ |
|
1269 | + ], |
|
1270 | + 'databases' |
|
1271 | + => [ |
|
1272 | + ], |
|
1273 | + 'shellCommands' |
|
1274 | + => [ |
|
1275 | + ], |
|
1276 | + 'phpVersionSpec' => '*', |
|
1277 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
1278 | + 'minIntSize' => 32, |
|
1279 | + 'download' => 'https://github.com/owncloud/richdocuments/releases/download/1.1.14/richdocuments.tar.gz', |
|
1280 | + 'created' => '2016-11-24T12:10:13.337165Z', |
|
1281 | + 'licenses' |
|
1282 | + => [ |
|
1283 | + 0 => 'agpl', |
|
1284 | + ], |
|
1285 | + 'lastModified' => '2016-11-24T12:13:53.963638Z', |
|
1286 | + 'isNightly' => false, |
|
1287 | + 'rawPhpVersionSpec' => '*', |
|
1288 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
1289 | + 'signature' => 'prDGlfRPxqT6LP0BsAFPwGww7P4Bngha2N4u5B6+F02N+RVOjGtTcXKqvM1KjZb1 |
|
1290 | 1290 | Co7qJvgJmjpvIvDmB+rup02i8ObfwP2ct6UdsD7ouzOWJG2sJANXK31bHyvOmQ2h |
1291 | 1291 | vKu5eNcOkf+WFyFKYi51TbsfWn2+1Wge3WWujKAVcEvqtcOOz+uMWNtqzBptEupk |
1292 | 1292 | E1aaRnQfTx488YB8Ubul06LIY0PNCHgGCWPgy817tOVT7JA+V0P0FFonl/PXE0dr |
1293 | 1293 | WgtxRJmvGaNiFzYq+kQmdKMfayZTm3kdVgP0W52t5wp878K0i4s2KPg5lANvjTz7 |
1294 | 1294 | DCT+VV2IGIE52o4RpMUGyQ==', |
1295 | - 'translations' |
|
1296 | - => [ |
|
1297 | - ], |
|
1298 | - ], |
|
1299 | - ], |
|
1300 | - 'screenshots' |
|
1301 | - => [ |
|
1302 | - 0 |
|
1303 | - => [ |
|
1304 | - 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-document.png', |
|
1305 | - ], |
|
1306 | - 1 |
|
1307 | - => [ |
|
1308 | - 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-app.png', |
|
1309 | - ], |
|
1310 | - 2 |
|
1311 | - => [ |
|
1312 | - 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-presentation.png', |
|
1313 | - ], |
|
1314 | - 3 |
|
1315 | - => [ |
|
1316 | - 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-spreadsheet.png', |
|
1317 | - ], |
|
1318 | - ], |
|
1319 | - 'translations' |
|
1320 | - => [ |
|
1321 | - 'en' |
|
1322 | - => [ |
|
1323 | - 'name' => 'Collabora Online', |
|
1324 | - 'summary' => 'Edit office documents directly in your browser.', |
|
1325 | - 'description' => 'Collabora Online allows you to to work with all kinds of office documents directly in your browser. This application requires Collabora Cloudsuite to be installed on one of your servers, please read the documentation to learn more about that.', |
|
1326 | - ], |
|
1327 | - ], |
|
1328 | - 'isFeatured' => false, |
|
1329 | - 'authors' |
|
1330 | - => [ |
|
1331 | - 0 |
|
1332 | - => [ |
|
1333 | - 'name' => 'Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk', |
|
1334 | - 'mail' => '', |
|
1335 | - 'homepage' => '', |
|
1336 | - ], |
|
1337 | - ], |
|
1338 | - 'ratingRecent' => 0.5, |
|
1339 | - 'ratingOverall' => 0.5, |
|
1340 | - 'ratingNumRecent' => 0, |
|
1341 | - 'ratingNumOverall' => 0, |
|
1342 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1295 | + 'translations' |
|
1296 | + => [ |
|
1297 | + ], |
|
1298 | + ], |
|
1299 | + ], |
|
1300 | + 'screenshots' |
|
1301 | + => [ |
|
1302 | + 0 |
|
1303 | + => [ |
|
1304 | + 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-document.png', |
|
1305 | + ], |
|
1306 | + 1 |
|
1307 | + => [ |
|
1308 | + 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-app.png', |
|
1309 | + ], |
|
1310 | + 2 |
|
1311 | + => [ |
|
1312 | + 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-presentation.png', |
|
1313 | + ], |
|
1314 | + 3 |
|
1315 | + => [ |
|
1316 | + 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-spreadsheet.png', |
|
1317 | + ], |
|
1318 | + ], |
|
1319 | + 'translations' |
|
1320 | + => [ |
|
1321 | + 'en' |
|
1322 | + => [ |
|
1323 | + 'name' => 'Collabora Online', |
|
1324 | + 'summary' => 'Edit office documents directly in your browser.', |
|
1325 | + 'description' => 'Collabora Online allows you to to work with all kinds of office documents directly in your browser. This application requires Collabora Cloudsuite to be installed on one of your servers, please read the documentation to learn more about that.', |
|
1326 | + ], |
|
1327 | + ], |
|
1328 | + 'isFeatured' => false, |
|
1329 | + 'authors' |
|
1330 | + => [ |
|
1331 | + 0 |
|
1332 | + => [ |
|
1333 | + 'name' => 'Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk', |
|
1334 | + 'mail' => '', |
|
1335 | + 'homepage' => '', |
|
1336 | + ], |
|
1337 | + ], |
|
1338 | + 'ratingRecent' => 0.5, |
|
1339 | + 'ratingOverall' => 0.5, |
|
1340 | + 'ratingNumRecent' => 0, |
|
1341 | + 'ratingNumOverall' => 0, |
|
1342 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1343 | 1343 | MIIDCDCCAfACAhAZMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
1344 | 1344 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
1345 | 1345 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1358,70 +1358,70 @@ discard block |
||
1358 | 1358 | myBOrjhrJgLIwvgH26MYZhdiSkFzoE38nMPZdrUmUDxcPCwucWJqgzDPudguFthj |
1359 | 1359 | WCVZ3TTG/2z3+tWM |
1360 | 1360 | -----END CERTIFICATE-----', |
1361 | - ], |
|
1362 | - 13 |
|
1363 | - => [ |
|
1364 | - 'id' => 'ocr', |
|
1365 | - 'categories' |
|
1366 | - => [ |
|
1367 | - 0 => 'files', |
|
1368 | - 1 => 'tools', |
|
1369 | - ], |
|
1370 | - 'userDocs' => 'https://janis91.github.io/ocr/', |
|
1371 | - 'adminDocs' => 'https://github.com/janis91/ocr/wiki', |
|
1372 | - 'developerDocs' => 'https://github.com/janis91/ocr/wiki', |
|
1373 | - 'issueTracker' => 'https://github.com/janis91/ocr/issues', |
|
1374 | - 'website' => 'https://janis91.github.io/ocr/', |
|
1375 | - 'created' => '2016-09-19T12:07:49.220376Z', |
|
1376 | - 'lastModified' => '2016-11-21T11:22:21.024501Z', |
|
1377 | - 'releases' |
|
1378 | - => [ |
|
1379 | - 0 |
|
1380 | - => [ |
|
1381 | - 'version' => '1.0.0', |
|
1382 | - 'phpExtensions' |
|
1383 | - => [ |
|
1384 | - ], |
|
1385 | - 'databases' |
|
1386 | - => [ |
|
1387 | - 0 |
|
1388 | - => [ |
|
1389 | - 'id' => 'pgsql', |
|
1390 | - 'versionSpec' => '*', |
|
1391 | - 'rawVersionSpec' => '*', |
|
1392 | - ], |
|
1393 | - 1 |
|
1394 | - => [ |
|
1395 | - 'id' => 'mysql', |
|
1396 | - 'versionSpec' => '*', |
|
1397 | - 'rawVersionSpec' => '*', |
|
1398 | - ], |
|
1399 | - 2 |
|
1400 | - => [ |
|
1401 | - 'id' => 'sqlite', |
|
1402 | - 'versionSpec' => '*', |
|
1403 | - 'rawVersionSpec' => '*', |
|
1404 | - ], |
|
1405 | - ], |
|
1406 | - 'shellCommands' |
|
1407 | - => [ |
|
1408 | - 0 => 'ocrmypdf', |
|
1409 | - 1 => 'tesseract', |
|
1410 | - ], |
|
1411 | - 'phpVersionSpec' => '>=5.6.0 <8.0.0', |
|
1412 | - 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
1413 | - 'minIntSize' => 32, |
|
1414 | - 'download' => 'https://github.com/janis91/ocr/releases/download/v1.0.0/ocr.tar.gz', |
|
1415 | - 'created' => '2016-10-24T06:50:43.283900Z', |
|
1416 | - 'licenses' |
|
1417 | - => [ |
|
1418 | - 0 => 'agpl', |
|
1419 | - ], |
|
1420 | - 'lastModified' => '2016-11-21T11:22:21.269108Z', |
|
1421 | - 'isNightly' => false, |
|
1422 | - 'rawPhpVersionSpec' => '>=5.6 <=7', |
|
1423 | - 'rawPlatformVersionSpec' => '>=10 <=11', |
|
1424 | - 'signature' => 'CBJkCIiUKyf2NuWfz2zJ3grhf8p7wJes7DPV/OxUzhlxIH0Fh7K54+U5A9JOOi6f |
|
1361 | + ], |
|
1362 | + 13 |
|
1363 | + => [ |
|
1364 | + 'id' => 'ocr', |
|
1365 | + 'categories' |
|
1366 | + => [ |
|
1367 | + 0 => 'files', |
|
1368 | + 1 => 'tools', |
|
1369 | + ], |
|
1370 | + 'userDocs' => 'https://janis91.github.io/ocr/', |
|
1371 | + 'adminDocs' => 'https://github.com/janis91/ocr/wiki', |
|
1372 | + 'developerDocs' => 'https://github.com/janis91/ocr/wiki', |
|
1373 | + 'issueTracker' => 'https://github.com/janis91/ocr/issues', |
|
1374 | + 'website' => 'https://janis91.github.io/ocr/', |
|
1375 | + 'created' => '2016-09-19T12:07:49.220376Z', |
|
1376 | + 'lastModified' => '2016-11-21T11:22:21.024501Z', |
|
1377 | + 'releases' |
|
1378 | + => [ |
|
1379 | + 0 |
|
1380 | + => [ |
|
1381 | + 'version' => '1.0.0', |
|
1382 | + 'phpExtensions' |
|
1383 | + => [ |
|
1384 | + ], |
|
1385 | + 'databases' |
|
1386 | + => [ |
|
1387 | + 0 |
|
1388 | + => [ |
|
1389 | + 'id' => 'pgsql', |
|
1390 | + 'versionSpec' => '*', |
|
1391 | + 'rawVersionSpec' => '*', |
|
1392 | + ], |
|
1393 | + 1 |
|
1394 | + => [ |
|
1395 | + 'id' => 'mysql', |
|
1396 | + 'versionSpec' => '*', |
|
1397 | + 'rawVersionSpec' => '*', |
|
1398 | + ], |
|
1399 | + 2 |
|
1400 | + => [ |
|
1401 | + 'id' => 'sqlite', |
|
1402 | + 'versionSpec' => '*', |
|
1403 | + 'rawVersionSpec' => '*', |
|
1404 | + ], |
|
1405 | + ], |
|
1406 | + 'shellCommands' |
|
1407 | + => [ |
|
1408 | + 0 => 'ocrmypdf', |
|
1409 | + 1 => 'tesseract', |
|
1410 | + ], |
|
1411 | + 'phpVersionSpec' => '>=5.6.0 <8.0.0', |
|
1412 | + 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
1413 | + 'minIntSize' => 32, |
|
1414 | + 'download' => 'https://github.com/janis91/ocr/releases/download/v1.0.0/ocr.tar.gz', |
|
1415 | + 'created' => '2016-10-24T06:50:43.283900Z', |
|
1416 | + 'licenses' |
|
1417 | + => [ |
|
1418 | + 0 => 'agpl', |
|
1419 | + ], |
|
1420 | + 'lastModified' => '2016-11-21T11:22:21.269108Z', |
|
1421 | + 'isNightly' => false, |
|
1422 | + 'rawPhpVersionSpec' => '>=5.6 <=7', |
|
1423 | + 'rawPlatformVersionSpec' => '>=10 <=11', |
|
1424 | + 'signature' => 'CBJkCIiUKyf2NuWfz2zJ3grhf8p7wJes7DPV/OxUzhlxIH0Fh7K54+U5A9JOOi6f |
|
1425 | 1425 | WPhjXG1ylkyIVY1glr/B8svWNsD4jAclpnUi1/9ZW5UPT8LnRBfTbtF9Uoj0OgNs |
1426 | 1426 | tsGQYbpuREoHnjbJWTRe0kq1OsOfX44xuf8PuX43B+lpQPW4iRSSz3ZIhdPcDGq1 |
1427 | 1427 | 7pyqQM7gdKhBQ6/tOiwd7Enyt5Hi4V6jhwhUOCYeTNiLD2V3yKL+qA9DzpXUfNNw |
@@ -1432,33 +1432,33 @@ discard block |
||
1432 | 1432 | D3tJOF7spnK6I3BhVLviou/zs30AIRVBDTU0Orzx78cbInwy6/vyJib2a1olAaHz |
1433 | 1433 | v05SzlQRnBWM4jYBe0mA/2ds9AO6VrXGrT/iLlHemj6JYoGBM185TGewA7OJyX3a |
1434 | 1434 | HSlSDqaremmi+aS3onx3AKhXykDxTRkMVarePwTzzFs=', |
1435 | - 'translations' |
|
1436 | - => [ |
|
1437 | - ], |
|
1438 | - ], |
|
1439 | - ], |
|
1440 | - 'screenshots' |
|
1441 | - => [ |
|
1442 | - 0 |
|
1443 | - => [ |
|
1444 | - 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc1.png', |
|
1445 | - ], |
|
1446 | - 1 |
|
1447 | - => [ |
|
1448 | - 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc2.png', |
|
1449 | - ], |
|
1450 | - 2 |
|
1451 | - => [ |
|
1452 | - 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc3.png', |
|
1453 | - ], |
|
1454 | - ], |
|
1455 | - 'translations' |
|
1456 | - => [ |
|
1457 | - 'en' |
|
1458 | - => [ |
|
1459 | - 'name' => 'OCR', |
|
1460 | - 'summary' => 'Character recoginition for your images and pdf files.', |
|
1461 | - 'description' => '# Description |
|
1435 | + 'translations' |
|
1436 | + => [ |
|
1437 | + ], |
|
1438 | + ], |
|
1439 | + ], |
|
1440 | + 'screenshots' |
|
1441 | + => [ |
|
1442 | + 0 |
|
1443 | + => [ |
|
1444 | + 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc1.png', |
|
1445 | + ], |
|
1446 | + 1 |
|
1447 | + => [ |
|
1448 | + 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc2.png', |
|
1449 | + ], |
|
1450 | + 2 |
|
1451 | + => [ |
|
1452 | + 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc3.png', |
|
1453 | + ], |
|
1454 | + ], |
|
1455 | + 'translations' |
|
1456 | + => [ |
|
1457 | + 'en' |
|
1458 | + => [ |
|
1459 | + 'name' => 'OCR', |
|
1460 | + 'summary' => 'Character recoginition for your images and pdf files.', |
|
1461 | + 'description' => '# Description |
|
1462 | 1462 | |
1463 | 1463 | Nextcloud OCR (optical character recoginition) processing for images and PDF with tesseract-ocr and OCRmyPDF brings OCR capability to your Nextcloud 10. |
1464 | 1464 | The app uses tesseract-ocr, OCRmyPDF and a php internal message queueing service in order to process images (png, jpeg, tiff) and PDF (currently not all PDF-types are supported, for more information see [here](https://github.com/jbarlow83/OCRmyPDF)) asynchronously and save the output file to the same folder in nextcloud, so you are able to search in it. |
@@ -1476,12 +1476,12 @@ discard block |
||
1476 | 1476 | - **[tesseract-ocr](https://github.com/tesseract-ocr/tesseract)** >v3.02.02 with corresponding language files (e.g. tesseract-ocr-eng) |
1477 | 1477 | |
1478 | 1478 | For further information see the homepage or the appropriate documentation.', |
1479 | - ], |
|
1480 | - 'de' |
|
1481 | - => [ |
|
1482 | - 'name' => 'OCR', |
|
1483 | - 'summary' => 'Schrifterkennung für Bilder (mit Text) und PDF Dateien.', |
|
1484 | - 'description' => '# Beschreibung |
|
1479 | + ], |
|
1480 | + 'de' |
|
1481 | + => [ |
|
1482 | + 'name' => 'OCR', |
|
1483 | + 'summary' => 'Schrifterkennung für Bilder (mit Text) und PDF Dateien.', |
|
1484 | + 'description' => '# Beschreibung |
|
1485 | 1485 | |
1486 | 1486 | OCR (Automatische Texterkennung) für Bilder (mit Text) und PDF Dateien mithilfe von tesseract-ocr und OCRmyPDF ermöglicht Ihnen automatische Schrifterkennung direkt in Ihrer Nextcloud 10. |
1487 | 1487 | Die App nutzt Tesseract-ocr, OCRmyPDF und den internen Message Queueing Service von PHP, um so asynchron (im Hintegrund) Bilder (PNG, JPEG, TIFF) und PDFs (aktuell werden nicht alle Typen unterstützt, näheres [hier](https://github.com/jbarlow83/OCRmyPDF)) zu verarbeiten. Das Ergebnis, welches jetzt durchsuchbar, kopierbar und ähnliches ist, wird anschließend im selben Ordner gespeichert, wie die Ursprungsdatei. |
@@ -1499,23 +1499,23 @@ discard block |
||
1499 | 1499 | - **[tesseract-ocr](https://github.com/tesseract-ocr/tesseract)** >v3.02.02 mit den dazugehörigen Übersetzungs- und Sprachdateien (z. B. tesseract-ocr-deu) |
1500 | 1500 | |
1501 | 1501 | Für weiter Informationen besuchen Sie die Homepage oder lesen Sie die zutreffende Dokumentation.', |
1502 | - ], |
|
1503 | - ], |
|
1504 | - 'isFeatured' => false, |
|
1505 | - 'authors' |
|
1506 | - => [ |
|
1507 | - 0 |
|
1508 | - => [ |
|
1509 | - 'name' => 'Janis Koehr', |
|
1510 | - 'mail' => '', |
|
1511 | - 'homepage' => '', |
|
1512 | - ], |
|
1513 | - ], |
|
1514 | - 'ratingRecent' => 0.5, |
|
1515 | - 'ratingOverall' => 0.5, |
|
1516 | - 'ratingNumRecent' => 0, |
|
1517 | - 'ratingNumOverall' => 0, |
|
1518 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1502 | + ], |
|
1503 | + ], |
|
1504 | + 'isFeatured' => false, |
|
1505 | + 'authors' |
|
1506 | + => [ |
|
1507 | + 0 |
|
1508 | + => [ |
|
1509 | + 'name' => 'Janis Koehr', |
|
1510 | + 'mail' => '', |
|
1511 | + 'homepage' => '', |
|
1512 | + ], |
|
1513 | + ], |
|
1514 | + 'ratingRecent' => 0.5, |
|
1515 | + 'ratingOverall' => 0.5, |
|
1516 | + 'ratingNumRecent' => 0, |
|
1517 | + 'ratingNumOverall' => 0, |
|
1518 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1519 | 1519 | MIID/jCCAuYCAhAKMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
1520 | 1520 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
1521 | 1521 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1539,49 +1539,49 @@ discard block |
||
1539 | 1539 | yA1z/MCBEyTRo80jxFmL+MpwbsdbUJi7Qxlnd56zb6HHDGrLHXZTh9LXgyVbnhWL |
1540 | 1540 | kxomWjIXQh4aMHQL4QF7U4EK |
1541 | 1541 | -----END CERTIFICATE-----', |
1542 | - ], |
|
1543 | - 14 |
|
1544 | - => [ |
|
1545 | - 'id' => 'spreedme', |
|
1546 | - 'categories' |
|
1547 | - => [ |
|
1548 | - 0 => 'tools', |
|
1549 | - ], |
|
1550 | - 'userDocs' => 'https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md', |
|
1551 | - 'adminDocs' => 'https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md', |
|
1552 | - 'developerDocs' => '', |
|
1553 | - 'issueTracker' => 'https://github.com/strukturag/nextcloud-spreedme/issues', |
|
1554 | - 'website' => '', |
|
1555 | - 'created' => '2016-09-27T08:43:07.835196Z', |
|
1556 | - 'lastModified' => '2016-11-21T16:51:23.703819Z', |
|
1557 | - 'releases' |
|
1558 | - => [ |
|
1559 | - 0 |
|
1560 | - => [ |
|
1561 | - 'version' => '0.3.4', |
|
1562 | - 'phpExtensions' |
|
1563 | - => [ |
|
1564 | - ], |
|
1565 | - 'databases' |
|
1566 | - => [ |
|
1567 | - ], |
|
1568 | - 'shellCommands' |
|
1569 | - => [ |
|
1570 | - ], |
|
1571 | - 'phpVersionSpec' => '*', |
|
1572 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
1573 | - 'minIntSize' => 32, |
|
1574 | - 'download' => 'https://apps.owncloud.com/CONTENT/content-files/174436-spreedme.tar.gz', |
|
1575 | - 'created' => '2016-11-21T16:51:23.689599Z', |
|
1576 | - 'licenses' |
|
1577 | - => [ |
|
1578 | - 0 => 'agpl', |
|
1579 | - ], |
|
1580 | - 'lastModified' => '2016-11-21T16:51:23.826509Z', |
|
1581 | - 'isNightly' => false, |
|
1582 | - 'rawPhpVersionSpec' => '*', |
|
1583 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
1584 | - 'signature' => 'Mhy3hXeGWlIujx1Op39MMRdqHYOo360BCwr4FPWoTNNggH3aS0gWlh48DAfGYK9W |
|
1542 | + ], |
|
1543 | + 14 |
|
1544 | + => [ |
|
1545 | + 'id' => 'spreedme', |
|
1546 | + 'categories' |
|
1547 | + => [ |
|
1548 | + 0 => 'tools', |
|
1549 | + ], |
|
1550 | + 'userDocs' => 'https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md', |
|
1551 | + 'adminDocs' => 'https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md', |
|
1552 | + 'developerDocs' => '', |
|
1553 | + 'issueTracker' => 'https://github.com/strukturag/nextcloud-spreedme/issues', |
|
1554 | + 'website' => '', |
|
1555 | + 'created' => '2016-09-27T08:43:07.835196Z', |
|
1556 | + 'lastModified' => '2016-11-21T16:51:23.703819Z', |
|
1557 | + 'releases' |
|
1558 | + => [ |
|
1559 | + 0 |
|
1560 | + => [ |
|
1561 | + 'version' => '0.3.4', |
|
1562 | + 'phpExtensions' |
|
1563 | + => [ |
|
1564 | + ], |
|
1565 | + 'databases' |
|
1566 | + => [ |
|
1567 | + ], |
|
1568 | + 'shellCommands' |
|
1569 | + => [ |
|
1570 | + ], |
|
1571 | + 'phpVersionSpec' => '*', |
|
1572 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
1573 | + 'minIntSize' => 32, |
|
1574 | + 'download' => 'https://apps.owncloud.com/CONTENT/content-files/174436-spreedme.tar.gz', |
|
1575 | + 'created' => '2016-11-21T16:51:23.689599Z', |
|
1576 | + 'licenses' |
|
1577 | + => [ |
|
1578 | + 0 => 'agpl', |
|
1579 | + ], |
|
1580 | + 'lastModified' => '2016-11-21T16:51:23.826509Z', |
|
1581 | + 'isNightly' => false, |
|
1582 | + 'rawPhpVersionSpec' => '*', |
|
1583 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
1584 | + 'signature' => 'Mhy3hXeGWlIujx1Op39MMRdqHYOo360BCwr4FPWoTNNggH3aS0gWlh48DAfGYK9W |
|
1585 | 1585 | etNiOqIuRyA0NrVlsqR2vDILgFtODJSbKPyHd3PQn3hcGsjogjQ+dkKciLNLinw7 |
1586 | 1586 | Ohbv6aDdRFLBeRHpX/7wOnWL5W3ko/gyn0Awvi88M9+nC5aARtqncQqPy2SxDGzH |
1587 | 1587 | KlOZHSNDnEQCGMhA8hNWWKdVwNUJHod/wmBWpW5QVNSJq5DqrKZcNwpGM2UUJoql |
@@ -1592,54 +1592,54 @@ discard block |
||
1592 | 1592 | 2Y28qLxwHVaINDFUUxD75WWdrlulRbqHwiSw8jolP9qrpXhDuLAqYam9tRwV5K5R |
1593 | 1593 | 8uNawnFwWkicBEYkN/WtBTouWzehOPn38tHXov6SyEyD6lkuxUBZrsGQ2ru+t33U |
1594 | 1594 | k0kKCbV0GFw43I+3Ji5DiB4TUVNZYVoPG1B7Qve+UfA=', |
1595 | - 'translations' |
|
1596 | - => [ |
|
1597 | - ], |
|
1598 | - ], |
|
1599 | - ], |
|
1600 | - 'screenshots' |
|
1601 | - => [ |
|
1602 | - 0 |
|
1603 | - => [ |
|
1604 | - 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/conference.gif', |
|
1605 | - ], |
|
1606 | - 1 |
|
1607 | - => [ |
|
1608 | - 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/presentation.png', |
|
1609 | - ], |
|
1610 | - 2 |
|
1611 | - => [ |
|
1612 | - 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/import.png', |
|
1613 | - ], |
|
1614 | - 3 |
|
1615 | - => [ |
|
1616 | - 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/users.png', |
|
1617 | - ], |
|
1618 | - ], |
|
1619 | - 'translations' |
|
1620 | - => [ |
|
1621 | - 'en' |
|
1622 | - => [ |
|
1623 | - 'name' => 'Spreed.ME', |
|
1624 | - 'summary' => 'Audio-, video- and text chat for your Nextcloud', |
|
1625 | - 'description' => 'Securely communicate with your friends and family using rich audio-, video- and text chat, and much more right from your Nextcloud – in your browser', |
|
1626 | - ], |
|
1627 | - ], |
|
1628 | - 'isFeatured' => false, |
|
1629 | - 'authors' |
|
1630 | - => [ |
|
1631 | - 0 |
|
1632 | - => [ |
|
1633 | - 'name' => 'struktur AG', |
|
1634 | - 'mail' => '', |
|
1635 | - 'homepage' => '', |
|
1636 | - ], |
|
1637 | - ], |
|
1638 | - 'ratingRecent' => 0.5, |
|
1639 | - 'ratingOverall' => 0.5, |
|
1640 | - 'ratingNumRecent' => 0, |
|
1641 | - 'ratingNumOverall' => 0, |
|
1642 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1595 | + 'translations' |
|
1596 | + => [ |
|
1597 | + ], |
|
1598 | + ], |
|
1599 | + ], |
|
1600 | + 'screenshots' |
|
1601 | + => [ |
|
1602 | + 0 |
|
1603 | + => [ |
|
1604 | + 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/conference.gif', |
|
1605 | + ], |
|
1606 | + 1 |
|
1607 | + => [ |
|
1608 | + 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/presentation.png', |
|
1609 | + ], |
|
1610 | + 2 |
|
1611 | + => [ |
|
1612 | + 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/import.png', |
|
1613 | + ], |
|
1614 | + 3 |
|
1615 | + => [ |
|
1616 | + 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/users.png', |
|
1617 | + ], |
|
1618 | + ], |
|
1619 | + 'translations' |
|
1620 | + => [ |
|
1621 | + 'en' |
|
1622 | + => [ |
|
1623 | + 'name' => 'Spreed.ME', |
|
1624 | + 'summary' => 'Audio-, video- and text chat for your Nextcloud', |
|
1625 | + 'description' => 'Securely communicate with your friends and family using rich audio-, video- and text chat, and much more right from your Nextcloud – in your browser', |
|
1626 | + ], |
|
1627 | + ], |
|
1628 | + 'isFeatured' => false, |
|
1629 | + 'authors' |
|
1630 | + => [ |
|
1631 | + 0 |
|
1632 | + => [ |
|
1633 | + 'name' => 'struktur AG', |
|
1634 | + 'mail' => '', |
|
1635 | + 'homepage' => '', |
|
1636 | + ], |
|
1637 | + ], |
|
1638 | + 'ratingRecent' => 0.5, |
|
1639 | + 'ratingOverall' => 0.5, |
|
1640 | + 'ratingNumRecent' => 0, |
|
1641 | + 'ratingNumOverall' => 0, |
|
1642 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1643 | 1643 | MIIEAzCCAusCAhANMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
1644 | 1644 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
1645 | 1645 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1663,50 +1663,50 @@ discard block |
||
1663 | 1663 | sUNUEU2Decyp0jxLVnrrpz6Y5UupfBR0V8yAv1t5Od/mCKLc5DxHsDWiKOpsob9U |
1664 | 1664 | JN+bdzJil2NNftihD4Dm7Ha7OS3O8W0= |
1665 | 1665 | -----END CERTIFICATE-----', |
1666 | - ], |
|
1667 | - 15 |
|
1668 | - => [ |
|
1669 | - 'id' => 'nextant', |
|
1670 | - 'categories' |
|
1671 | - => [ |
|
1672 | - 0 => 'files', |
|
1673 | - 1 => 'tools', |
|
1674 | - ], |
|
1675 | - 'userDocs' => '', |
|
1676 | - 'adminDocs' => 'https://github.com/nextcloud/nextant/wiki', |
|
1677 | - 'developerDocs' => '', |
|
1678 | - 'issueTracker' => 'https://github.com/nextcloud/nextant/issues', |
|
1679 | - 'website' => 'https://github.com/nextcloud/nextant/wiki', |
|
1680 | - 'created' => '2016-09-14T14:34:35.977699Z', |
|
1681 | - 'lastModified' => '2016-11-22T16:02:57.758477Z', |
|
1682 | - 'releases' |
|
1683 | - => [ |
|
1684 | - 0 |
|
1685 | - => [ |
|
1686 | - 'version' => '0.6.6', |
|
1687 | - 'phpExtensions' |
|
1688 | - => [ |
|
1689 | - ], |
|
1690 | - 'databases' |
|
1691 | - => [ |
|
1692 | - ], |
|
1693 | - 'shellCommands' |
|
1694 | - => [ |
|
1695 | - ], |
|
1696 | - 'phpVersionSpec' => '*', |
|
1697 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
1698 | - 'minIntSize' => 32, |
|
1699 | - 'download' => 'https://github.com/nextcloud/nextant/releases/download/v0.6.6/nextant-0.6.6.tar.gz', |
|
1700 | - 'created' => '2016-11-16T15:11:14.344704Z', |
|
1701 | - 'licenses' |
|
1702 | - => [ |
|
1703 | - 0 => 'agpl', |
|
1704 | - ], |
|
1705 | - 'lastModified' => '2016-11-16T20:39:59.030384Z', |
|
1706 | - 'isNightly' => false, |
|
1707 | - 'rawPhpVersionSpec' => '*', |
|
1708 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
1709 | - 'signature' => 'aOZeEeThyZ0V/vXBcn6c+Z0vyCsZcN6nfSJ8oWEea4zXh4g705Si+MFZESqix3M2 |
|
1666 | + ], |
|
1667 | + 15 |
|
1668 | + => [ |
|
1669 | + 'id' => 'nextant', |
|
1670 | + 'categories' |
|
1671 | + => [ |
|
1672 | + 0 => 'files', |
|
1673 | + 1 => 'tools', |
|
1674 | + ], |
|
1675 | + 'userDocs' => '', |
|
1676 | + 'adminDocs' => 'https://github.com/nextcloud/nextant/wiki', |
|
1677 | + 'developerDocs' => '', |
|
1678 | + 'issueTracker' => 'https://github.com/nextcloud/nextant/issues', |
|
1679 | + 'website' => 'https://github.com/nextcloud/nextant/wiki', |
|
1680 | + 'created' => '2016-09-14T14:34:35.977699Z', |
|
1681 | + 'lastModified' => '2016-11-22T16:02:57.758477Z', |
|
1682 | + 'releases' |
|
1683 | + => [ |
|
1684 | + 0 |
|
1685 | + => [ |
|
1686 | + 'version' => '0.6.6', |
|
1687 | + 'phpExtensions' |
|
1688 | + => [ |
|
1689 | + ], |
|
1690 | + 'databases' |
|
1691 | + => [ |
|
1692 | + ], |
|
1693 | + 'shellCommands' |
|
1694 | + => [ |
|
1695 | + ], |
|
1696 | + 'phpVersionSpec' => '*', |
|
1697 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
1698 | + 'minIntSize' => 32, |
|
1699 | + 'download' => 'https://github.com/nextcloud/nextant/releases/download/v0.6.6/nextant-0.6.6.tar.gz', |
|
1700 | + 'created' => '2016-11-16T15:11:14.344704Z', |
|
1701 | + 'licenses' |
|
1702 | + => [ |
|
1703 | + 0 => 'agpl', |
|
1704 | + ], |
|
1705 | + 'lastModified' => '2016-11-16T20:39:59.030384Z', |
|
1706 | + 'isNightly' => false, |
|
1707 | + 'rawPhpVersionSpec' => '*', |
|
1708 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
1709 | + 'signature' => 'aOZeEeThyZ0V/vXBcn6c+Z0vyCsZcN6nfSJ8oWEea4zXh4g705Si+MFZESqix3M2 |
|
1710 | 1710 | OPCnA/U8eASwdRTAEwQJrW5ECmu1THXSIsrzQzc9kFycvyOGzCgAWtuu0ayzZD2/ |
1711 | 1711 | U5aDWlzpLHC1Czg9QJ5UnfZR0AfChWQ402N1YzGqMShdJv6AHXFrVE+uYnIyxuYI |
1712 | 1712 | oPJQBUYbQwthVUjpYwFwSxw50YU17gmx5RZ0Y0OPz3i/EiuEUrxopXtfDVYAuCML |
@@ -1717,29 +1717,29 @@ discard block |
||
1717 | 1717 | 9P3iPd2hQ6yOM9fG21LVN74b6wggI81BzFf/xJPd4ZqYLjfeG/yqd0zaiMOzMm1W |
1718 | 1718 | se+kc/a4iB3BoCNX3E942pBBzew4ya8LkCXdCHUUsuelDf1va1ikTh/G7D84ll9/ |
1719 | 1719 | 2avNqQnUh3hgOnxFCLI/5VrbqxfSTVdO6O/LTuAmwgw=', |
1720 | - 'translations' |
|
1721 | - => [ |
|
1722 | - ], |
|
1723 | - ], |
|
1724 | - ], |
|
1725 | - 'screenshots' |
|
1726 | - => [ |
|
1727 | - 0 |
|
1728 | - => [ |
|
1729 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/displayResult.jpg', |
|
1730 | - ], |
|
1731 | - 1 |
|
1732 | - => [ |
|
1733 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/admin.jpg', |
|
1734 | - ], |
|
1735 | - ], |
|
1736 | - 'translations' |
|
1737 | - => [ |
|
1738 | - 'en' |
|
1739 | - => [ |
|
1740 | - 'name' => 'Nextant', |
|
1741 | - 'summary' => 'Navigate through your cloud using Solr', |
|
1742 | - 'description' => ' |
|
1720 | + 'translations' |
|
1721 | + => [ |
|
1722 | + ], |
|
1723 | + ], |
|
1724 | + ], |
|
1725 | + 'screenshots' |
|
1726 | + => [ |
|
1727 | + 0 |
|
1728 | + => [ |
|
1729 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/displayResult.jpg', |
|
1730 | + ], |
|
1731 | + 1 |
|
1732 | + => [ |
|
1733 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/admin.jpg', |
|
1734 | + ], |
|
1735 | + ], |
|
1736 | + 'translations' |
|
1737 | + => [ |
|
1738 | + 'en' |
|
1739 | + => [ |
|
1740 | + 'name' => 'Nextant', |
|
1741 | + 'summary' => 'Navigate through your cloud using Solr', |
|
1742 | + 'description' => ' |
|
1743 | 1743 | Navigate through your cloud using Solr |
1744 | 1744 | |
1745 | 1745 | |
@@ -1775,23 +1775,23 @@ discard block |
||
1775 | 1775 | |
1776 | 1776 | |
1777 | 1777 | ', |
1778 | - ], |
|
1779 | - ], |
|
1780 | - 'isFeatured' => false, |
|
1781 | - 'authors' |
|
1782 | - => [ |
|
1783 | - 0 |
|
1784 | - => [ |
|
1785 | - 'name' => 'Maxence Lange', |
|
1786 | - 'mail' => '', |
|
1787 | - 'homepage' => '', |
|
1788 | - ], |
|
1789 | - ], |
|
1790 | - 'ratingRecent' => 0.5, |
|
1791 | - 'ratingOverall' => 0.5, |
|
1792 | - 'ratingNumRecent' => 0, |
|
1793 | - 'ratingNumOverall' => 0, |
|
1794 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1778 | + ], |
|
1779 | + ], |
|
1780 | + 'isFeatured' => false, |
|
1781 | + 'authors' |
|
1782 | + => [ |
|
1783 | + 0 |
|
1784 | + => [ |
|
1785 | + 'name' => 'Maxence Lange', |
|
1786 | + 'mail' => '', |
|
1787 | + 'homepage' => '', |
|
1788 | + ], |
|
1789 | + ], |
|
1790 | + 'ratingRecent' => 0.5, |
|
1791 | + 'ratingOverall' => 0.5, |
|
1792 | + 'ratingNumRecent' => 0, |
|
1793 | + 'ratingNumOverall' => 0, |
|
1794 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
1795 | 1795 | MIIEAjCCAuoCAhAFMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
1796 | 1796 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
1797 | 1797 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1815,444 +1815,444 @@ discard block |
||
1815 | 1815 | 0bfhnvTZ2VhMmK83t7ovo71An4ycmsolGD/MA0vNI78VrVISrdI8rRh2WntUnCBU |
1816 | 1816 | EJL3BaQAQaASSsvFrcozYxrQG4VzEg== |
1817 | 1817 | -----END CERTIFICATE-----', |
1818 | - ], |
|
1819 | - ], |
|
1820 | - 'timestamp' => 1234, |
|
1821 | - 'ncversion' => '11.0.0.2', |
|
1822 | - 'ETag' => '"myETag"', |
|
1823 | - ]; |
|
1824 | - |
|
1825 | - |
|
1826 | - protected function setUp(): void { |
|
1827 | - parent::setUp(); |
|
1828 | - |
|
1829 | - /** @var Factory|\PHPUnit\Framework\MockObject\MockObject $factory */ |
|
1830 | - $factory = $this->createMock(Factory::class); |
|
1831 | - $this->appData = $this->createMock(AppData::class); |
|
1832 | - $factory->expects($this->once()) |
|
1833 | - ->method('get') |
|
1834 | - ->with('appstore') |
|
1835 | - ->willReturn($this->appData); |
|
1836 | - $this->clientService = $this->createMock(IClientService::class); |
|
1837 | - $this->timeFactory = $this->createMock(ITimeFactory::class); |
|
1838 | - $this->config = $this->createMock(IConfig::class); |
|
1839 | - $this->compareVersion = new CompareVersion(); |
|
1840 | - $this->logger = $this->createMock(LoggerInterface::class); |
|
1841 | - $this->registry = $this->createMock(IRegistry::class); |
|
1842 | - |
|
1843 | - $this->fetcher = $this->getMockBuilder(AppFetcher::class) |
|
1844 | - ->onlyMethods(['getChannel']) |
|
1845 | - ->setConstructorArgs([ |
|
1846 | - $factory, |
|
1847 | - $this->clientService, |
|
1848 | - $this->timeFactory, |
|
1849 | - $this->config, |
|
1850 | - $this->compareVersion, |
|
1851 | - $this->logger, |
|
1852 | - $this->registry, |
|
1853 | - ]) |
|
1854 | - ->getMock(); |
|
1855 | - |
|
1856 | - $this->fetcher->method('getChannel') |
|
1857 | - ->willReturn('stable'); |
|
1858 | - } |
|
1859 | - |
|
1860 | - public function testGetWithFilter(): void { |
|
1861 | - $this->config->method('getSystemValueString') |
|
1862 | - ->willReturnCallback(function ($key, $default) { |
|
1863 | - if ($key === 'version') { |
|
1864 | - return '11.0.0.2'; |
|
1865 | - } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
1866 | - return 'https://custom.appsstore.endpoint/api/v1'; |
|
1867 | - } else { |
|
1868 | - return $default; |
|
1869 | - } |
|
1870 | - }); |
|
1871 | - $this->config |
|
1872 | - ->method('getSystemValueBool') |
|
1873 | - ->willReturnArgument(1); |
|
1874 | - |
|
1875 | - $file = $this->createMock(ISimpleFile::class); |
|
1876 | - $folder = $this->createMock(ISimpleFolder::class); |
|
1877 | - $folder |
|
1878 | - ->expects($this->once()) |
|
1879 | - ->method('getFile') |
|
1880 | - ->with('apps.json') |
|
1881 | - ->willThrowException(new NotFoundException()); |
|
1882 | - $folder |
|
1883 | - ->expects($this->once()) |
|
1884 | - ->method('newFile') |
|
1885 | - ->with('apps.json') |
|
1886 | - ->willReturn($file); |
|
1887 | - $this->appData |
|
1888 | - ->expects($this->once()) |
|
1889 | - ->method('getFolder') |
|
1890 | - ->with('/') |
|
1891 | - ->willReturn($folder); |
|
1892 | - $client = $this->createMock(IClient::class); |
|
1893 | - $this->clientService |
|
1894 | - ->expects($this->once()) |
|
1895 | - ->method('newClient') |
|
1896 | - ->willReturn($client); |
|
1897 | - $response = $this->createMock(IResponse::class); |
|
1898 | - $client |
|
1899 | - ->method('get') |
|
1900 | - ->with('https://custom.appsstore.endpoint/api/v1/apps.json') |
|
1901 | - ->willReturn($response); |
|
1902 | - $response |
|
1903 | - ->expects($this->once()) |
|
1904 | - ->method('getBody') |
|
1905 | - ->willReturn(self::$responseJson); |
|
1906 | - $response->method('getHeader') |
|
1907 | - ->with($this->equalTo('ETag')) |
|
1908 | - ->willReturn('"myETag"'); |
|
1909 | - $this->timeFactory |
|
1910 | - ->expects($this->once()) |
|
1911 | - ->method('getTime') |
|
1912 | - ->willReturn(1234); |
|
1913 | - |
|
1914 | - $dataToPut = self::$expectedResponse; |
|
1915 | - $dataToPut['data'] = array_values($dataToPut['data']); |
|
1916 | - $originalArray = json_decode(self::$responseJson, true); |
|
1917 | - $mappedOriginalArray = []; |
|
1918 | - foreach ($originalArray as $key => $value) { |
|
1919 | - foreach ($value as $releaseKey => $releaseValue) { |
|
1920 | - if ($releaseKey === 'id') { |
|
1921 | - $mappedOriginalArray[$releaseValue] = $originalArray[$key]; |
|
1922 | - } |
|
1923 | - } |
|
1924 | - } |
|
1925 | - foreach ($dataToPut['data'] as $key => $appValue) { |
|
1926 | - foreach ($appValue as $appKey => $value) { |
|
1927 | - if ($appKey === 'certificate' || $appKey === 'description') { |
|
1928 | - $dataToPut['data'][$key][$appKey] = $mappedOriginalArray[$appValue['id']][$appKey]; |
|
1929 | - } |
|
1930 | - } |
|
1931 | - } |
|
1932 | - |
|
1933 | - $file |
|
1934 | - ->expects($this->once()) |
|
1935 | - ->method('putContent'); |
|
1936 | - $file |
|
1937 | - ->method('getContent') |
|
1938 | - ->willReturn(json_encode(self::$expectedResponse)); |
|
1939 | - |
|
1940 | - $this->assertEquals(self::$expectedResponse['data'], $this->fetcher->get()); |
|
1941 | - } |
|
1942 | - |
|
1943 | - public function testAppstoreDisabled(): void { |
|
1944 | - $this->config |
|
1945 | - ->method('getSystemValueString') |
|
1946 | - ->willReturnCallback(function ($var, $default) { |
|
1947 | - if ($var === 'version') { |
|
1948 | - return '11.0.0.2'; |
|
1949 | - } |
|
1950 | - return $default; |
|
1951 | - }); |
|
1952 | - $this->config |
|
1953 | - ->method('getSystemValueBool') |
|
1954 | - ->willReturnCallback(function ($var, $default) { |
|
1955 | - if ($var === 'has_internet_connection') { |
|
1956 | - return true; |
|
1957 | - } elseif ($var === 'appstoreenabled') { |
|
1958 | - return false; |
|
1959 | - } |
|
1960 | - return $default; |
|
1961 | - }); |
|
1962 | - $this->appData |
|
1963 | - ->expects($this->never()) |
|
1964 | - ->method('getFolder'); |
|
1965 | - |
|
1966 | - $this->assertEquals([], $this->fetcher->get()); |
|
1967 | - } |
|
1968 | - |
|
1969 | - |
|
1970 | - public function testNoInternet(): void { |
|
1971 | - $this->config |
|
1972 | - ->method('getSystemValueString') |
|
1973 | - ->willReturnCallback(function ($var, $default) { |
|
1974 | - if ($var === 'has_internet_connection') { |
|
1975 | - return false; |
|
1976 | - } elseif ($var === 'version') { |
|
1977 | - return '11.0.0.2'; |
|
1978 | - } |
|
1979 | - return $default; |
|
1980 | - }); |
|
1981 | - $this->config |
|
1982 | - ->method('getSystemValueBool') |
|
1983 | - ->willReturnCallback(function ($var, $default) { |
|
1984 | - if ($var === 'has_internet_connection') { |
|
1985 | - return false; |
|
1986 | - } elseif ($var === 'appstoreenabled') { |
|
1987 | - return true; |
|
1988 | - } |
|
1989 | - return $default; |
|
1990 | - }); |
|
1991 | - $this->appData |
|
1992 | - ->expects($this->never()) |
|
1993 | - ->method('getFolder'); |
|
1994 | - |
|
1995 | - $this->assertEquals([], $this->fetcher->get()); |
|
1996 | - } |
|
1997 | - |
|
1998 | - public function testSetVersion(): void { |
|
1999 | - $this->config->method('getSystemValueString') |
|
2000 | - ->willReturnCallback(function ($key, $default) { |
|
2001 | - if ($key === 'version') { |
|
2002 | - return '10.0.7.2'; |
|
2003 | - } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
2004 | - return 'https://custom.appsstore.endpoint/api/v1'; |
|
2005 | - } else { |
|
2006 | - return $default; |
|
2007 | - } |
|
2008 | - }); |
|
2009 | - $this->config |
|
2010 | - ->method('getSystemValueBool') |
|
2011 | - ->willReturnArgument(1); |
|
2012 | - |
|
2013 | - $file = $this->createMock(ISimpleFile::class); |
|
2014 | - $folder = $this->createMock(ISimpleFolder::class); |
|
2015 | - $folder |
|
2016 | - ->expects($this->once()) |
|
2017 | - ->method('getFile') |
|
2018 | - ->with('future-apps.json') |
|
2019 | - ->willThrowException(new NotFoundException()); |
|
2020 | - $folder |
|
2021 | - ->expects($this->once()) |
|
2022 | - ->method('newFile') |
|
2023 | - ->with('future-apps.json') |
|
2024 | - ->willReturn($file); |
|
2025 | - $this->appData |
|
2026 | - ->expects($this->once()) |
|
2027 | - ->method('getFolder') |
|
2028 | - ->with('/') |
|
2029 | - ->willReturn($folder); |
|
2030 | - $client = $this->createMock(IClient::class); |
|
2031 | - $this->clientService |
|
2032 | - ->expects($this->once()) |
|
2033 | - ->method('newClient') |
|
2034 | - ->willReturn($client); |
|
2035 | - $response = $this->createMock(IResponse::class); |
|
2036 | - $client |
|
2037 | - ->method('get') |
|
2038 | - ->with('https://custom.appsstore.endpoint/api/v1/apps.json') |
|
2039 | - ->willReturn($response); |
|
2040 | - $response |
|
2041 | - ->expects($this->once()) |
|
2042 | - ->method('getBody') |
|
2043 | - ->willReturn(self::$responseJson); |
|
2044 | - $response->method('getHeader') |
|
2045 | - ->with($this->equalTo('ETag')) |
|
2046 | - ->willReturn('"myETag"'); |
|
2047 | - $this->timeFactory |
|
2048 | - ->expects($this->once()) |
|
2049 | - ->method('getTime') |
|
2050 | - ->willReturn(1234); |
|
2051 | - |
|
2052 | - $dataToPut = self::$expectedResponse; |
|
2053 | - $dataToPut['data'] = array_values($dataToPut['data']); |
|
2054 | - $originalArray = json_decode(self::$responseJson, true); |
|
2055 | - $mappedOriginalArray = []; |
|
2056 | - foreach ($originalArray as $key => $value) { |
|
2057 | - foreach ($value as $releaseKey => $releaseValue) { |
|
2058 | - if ($releaseKey === 'id') { |
|
2059 | - $mappedOriginalArray[$releaseValue] = $originalArray[$key]; |
|
2060 | - } |
|
2061 | - } |
|
2062 | - } |
|
2063 | - foreach ($dataToPut['data'] as $key => $appValue) { |
|
2064 | - foreach ($appValue as $appKey => $value) { |
|
2065 | - if ($appKey === 'certificate' || $appKey === 'description') { |
|
2066 | - $dataToPut['data'][$key][$appKey] = $mappedOriginalArray[$appValue['id']][$appKey]; |
|
2067 | - } |
|
2068 | - } |
|
2069 | - } |
|
2070 | - |
|
2071 | - $file |
|
2072 | - ->expects($this->once()) |
|
2073 | - ->method('putContent'); |
|
2074 | - $file |
|
2075 | - ->method('getContent') |
|
2076 | - ->willReturn(json_encode(self::$expectedResponse)); |
|
2077 | - |
|
2078 | - $this->fetcher->setVersion('11.0.0.2', 'future-apps.json', false); |
|
2079 | - $this->assertEquals(self::$expectedResponse['data'], $this->fetcher->get()); |
|
2080 | - } |
|
2081 | - |
|
2082 | - public function testGetAppsAllowlist(): void { |
|
2083 | - $this->config->method('getSystemValueString') |
|
2084 | - ->willReturnCallback(function ($key, $default) { |
|
2085 | - if ($key === 'version') { |
|
2086 | - return '11.0.0.2'; |
|
2087 | - } else { |
|
2088 | - return $default; |
|
2089 | - } |
|
2090 | - }); |
|
2091 | - $this->config->method('getSystemValue') |
|
2092 | - ->willReturnCallback(function ($key, $default) { |
|
2093 | - if ($key === 'appsallowlist') { |
|
2094 | - return ['contacts']; |
|
2095 | - } |
|
2096 | - return $default; |
|
2097 | - }); |
|
2098 | - $this->config->method('getAppValue') |
|
2099 | - ->willReturnCallback(function ($app, $key, $default) { |
|
2100 | - if ($app === 'support' && $key === 'subscription_key') { |
|
2101 | - return 'subscription-key'; |
|
2102 | - } |
|
2103 | - return $default; |
|
2104 | - }); |
|
2105 | - $this->config |
|
2106 | - ->method('getSystemValueBool') |
|
2107 | - ->willReturnArgument(1); |
|
2108 | - |
|
2109 | - $file = $this->createMock(ISimpleFile::class); |
|
2110 | - $folder = $this->createMock(ISimpleFolder::class); |
|
2111 | - $folder |
|
2112 | - ->expects($this->once()) |
|
2113 | - ->method('getFile') |
|
2114 | - ->with('apps.json') |
|
2115 | - ->willThrowException(new NotFoundException()); |
|
2116 | - $folder |
|
2117 | - ->expects($this->once()) |
|
2118 | - ->method('newFile') |
|
2119 | - ->with('apps.json') |
|
2120 | - ->willReturn($file); |
|
2121 | - $this->appData |
|
2122 | - ->expects($this->once()) |
|
2123 | - ->method('getFolder') |
|
2124 | - ->with('/') |
|
2125 | - ->willReturn($folder); |
|
2126 | - $client = $this->createMock(IClient::class); |
|
2127 | - $this->clientService |
|
2128 | - ->expects($this->once()) |
|
2129 | - ->method('newClient') |
|
2130 | - ->willReturn($client); |
|
2131 | - $response = $this->createMock(IResponse::class); |
|
2132 | - $client |
|
2133 | - ->expects($this->once()) |
|
2134 | - ->method('get') |
|
2135 | - ->with('https://apps.nextcloud.com/api/v1/apps.json', [ |
|
2136 | - 'timeout' => 120, |
|
2137 | - 'headers' => [ |
|
2138 | - 'X-NC-Subscription-Key' => 'subscription-key', |
|
2139 | - ], |
|
2140 | - ]) |
|
2141 | - ->willReturn($response); |
|
2142 | - $response |
|
2143 | - ->expects($this->once()) |
|
2144 | - ->method('getBody') |
|
2145 | - ->willReturn(self::$responseJson); |
|
2146 | - $response->method('getHeader') |
|
2147 | - ->with($this->equalTo('ETag')) |
|
2148 | - ->willReturn('"myETag"'); |
|
2149 | - $this->timeFactory |
|
2150 | - ->expects($this->once()) |
|
2151 | - ->method('getTime') |
|
2152 | - ->willReturn(1234); |
|
2153 | - |
|
2154 | - $this->registry |
|
2155 | - ->expects($this->exactly(2)) |
|
2156 | - ->method('delegateHasValidSubscription') |
|
2157 | - ->willReturn(true); |
|
2158 | - |
|
2159 | - $file |
|
2160 | - ->expects($this->once()) |
|
2161 | - ->method('putContent'); |
|
2162 | - $file |
|
2163 | - ->method('getContent') |
|
2164 | - ->willReturn(json_encode(self::$expectedResponse)); |
|
2165 | - |
|
2166 | - $apps = array_values($this->fetcher->get()); |
|
2167 | - $this->assertEquals(count($apps), 1); |
|
2168 | - $this->assertEquals($apps[0]['id'], 'contacts'); |
|
2169 | - } |
|
2170 | - |
|
2171 | - public function testGetAppsAllowlistCustomAppstore(): void { |
|
2172 | - $this->config->method('getSystemValueString') |
|
2173 | - ->willReturnCallback(function ($key, $default) { |
|
2174 | - if ($key === 'version') { |
|
2175 | - return '11.0.0.2'; |
|
2176 | - } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
2177 | - return 'https://custom.appsstore.endpoint/api/v1'; |
|
2178 | - } else { |
|
2179 | - return $default; |
|
2180 | - } |
|
2181 | - }); |
|
2182 | - $this->config->method('getSystemValue') |
|
2183 | - ->willReturnCallback(function ($key, $default) { |
|
2184 | - if ($key === 'appsallowlist') { |
|
2185 | - return ['contacts']; |
|
2186 | - } else { |
|
2187 | - return $default; |
|
2188 | - } |
|
2189 | - }); |
|
2190 | - $this->config |
|
2191 | - ->method('getSystemValueBool') |
|
2192 | - ->willReturnArgument(1); |
|
2193 | - |
|
2194 | - $this->config->method('getAppValue') |
|
2195 | - ->willReturnMap([ |
|
2196 | - ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
2197 | - ['settings', 'appstore-timeout', '120', '120'], |
|
2198 | - ]); |
|
2199 | - |
|
2200 | - $file = $this->createMock(ISimpleFile::class); |
|
2201 | - $folder = $this->createMock(ISimpleFolder::class); |
|
2202 | - $folder |
|
2203 | - ->expects($this->once()) |
|
2204 | - ->method('getFile') |
|
2205 | - ->with('apps.json') |
|
2206 | - ->willThrowException(new NotFoundException()); |
|
2207 | - $folder |
|
2208 | - ->expects($this->once()) |
|
2209 | - ->method('newFile') |
|
2210 | - ->with('apps.json') |
|
2211 | - ->willReturn($file); |
|
2212 | - $this->appData |
|
2213 | - ->expects($this->once()) |
|
2214 | - ->method('getFolder') |
|
2215 | - ->with('/') |
|
2216 | - ->willReturn($folder); |
|
2217 | - $client = $this->createMock(IClient::class); |
|
2218 | - $this->clientService |
|
2219 | - ->expects($this->once()) |
|
2220 | - ->method('newClient') |
|
2221 | - ->willReturn($client); |
|
2222 | - $response = $this->createMock(IResponse::class); |
|
2223 | - $client |
|
2224 | - ->expects($this->once()) |
|
2225 | - ->method('get') |
|
2226 | - ->with('https://custom.appsstore.endpoint/api/v1/apps.json', [ |
|
2227 | - 'timeout' => 120, |
|
2228 | - ]) |
|
2229 | - ->willReturn($response); |
|
2230 | - $response |
|
2231 | - ->expects($this->once()) |
|
2232 | - ->method('getBody') |
|
2233 | - ->willReturn(self::$responseJson); |
|
2234 | - $response->method('getHeader') |
|
2235 | - ->with($this->equalTo('ETag')) |
|
2236 | - ->willReturn('"myETag"'); |
|
2237 | - $this->timeFactory |
|
2238 | - ->expects($this->once()) |
|
2239 | - ->method('getTime') |
|
2240 | - ->willReturn(1234); |
|
2241 | - |
|
2242 | - $this->registry |
|
2243 | - ->expects($this->exactly(1)) |
|
2244 | - ->method('delegateHasValidSubscription') |
|
2245 | - ->willReturn(true); |
|
2246 | - |
|
2247 | - $file |
|
2248 | - ->expects($this->once()) |
|
2249 | - ->method('putContent'); |
|
2250 | - $file |
|
2251 | - ->method('getContent') |
|
2252 | - ->willReturn(json_encode(self::$expectedResponse)); |
|
2253 | - |
|
2254 | - $apps = array_values($this->fetcher->get()); |
|
2255 | - $this->assertEquals(count($apps), 1); |
|
2256 | - $this->assertEquals($apps[0]['id'], 'contacts'); |
|
2257 | - } |
|
1818 | + ], |
|
1819 | + ], |
|
1820 | + 'timestamp' => 1234, |
|
1821 | + 'ncversion' => '11.0.0.2', |
|
1822 | + 'ETag' => '"myETag"', |
|
1823 | + ]; |
|
1824 | + |
|
1825 | + |
|
1826 | + protected function setUp(): void { |
|
1827 | + parent::setUp(); |
|
1828 | + |
|
1829 | + /** @var Factory|\PHPUnit\Framework\MockObject\MockObject $factory */ |
|
1830 | + $factory = $this->createMock(Factory::class); |
|
1831 | + $this->appData = $this->createMock(AppData::class); |
|
1832 | + $factory->expects($this->once()) |
|
1833 | + ->method('get') |
|
1834 | + ->with('appstore') |
|
1835 | + ->willReturn($this->appData); |
|
1836 | + $this->clientService = $this->createMock(IClientService::class); |
|
1837 | + $this->timeFactory = $this->createMock(ITimeFactory::class); |
|
1838 | + $this->config = $this->createMock(IConfig::class); |
|
1839 | + $this->compareVersion = new CompareVersion(); |
|
1840 | + $this->logger = $this->createMock(LoggerInterface::class); |
|
1841 | + $this->registry = $this->createMock(IRegistry::class); |
|
1842 | + |
|
1843 | + $this->fetcher = $this->getMockBuilder(AppFetcher::class) |
|
1844 | + ->onlyMethods(['getChannel']) |
|
1845 | + ->setConstructorArgs([ |
|
1846 | + $factory, |
|
1847 | + $this->clientService, |
|
1848 | + $this->timeFactory, |
|
1849 | + $this->config, |
|
1850 | + $this->compareVersion, |
|
1851 | + $this->logger, |
|
1852 | + $this->registry, |
|
1853 | + ]) |
|
1854 | + ->getMock(); |
|
1855 | + |
|
1856 | + $this->fetcher->method('getChannel') |
|
1857 | + ->willReturn('stable'); |
|
1858 | + } |
|
1859 | + |
|
1860 | + public function testGetWithFilter(): void { |
|
1861 | + $this->config->method('getSystemValueString') |
|
1862 | + ->willReturnCallback(function ($key, $default) { |
|
1863 | + if ($key === 'version') { |
|
1864 | + return '11.0.0.2'; |
|
1865 | + } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
1866 | + return 'https://custom.appsstore.endpoint/api/v1'; |
|
1867 | + } else { |
|
1868 | + return $default; |
|
1869 | + } |
|
1870 | + }); |
|
1871 | + $this->config |
|
1872 | + ->method('getSystemValueBool') |
|
1873 | + ->willReturnArgument(1); |
|
1874 | + |
|
1875 | + $file = $this->createMock(ISimpleFile::class); |
|
1876 | + $folder = $this->createMock(ISimpleFolder::class); |
|
1877 | + $folder |
|
1878 | + ->expects($this->once()) |
|
1879 | + ->method('getFile') |
|
1880 | + ->with('apps.json') |
|
1881 | + ->willThrowException(new NotFoundException()); |
|
1882 | + $folder |
|
1883 | + ->expects($this->once()) |
|
1884 | + ->method('newFile') |
|
1885 | + ->with('apps.json') |
|
1886 | + ->willReturn($file); |
|
1887 | + $this->appData |
|
1888 | + ->expects($this->once()) |
|
1889 | + ->method('getFolder') |
|
1890 | + ->with('/') |
|
1891 | + ->willReturn($folder); |
|
1892 | + $client = $this->createMock(IClient::class); |
|
1893 | + $this->clientService |
|
1894 | + ->expects($this->once()) |
|
1895 | + ->method('newClient') |
|
1896 | + ->willReturn($client); |
|
1897 | + $response = $this->createMock(IResponse::class); |
|
1898 | + $client |
|
1899 | + ->method('get') |
|
1900 | + ->with('https://custom.appsstore.endpoint/api/v1/apps.json') |
|
1901 | + ->willReturn($response); |
|
1902 | + $response |
|
1903 | + ->expects($this->once()) |
|
1904 | + ->method('getBody') |
|
1905 | + ->willReturn(self::$responseJson); |
|
1906 | + $response->method('getHeader') |
|
1907 | + ->with($this->equalTo('ETag')) |
|
1908 | + ->willReturn('"myETag"'); |
|
1909 | + $this->timeFactory |
|
1910 | + ->expects($this->once()) |
|
1911 | + ->method('getTime') |
|
1912 | + ->willReturn(1234); |
|
1913 | + |
|
1914 | + $dataToPut = self::$expectedResponse; |
|
1915 | + $dataToPut['data'] = array_values($dataToPut['data']); |
|
1916 | + $originalArray = json_decode(self::$responseJson, true); |
|
1917 | + $mappedOriginalArray = []; |
|
1918 | + foreach ($originalArray as $key => $value) { |
|
1919 | + foreach ($value as $releaseKey => $releaseValue) { |
|
1920 | + if ($releaseKey === 'id') { |
|
1921 | + $mappedOriginalArray[$releaseValue] = $originalArray[$key]; |
|
1922 | + } |
|
1923 | + } |
|
1924 | + } |
|
1925 | + foreach ($dataToPut['data'] as $key => $appValue) { |
|
1926 | + foreach ($appValue as $appKey => $value) { |
|
1927 | + if ($appKey === 'certificate' || $appKey === 'description') { |
|
1928 | + $dataToPut['data'][$key][$appKey] = $mappedOriginalArray[$appValue['id']][$appKey]; |
|
1929 | + } |
|
1930 | + } |
|
1931 | + } |
|
1932 | + |
|
1933 | + $file |
|
1934 | + ->expects($this->once()) |
|
1935 | + ->method('putContent'); |
|
1936 | + $file |
|
1937 | + ->method('getContent') |
|
1938 | + ->willReturn(json_encode(self::$expectedResponse)); |
|
1939 | + |
|
1940 | + $this->assertEquals(self::$expectedResponse['data'], $this->fetcher->get()); |
|
1941 | + } |
|
1942 | + |
|
1943 | + public function testAppstoreDisabled(): void { |
|
1944 | + $this->config |
|
1945 | + ->method('getSystemValueString') |
|
1946 | + ->willReturnCallback(function ($var, $default) { |
|
1947 | + if ($var === 'version') { |
|
1948 | + return '11.0.0.2'; |
|
1949 | + } |
|
1950 | + return $default; |
|
1951 | + }); |
|
1952 | + $this->config |
|
1953 | + ->method('getSystemValueBool') |
|
1954 | + ->willReturnCallback(function ($var, $default) { |
|
1955 | + if ($var === 'has_internet_connection') { |
|
1956 | + return true; |
|
1957 | + } elseif ($var === 'appstoreenabled') { |
|
1958 | + return false; |
|
1959 | + } |
|
1960 | + return $default; |
|
1961 | + }); |
|
1962 | + $this->appData |
|
1963 | + ->expects($this->never()) |
|
1964 | + ->method('getFolder'); |
|
1965 | + |
|
1966 | + $this->assertEquals([], $this->fetcher->get()); |
|
1967 | + } |
|
1968 | + |
|
1969 | + |
|
1970 | + public function testNoInternet(): void { |
|
1971 | + $this->config |
|
1972 | + ->method('getSystemValueString') |
|
1973 | + ->willReturnCallback(function ($var, $default) { |
|
1974 | + if ($var === 'has_internet_connection') { |
|
1975 | + return false; |
|
1976 | + } elseif ($var === 'version') { |
|
1977 | + return '11.0.0.2'; |
|
1978 | + } |
|
1979 | + return $default; |
|
1980 | + }); |
|
1981 | + $this->config |
|
1982 | + ->method('getSystemValueBool') |
|
1983 | + ->willReturnCallback(function ($var, $default) { |
|
1984 | + if ($var === 'has_internet_connection') { |
|
1985 | + return false; |
|
1986 | + } elseif ($var === 'appstoreenabled') { |
|
1987 | + return true; |
|
1988 | + } |
|
1989 | + return $default; |
|
1990 | + }); |
|
1991 | + $this->appData |
|
1992 | + ->expects($this->never()) |
|
1993 | + ->method('getFolder'); |
|
1994 | + |
|
1995 | + $this->assertEquals([], $this->fetcher->get()); |
|
1996 | + } |
|
1997 | + |
|
1998 | + public function testSetVersion(): void { |
|
1999 | + $this->config->method('getSystemValueString') |
|
2000 | + ->willReturnCallback(function ($key, $default) { |
|
2001 | + if ($key === 'version') { |
|
2002 | + return '10.0.7.2'; |
|
2003 | + } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
2004 | + return 'https://custom.appsstore.endpoint/api/v1'; |
|
2005 | + } else { |
|
2006 | + return $default; |
|
2007 | + } |
|
2008 | + }); |
|
2009 | + $this->config |
|
2010 | + ->method('getSystemValueBool') |
|
2011 | + ->willReturnArgument(1); |
|
2012 | + |
|
2013 | + $file = $this->createMock(ISimpleFile::class); |
|
2014 | + $folder = $this->createMock(ISimpleFolder::class); |
|
2015 | + $folder |
|
2016 | + ->expects($this->once()) |
|
2017 | + ->method('getFile') |
|
2018 | + ->with('future-apps.json') |
|
2019 | + ->willThrowException(new NotFoundException()); |
|
2020 | + $folder |
|
2021 | + ->expects($this->once()) |
|
2022 | + ->method('newFile') |
|
2023 | + ->with('future-apps.json') |
|
2024 | + ->willReturn($file); |
|
2025 | + $this->appData |
|
2026 | + ->expects($this->once()) |
|
2027 | + ->method('getFolder') |
|
2028 | + ->with('/') |
|
2029 | + ->willReturn($folder); |
|
2030 | + $client = $this->createMock(IClient::class); |
|
2031 | + $this->clientService |
|
2032 | + ->expects($this->once()) |
|
2033 | + ->method('newClient') |
|
2034 | + ->willReturn($client); |
|
2035 | + $response = $this->createMock(IResponse::class); |
|
2036 | + $client |
|
2037 | + ->method('get') |
|
2038 | + ->with('https://custom.appsstore.endpoint/api/v1/apps.json') |
|
2039 | + ->willReturn($response); |
|
2040 | + $response |
|
2041 | + ->expects($this->once()) |
|
2042 | + ->method('getBody') |
|
2043 | + ->willReturn(self::$responseJson); |
|
2044 | + $response->method('getHeader') |
|
2045 | + ->with($this->equalTo('ETag')) |
|
2046 | + ->willReturn('"myETag"'); |
|
2047 | + $this->timeFactory |
|
2048 | + ->expects($this->once()) |
|
2049 | + ->method('getTime') |
|
2050 | + ->willReturn(1234); |
|
2051 | + |
|
2052 | + $dataToPut = self::$expectedResponse; |
|
2053 | + $dataToPut['data'] = array_values($dataToPut['data']); |
|
2054 | + $originalArray = json_decode(self::$responseJson, true); |
|
2055 | + $mappedOriginalArray = []; |
|
2056 | + foreach ($originalArray as $key => $value) { |
|
2057 | + foreach ($value as $releaseKey => $releaseValue) { |
|
2058 | + if ($releaseKey === 'id') { |
|
2059 | + $mappedOriginalArray[$releaseValue] = $originalArray[$key]; |
|
2060 | + } |
|
2061 | + } |
|
2062 | + } |
|
2063 | + foreach ($dataToPut['data'] as $key => $appValue) { |
|
2064 | + foreach ($appValue as $appKey => $value) { |
|
2065 | + if ($appKey === 'certificate' || $appKey === 'description') { |
|
2066 | + $dataToPut['data'][$key][$appKey] = $mappedOriginalArray[$appValue['id']][$appKey]; |
|
2067 | + } |
|
2068 | + } |
|
2069 | + } |
|
2070 | + |
|
2071 | + $file |
|
2072 | + ->expects($this->once()) |
|
2073 | + ->method('putContent'); |
|
2074 | + $file |
|
2075 | + ->method('getContent') |
|
2076 | + ->willReturn(json_encode(self::$expectedResponse)); |
|
2077 | + |
|
2078 | + $this->fetcher->setVersion('11.0.0.2', 'future-apps.json', false); |
|
2079 | + $this->assertEquals(self::$expectedResponse['data'], $this->fetcher->get()); |
|
2080 | + } |
|
2081 | + |
|
2082 | + public function testGetAppsAllowlist(): void { |
|
2083 | + $this->config->method('getSystemValueString') |
|
2084 | + ->willReturnCallback(function ($key, $default) { |
|
2085 | + if ($key === 'version') { |
|
2086 | + return '11.0.0.2'; |
|
2087 | + } else { |
|
2088 | + return $default; |
|
2089 | + } |
|
2090 | + }); |
|
2091 | + $this->config->method('getSystemValue') |
|
2092 | + ->willReturnCallback(function ($key, $default) { |
|
2093 | + if ($key === 'appsallowlist') { |
|
2094 | + return ['contacts']; |
|
2095 | + } |
|
2096 | + return $default; |
|
2097 | + }); |
|
2098 | + $this->config->method('getAppValue') |
|
2099 | + ->willReturnCallback(function ($app, $key, $default) { |
|
2100 | + if ($app === 'support' && $key === 'subscription_key') { |
|
2101 | + return 'subscription-key'; |
|
2102 | + } |
|
2103 | + return $default; |
|
2104 | + }); |
|
2105 | + $this->config |
|
2106 | + ->method('getSystemValueBool') |
|
2107 | + ->willReturnArgument(1); |
|
2108 | + |
|
2109 | + $file = $this->createMock(ISimpleFile::class); |
|
2110 | + $folder = $this->createMock(ISimpleFolder::class); |
|
2111 | + $folder |
|
2112 | + ->expects($this->once()) |
|
2113 | + ->method('getFile') |
|
2114 | + ->with('apps.json') |
|
2115 | + ->willThrowException(new NotFoundException()); |
|
2116 | + $folder |
|
2117 | + ->expects($this->once()) |
|
2118 | + ->method('newFile') |
|
2119 | + ->with('apps.json') |
|
2120 | + ->willReturn($file); |
|
2121 | + $this->appData |
|
2122 | + ->expects($this->once()) |
|
2123 | + ->method('getFolder') |
|
2124 | + ->with('/') |
|
2125 | + ->willReturn($folder); |
|
2126 | + $client = $this->createMock(IClient::class); |
|
2127 | + $this->clientService |
|
2128 | + ->expects($this->once()) |
|
2129 | + ->method('newClient') |
|
2130 | + ->willReturn($client); |
|
2131 | + $response = $this->createMock(IResponse::class); |
|
2132 | + $client |
|
2133 | + ->expects($this->once()) |
|
2134 | + ->method('get') |
|
2135 | + ->with('https://apps.nextcloud.com/api/v1/apps.json', [ |
|
2136 | + 'timeout' => 120, |
|
2137 | + 'headers' => [ |
|
2138 | + 'X-NC-Subscription-Key' => 'subscription-key', |
|
2139 | + ], |
|
2140 | + ]) |
|
2141 | + ->willReturn($response); |
|
2142 | + $response |
|
2143 | + ->expects($this->once()) |
|
2144 | + ->method('getBody') |
|
2145 | + ->willReturn(self::$responseJson); |
|
2146 | + $response->method('getHeader') |
|
2147 | + ->with($this->equalTo('ETag')) |
|
2148 | + ->willReturn('"myETag"'); |
|
2149 | + $this->timeFactory |
|
2150 | + ->expects($this->once()) |
|
2151 | + ->method('getTime') |
|
2152 | + ->willReturn(1234); |
|
2153 | + |
|
2154 | + $this->registry |
|
2155 | + ->expects($this->exactly(2)) |
|
2156 | + ->method('delegateHasValidSubscription') |
|
2157 | + ->willReturn(true); |
|
2158 | + |
|
2159 | + $file |
|
2160 | + ->expects($this->once()) |
|
2161 | + ->method('putContent'); |
|
2162 | + $file |
|
2163 | + ->method('getContent') |
|
2164 | + ->willReturn(json_encode(self::$expectedResponse)); |
|
2165 | + |
|
2166 | + $apps = array_values($this->fetcher->get()); |
|
2167 | + $this->assertEquals(count($apps), 1); |
|
2168 | + $this->assertEquals($apps[0]['id'], 'contacts'); |
|
2169 | + } |
|
2170 | + |
|
2171 | + public function testGetAppsAllowlistCustomAppstore(): void { |
|
2172 | + $this->config->method('getSystemValueString') |
|
2173 | + ->willReturnCallback(function ($key, $default) { |
|
2174 | + if ($key === 'version') { |
|
2175 | + return '11.0.0.2'; |
|
2176 | + } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
2177 | + return 'https://custom.appsstore.endpoint/api/v1'; |
|
2178 | + } else { |
|
2179 | + return $default; |
|
2180 | + } |
|
2181 | + }); |
|
2182 | + $this->config->method('getSystemValue') |
|
2183 | + ->willReturnCallback(function ($key, $default) { |
|
2184 | + if ($key === 'appsallowlist') { |
|
2185 | + return ['contacts']; |
|
2186 | + } else { |
|
2187 | + return $default; |
|
2188 | + } |
|
2189 | + }); |
|
2190 | + $this->config |
|
2191 | + ->method('getSystemValueBool') |
|
2192 | + ->willReturnArgument(1); |
|
2193 | + |
|
2194 | + $this->config->method('getAppValue') |
|
2195 | + ->willReturnMap([ |
|
2196 | + ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
2197 | + ['settings', 'appstore-timeout', '120', '120'], |
|
2198 | + ]); |
|
2199 | + |
|
2200 | + $file = $this->createMock(ISimpleFile::class); |
|
2201 | + $folder = $this->createMock(ISimpleFolder::class); |
|
2202 | + $folder |
|
2203 | + ->expects($this->once()) |
|
2204 | + ->method('getFile') |
|
2205 | + ->with('apps.json') |
|
2206 | + ->willThrowException(new NotFoundException()); |
|
2207 | + $folder |
|
2208 | + ->expects($this->once()) |
|
2209 | + ->method('newFile') |
|
2210 | + ->with('apps.json') |
|
2211 | + ->willReturn($file); |
|
2212 | + $this->appData |
|
2213 | + ->expects($this->once()) |
|
2214 | + ->method('getFolder') |
|
2215 | + ->with('/') |
|
2216 | + ->willReturn($folder); |
|
2217 | + $client = $this->createMock(IClient::class); |
|
2218 | + $this->clientService |
|
2219 | + ->expects($this->once()) |
|
2220 | + ->method('newClient') |
|
2221 | + ->willReturn($client); |
|
2222 | + $response = $this->createMock(IResponse::class); |
|
2223 | + $client |
|
2224 | + ->expects($this->once()) |
|
2225 | + ->method('get') |
|
2226 | + ->with('https://custom.appsstore.endpoint/api/v1/apps.json', [ |
|
2227 | + 'timeout' => 120, |
|
2228 | + ]) |
|
2229 | + ->willReturn($response); |
|
2230 | + $response |
|
2231 | + ->expects($this->once()) |
|
2232 | + ->method('getBody') |
|
2233 | + ->willReturn(self::$responseJson); |
|
2234 | + $response->method('getHeader') |
|
2235 | + ->with($this->equalTo('ETag')) |
|
2236 | + ->willReturn('"myETag"'); |
|
2237 | + $this->timeFactory |
|
2238 | + ->expects($this->once()) |
|
2239 | + ->method('getTime') |
|
2240 | + ->willReturn(1234); |
|
2241 | + |
|
2242 | + $this->registry |
|
2243 | + ->expects($this->exactly(1)) |
|
2244 | + ->method('delegateHasValidSubscription') |
|
2245 | + ->willReturn(true); |
|
2246 | + |
|
2247 | + $file |
|
2248 | + ->expects($this->once()) |
|
2249 | + ->method('putContent'); |
|
2250 | + $file |
|
2251 | + ->method('getContent') |
|
2252 | + ->willReturn(json_encode(self::$expectedResponse)); |
|
2253 | + |
|
2254 | + $apps = array_values($this->fetcher->get()); |
|
2255 | + $this->assertEquals(count($apps), 1); |
|
2256 | + $this->assertEquals($apps[0]['id'], 'contacts'); |
|
2257 | + } |
|
2258 | 2258 | } |
@@ -24,670 +24,670 @@ |
||
24 | 24 | use Test\TestCase; |
25 | 25 | |
26 | 26 | abstract class FetcherBase extends TestCase { |
27 | - /** @var Factory|\PHPUnit\Framework\MockObject\MockObject */ |
|
28 | - protected $appDataFactory; |
|
29 | - /** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */ |
|
30 | - protected $appData; |
|
31 | - /** @var IClientService|\PHPUnit\Framework\MockObject\MockObject */ |
|
32 | - protected $clientService; |
|
33 | - /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ |
|
34 | - protected $timeFactory; |
|
35 | - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ |
|
36 | - protected $config; |
|
37 | - /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ |
|
38 | - protected $logger; |
|
39 | - /** @var IRegistry|\PHPUnit\Framework\MockObject\MockObject */ |
|
40 | - protected $registry; |
|
41 | - /** @var Fetcher */ |
|
42 | - protected $fetcher; |
|
43 | - /** @var string */ |
|
44 | - protected $fileName; |
|
45 | - /** @var string */ |
|
46 | - protected $endpoint; |
|
47 | - |
|
48 | - protected function setUp(): void { |
|
49 | - parent::setUp(); |
|
50 | - $this->appDataFactory = $this->createMock(Factory::class); |
|
51 | - $this->appData = $this->createMock(AppData::class); |
|
52 | - $this->appDataFactory->expects($this->once()) |
|
53 | - ->method('get') |
|
54 | - ->with('appstore') |
|
55 | - ->willReturn($this->appData); |
|
56 | - $this->clientService = $this->createMock(IClientService::class); |
|
57 | - $this->timeFactory = $this->createMock(ITimeFactory::class); |
|
58 | - $this->config = $this->createMock(IConfig::class); |
|
59 | - $this->logger = $this->createMock(LoggerInterface::class); |
|
60 | - $this->registry = $this->createMock(IRegistry::class); |
|
61 | - } |
|
62 | - |
|
63 | - public function testGetWithAlreadyExistingFileAndUpToDateTimestampAndVersion(): void { |
|
64 | - $this->config |
|
65 | - ->method('getSystemValueString') |
|
66 | - ->willReturnCallback(function ($var, $default) { |
|
67 | - if ($var === 'version') { |
|
68 | - return '11.0.0.2'; |
|
69 | - } |
|
70 | - return $default; |
|
71 | - }); |
|
72 | - $this->config->method('getSystemValueBool') |
|
73 | - ->willReturnArgument(1); |
|
74 | - |
|
75 | - $folder = $this->createMock(ISimpleFolder::class); |
|
76 | - $file = $this->createMock(ISimpleFile::class); |
|
77 | - $this->appData |
|
78 | - ->expects($this->once()) |
|
79 | - ->method('getFolder') |
|
80 | - ->with('/') |
|
81 | - ->willReturn($folder); |
|
82 | - $folder |
|
83 | - ->expects($this->once()) |
|
84 | - ->method('getFile') |
|
85 | - ->with($this->fileName) |
|
86 | - ->willReturn($file); |
|
87 | - $file |
|
88 | - ->expects($this->once()) |
|
89 | - ->method('getContent') |
|
90 | - ->willReturn('{"timestamp":1200,"data":[{"id":"MyApp"}],"ncversion":"11.0.0.2"}'); |
|
91 | - $this->timeFactory |
|
92 | - ->expects($this->once()) |
|
93 | - ->method('getTime') |
|
94 | - ->willReturn(1499); |
|
95 | - |
|
96 | - $expected = [ |
|
97 | - [ |
|
98 | - 'id' => 'MyApp', |
|
99 | - ], |
|
100 | - ]; |
|
101 | - $this->assertSame($expected, $this->fetcher->get()); |
|
102 | - } |
|
103 | - |
|
104 | - public function testGetWithNotExistingFileAndUpToDateTimestampAndVersion(): void { |
|
105 | - $this->config |
|
106 | - ->method('getSystemValueString') |
|
107 | - ->willReturnCallback(function ($var, $default) { |
|
108 | - if ($var === 'appstoreurl') { |
|
109 | - return 'https://apps.nextcloud.com/api/v1'; |
|
110 | - } elseif ($var === 'version') { |
|
111 | - return '11.0.0.2'; |
|
112 | - } |
|
113 | - return $default; |
|
114 | - }); |
|
115 | - $this->config->method('getSystemValueBool') |
|
116 | - ->willReturnArgument(1); |
|
117 | - |
|
118 | - $folder = $this->createMock(ISimpleFolder::class); |
|
119 | - $file = $this->createMock(ISimpleFile::class); |
|
120 | - $this->appData |
|
121 | - ->expects($this->once()) |
|
122 | - ->method('getFolder') |
|
123 | - ->with('/') |
|
124 | - ->willReturn($folder); |
|
125 | - $folder |
|
126 | - ->expects($this->once()) |
|
127 | - ->method('getFile') |
|
128 | - ->with($this->fileName) |
|
129 | - ->willThrowException(new NotFoundException()); |
|
130 | - $folder |
|
131 | - ->expects($this->once()) |
|
132 | - ->method('newFile') |
|
133 | - ->with($this->fileName) |
|
134 | - ->willReturn($file); |
|
135 | - $client = $this->createMock(IClient::class); |
|
136 | - $this->clientService |
|
137 | - ->expects($this->once()) |
|
138 | - ->method('newClient') |
|
139 | - ->willReturn($client); |
|
140 | - $response = $this->createMock(IResponse::class); |
|
141 | - $client |
|
142 | - ->expects($this->once()) |
|
143 | - ->method('get') |
|
144 | - ->with($this->endpoint) |
|
145 | - ->willReturn($response); |
|
146 | - $response |
|
147 | - ->expects($this->once()) |
|
148 | - ->method('getBody') |
|
149 | - ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
150 | - $response->method('getHeader') |
|
151 | - ->with($this->equalTo('ETag')) |
|
152 | - ->willReturn('"myETag"'); |
|
153 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
154 | - $file |
|
155 | - ->expects($this->once()) |
|
156 | - ->method('putContent') |
|
157 | - ->with($fileData); |
|
158 | - $file |
|
159 | - ->expects($this->once()) |
|
160 | - ->method('getContent') |
|
161 | - ->willReturn($fileData); |
|
162 | - $this->timeFactory |
|
163 | - ->expects($this->once()) |
|
164 | - ->method('getTime') |
|
165 | - ->willReturn(1502); |
|
166 | - |
|
167 | - $expected = [ |
|
168 | - [ |
|
169 | - 'id' => 'MyNewApp', |
|
170 | - 'foo' => 'foo', |
|
171 | - ], |
|
172 | - [ |
|
173 | - 'id' => 'bar', |
|
174 | - ], |
|
175 | - ]; |
|
176 | - $this->assertSame($expected, $this->fetcher->get()); |
|
177 | - } |
|
178 | - |
|
179 | - public function testGetWithAlreadyExistingFileAndOutdatedTimestamp(): void { |
|
180 | - $this->config->method('getSystemValueString') |
|
181 | - ->willReturnCallback(function ($key, $default) { |
|
182 | - if ($key === 'version') { |
|
183 | - return '11.0.0.2'; |
|
184 | - } else { |
|
185 | - return $default; |
|
186 | - } |
|
187 | - }); |
|
188 | - $this->config->method('getSystemValueBool') |
|
189 | - ->willReturnArgument(1); |
|
190 | - |
|
191 | - $folder = $this->createMock(ISimpleFolder::class); |
|
192 | - $file = $this->createMock(ISimpleFile::class); |
|
193 | - $this->appData |
|
194 | - ->expects($this->once()) |
|
195 | - ->method('getFolder') |
|
196 | - ->with('/') |
|
197 | - ->willReturn($folder); |
|
198 | - $folder |
|
199 | - ->expects($this->once()) |
|
200 | - ->method('getFile') |
|
201 | - ->with($this->fileName) |
|
202 | - ->willReturn($file); |
|
203 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
204 | - $file |
|
205 | - ->expects($this->once()) |
|
206 | - ->method('putContent') |
|
207 | - ->with($fileData); |
|
208 | - $file |
|
209 | - ->expects($this->exactly(2)) |
|
210 | - ->method('getContent') |
|
211 | - ->willReturnOnConsecutiveCalls( |
|
212 | - '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.2"}', |
|
213 | - $fileData |
|
214 | - ); |
|
215 | - $this->timeFactory |
|
216 | - ->expects($this->exactly(2)) |
|
217 | - ->method('getTime') |
|
218 | - ->willReturnOnConsecutiveCalls( |
|
219 | - 4801, |
|
220 | - 1502 |
|
221 | - ); |
|
222 | - $client = $this->createMock(IClient::class); |
|
223 | - $this->clientService |
|
224 | - ->expects($this->once()) |
|
225 | - ->method('newClient') |
|
226 | - ->willReturn($client); |
|
227 | - $response = $this->createMock(IResponse::class); |
|
228 | - $client |
|
229 | - ->expects($this->once()) |
|
230 | - ->method('get') |
|
231 | - ->with($this->endpoint) |
|
232 | - ->willReturn($response); |
|
233 | - $response |
|
234 | - ->expects($this->once()) |
|
235 | - ->method('getBody') |
|
236 | - ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
237 | - $response->method('getHeader') |
|
238 | - ->with($this->equalTo('ETag')) |
|
239 | - ->willReturn('"myETag"'); |
|
240 | - |
|
241 | - $expected = [ |
|
242 | - [ |
|
243 | - 'id' => 'MyNewApp', |
|
244 | - 'foo' => 'foo', |
|
245 | - ], |
|
246 | - [ |
|
247 | - 'id' => 'bar', |
|
248 | - ], |
|
249 | - ]; |
|
250 | - $this->assertSame($expected, $this->fetcher->get()); |
|
251 | - } |
|
252 | - |
|
253 | - public function testGetWithAlreadyExistingFileAndNoVersion(): void { |
|
254 | - $this->config |
|
255 | - ->method('getSystemValueString') |
|
256 | - ->willReturnCallback(function ($var, $default) { |
|
257 | - if ($var === 'appstoreurl') { |
|
258 | - return 'https://apps.nextcloud.com/api/v1'; |
|
259 | - } elseif ($var === 'version') { |
|
260 | - return '11.0.0.2'; |
|
261 | - } |
|
262 | - return $default; |
|
263 | - }); |
|
264 | - $this->config->method('getSystemValueBool') |
|
265 | - ->willReturnArgument(1); |
|
266 | - |
|
267 | - $folder = $this->createMock(ISimpleFolder::class); |
|
268 | - $file = $this->createMock(ISimpleFile::class); |
|
269 | - $this->appData |
|
270 | - ->expects($this->once()) |
|
271 | - ->method('getFolder') |
|
272 | - ->with('/') |
|
273 | - ->willReturn($folder); |
|
274 | - $folder |
|
275 | - ->expects($this->once()) |
|
276 | - ->method('getFile') |
|
277 | - ->with($this->fileName) |
|
278 | - ->willReturn($file); |
|
279 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
280 | - $file |
|
281 | - ->expects($this->once()) |
|
282 | - ->method('putContent') |
|
283 | - ->with($fileData); |
|
284 | - $file |
|
285 | - ->expects($this->exactly(2)) |
|
286 | - ->method('getContent') |
|
287 | - ->willReturnOnConsecutiveCalls( |
|
288 | - '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}', |
|
289 | - $fileData |
|
290 | - ); |
|
291 | - $this->timeFactory |
|
292 | - ->expects($this->once()) |
|
293 | - ->method('getTime') |
|
294 | - ->willReturn(1201); |
|
295 | - $client = $this->createMock(IClient::class); |
|
296 | - $this->clientService |
|
297 | - ->expects($this->once()) |
|
298 | - ->method('newClient') |
|
299 | - ->willReturn($client); |
|
300 | - $response = $this->createMock(IResponse::class); |
|
301 | - $client |
|
302 | - ->expects($this->once()) |
|
303 | - ->method('get') |
|
304 | - ->with($this->endpoint) |
|
305 | - ->willReturn($response); |
|
306 | - $response |
|
307 | - ->expects($this->once()) |
|
308 | - ->method('getBody') |
|
309 | - ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
310 | - $response->method('getHeader') |
|
311 | - ->with($this->equalTo('ETag')) |
|
312 | - ->willReturn('"myETag"'); |
|
313 | - |
|
314 | - $expected = [ |
|
315 | - [ |
|
316 | - 'id' => 'MyNewApp', |
|
317 | - 'foo' => 'foo', |
|
318 | - ], |
|
319 | - [ |
|
320 | - 'id' => 'bar', |
|
321 | - ], |
|
322 | - ]; |
|
323 | - $this->assertSame($expected, $this->fetcher->get()); |
|
324 | - } |
|
325 | - |
|
326 | - public function testGetWithAlreadyExistingFileAndOutdatedVersion(): void { |
|
327 | - $this->config |
|
328 | - ->method('getSystemValueString') |
|
329 | - ->willReturnCallback(function ($var, $default) { |
|
330 | - if ($var === 'appstoreurl') { |
|
331 | - return 'https://apps.nextcloud.com/api/v1'; |
|
332 | - } elseif ($var === 'version') { |
|
333 | - return '11.0.0.2'; |
|
334 | - } |
|
335 | - return $default; |
|
336 | - }); |
|
337 | - $this->config->method('getSystemValueBool') |
|
338 | - ->willReturnArgument(1); |
|
339 | - |
|
340 | - $folder = $this->createMock(ISimpleFolder::class); |
|
341 | - $file = $this->createMock(ISimpleFile::class); |
|
342 | - $this->appData |
|
343 | - ->expects($this->once()) |
|
344 | - ->method('getFolder') |
|
345 | - ->with('/') |
|
346 | - ->willReturn($folder); |
|
347 | - $folder |
|
348 | - ->expects($this->once()) |
|
349 | - ->method('getFile') |
|
350 | - ->with($this->fileName) |
|
351 | - ->willReturn($file); |
|
352 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
353 | - $file |
|
354 | - ->expects($this->once()) |
|
355 | - ->method('putContent') |
|
356 | - ->with($fileData); |
|
357 | - $file |
|
358 | - ->expects($this->exactly(2)) |
|
359 | - ->method('getContent') |
|
360 | - ->willReturnOnConsecutiveCalls( |
|
361 | - '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.1"', |
|
362 | - $fileData |
|
363 | - ); |
|
364 | - $this->timeFactory |
|
365 | - ->method('getTime') |
|
366 | - ->willReturn(1201); |
|
367 | - $client = $this->createMock(IClient::class); |
|
368 | - $this->clientService |
|
369 | - ->expects($this->once()) |
|
370 | - ->method('newClient') |
|
371 | - ->willReturn($client); |
|
372 | - $response = $this->createMock(IResponse::class); |
|
373 | - $client |
|
374 | - ->expects($this->once()) |
|
375 | - ->method('get') |
|
376 | - ->with($this->endpoint) |
|
377 | - ->willReturn($response); |
|
378 | - $response |
|
379 | - ->expects($this->once()) |
|
380 | - ->method('getBody') |
|
381 | - ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
382 | - $response->method('getHeader') |
|
383 | - ->with($this->equalTo('ETag')) |
|
384 | - ->willReturn('"myETag"'); |
|
385 | - |
|
386 | - $expected = [ |
|
387 | - [ |
|
388 | - 'id' => 'MyNewApp', |
|
389 | - 'foo' => 'foo', |
|
390 | - ], |
|
391 | - [ |
|
392 | - 'id' => 'bar', |
|
393 | - ], |
|
394 | - ]; |
|
395 | - $this->assertSame($expected, $this->fetcher->get()); |
|
396 | - } |
|
397 | - |
|
398 | - public function testGetWithExceptionInClient(): void { |
|
399 | - $this->config->method('getSystemValueString') |
|
400 | - ->willReturnArgument(1); |
|
401 | - $this->config->method('getSystemValueBool') |
|
402 | - ->willReturnArgument(1); |
|
403 | - |
|
404 | - $folder = $this->createMock(ISimpleFolder::class); |
|
405 | - $file = $this->createMock(ISimpleFile::class); |
|
406 | - $this->appData |
|
407 | - ->expects($this->once()) |
|
408 | - ->method('getFolder') |
|
409 | - ->with('/') |
|
410 | - ->willReturn($folder); |
|
411 | - $folder |
|
412 | - ->expects($this->once()) |
|
413 | - ->method('getFile') |
|
414 | - ->with($this->fileName) |
|
415 | - ->willReturn($file); |
|
416 | - $file |
|
417 | - ->expects($this->once()) |
|
418 | - ->method('getContent') |
|
419 | - ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}}'); |
|
420 | - $client = $this->createMock(IClient::class); |
|
421 | - $this->clientService |
|
422 | - ->expects($this->once()) |
|
423 | - ->method('newClient') |
|
424 | - ->willReturn($client); |
|
425 | - $client |
|
426 | - ->expects($this->once()) |
|
427 | - ->method('get') |
|
428 | - ->with($this->endpoint) |
|
429 | - ->willThrowException(new \Exception()); |
|
430 | - |
|
431 | - $this->assertSame([], $this->fetcher->get()); |
|
432 | - } |
|
433 | - |
|
434 | - public function testGetMatchingETag(): void { |
|
435 | - $this->config->method('getSystemValueString') |
|
436 | - ->willReturnCallback(function ($key, $default) { |
|
437 | - if ($key === 'version') { |
|
438 | - return '11.0.0.2'; |
|
439 | - } else { |
|
440 | - return $default; |
|
441 | - } |
|
442 | - }); |
|
443 | - $this->config->method('getSystemValueBool') |
|
444 | - ->willReturnArgument(1); |
|
445 | - |
|
446 | - $this->config->method('getAppValue') |
|
447 | - ->willReturnMap([ |
|
448 | - ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
449 | - ['settings', 'appstore-timeout', '120', '120'], |
|
450 | - ]); |
|
451 | - |
|
452 | - $folder = $this->createMock(ISimpleFolder::class); |
|
453 | - $file = $this->createMock(ISimpleFile::class); |
|
454 | - $this->appData |
|
455 | - ->expects($this->once()) |
|
456 | - ->method('getFolder') |
|
457 | - ->with('/') |
|
458 | - ->willReturn($folder); |
|
459 | - $folder |
|
460 | - ->expects($this->once()) |
|
461 | - ->method('getFile') |
|
462 | - ->with($this->fileName) |
|
463 | - ->willReturn($file); |
|
464 | - $origData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
465 | - |
|
466 | - $newData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
467 | - $file |
|
468 | - ->expects($this->once()) |
|
469 | - ->method('putContent') |
|
470 | - ->with($newData); |
|
471 | - $file |
|
472 | - ->expects($this->exactly(2)) |
|
473 | - ->method('getContent') |
|
474 | - ->willReturnOnConsecutiveCalls( |
|
475 | - $origData, |
|
476 | - $newData, |
|
477 | - ); |
|
478 | - $this->timeFactory |
|
479 | - ->expects($this->exactly(2)) |
|
480 | - ->method('getTime') |
|
481 | - ->willReturnOnConsecutiveCalls( |
|
482 | - 4801, |
|
483 | - 4802 |
|
484 | - ); |
|
485 | - $client = $this->createMock(IClient::class); |
|
486 | - $this->clientService |
|
487 | - ->expects($this->once()) |
|
488 | - ->method('newClient') |
|
489 | - ->willReturn($client); |
|
490 | - $response = $this->createMock(IResponse::class); |
|
491 | - $client |
|
492 | - ->expects($this->once()) |
|
493 | - ->method('get') |
|
494 | - ->with( |
|
495 | - $this->equalTo($this->endpoint), |
|
496 | - $this->equalTo([ |
|
497 | - 'timeout' => 120, |
|
498 | - 'headers' => [ |
|
499 | - 'If-None-Match' => '"myETag"' |
|
500 | - ] |
|
501 | - ]) |
|
502 | - )->willReturn($response); |
|
503 | - $response->method('getStatusCode') |
|
504 | - ->willReturn(304); |
|
505 | - |
|
506 | - $expected = [ |
|
507 | - [ |
|
508 | - 'id' => 'MyNewApp', |
|
509 | - 'foo' => 'foo', |
|
510 | - ], |
|
511 | - [ |
|
512 | - 'id' => 'bar', |
|
513 | - ], |
|
514 | - ]; |
|
515 | - |
|
516 | - $this->assertSame($expected, $this->fetcher->get()); |
|
517 | - } |
|
518 | - |
|
519 | - public function testGetNoMatchingETag(): void { |
|
520 | - $this->config->method('getSystemValueString') |
|
521 | - ->willReturnCallback(function ($key, $default) { |
|
522 | - if ($key === 'version') { |
|
523 | - return '11.0.0.2'; |
|
524 | - } else { |
|
525 | - return $default; |
|
526 | - } |
|
527 | - }); |
|
528 | - $this->config->method('getSystemValueBool') |
|
529 | - ->willReturnArgument(1); |
|
530 | - |
|
531 | - $this->config->method('getAppValue') |
|
532 | - ->willReturnMap([ |
|
533 | - ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
534 | - ['settings', 'appstore-timeout', '120', '120'], |
|
535 | - ]); |
|
536 | - |
|
537 | - $folder = $this->createMock(ISimpleFolder::class); |
|
538 | - $file = $this->createMock(ISimpleFile::class); |
|
539 | - $this->appData |
|
540 | - ->expects($this->once()) |
|
541 | - ->method('getFolder') |
|
542 | - ->with('/') |
|
543 | - ->willReturn($folder); |
|
544 | - $folder |
|
545 | - ->expects($this->once()) |
|
546 | - ->method('getFile') |
|
547 | - ->with($this->fileName) |
|
548 | - ->willReturn($file); |
|
549 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"newETag\""}'; |
|
550 | - $file |
|
551 | - ->expects($this->once()) |
|
552 | - ->method('putContent') |
|
553 | - ->with($fileData); |
|
554 | - $file |
|
555 | - ->expects($this->exactly(2)) |
|
556 | - ->method('getContent') |
|
557 | - ->willReturnOnConsecutiveCalls( |
|
558 | - '{"data":[{"id":"MyOldApp","abc":"def"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}', |
|
559 | - $fileData, |
|
560 | - ); |
|
561 | - $this->timeFactory |
|
562 | - ->expects($this->exactly(2)) |
|
563 | - ->method('getTime') |
|
564 | - ->willReturnOnConsecutiveCalls( |
|
565 | - 4801, |
|
566 | - 4802, |
|
567 | - ); |
|
568 | - $client = $this->createMock(IClient::class); |
|
569 | - $this->clientService |
|
570 | - ->expects($this->once()) |
|
571 | - ->method('newClient') |
|
572 | - ->willReturn($client); |
|
573 | - $response = $this->createMock(IResponse::class); |
|
574 | - $client |
|
575 | - ->expects($this->once()) |
|
576 | - ->method('get') |
|
577 | - ->with( |
|
578 | - $this->equalTo($this->endpoint), |
|
579 | - $this->equalTo([ |
|
580 | - 'timeout' => 120, |
|
581 | - 'headers' => [ |
|
582 | - 'If-None-Match' => '"myETag"', |
|
583 | - ] |
|
584 | - ]) |
|
585 | - ) |
|
586 | - ->willReturn($response); |
|
587 | - $response->method('getStatusCode') |
|
588 | - ->willReturn(200); |
|
589 | - $response |
|
590 | - ->expects($this->once()) |
|
591 | - ->method('getBody') |
|
592 | - ->willReturn('[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}]'); |
|
593 | - $response->method('getHeader') |
|
594 | - ->with($this->equalTo('ETag')) |
|
595 | - ->willReturn('"newETag"'); |
|
596 | - |
|
597 | - $expected = [ |
|
598 | - [ |
|
599 | - 'id' => 'MyNewApp', |
|
600 | - 'foo' => 'foo', |
|
601 | - ], |
|
602 | - [ |
|
603 | - 'id' => 'bar', |
|
604 | - ], |
|
605 | - ]; |
|
606 | - $this->assertSame($expected, $this->fetcher->get()); |
|
607 | - } |
|
608 | - |
|
609 | - |
|
610 | - public function testFetchAfterUpgradeNoETag(): void { |
|
611 | - $this->config->method('getSystemValueString') |
|
612 | - ->willReturnCallback(function ($key, $default) { |
|
613 | - if ($key === 'version') { |
|
614 | - return '11.0.0.3'; |
|
615 | - } else { |
|
616 | - return $default; |
|
617 | - } |
|
618 | - }); |
|
619 | - $this->config->method('getSystemValueBool') |
|
620 | - ->willReturnArgument(1); |
|
621 | - |
|
622 | - $this->config->method('getAppValue') |
|
623 | - ->willReturnMap([ |
|
624 | - ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
625 | - ['settings', 'appstore-timeout', '120', '120'], |
|
626 | - ]); |
|
627 | - |
|
628 | - $folder = $this->createMock(ISimpleFolder::class); |
|
629 | - $file = $this->createMock(ISimpleFile::class); |
|
630 | - $this->appData |
|
631 | - ->expects($this->once()) |
|
632 | - ->method('getFolder') |
|
633 | - ->with('/') |
|
634 | - ->willReturn($folder); |
|
635 | - $folder |
|
636 | - ->expects($this->once()) |
|
637 | - ->method('getFile') |
|
638 | - ->with($this->fileName) |
|
639 | - ->willReturn($file); |
|
640 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1501,"ncversion":"11.0.0.3","ETag":"\"newETag\""}'; |
|
641 | - $file |
|
642 | - ->expects($this->once()) |
|
643 | - ->method('putContent') |
|
644 | - ->with($fileData); |
|
645 | - $file |
|
646 | - ->expects($this->exactly(2)) |
|
647 | - ->method('getContent') |
|
648 | - ->willReturnOnConsecutiveCalls( |
|
649 | - '{"data":[{"id":"MyOldApp","abc":"def"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}', |
|
650 | - $fileData |
|
651 | - ); |
|
652 | - $client = $this->createMock(IClient::class); |
|
653 | - $this->clientService |
|
654 | - ->expects($this->once()) |
|
655 | - ->method('newClient') |
|
656 | - ->willReturn($client); |
|
657 | - $response = $this->createMock(IResponse::class); |
|
658 | - $client |
|
659 | - ->expects($this->once()) |
|
660 | - ->method('get') |
|
661 | - ->with( |
|
662 | - $this->equalTo($this->endpoint), |
|
663 | - $this->equalTo([ |
|
664 | - 'timeout' => 120, |
|
665 | - ]) |
|
666 | - ) |
|
667 | - ->willReturn($response); |
|
668 | - $response->method('getStatusCode') |
|
669 | - ->willReturn(200); |
|
670 | - $response |
|
671 | - ->expects($this->once()) |
|
672 | - ->method('getBody') |
|
673 | - ->willReturn('[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}]'); |
|
674 | - $response->method('getHeader') |
|
675 | - ->with($this->equalTo('ETag')) |
|
676 | - ->willReturn('"newETag"'); |
|
677 | - $this->timeFactory |
|
678 | - ->expects($this->once()) |
|
679 | - ->method('getTime') |
|
680 | - ->willReturn(1501); |
|
681 | - |
|
682 | - $expected = [ |
|
683 | - [ |
|
684 | - 'id' => 'MyNewApp', |
|
685 | - 'foo' => 'foo', |
|
686 | - ], |
|
687 | - [ |
|
688 | - 'id' => 'bar', |
|
689 | - ], |
|
690 | - ]; |
|
691 | - $this->assertSame($expected, $this->fetcher->get()); |
|
692 | - } |
|
27 | + /** @var Factory|\PHPUnit\Framework\MockObject\MockObject */ |
|
28 | + protected $appDataFactory; |
|
29 | + /** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */ |
|
30 | + protected $appData; |
|
31 | + /** @var IClientService|\PHPUnit\Framework\MockObject\MockObject */ |
|
32 | + protected $clientService; |
|
33 | + /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ |
|
34 | + protected $timeFactory; |
|
35 | + /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ |
|
36 | + protected $config; |
|
37 | + /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ |
|
38 | + protected $logger; |
|
39 | + /** @var IRegistry|\PHPUnit\Framework\MockObject\MockObject */ |
|
40 | + protected $registry; |
|
41 | + /** @var Fetcher */ |
|
42 | + protected $fetcher; |
|
43 | + /** @var string */ |
|
44 | + protected $fileName; |
|
45 | + /** @var string */ |
|
46 | + protected $endpoint; |
|
47 | + |
|
48 | + protected function setUp(): void { |
|
49 | + parent::setUp(); |
|
50 | + $this->appDataFactory = $this->createMock(Factory::class); |
|
51 | + $this->appData = $this->createMock(AppData::class); |
|
52 | + $this->appDataFactory->expects($this->once()) |
|
53 | + ->method('get') |
|
54 | + ->with('appstore') |
|
55 | + ->willReturn($this->appData); |
|
56 | + $this->clientService = $this->createMock(IClientService::class); |
|
57 | + $this->timeFactory = $this->createMock(ITimeFactory::class); |
|
58 | + $this->config = $this->createMock(IConfig::class); |
|
59 | + $this->logger = $this->createMock(LoggerInterface::class); |
|
60 | + $this->registry = $this->createMock(IRegistry::class); |
|
61 | + } |
|
62 | + |
|
63 | + public function testGetWithAlreadyExistingFileAndUpToDateTimestampAndVersion(): void { |
|
64 | + $this->config |
|
65 | + ->method('getSystemValueString') |
|
66 | + ->willReturnCallback(function ($var, $default) { |
|
67 | + if ($var === 'version') { |
|
68 | + return '11.0.0.2'; |
|
69 | + } |
|
70 | + return $default; |
|
71 | + }); |
|
72 | + $this->config->method('getSystemValueBool') |
|
73 | + ->willReturnArgument(1); |
|
74 | + |
|
75 | + $folder = $this->createMock(ISimpleFolder::class); |
|
76 | + $file = $this->createMock(ISimpleFile::class); |
|
77 | + $this->appData |
|
78 | + ->expects($this->once()) |
|
79 | + ->method('getFolder') |
|
80 | + ->with('/') |
|
81 | + ->willReturn($folder); |
|
82 | + $folder |
|
83 | + ->expects($this->once()) |
|
84 | + ->method('getFile') |
|
85 | + ->with($this->fileName) |
|
86 | + ->willReturn($file); |
|
87 | + $file |
|
88 | + ->expects($this->once()) |
|
89 | + ->method('getContent') |
|
90 | + ->willReturn('{"timestamp":1200,"data":[{"id":"MyApp"}],"ncversion":"11.0.0.2"}'); |
|
91 | + $this->timeFactory |
|
92 | + ->expects($this->once()) |
|
93 | + ->method('getTime') |
|
94 | + ->willReturn(1499); |
|
95 | + |
|
96 | + $expected = [ |
|
97 | + [ |
|
98 | + 'id' => 'MyApp', |
|
99 | + ], |
|
100 | + ]; |
|
101 | + $this->assertSame($expected, $this->fetcher->get()); |
|
102 | + } |
|
103 | + |
|
104 | + public function testGetWithNotExistingFileAndUpToDateTimestampAndVersion(): void { |
|
105 | + $this->config |
|
106 | + ->method('getSystemValueString') |
|
107 | + ->willReturnCallback(function ($var, $default) { |
|
108 | + if ($var === 'appstoreurl') { |
|
109 | + return 'https://apps.nextcloud.com/api/v1'; |
|
110 | + } elseif ($var === 'version') { |
|
111 | + return '11.0.0.2'; |
|
112 | + } |
|
113 | + return $default; |
|
114 | + }); |
|
115 | + $this->config->method('getSystemValueBool') |
|
116 | + ->willReturnArgument(1); |
|
117 | + |
|
118 | + $folder = $this->createMock(ISimpleFolder::class); |
|
119 | + $file = $this->createMock(ISimpleFile::class); |
|
120 | + $this->appData |
|
121 | + ->expects($this->once()) |
|
122 | + ->method('getFolder') |
|
123 | + ->with('/') |
|
124 | + ->willReturn($folder); |
|
125 | + $folder |
|
126 | + ->expects($this->once()) |
|
127 | + ->method('getFile') |
|
128 | + ->with($this->fileName) |
|
129 | + ->willThrowException(new NotFoundException()); |
|
130 | + $folder |
|
131 | + ->expects($this->once()) |
|
132 | + ->method('newFile') |
|
133 | + ->with($this->fileName) |
|
134 | + ->willReturn($file); |
|
135 | + $client = $this->createMock(IClient::class); |
|
136 | + $this->clientService |
|
137 | + ->expects($this->once()) |
|
138 | + ->method('newClient') |
|
139 | + ->willReturn($client); |
|
140 | + $response = $this->createMock(IResponse::class); |
|
141 | + $client |
|
142 | + ->expects($this->once()) |
|
143 | + ->method('get') |
|
144 | + ->with($this->endpoint) |
|
145 | + ->willReturn($response); |
|
146 | + $response |
|
147 | + ->expects($this->once()) |
|
148 | + ->method('getBody') |
|
149 | + ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
150 | + $response->method('getHeader') |
|
151 | + ->with($this->equalTo('ETag')) |
|
152 | + ->willReturn('"myETag"'); |
|
153 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
154 | + $file |
|
155 | + ->expects($this->once()) |
|
156 | + ->method('putContent') |
|
157 | + ->with($fileData); |
|
158 | + $file |
|
159 | + ->expects($this->once()) |
|
160 | + ->method('getContent') |
|
161 | + ->willReturn($fileData); |
|
162 | + $this->timeFactory |
|
163 | + ->expects($this->once()) |
|
164 | + ->method('getTime') |
|
165 | + ->willReturn(1502); |
|
166 | + |
|
167 | + $expected = [ |
|
168 | + [ |
|
169 | + 'id' => 'MyNewApp', |
|
170 | + 'foo' => 'foo', |
|
171 | + ], |
|
172 | + [ |
|
173 | + 'id' => 'bar', |
|
174 | + ], |
|
175 | + ]; |
|
176 | + $this->assertSame($expected, $this->fetcher->get()); |
|
177 | + } |
|
178 | + |
|
179 | + public function testGetWithAlreadyExistingFileAndOutdatedTimestamp(): void { |
|
180 | + $this->config->method('getSystemValueString') |
|
181 | + ->willReturnCallback(function ($key, $default) { |
|
182 | + if ($key === 'version') { |
|
183 | + return '11.0.0.2'; |
|
184 | + } else { |
|
185 | + return $default; |
|
186 | + } |
|
187 | + }); |
|
188 | + $this->config->method('getSystemValueBool') |
|
189 | + ->willReturnArgument(1); |
|
190 | + |
|
191 | + $folder = $this->createMock(ISimpleFolder::class); |
|
192 | + $file = $this->createMock(ISimpleFile::class); |
|
193 | + $this->appData |
|
194 | + ->expects($this->once()) |
|
195 | + ->method('getFolder') |
|
196 | + ->with('/') |
|
197 | + ->willReturn($folder); |
|
198 | + $folder |
|
199 | + ->expects($this->once()) |
|
200 | + ->method('getFile') |
|
201 | + ->with($this->fileName) |
|
202 | + ->willReturn($file); |
|
203 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
204 | + $file |
|
205 | + ->expects($this->once()) |
|
206 | + ->method('putContent') |
|
207 | + ->with($fileData); |
|
208 | + $file |
|
209 | + ->expects($this->exactly(2)) |
|
210 | + ->method('getContent') |
|
211 | + ->willReturnOnConsecutiveCalls( |
|
212 | + '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.2"}', |
|
213 | + $fileData |
|
214 | + ); |
|
215 | + $this->timeFactory |
|
216 | + ->expects($this->exactly(2)) |
|
217 | + ->method('getTime') |
|
218 | + ->willReturnOnConsecutiveCalls( |
|
219 | + 4801, |
|
220 | + 1502 |
|
221 | + ); |
|
222 | + $client = $this->createMock(IClient::class); |
|
223 | + $this->clientService |
|
224 | + ->expects($this->once()) |
|
225 | + ->method('newClient') |
|
226 | + ->willReturn($client); |
|
227 | + $response = $this->createMock(IResponse::class); |
|
228 | + $client |
|
229 | + ->expects($this->once()) |
|
230 | + ->method('get') |
|
231 | + ->with($this->endpoint) |
|
232 | + ->willReturn($response); |
|
233 | + $response |
|
234 | + ->expects($this->once()) |
|
235 | + ->method('getBody') |
|
236 | + ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
237 | + $response->method('getHeader') |
|
238 | + ->with($this->equalTo('ETag')) |
|
239 | + ->willReturn('"myETag"'); |
|
240 | + |
|
241 | + $expected = [ |
|
242 | + [ |
|
243 | + 'id' => 'MyNewApp', |
|
244 | + 'foo' => 'foo', |
|
245 | + ], |
|
246 | + [ |
|
247 | + 'id' => 'bar', |
|
248 | + ], |
|
249 | + ]; |
|
250 | + $this->assertSame($expected, $this->fetcher->get()); |
|
251 | + } |
|
252 | + |
|
253 | + public function testGetWithAlreadyExistingFileAndNoVersion(): void { |
|
254 | + $this->config |
|
255 | + ->method('getSystemValueString') |
|
256 | + ->willReturnCallback(function ($var, $default) { |
|
257 | + if ($var === 'appstoreurl') { |
|
258 | + return 'https://apps.nextcloud.com/api/v1'; |
|
259 | + } elseif ($var === 'version') { |
|
260 | + return '11.0.0.2'; |
|
261 | + } |
|
262 | + return $default; |
|
263 | + }); |
|
264 | + $this->config->method('getSystemValueBool') |
|
265 | + ->willReturnArgument(1); |
|
266 | + |
|
267 | + $folder = $this->createMock(ISimpleFolder::class); |
|
268 | + $file = $this->createMock(ISimpleFile::class); |
|
269 | + $this->appData |
|
270 | + ->expects($this->once()) |
|
271 | + ->method('getFolder') |
|
272 | + ->with('/') |
|
273 | + ->willReturn($folder); |
|
274 | + $folder |
|
275 | + ->expects($this->once()) |
|
276 | + ->method('getFile') |
|
277 | + ->with($this->fileName) |
|
278 | + ->willReturn($file); |
|
279 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
280 | + $file |
|
281 | + ->expects($this->once()) |
|
282 | + ->method('putContent') |
|
283 | + ->with($fileData); |
|
284 | + $file |
|
285 | + ->expects($this->exactly(2)) |
|
286 | + ->method('getContent') |
|
287 | + ->willReturnOnConsecutiveCalls( |
|
288 | + '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}', |
|
289 | + $fileData |
|
290 | + ); |
|
291 | + $this->timeFactory |
|
292 | + ->expects($this->once()) |
|
293 | + ->method('getTime') |
|
294 | + ->willReturn(1201); |
|
295 | + $client = $this->createMock(IClient::class); |
|
296 | + $this->clientService |
|
297 | + ->expects($this->once()) |
|
298 | + ->method('newClient') |
|
299 | + ->willReturn($client); |
|
300 | + $response = $this->createMock(IResponse::class); |
|
301 | + $client |
|
302 | + ->expects($this->once()) |
|
303 | + ->method('get') |
|
304 | + ->with($this->endpoint) |
|
305 | + ->willReturn($response); |
|
306 | + $response |
|
307 | + ->expects($this->once()) |
|
308 | + ->method('getBody') |
|
309 | + ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
310 | + $response->method('getHeader') |
|
311 | + ->with($this->equalTo('ETag')) |
|
312 | + ->willReturn('"myETag"'); |
|
313 | + |
|
314 | + $expected = [ |
|
315 | + [ |
|
316 | + 'id' => 'MyNewApp', |
|
317 | + 'foo' => 'foo', |
|
318 | + ], |
|
319 | + [ |
|
320 | + 'id' => 'bar', |
|
321 | + ], |
|
322 | + ]; |
|
323 | + $this->assertSame($expected, $this->fetcher->get()); |
|
324 | + } |
|
325 | + |
|
326 | + public function testGetWithAlreadyExistingFileAndOutdatedVersion(): void { |
|
327 | + $this->config |
|
328 | + ->method('getSystemValueString') |
|
329 | + ->willReturnCallback(function ($var, $default) { |
|
330 | + if ($var === 'appstoreurl') { |
|
331 | + return 'https://apps.nextcloud.com/api/v1'; |
|
332 | + } elseif ($var === 'version') { |
|
333 | + return '11.0.0.2'; |
|
334 | + } |
|
335 | + return $default; |
|
336 | + }); |
|
337 | + $this->config->method('getSystemValueBool') |
|
338 | + ->willReturnArgument(1); |
|
339 | + |
|
340 | + $folder = $this->createMock(ISimpleFolder::class); |
|
341 | + $file = $this->createMock(ISimpleFile::class); |
|
342 | + $this->appData |
|
343 | + ->expects($this->once()) |
|
344 | + ->method('getFolder') |
|
345 | + ->with('/') |
|
346 | + ->willReturn($folder); |
|
347 | + $folder |
|
348 | + ->expects($this->once()) |
|
349 | + ->method('getFile') |
|
350 | + ->with($this->fileName) |
|
351 | + ->willReturn($file); |
|
352 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
353 | + $file |
|
354 | + ->expects($this->once()) |
|
355 | + ->method('putContent') |
|
356 | + ->with($fileData); |
|
357 | + $file |
|
358 | + ->expects($this->exactly(2)) |
|
359 | + ->method('getContent') |
|
360 | + ->willReturnOnConsecutiveCalls( |
|
361 | + '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.1"', |
|
362 | + $fileData |
|
363 | + ); |
|
364 | + $this->timeFactory |
|
365 | + ->method('getTime') |
|
366 | + ->willReturn(1201); |
|
367 | + $client = $this->createMock(IClient::class); |
|
368 | + $this->clientService |
|
369 | + ->expects($this->once()) |
|
370 | + ->method('newClient') |
|
371 | + ->willReturn($client); |
|
372 | + $response = $this->createMock(IResponse::class); |
|
373 | + $client |
|
374 | + ->expects($this->once()) |
|
375 | + ->method('get') |
|
376 | + ->with($this->endpoint) |
|
377 | + ->willReturn($response); |
|
378 | + $response |
|
379 | + ->expects($this->once()) |
|
380 | + ->method('getBody') |
|
381 | + ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
382 | + $response->method('getHeader') |
|
383 | + ->with($this->equalTo('ETag')) |
|
384 | + ->willReturn('"myETag"'); |
|
385 | + |
|
386 | + $expected = [ |
|
387 | + [ |
|
388 | + 'id' => 'MyNewApp', |
|
389 | + 'foo' => 'foo', |
|
390 | + ], |
|
391 | + [ |
|
392 | + 'id' => 'bar', |
|
393 | + ], |
|
394 | + ]; |
|
395 | + $this->assertSame($expected, $this->fetcher->get()); |
|
396 | + } |
|
397 | + |
|
398 | + public function testGetWithExceptionInClient(): void { |
|
399 | + $this->config->method('getSystemValueString') |
|
400 | + ->willReturnArgument(1); |
|
401 | + $this->config->method('getSystemValueBool') |
|
402 | + ->willReturnArgument(1); |
|
403 | + |
|
404 | + $folder = $this->createMock(ISimpleFolder::class); |
|
405 | + $file = $this->createMock(ISimpleFile::class); |
|
406 | + $this->appData |
|
407 | + ->expects($this->once()) |
|
408 | + ->method('getFolder') |
|
409 | + ->with('/') |
|
410 | + ->willReturn($folder); |
|
411 | + $folder |
|
412 | + ->expects($this->once()) |
|
413 | + ->method('getFile') |
|
414 | + ->with($this->fileName) |
|
415 | + ->willReturn($file); |
|
416 | + $file |
|
417 | + ->expects($this->once()) |
|
418 | + ->method('getContent') |
|
419 | + ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}}'); |
|
420 | + $client = $this->createMock(IClient::class); |
|
421 | + $this->clientService |
|
422 | + ->expects($this->once()) |
|
423 | + ->method('newClient') |
|
424 | + ->willReturn($client); |
|
425 | + $client |
|
426 | + ->expects($this->once()) |
|
427 | + ->method('get') |
|
428 | + ->with($this->endpoint) |
|
429 | + ->willThrowException(new \Exception()); |
|
430 | + |
|
431 | + $this->assertSame([], $this->fetcher->get()); |
|
432 | + } |
|
433 | + |
|
434 | + public function testGetMatchingETag(): void { |
|
435 | + $this->config->method('getSystemValueString') |
|
436 | + ->willReturnCallback(function ($key, $default) { |
|
437 | + if ($key === 'version') { |
|
438 | + return '11.0.0.2'; |
|
439 | + } else { |
|
440 | + return $default; |
|
441 | + } |
|
442 | + }); |
|
443 | + $this->config->method('getSystemValueBool') |
|
444 | + ->willReturnArgument(1); |
|
445 | + |
|
446 | + $this->config->method('getAppValue') |
|
447 | + ->willReturnMap([ |
|
448 | + ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
449 | + ['settings', 'appstore-timeout', '120', '120'], |
|
450 | + ]); |
|
451 | + |
|
452 | + $folder = $this->createMock(ISimpleFolder::class); |
|
453 | + $file = $this->createMock(ISimpleFile::class); |
|
454 | + $this->appData |
|
455 | + ->expects($this->once()) |
|
456 | + ->method('getFolder') |
|
457 | + ->with('/') |
|
458 | + ->willReturn($folder); |
|
459 | + $folder |
|
460 | + ->expects($this->once()) |
|
461 | + ->method('getFile') |
|
462 | + ->with($this->fileName) |
|
463 | + ->willReturn($file); |
|
464 | + $origData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
465 | + |
|
466 | + $newData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
467 | + $file |
|
468 | + ->expects($this->once()) |
|
469 | + ->method('putContent') |
|
470 | + ->with($newData); |
|
471 | + $file |
|
472 | + ->expects($this->exactly(2)) |
|
473 | + ->method('getContent') |
|
474 | + ->willReturnOnConsecutiveCalls( |
|
475 | + $origData, |
|
476 | + $newData, |
|
477 | + ); |
|
478 | + $this->timeFactory |
|
479 | + ->expects($this->exactly(2)) |
|
480 | + ->method('getTime') |
|
481 | + ->willReturnOnConsecutiveCalls( |
|
482 | + 4801, |
|
483 | + 4802 |
|
484 | + ); |
|
485 | + $client = $this->createMock(IClient::class); |
|
486 | + $this->clientService |
|
487 | + ->expects($this->once()) |
|
488 | + ->method('newClient') |
|
489 | + ->willReturn($client); |
|
490 | + $response = $this->createMock(IResponse::class); |
|
491 | + $client |
|
492 | + ->expects($this->once()) |
|
493 | + ->method('get') |
|
494 | + ->with( |
|
495 | + $this->equalTo($this->endpoint), |
|
496 | + $this->equalTo([ |
|
497 | + 'timeout' => 120, |
|
498 | + 'headers' => [ |
|
499 | + 'If-None-Match' => '"myETag"' |
|
500 | + ] |
|
501 | + ]) |
|
502 | + )->willReturn($response); |
|
503 | + $response->method('getStatusCode') |
|
504 | + ->willReturn(304); |
|
505 | + |
|
506 | + $expected = [ |
|
507 | + [ |
|
508 | + 'id' => 'MyNewApp', |
|
509 | + 'foo' => 'foo', |
|
510 | + ], |
|
511 | + [ |
|
512 | + 'id' => 'bar', |
|
513 | + ], |
|
514 | + ]; |
|
515 | + |
|
516 | + $this->assertSame($expected, $this->fetcher->get()); |
|
517 | + } |
|
518 | + |
|
519 | + public function testGetNoMatchingETag(): void { |
|
520 | + $this->config->method('getSystemValueString') |
|
521 | + ->willReturnCallback(function ($key, $default) { |
|
522 | + if ($key === 'version') { |
|
523 | + return '11.0.0.2'; |
|
524 | + } else { |
|
525 | + return $default; |
|
526 | + } |
|
527 | + }); |
|
528 | + $this->config->method('getSystemValueBool') |
|
529 | + ->willReturnArgument(1); |
|
530 | + |
|
531 | + $this->config->method('getAppValue') |
|
532 | + ->willReturnMap([ |
|
533 | + ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
534 | + ['settings', 'appstore-timeout', '120', '120'], |
|
535 | + ]); |
|
536 | + |
|
537 | + $folder = $this->createMock(ISimpleFolder::class); |
|
538 | + $file = $this->createMock(ISimpleFile::class); |
|
539 | + $this->appData |
|
540 | + ->expects($this->once()) |
|
541 | + ->method('getFolder') |
|
542 | + ->with('/') |
|
543 | + ->willReturn($folder); |
|
544 | + $folder |
|
545 | + ->expects($this->once()) |
|
546 | + ->method('getFile') |
|
547 | + ->with($this->fileName) |
|
548 | + ->willReturn($file); |
|
549 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"newETag\""}'; |
|
550 | + $file |
|
551 | + ->expects($this->once()) |
|
552 | + ->method('putContent') |
|
553 | + ->with($fileData); |
|
554 | + $file |
|
555 | + ->expects($this->exactly(2)) |
|
556 | + ->method('getContent') |
|
557 | + ->willReturnOnConsecutiveCalls( |
|
558 | + '{"data":[{"id":"MyOldApp","abc":"def"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}', |
|
559 | + $fileData, |
|
560 | + ); |
|
561 | + $this->timeFactory |
|
562 | + ->expects($this->exactly(2)) |
|
563 | + ->method('getTime') |
|
564 | + ->willReturnOnConsecutiveCalls( |
|
565 | + 4801, |
|
566 | + 4802, |
|
567 | + ); |
|
568 | + $client = $this->createMock(IClient::class); |
|
569 | + $this->clientService |
|
570 | + ->expects($this->once()) |
|
571 | + ->method('newClient') |
|
572 | + ->willReturn($client); |
|
573 | + $response = $this->createMock(IResponse::class); |
|
574 | + $client |
|
575 | + ->expects($this->once()) |
|
576 | + ->method('get') |
|
577 | + ->with( |
|
578 | + $this->equalTo($this->endpoint), |
|
579 | + $this->equalTo([ |
|
580 | + 'timeout' => 120, |
|
581 | + 'headers' => [ |
|
582 | + 'If-None-Match' => '"myETag"', |
|
583 | + ] |
|
584 | + ]) |
|
585 | + ) |
|
586 | + ->willReturn($response); |
|
587 | + $response->method('getStatusCode') |
|
588 | + ->willReturn(200); |
|
589 | + $response |
|
590 | + ->expects($this->once()) |
|
591 | + ->method('getBody') |
|
592 | + ->willReturn('[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}]'); |
|
593 | + $response->method('getHeader') |
|
594 | + ->with($this->equalTo('ETag')) |
|
595 | + ->willReturn('"newETag"'); |
|
596 | + |
|
597 | + $expected = [ |
|
598 | + [ |
|
599 | + 'id' => 'MyNewApp', |
|
600 | + 'foo' => 'foo', |
|
601 | + ], |
|
602 | + [ |
|
603 | + 'id' => 'bar', |
|
604 | + ], |
|
605 | + ]; |
|
606 | + $this->assertSame($expected, $this->fetcher->get()); |
|
607 | + } |
|
608 | + |
|
609 | + |
|
610 | + public function testFetchAfterUpgradeNoETag(): void { |
|
611 | + $this->config->method('getSystemValueString') |
|
612 | + ->willReturnCallback(function ($key, $default) { |
|
613 | + if ($key === 'version') { |
|
614 | + return '11.0.0.3'; |
|
615 | + } else { |
|
616 | + return $default; |
|
617 | + } |
|
618 | + }); |
|
619 | + $this->config->method('getSystemValueBool') |
|
620 | + ->willReturnArgument(1); |
|
621 | + |
|
622 | + $this->config->method('getAppValue') |
|
623 | + ->willReturnMap([ |
|
624 | + ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
625 | + ['settings', 'appstore-timeout', '120', '120'], |
|
626 | + ]); |
|
627 | + |
|
628 | + $folder = $this->createMock(ISimpleFolder::class); |
|
629 | + $file = $this->createMock(ISimpleFile::class); |
|
630 | + $this->appData |
|
631 | + ->expects($this->once()) |
|
632 | + ->method('getFolder') |
|
633 | + ->with('/') |
|
634 | + ->willReturn($folder); |
|
635 | + $folder |
|
636 | + ->expects($this->once()) |
|
637 | + ->method('getFile') |
|
638 | + ->with($this->fileName) |
|
639 | + ->willReturn($file); |
|
640 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1501,"ncversion":"11.0.0.3","ETag":"\"newETag\""}'; |
|
641 | + $file |
|
642 | + ->expects($this->once()) |
|
643 | + ->method('putContent') |
|
644 | + ->with($fileData); |
|
645 | + $file |
|
646 | + ->expects($this->exactly(2)) |
|
647 | + ->method('getContent') |
|
648 | + ->willReturnOnConsecutiveCalls( |
|
649 | + '{"data":[{"id":"MyOldApp","abc":"def"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}', |
|
650 | + $fileData |
|
651 | + ); |
|
652 | + $client = $this->createMock(IClient::class); |
|
653 | + $this->clientService |
|
654 | + ->expects($this->once()) |
|
655 | + ->method('newClient') |
|
656 | + ->willReturn($client); |
|
657 | + $response = $this->createMock(IResponse::class); |
|
658 | + $client |
|
659 | + ->expects($this->once()) |
|
660 | + ->method('get') |
|
661 | + ->with( |
|
662 | + $this->equalTo($this->endpoint), |
|
663 | + $this->equalTo([ |
|
664 | + 'timeout' => 120, |
|
665 | + ]) |
|
666 | + ) |
|
667 | + ->willReturn($response); |
|
668 | + $response->method('getStatusCode') |
|
669 | + ->willReturn(200); |
|
670 | + $response |
|
671 | + ->expects($this->once()) |
|
672 | + ->method('getBody') |
|
673 | + ->willReturn('[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}]'); |
|
674 | + $response->method('getHeader') |
|
675 | + ->with($this->equalTo('ETag')) |
|
676 | + ->willReturn('"newETag"'); |
|
677 | + $this->timeFactory |
|
678 | + ->expects($this->once()) |
|
679 | + ->method('getTime') |
|
680 | + ->willReturn(1501); |
|
681 | + |
|
682 | + $expected = [ |
|
683 | + [ |
|
684 | + 'id' => 'MyNewApp', |
|
685 | + 'foo' => 'foo', |
|
686 | + ], |
|
687 | + [ |
|
688 | + 'id' => 'bar', |
|
689 | + ], |
|
690 | + ]; |
|
691 | + $this->assertSame($expected, $this->fetcher->get()); |
|
692 | + } |
|
693 | 693 | } |
@@ -22,210 +22,210 @@ |
||
22 | 22 | use Psr\Log\LoggerInterface; |
23 | 23 | |
24 | 24 | abstract class Fetcher { |
25 | - public const INVALIDATE_AFTER_SECONDS = 3600; |
|
26 | - public const INVALIDATE_AFTER_SECONDS_UNSTABLE = 900; |
|
27 | - public const RETRY_AFTER_FAILURE_SECONDS = 300; |
|
28 | - public const APP_STORE_URL = 'https://apps.nextcloud.com/api/v1'; |
|
29 | - |
|
30 | - /** @var IAppData */ |
|
31 | - protected $appData; |
|
32 | - |
|
33 | - /** @var string */ |
|
34 | - protected $fileName; |
|
35 | - /** @var string */ |
|
36 | - protected $endpointName; |
|
37 | - /** @var ?string */ |
|
38 | - protected $version = null; |
|
39 | - /** @var ?string */ |
|
40 | - protected $channel = null; |
|
41 | - |
|
42 | - public function __construct( |
|
43 | - Factory $appDataFactory, |
|
44 | - protected IClientService $clientService, |
|
45 | - protected ITimeFactory $timeFactory, |
|
46 | - protected IConfig $config, |
|
47 | - protected LoggerInterface $logger, |
|
48 | - protected IRegistry $registry, |
|
49 | - ) { |
|
50 | - $this->appData = $appDataFactory->get('appstore'); |
|
51 | - } |
|
52 | - |
|
53 | - /** |
|
54 | - * Fetches the response from the server |
|
55 | - * |
|
56 | - * @param string $ETag |
|
57 | - * @param string $content |
|
58 | - * |
|
59 | - * @return array |
|
60 | - */ |
|
61 | - protected function fetch($ETag, $content, $allowUnstable = false) { |
|
62 | - $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true); |
|
63 | - if ((int)$this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) { |
|
64 | - return []; |
|
65 | - } |
|
66 | - |
|
67 | - if (!$appstoreenabled) { |
|
68 | - return []; |
|
69 | - } |
|
70 | - |
|
71 | - $options = [ |
|
72 | - 'timeout' => (int)$this->config->getAppValue('settings', 'appstore-timeout', '120') |
|
73 | - ]; |
|
74 | - |
|
75 | - if ($ETag !== '') { |
|
76 | - $options['headers'] = [ |
|
77 | - 'If-None-Match' => $ETag, |
|
78 | - ]; |
|
79 | - } |
|
80 | - |
|
81 | - if ($this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL) { |
|
82 | - // If we have a valid subscription key, send it to the appstore |
|
83 | - $subscriptionKey = $this->config->getAppValue('support', 'subscription_key'); |
|
84 | - if ($this->registry->delegateHasValidSubscription() && $subscriptionKey) { |
|
85 | - $options['headers'] ??= []; |
|
86 | - $options['headers']['X-NC-Subscription-Key'] = $subscriptionKey; |
|
87 | - } |
|
88 | - } |
|
89 | - |
|
90 | - $client = $this->clientService->newClient(); |
|
91 | - try { |
|
92 | - $response = $client->get($this->getEndpoint(), $options); |
|
93 | - } catch (ConnectException|ClientException|ServerException $e) { |
|
94 | - $this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string)time()); |
|
95 | - $this->logger->error('Failed to connect to the app store', ['exception' => $e]); |
|
96 | - return []; |
|
97 | - } |
|
98 | - |
|
99 | - $responseJson = []; |
|
100 | - if ($response->getStatusCode() === Http::STATUS_NOT_MODIFIED) { |
|
101 | - $responseJson['data'] = json_decode($content, true); |
|
102 | - } else { |
|
103 | - $responseJson['data'] = json_decode($response->getBody(), true); |
|
104 | - $ETag = $response->getHeader('ETag'); |
|
105 | - } |
|
106 | - $this->config->deleteAppValue('settings', 'appstore-fetcher-lastFailure'); |
|
107 | - |
|
108 | - $responseJson['timestamp'] = $this->timeFactory->getTime(); |
|
109 | - $responseJson['ncversion'] = $this->getVersion(); |
|
110 | - if ($ETag !== '') { |
|
111 | - $responseJson['ETag'] = $ETag; |
|
112 | - } |
|
113 | - |
|
114 | - return $responseJson; |
|
115 | - } |
|
116 | - |
|
117 | - /** |
|
118 | - * Returns the array with the entries on the appstore server |
|
119 | - * |
|
120 | - * @param bool [$allowUnstable] Allow unstable releases |
|
121 | - * @return array |
|
122 | - */ |
|
123 | - public function get($allowUnstable = false) { |
|
124 | - $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true); |
|
125 | - $internetavailable = $this->config->getSystemValueBool('has_internet_connection', true); |
|
126 | - $isDefaultAppStore = $this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL; |
|
127 | - |
|
128 | - if (!$appstoreenabled || (!$internetavailable && $isDefaultAppStore)) { |
|
129 | - $this->logger->info('AppStore is disabled or this instance has no Internet connection to access the default app store', ['app' => 'appstoreFetcher']); |
|
130 | - return []; |
|
131 | - } |
|
132 | - |
|
133 | - $rootFolder = $this->appData->getFolder('/'); |
|
134 | - |
|
135 | - $ETag = ''; |
|
136 | - $content = ''; |
|
137 | - |
|
138 | - try { |
|
139 | - // File does already exists |
|
140 | - $file = $rootFolder->getFile($this->fileName); |
|
141 | - $jsonBlob = json_decode($file->getContent(), true); |
|
142 | - |
|
143 | - if (is_array($jsonBlob)) { |
|
144 | - // No caching when the version has been updated |
|
145 | - if (isset($jsonBlob['ncversion']) && $jsonBlob['ncversion'] === $this->getVersion()) { |
|
146 | - // If the timestamp is older than 3600 seconds request the files new |
|
147 | - $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS; |
|
148 | - |
|
149 | - if ($allowUnstable) { |
|
150 | - $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS_UNSTABLE; |
|
151 | - } |
|
152 | - |
|
153 | - if ((int)$jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) { |
|
154 | - return $jsonBlob['data']; |
|
155 | - } |
|
156 | - |
|
157 | - if (isset($jsonBlob['ETag'])) { |
|
158 | - $ETag = $jsonBlob['ETag']; |
|
159 | - $content = json_encode($jsonBlob['data']); |
|
160 | - } |
|
161 | - } |
|
162 | - } |
|
163 | - } catch (NotFoundException $e) { |
|
164 | - // File does not already exists |
|
165 | - $file = $rootFolder->newFile($this->fileName); |
|
166 | - } |
|
167 | - |
|
168 | - // Refresh the file content |
|
169 | - try { |
|
170 | - $responseJson = $this->fetch($ETag, $content, $allowUnstable); |
|
171 | - |
|
172 | - if (empty($responseJson) || empty($responseJson['data'])) { |
|
173 | - return []; |
|
174 | - } |
|
175 | - |
|
176 | - $file->putContent(json_encode($responseJson)); |
|
177 | - return json_decode($file->getContent(), true)['data']; |
|
178 | - } catch (ConnectException $e) { |
|
179 | - $this->logger->warning('Could not connect to appstore: ' . $e->getMessage(), ['app' => 'appstoreFetcher']); |
|
180 | - return []; |
|
181 | - } catch (\Exception $e) { |
|
182 | - $this->logger->warning($e->getMessage(), [ |
|
183 | - 'exception' => $e, |
|
184 | - 'app' => 'appstoreFetcher', |
|
185 | - ]); |
|
186 | - return []; |
|
187 | - } |
|
188 | - } |
|
189 | - |
|
190 | - /** |
|
191 | - * Get the currently Nextcloud version |
|
192 | - * @return string |
|
193 | - */ |
|
194 | - protected function getVersion() { |
|
195 | - if ($this->version === null) { |
|
196 | - $this->version = $this->config->getSystemValueString('version', '0.0.0'); |
|
197 | - } |
|
198 | - return $this->version; |
|
199 | - } |
|
200 | - |
|
201 | - /** |
|
202 | - * Set the current Nextcloud version |
|
203 | - * @param string $version |
|
204 | - */ |
|
205 | - public function setVersion(string $version) { |
|
206 | - $this->version = $version; |
|
207 | - } |
|
208 | - |
|
209 | - /** |
|
210 | - * Get the currently Nextcloud update channel |
|
211 | - * @return string |
|
212 | - */ |
|
213 | - protected function getChannel() { |
|
214 | - if ($this->channel === null) { |
|
215 | - $this->channel = Server::get(ServerVersion::class)->getChannel(); |
|
216 | - } |
|
217 | - return $this->channel; |
|
218 | - } |
|
219 | - |
|
220 | - /** |
|
221 | - * Set the current Nextcloud update channel |
|
222 | - * @param string $channel |
|
223 | - */ |
|
224 | - public function setChannel(string $channel) { |
|
225 | - $this->channel = $channel; |
|
226 | - } |
|
227 | - |
|
228 | - protected function getEndpoint(): string { |
|
229 | - return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1') . '/' . $this->endpointName; |
|
230 | - } |
|
25 | + public const INVALIDATE_AFTER_SECONDS = 3600; |
|
26 | + public const INVALIDATE_AFTER_SECONDS_UNSTABLE = 900; |
|
27 | + public const RETRY_AFTER_FAILURE_SECONDS = 300; |
|
28 | + public const APP_STORE_URL = 'https://apps.nextcloud.com/api/v1'; |
|
29 | + |
|
30 | + /** @var IAppData */ |
|
31 | + protected $appData; |
|
32 | + |
|
33 | + /** @var string */ |
|
34 | + protected $fileName; |
|
35 | + /** @var string */ |
|
36 | + protected $endpointName; |
|
37 | + /** @var ?string */ |
|
38 | + protected $version = null; |
|
39 | + /** @var ?string */ |
|
40 | + protected $channel = null; |
|
41 | + |
|
42 | + public function __construct( |
|
43 | + Factory $appDataFactory, |
|
44 | + protected IClientService $clientService, |
|
45 | + protected ITimeFactory $timeFactory, |
|
46 | + protected IConfig $config, |
|
47 | + protected LoggerInterface $logger, |
|
48 | + protected IRegistry $registry, |
|
49 | + ) { |
|
50 | + $this->appData = $appDataFactory->get('appstore'); |
|
51 | + } |
|
52 | + |
|
53 | + /** |
|
54 | + * Fetches the response from the server |
|
55 | + * |
|
56 | + * @param string $ETag |
|
57 | + * @param string $content |
|
58 | + * |
|
59 | + * @return array |
|
60 | + */ |
|
61 | + protected function fetch($ETag, $content, $allowUnstable = false) { |
|
62 | + $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true); |
|
63 | + if ((int)$this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) { |
|
64 | + return []; |
|
65 | + } |
|
66 | + |
|
67 | + if (!$appstoreenabled) { |
|
68 | + return []; |
|
69 | + } |
|
70 | + |
|
71 | + $options = [ |
|
72 | + 'timeout' => (int)$this->config->getAppValue('settings', 'appstore-timeout', '120') |
|
73 | + ]; |
|
74 | + |
|
75 | + if ($ETag !== '') { |
|
76 | + $options['headers'] = [ |
|
77 | + 'If-None-Match' => $ETag, |
|
78 | + ]; |
|
79 | + } |
|
80 | + |
|
81 | + if ($this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL) { |
|
82 | + // If we have a valid subscription key, send it to the appstore |
|
83 | + $subscriptionKey = $this->config->getAppValue('support', 'subscription_key'); |
|
84 | + if ($this->registry->delegateHasValidSubscription() && $subscriptionKey) { |
|
85 | + $options['headers'] ??= []; |
|
86 | + $options['headers']['X-NC-Subscription-Key'] = $subscriptionKey; |
|
87 | + } |
|
88 | + } |
|
89 | + |
|
90 | + $client = $this->clientService->newClient(); |
|
91 | + try { |
|
92 | + $response = $client->get($this->getEndpoint(), $options); |
|
93 | + } catch (ConnectException|ClientException|ServerException $e) { |
|
94 | + $this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string)time()); |
|
95 | + $this->logger->error('Failed to connect to the app store', ['exception' => $e]); |
|
96 | + return []; |
|
97 | + } |
|
98 | + |
|
99 | + $responseJson = []; |
|
100 | + if ($response->getStatusCode() === Http::STATUS_NOT_MODIFIED) { |
|
101 | + $responseJson['data'] = json_decode($content, true); |
|
102 | + } else { |
|
103 | + $responseJson['data'] = json_decode($response->getBody(), true); |
|
104 | + $ETag = $response->getHeader('ETag'); |
|
105 | + } |
|
106 | + $this->config->deleteAppValue('settings', 'appstore-fetcher-lastFailure'); |
|
107 | + |
|
108 | + $responseJson['timestamp'] = $this->timeFactory->getTime(); |
|
109 | + $responseJson['ncversion'] = $this->getVersion(); |
|
110 | + if ($ETag !== '') { |
|
111 | + $responseJson['ETag'] = $ETag; |
|
112 | + } |
|
113 | + |
|
114 | + return $responseJson; |
|
115 | + } |
|
116 | + |
|
117 | + /** |
|
118 | + * Returns the array with the entries on the appstore server |
|
119 | + * |
|
120 | + * @param bool [$allowUnstable] Allow unstable releases |
|
121 | + * @return array |
|
122 | + */ |
|
123 | + public function get($allowUnstable = false) { |
|
124 | + $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true); |
|
125 | + $internetavailable = $this->config->getSystemValueBool('has_internet_connection', true); |
|
126 | + $isDefaultAppStore = $this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL; |
|
127 | + |
|
128 | + if (!$appstoreenabled || (!$internetavailable && $isDefaultAppStore)) { |
|
129 | + $this->logger->info('AppStore is disabled or this instance has no Internet connection to access the default app store', ['app' => 'appstoreFetcher']); |
|
130 | + return []; |
|
131 | + } |
|
132 | + |
|
133 | + $rootFolder = $this->appData->getFolder('/'); |
|
134 | + |
|
135 | + $ETag = ''; |
|
136 | + $content = ''; |
|
137 | + |
|
138 | + try { |
|
139 | + // File does already exists |
|
140 | + $file = $rootFolder->getFile($this->fileName); |
|
141 | + $jsonBlob = json_decode($file->getContent(), true); |
|
142 | + |
|
143 | + if (is_array($jsonBlob)) { |
|
144 | + // No caching when the version has been updated |
|
145 | + if (isset($jsonBlob['ncversion']) && $jsonBlob['ncversion'] === $this->getVersion()) { |
|
146 | + // If the timestamp is older than 3600 seconds request the files new |
|
147 | + $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS; |
|
148 | + |
|
149 | + if ($allowUnstable) { |
|
150 | + $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS_UNSTABLE; |
|
151 | + } |
|
152 | + |
|
153 | + if ((int)$jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) { |
|
154 | + return $jsonBlob['data']; |
|
155 | + } |
|
156 | + |
|
157 | + if (isset($jsonBlob['ETag'])) { |
|
158 | + $ETag = $jsonBlob['ETag']; |
|
159 | + $content = json_encode($jsonBlob['data']); |
|
160 | + } |
|
161 | + } |
|
162 | + } |
|
163 | + } catch (NotFoundException $e) { |
|
164 | + // File does not already exists |
|
165 | + $file = $rootFolder->newFile($this->fileName); |
|
166 | + } |
|
167 | + |
|
168 | + // Refresh the file content |
|
169 | + try { |
|
170 | + $responseJson = $this->fetch($ETag, $content, $allowUnstable); |
|
171 | + |
|
172 | + if (empty($responseJson) || empty($responseJson['data'])) { |
|
173 | + return []; |
|
174 | + } |
|
175 | + |
|
176 | + $file->putContent(json_encode($responseJson)); |
|
177 | + return json_decode($file->getContent(), true)['data']; |
|
178 | + } catch (ConnectException $e) { |
|
179 | + $this->logger->warning('Could not connect to appstore: ' . $e->getMessage(), ['app' => 'appstoreFetcher']); |
|
180 | + return []; |
|
181 | + } catch (\Exception $e) { |
|
182 | + $this->logger->warning($e->getMessage(), [ |
|
183 | + 'exception' => $e, |
|
184 | + 'app' => 'appstoreFetcher', |
|
185 | + ]); |
|
186 | + return []; |
|
187 | + } |
|
188 | + } |
|
189 | + |
|
190 | + /** |
|
191 | + * Get the currently Nextcloud version |
|
192 | + * @return string |
|
193 | + */ |
|
194 | + protected function getVersion() { |
|
195 | + if ($this->version === null) { |
|
196 | + $this->version = $this->config->getSystemValueString('version', '0.0.0'); |
|
197 | + } |
|
198 | + return $this->version; |
|
199 | + } |
|
200 | + |
|
201 | + /** |
|
202 | + * Set the current Nextcloud version |
|
203 | + * @param string $version |
|
204 | + */ |
|
205 | + public function setVersion(string $version) { |
|
206 | + $this->version = $version; |
|
207 | + } |
|
208 | + |
|
209 | + /** |
|
210 | + * Get the currently Nextcloud update channel |
|
211 | + * @return string |
|
212 | + */ |
|
213 | + protected function getChannel() { |
|
214 | + if ($this->channel === null) { |
|
215 | + $this->channel = Server::get(ServerVersion::class)->getChannel(); |
|
216 | + } |
|
217 | + return $this->channel; |
|
218 | + } |
|
219 | + |
|
220 | + /** |
|
221 | + * Set the current Nextcloud update channel |
|
222 | + * @param string $channel |
|
223 | + */ |
|
224 | + public function setChannel(string $channel) { |
|
225 | + $this->channel = $channel; |
|
226 | + } |
|
227 | + |
|
228 | + protected function getEndpoint(): string { |
|
229 | + return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1') . '/' . $this->endpointName; |
|
230 | + } |
|
231 | 231 | } |
@@ -60,7 +60,7 @@ discard block |
||
60 | 60 | */ |
61 | 61 | protected function fetch($ETag, $content, $allowUnstable = false) { |
62 | 62 | $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true); |
63 | - if ((int)$this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) { |
|
63 | + if ((int) $this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) { |
|
64 | 64 | return []; |
65 | 65 | } |
66 | 66 | |
@@ -69,7 +69,7 @@ discard block |
||
69 | 69 | } |
70 | 70 | |
71 | 71 | $options = [ |
72 | - 'timeout' => (int)$this->config->getAppValue('settings', 'appstore-timeout', '120') |
|
72 | + 'timeout' => (int) $this->config->getAppValue('settings', 'appstore-timeout', '120') |
|
73 | 73 | ]; |
74 | 74 | |
75 | 75 | if ($ETag !== '') { |
@@ -90,8 +90,8 @@ discard block |
||
90 | 90 | $client = $this->clientService->newClient(); |
91 | 91 | try { |
92 | 92 | $response = $client->get($this->getEndpoint(), $options); |
93 | - } catch (ConnectException|ClientException|ServerException $e) { |
|
94 | - $this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string)time()); |
|
93 | + } catch (ConnectException | ClientException | ServerException $e) { |
|
94 | + $this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string) time()); |
|
95 | 95 | $this->logger->error('Failed to connect to the app store', ['exception' => $e]); |
96 | 96 | return []; |
97 | 97 | } |
@@ -150,7 +150,7 @@ discard block |
||
150 | 150 | $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS_UNSTABLE; |
151 | 151 | } |
152 | 152 | |
153 | - if ((int)$jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) { |
|
153 | + if ((int) $jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) { |
|
154 | 154 | return $jsonBlob['data']; |
155 | 155 | } |
156 | 156 | |
@@ -176,7 +176,7 @@ discard block |
||
176 | 176 | $file->putContent(json_encode($responseJson)); |
177 | 177 | return json_decode($file->getContent(), true)['data']; |
178 | 178 | } catch (ConnectException $e) { |
179 | - $this->logger->warning('Could not connect to appstore: ' . $e->getMessage(), ['app' => 'appstoreFetcher']); |
|
179 | + $this->logger->warning('Could not connect to appstore: '.$e->getMessage(), ['app' => 'appstoreFetcher']); |
|
180 | 180 | return []; |
181 | 181 | } catch (\Exception $e) { |
182 | 182 | $this->logger->warning($e->getMessage(), [ |
@@ -226,6 +226,6 @@ discard block |
||
226 | 226 | } |
227 | 227 | |
228 | 228 | protected function getEndpoint(): string { |
229 | - return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1') . '/' . $this->endpointName; |
|
229 | + return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1').'/'.$this->endpointName; |
|
230 | 230 | } |
231 | 231 | } |