Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Notification api #132

Merged
merged 4 commits into from

3 participants

@Seldaek
Owner

No description provided.

@naderman naderman merged commit 2b68759 into composer:master
@stof stof commented on the diff
src/Packagist/WebBundle/Package/Dumper.php
@@ -55,10 +61,11 @@ class Dumper
* @param string $webDir web root
* @param string $cacheDir cache dir
*/
- public function __construct(RegistryInterface $doctrine, Filesystem $filesystem, $webDir, $cacheDir)
+ public function __construct(RegistryInterface $doctrine, Filesystem $filesystem, RouterInterface $router, $webDir, $cacheDir)
@stof
stof added a note

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

@Seldaek Owner
Seldaek added a note
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@stof stof commented on the diff
src/Packagist/WebBundle/Controller/ApiController.php
((11 lines not shown))
foreach ($packages as $package) {
$versions = array();
foreach ($package->getVersions() as $version) {
$versions[$version->getVersion()] = $version->toArray();
$em->detach($version);
}
- $data[$package->getName()] = array('versions' => $versions);
+ $data['packages'][$package->getName()] = array($versions);
@stof
stof added a note

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

@Seldaek 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.
View
1  app/AppKernel.php
@@ -20,6 +20,7 @@ public function registerBundles()
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new FOS\UserBundle\FOSUserBundle(),
+ new Snc\RedisBundle\SncRedisBundle(),
new Packagist\WebBundle\PackagistWebBundle(),
new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
new Nelmio\SolariumBundle\NelmioSolariumBundle(),
View
2  app/autoload.php
@@ -15,6 +15,8 @@
'Assetic' => __DIR__.'/../vendor/assetic/src',
'Metadata' => __DIR__.'/../vendor/metadata/src',
'FOS' => __DIR__.'/../vendor/bundles',
+ 'Snc' => __DIR__.'/../vendor/bundles',
+ 'Predis' => __DIR__.'/../vendor/predis/lib',
'Composer' => __DIR__.'/../vendor/composer/src',
'Packagist' => __DIR__.'/../src',
'WhiteOctober\PagerfantaBundle' => __DIR__.'/../vendor/bundles',
View
7 app/config/config.yml
@@ -48,6 +48,13 @@ doctrine:
auto_generate_proxy_classes: %kernel.debug%
auto_mapping: true
+snc_redis:
+ clients:
+ default:
+ type: predis
+ alias: default
+ dsn: %redis_dsn%
+
# Swiftmailer Configuration
swiftmailer:
transport: %mailer_transport%
View
2  app/config/parameters.yml.dist
@@ -12,6 +12,8 @@ parameters:
mailer_from_email: admin@example.org
mailer_from_name: Admin Team
+ redis_dsn: redis://localhost/1
+
locale: en
secret: CHANGE_ME_IN_PROD
View
9 deps
@@ -85,3 +85,12 @@
[jsonlint]
git=https://github.com/Seldaek/jsonlint.git
+
+[SncRedisBundle]
+ git=git://github.com/snc/SncRedisBundle.git
+ target=/bundles/Snc/RedisBundle
+ version=origin/master
+
+[predis]
+ git=git://github.com/nrk/predis.git
+ version=origin/v0.7
View
13 deps.lock
@@ -6,15 +6,18 @@ doctrine-dbal 2.1.6
doctrine 2.1.6
swiftmailer v4.1.5
assetic v1.0.2
-twig-extensions 1dfff8e793f50f651c4f74f796c2c68a4aee3147
+twig-extensions 4c831657215e51568fcb31bb9142e827f9a69bd5
metadata 1.0.0
-composer bfd48b06bd85619a36f660c43dda4fabfe980a67
+composer 470153989284bc41d13a8e279e2b9cb607e96d34
SensioFrameworkExtraBundle 638f545b7020b9e9d5944a7e3167f60ed848250d
SensioDistributionBundle 20b66a408084ad8752f98e50f10533f5245310bf
-SensioGeneratorBundle dd37fc4487bc09ac01bdcf89e0ff4ee4484b7fab
+SensioGeneratorBundle b1ccb78c1743f30817b0fce9bb5c6baff6ed7bf8
AsseticBundle v1.0.1
FOSUserBundle 1.1.0
WhiteOctoberPagerfanta c490684def33e992241e7fad33bcbd03d9d18643
-WhiteOctoberPagerfantaBundle 3fad72a0916d12f50b7a56da470175f560991724
+WhiteOctoberPagerfantaBundle 40209ef994fa2f342660d96bf6bea3f88171cd2d
solarium 2.3.0-RC1
-NelmioSolariumBundle f1f0c436e727e28acd209c5c9e1176a8ae306ea6
+NelmioSolariumBundle 75c1c8481b3e6be50f1509ab8290181c48b1169e
+jsonlint 869e5d011fe1c82501ae0a3b427a686c21fd5baf
+SncRedisBundle 23c1814a179598d62f6c50290472234e8e4faedd
+predis v0.7.2
View
52 src/Packagist/WebBundle/Controller/ApiController.php
@@ -15,6 +15,7 @@
use Composer\IO\NullIO;
use Composer\Repository\VcsRepository;
use Packagist\WebBundle\Package\Updater;
+use Packagist\WebBundle\Entity\Package;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
@@ -40,14 +41,19 @@ public function packagesAction()
$packages = $em->getRepository('Packagist\WebBundle\Entity\Package')
->getFullPackages();
- $data = array();
+ $notifyUrl = $this->generateUrl('track_download', array('name' => 'VND/PKG'));
+
+ $data = array(
+ 'notify' => str_replace('VND/PKG', '%package%', $notifyUrl),
+ 'packages' => array(),
+ );
foreach ($packages as $package) {
$versions = array();
foreach ($package->getVersions() as $version) {
$versions[$version->getVersion()] = $version->toArray();
$em->detach($version);
}
- $data[$package->getName()] = array('versions' => $versions);
+ $data['packages'][$package->getName()] = array($versions);
@stof
stof added a note

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

@Seldaek 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
$em->detach($package);
}
unset($versions, $package, $packages);
@@ -106,4 +112,46 @@ public function githubPostReceive(Request $request)
return new Response(json_encode(array('status' => 'error', 'message' => 'Could not find a package that matches this request (does user maintain the package?)',)), 404);
}
+
+ /**
+ * @Route("/downloads/{name}", name="track_download", requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+"}, defaults={"_format" = "json"})
+ * @Method({"POST"})
+ */
+ public function trackDownloadAction(Request $request, $name)
+ {
+ $result = $this->getDoctrine()->getConnection()->fetchAssoc(
+ 'SELECT p.id, v.id vid
+ FROM package p
+ LEFT JOIN package_version v ON p.id = v.package_id
+ WHERE p.name = ?
+ AND v.normalizedVersion = ?
+ LIMIT 1',
+ array($name, $request->request->get('version_normalized'))
+ );
+
+ if (!$result) {
+ return new Response('{"status": "error", "message": "Package not found"}', 200);
+ }
+
+ $redis = $this->get('snc_redis.default');
+ $id = $result['id'];
+ $version = $result['vid'];
+
+ $throttleKey = 'dl:'.$id.':'.$request->getClientIp().':'.date('Ymd');
+ $requests = $redis->incr($throttleKey);
+ if (1 === $requests) {
+ $redis->expire($throttleKey, 86400);
+ }
+ if ($requests <= 10) {
+ $redis->incr('dl:'.$id.':'.date('Ymd'));
+ $redis->incr('dl:'.$id.':'.date('Ym'));
+ $redis->incr('dl:'.$id);
+
+ $redis->incr('dl:'.$id.'-'.$version.':'.date('Ymd'));
+ $redis->incr('dl:'.$id.'-'.$version.':'.date('Ym'));
+ $redis->incr('dl:'.$id.'-'.$version);
+ }
+
+ return new Response('{"status": "success"}', 201);
+ }
}
View
1  src/Packagist/WebBundle/Entity/Version.php
@@ -212,6 +212,7 @@ public function toArray()
'keywords' => $tags,
'homepage' => $this->getHomepage(),
'version' => $this->getVersion(),
+ 'version_normalized' => $this->getNormalizedVersion(),
'license' => $this->getLicense(),
'authors' => $authors,
'source' => $this->getSource(),
View
11 src/Packagist/WebBundle/Package/Dumper.php
@@ -14,6 +14,7 @@
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Bridge\Doctrine\RegistryInterface;
+use Symfony\Component\Routing\RouterInterface;
use Packagist\WebBundle\Entity\Version;
/**
@@ -43,6 +44,11 @@ class Dumper
protected $buildDir;
/**
+ * @var RouterInterface
+ */
+ protected $router;
+
+ /**
* Data cache
* @var array
*/
@@ -55,10 +61,11 @@ class Dumper
* @param string $webDir web root
* @param string $cacheDir cache dir
*/
- public function __construct(RegistryInterface $doctrine, Filesystem $filesystem, $webDir, $cacheDir)
+ public function __construct(RegistryInterface $doctrine, Filesystem $filesystem, RouterInterface $router, $webDir, $cacheDir)
@stof
stof added a note

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

@Seldaek Owner
Seldaek added a note
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
{
$this->doctrine = $doctrine;
$this->fs = $filesystem;
+ $this->router = $router;
$this->webDir = realpath($webDir);
$this->buildDir = $cacheDir . '/composer-packages-build';
}
@@ -112,6 +119,8 @@ public function dump(array $packages, $force = false)
if (!isset($this->files['packages.json']['packages'])) {
$this->files['packages.json']['packages'] = array();
}
+ $url = $this->router->generate('track_download', array('name' => 'VND/PKG'));
+ $this->files['packages.json']['notify'] = str_replace('VND/PKG', '%package%', $url);
// dump files to build dir
foreach ($modifiedFiles as $file => $dummy) {
View
2  src/Packagist/WebBundle/Resources/config/services.yml
@@ -7,4 +7,4 @@ services:
packagist.package_dumper:
class: Packagist\WebBundle\Package\Dumper
- arguments: [ @doctrine, @filesystem, %kernel.root_dir%/../web/, %kernel.cache_dir% ]
+ arguments: [ @doctrine, @filesystem, @router, %kernel.root_dir%/../web/, %kernel.cache_dir% ]
Something went wrong with that request. Please try again.