Skip to content
This repository

Notification api #132

Merged
merged 4 commits into from over 2 years ago

3 participants

Jordi Boggiano Christophe Coevoet Nils Adermann
Jordi Boggiano
Owner

No description provided.

Nils Adermann naderman merged commit 2b68759 into from
Nils Adermann naderman closed this
Christophe Coevoet stof commented on the diff
src/Packagist/WebBundle/Package/Dumper.php
@@ -55,10 +61,11 @@ class Dumper
55 61 * @param string $webDir web root
56 62 * @param string $cacheDir cache dir
57 63 */
58   - public function __construct(RegistryInterface $doctrine, Filesystem $filesystem, $webDir, $cacheDir)
  64 + public function __construct(RegistryInterface $doctrine, Filesystem $filesystem, RouterInterface $router, $webDir, $cacheDir)
2
Christophe Coevoet
stof added a note

you should typehint the UrlGeneratorInterface as it is the only part of RouterInterface you really need :)

Jordi Boggiano Owner
Seldaek added a note
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Christophe Coevoet stof commented on the diff
src/Packagist/WebBundle/Controller/ApiController.php
((11 lines not shown))
44 50 foreach ($packages as $package) {
45 51 $versions = array();
46 52 foreach ($package->getVersions() as $version) {
47 53 $versions[$version->getVersion()] = $version->toArray();
48 54 $em->detach($version);
49 55 }
50   - $data[$package->getName()] = array('versions' => $versions);
  56 + $data['packages'][$package->getName()] = array($versions);
2
Christophe Coevoet
stof added a note

This changes the format of the packages.json, isn't it ?

Jordi Boggiano Owner
Seldaek added a note

Well that file is now generated by the dumper, this controller is just there in case people do their own setup and don't call the packagist:dump command. Anyway the controller was outdated, so yes it changes it, but it just brings it in line with the dumper command.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
1  app/AppKernel.php
@@ -20,6 +20,7 @@ public function registerBundles()
20 20 new Symfony\Bundle\AsseticBundle\AsseticBundle(),
21 21 new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
22 22 new FOS\UserBundle\FOSUserBundle(),
  23 + new Snc\RedisBundle\SncRedisBundle(),
23 24 new Packagist\WebBundle\PackagistWebBundle(),
24 25 new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
25 26 new Nelmio\SolariumBundle\NelmioSolariumBundle(),
2  app/autoload.php
@@ -15,6 +15,8 @@
15 15 'Assetic' => __DIR__.'/../vendor/assetic/src',
16 16 'Metadata' => __DIR__.'/../vendor/metadata/src',
17 17 'FOS' => __DIR__.'/../vendor/bundles',
  18 + 'Snc' => __DIR__.'/../vendor/bundles',
  19 + 'Predis' => __DIR__.'/../vendor/predis/lib',
18 20 'Composer' => __DIR__.'/../vendor/composer/src',
19 21 'Packagist' => __DIR__.'/../src',
20 22 'WhiteOctober\PagerfantaBundle' => __DIR__.'/../vendor/bundles',
7 app/config/config.yml
@@ -48,6 +48,13 @@ doctrine:
48 48 auto_generate_proxy_classes: %kernel.debug%
49 49 auto_mapping: true
50 50
  51 +snc_redis:
  52 + clients:
  53 + default:
  54 + type: predis
  55 + alias: default
  56 + dsn: %redis_dsn%
  57 +
51 58 # Swiftmailer Configuration
52 59 swiftmailer:
53 60 transport: %mailer_transport%
2  app/config/parameters.yml.dist
@@ -12,6 +12,8 @@ parameters:
12 12 mailer_from_email: admin@example.org
13 13 mailer_from_name: Admin Team
14 14
  15 + redis_dsn: redis://localhost/1
  16 +
15 17 locale: en
16 18
17 19 secret: CHANGE_ME_IN_PROD
9 deps
@@ -85,3 +85,12 @@
85 85
86 86 [jsonlint]
87 87 git=https://github.com/Seldaek/jsonlint.git
  88 +
  89 +[SncRedisBundle]
  90 + git=git://github.com/snc/SncRedisBundle.git
  91 + target=/bundles/Snc/RedisBundle
  92 + version=origin/master
  93 +
  94 +[predis]
  95 + git=git://github.com/nrk/predis.git
  96 + version=origin/v0.7
13 deps.lock
@@ -6,15 +6,18 @@ doctrine-dbal 2.1.6
6 6 doctrine 2.1.6
7 7 swiftmailer v4.1.5
8 8 assetic v1.0.2
9   -twig-extensions 1dfff8e793f50f651c4f74f796c2c68a4aee3147
  9 +twig-extensions 4c831657215e51568fcb31bb9142e827f9a69bd5
10 10 metadata 1.0.0
11   -composer bfd48b06bd85619a36f660c43dda4fabfe980a67
  11 +composer 470153989284bc41d13a8e279e2b9cb607e96d34
12 12 SensioFrameworkExtraBundle 638f545b7020b9e9d5944a7e3167f60ed848250d
13 13 SensioDistributionBundle 20b66a408084ad8752f98e50f10533f5245310bf
14   -SensioGeneratorBundle dd37fc4487bc09ac01bdcf89e0ff4ee4484b7fab
  14 +SensioGeneratorBundle b1ccb78c1743f30817b0fce9bb5c6baff6ed7bf8
15 15 AsseticBundle v1.0.1
16 16 FOSUserBundle 1.1.0
17 17 WhiteOctoberPagerfanta c490684def33e992241e7fad33bcbd03d9d18643
18   -WhiteOctoberPagerfantaBundle 3fad72a0916d12f50b7a56da470175f560991724
  18 +WhiteOctoberPagerfantaBundle 40209ef994fa2f342660d96bf6bea3f88171cd2d
19 19 solarium 2.3.0-RC1
20   -NelmioSolariumBundle f1f0c436e727e28acd209c5c9e1176a8ae306ea6
  20 +NelmioSolariumBundle 75c1c8481b3e6be50f1509ab8290181c48b1169e
  21 +jsonlint 869e5d011fe1c82501ae0a3b427a686c21fd5baf
  22 +SncRedisBundle 23c1814a179598d62f6c50290472234e8e4faedd
  23 +predis v0.7.2
52 src/Packagist/WebBundle/Controller/ApiController.php
@@ -15,6 +15,7 @@
15 15 use Composer\IO\NullIO;
16 16 use Composer\Repository\VcsRepository;
17 17 use Packagist\WebBundle\Package\Updater;
  18 +use Packagist\WebBundle\Entity\Package;
18 19 use Symfony\Bundle\FrameworkBundle\Controller\Controller;
19 20 use Symfony\Component\HttpFoundation\Response;
20 21 use Symfony\Component\HttpFoundation\Request;
@@ -40,14 +41,19 @@ public function packagesAction()
40 41 $packages = $em->getRepository('Packagist\WebBundle\Entity\Package')
41 42 ->getFullPackages();
42 43
43   - $data = array();
  44 + $notifyUrl = $this->generateUrl('track_download', array('name' => 'VND/PKG'));
  45 +
  46 + $data = array(
  47 + 'notify' => str_replace('VND/PKG', '%package%', $notifyUrl),
  48 + 'packages' => array(),
  49 + );
44 50 foreach ($packages as $package) {
45 51 $versions = array();
46 52 foreach ($package->getVersions() as $version) {
47 53 $versions[$version->getVersion()] = $version->toArray();
48 54 $em->detach($version);
49 55 }
50   - $data[$package->getName()] = array('versions' => $versions);
  56 + $data['packages'][$package->getName()] = array($versions);
51 57 $em->detach($package);
52 58 }
53 59 unset($versions, $package, $packages);
@@ -106,4 +112,46 @@ public function githubPostReceive(Request $request)
106 112
107 113 return new Response(json_encode(array('status' => 'error', 'message' => 'Could not find a package that matches this request (does user maintain the package?)',)), 404);
108 114 }
  115 +
  116 + /**
  117 + * @Route("/downloads/{name}", name="track_download", requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+"}, defaults={"_format" = "json"})
  118 + * @Method({"POST"})
  119 + */
  120 + public function trackDownloadAction(Request $request, $name)
  121 + {
  122 + $result = $this->getDoctrine()->getConnection()->fetchAssoc(
  123 + 'SELECT p.id, v.id vid
  124 + FROM package p
  125 + LEFT JOIN package_version v ON p.id = v.package_id
  126 + WHERE p.name = ?
  127 + AND v.normalizedVersion = ?
  128 + LIMIT 1',
  129 + array($name, $request->request->get('version_normalized'))
  130 + );
  131 +
  132 + if (!$result) {
  133 + return new Response('{"status": "error", "message": "Package not found"}', 200);
  134 + }
  135 +
  136 + $redis = $this->get('snc_redis.default');
  137 + $id = $result['id'];
  138 + $version = $result['vid'];
  139 +
  140 + $throttleKey = 'dl:'.$id.':'.$request->getClientIp().':'.date('Ymd');
  141 + $requests = $redis->incr($throttleKey);
  142 + if (1 === $requests) {
  143 + $redis->expire($throttleKey, 86400);
  144 + }
  145 + if ($requests <= 10) {
  146 + $redis->incr('dl:'.$id.':'.date('Ymd'));
  147 + $redis->incr('dl:'.$id.':'.date('Ym'));
  148 + $redis->incr('dl:'.$id);
  149 +
  150 + $redis->incr('dl:'.$id.'-'.$version.':'.date('Ymd'));
  151 + $redis->incr('dl:'.$id.'-'.$version.':'.date('Ym'));
  152 + $redis->incr('dl:'.$id.'-'.$version);
  153 + }
  154 +
  155 + return new Response('{"status": "success"}', 201);
  156 + }
109 157 }
1  src/Packagist/WebBundle/Entity/Version.php
@@ -212,6 +212,7 @@ public function toArray()
212 212 'keywords' => $tags,
213 213 'homepage' => $this->getHomepage(),
214 214 'version' => $this->getVersion(),
  215 + 'version_normalized' => $this->getNormalizedVersion(),
215 216 'license' => $this->getLicense(),
216 217 'authors' => $authors,
217 218 'source' => $this->getSource(),
11 src/Packagist/WebBundle/Package/Dumper.php
@@ -14,6 +14,7 @@
14 14
15 15 use Symfony\Component\Filesystem\Filesystem;
16 16 use Symfony\Bridge\Doctrine\RegistryInterface;
  17 +use Symfony\Component\Routing\RouterInterface;
17 18 use Packagist\WebBundle\Entity\Version;
18 19
19 20 /**
@@ -43,6 +44,11 @@ class Dumper
43 44 protected $buildDir;
44 45
45 46 /**
  47 + * @var RouterInterface
  48 + */
  49 + protected $router;
  50 +
  51 + /**
46 52 * Data cache
47 53 * @var array
48 54 */
@@ -55,10 +61,11 @@ class Dumper
55 61 * @param string $webDir web root
56 62 * @param string $cacheDir cache dir
57 63 */
58   - public function __construct(RegistryInterface $doctrine, Filesystem $filesystem, $webDir, $cacheDir)
  64 + public function __construct(RegistryInterface $doctrine, Filesystem $filesystem, RouterInterface $router, $webDir, $cacheDir)
59 65 {
60 66 $this->doctrine = $doctrine;
61 67 $this->fs = $filesystem;
  68 + $this->router = $router;
62 69 $this->webDir = realpath($webDir);
63 70 $this->buildDir = $cacheDir . '/composer-packages-build';
64 71 }
@@ -112,6 +119,8 @@ public function dump(array $packages, $force = false)
112 119 if (!isset($this->files['packages.json']['packages'])) {
113 120 $this->files['packages.json']['packages'] = array();
114 121 }
  122 + $url = $this->router->generate('track_download', array('name' => 'VND/PKG'));
  123 + $this->files['packages.json']['notify'] = str_replace('VND/PKG', '%package%', $url);
115 124
116 125 // dump files to build dir
117 126 foreach ($modifiedFiles as $file => $dummy) {
2  src/Packagist/WebBundle/Resources/config/services.yml
@@ -7,4 +7,4 @@ services:
7 7
8 8 packagist.package_dumper:
9 9 class: Packagist\WebBundle\Package\Dumper
10   - arguments: [ @doctrine, @filesystem, %kernel.root_dir%/../web/, %kernel.cache_dir% ]
  10 + arguments: [ @doctrine, @filesystem, @router, %kernel.root_dir%/../web/, %kernel.cache_dir% ]

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.