diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..2807d5f7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+web/bundles/
+app/bootstrap*
+app/cache/*
+app/logs/*
+build/
+vendor/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..51efd884
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Jordi Boggiano, Nils Adermann
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/app/.htaccess b/app/.htaccess
new file mode 100644
index 00000000..3418e55a
--- /dev/null
+++ b/app/.htaccess
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/app/AppCache.php b/app/AppCache.php
new file mode 100644
index 00000000..ddb51db0
--- /dev/null
+++ b/app/AppCache.php
@@ -0,0 +1,9 @@
+getEnvironment(), array('dev', 'test'))) {
+ $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
+ }
+
+ return $bundles;
+ }
+
+ public function init()
+ {
+ if ($this->debug) {
+ ini_set('display_errors', 1);
+ error_reporting(-1);
+
+ DebugUniversalClassLoader::enable();
+ ErrorHandler::register();
+ if ('cli' !== php_sapi_name()) {
+ ExceptionHandler::register();
+ }
+ } else {
+ ini_set('display_errors', 0);
+ }
+ }
+
+ public function registerContainerConfiguration(LoaderInterface $loader)
+ {
+ $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
+ }
+}
diff --git a/app/Resources/views/base.html.twig b/app/Resources/views/base.html.twig
new file mode 100644
index 00000000..c19978f0
--- /dev/null
+++ b/app/Resources/views/base.html.twig
@@ -0,0 +1,13 @@
+
+
+
+
+ {% block title %}Welcome!{% endblock %}
+ {% block stylesheets %}{% endblock %}
+
+
+
+ {% block body %}{% endblock %}
+ {% block javascripts %}{% endblock %}
+
+
diff --git a/app/autoload.php b/app/autoload.php
new file mode 100644
index 00000000..9c80e26c
--- /dev/null
+++ b/app/autoload.php
@@ -0,0 +1,33 @@
+registerNamespaces(array(
+ 'Symfony' => array(__DIR__.'/../vendor/symfony/src', __DIR__.'/../vendor/bundles'),
+ 'Sensio' => __DIR__.'/../vendor/bundles',
+ 'JMS' => __DIR__.'/../vendor/bundles',
+ 'Doctrine\\Common' => __DIR__.'/../vendor/doctrine-common/lib',
+ 'Doctrine\\DBAL' => __DIR__.'/../vendor/doctrine-dbal/lib',
+ 'Doctrine' => __DIR__.'/../vendor/doctrine/lib',
+ 'Monolog' => __DIR__.'/../vendor/monolog/src',
+ 'Assetic' => __DIR__.'/../vendor/assetic/src',
+ 'Metadata' => __DIR__.'/../vendor/metadata/src',
+ 'Packagist' => __DIR__.'/../src',
+));
+$loader->registerPrefixes(array(
+ 'Twig_Extensions_' => __DIR__.'/../vendor/twig-extensions/lib',
+ 'Twig_' => __DIR__.'/../vendor/twig/lib',
+));
+$loader->registerPrefixFallbacks(array(
+ __DIR__.'/../vendor/symfony/src/Symfony/Component/Locale/Resources/stubs',
+));
+$loader->registerNamespaceFallbacks(array(
+ __DIR__.'/../src',
+));
+$loader->register();
+
+// Swiftmailer needs a special autoloader to allow
+// the lazy loading of the init file (which is expensive)
+require_once __DIR__.'/../vendor/swiftmailer/lib/classes/Swift.php';
+Swift::registerAutoload(__DIR__.'/../vendor/swiftmailer/lib/swift_init.php');
diff --git a/app/check.php b/app/check.php
new file mode 100644
index 00000000..c10f1ab2
--- /dev/null
+++ b/app/check.php
@@ -0,0 +1,84 @@
+='), sprintf('Checking that PHP version is at least 5.3.2 (%s installed)', phpversion()), 'Install PHP 5.3.2 or newer (current version is '.phpversion(), true);
+check(ini_get('date.timezone'), 'Checking that the "date.timezone" setting is set', 'Set the "date.timezone" setting in php.ini (like Europe/Paris)', true);
+check(is_writable(__DIR__.'/../app/cache'), sprintf('Checking that app/cache/ directory is writable'), 'Change the permissions of the app/cache/ directory so that the web server can write in it', true);
+check(is_writable(__DIR__.'/../app/logs'), sprintf('Checking that the app/logs/ directory is writable'), 'Change the permissions of the app/logs/ directory so that the web server can write in it', true);
+check(function_exists('json_encode'), 'Checking that the json_encode() is available', 'Install and enable the json extension', true);
+
+// warnings
+echo_title("Optional checks");
+check(class_exists('DomDocument'), 'Checking that the PHP-XML module is installed', 'Install and enable the php-xml module', false);
+check(defined('LIBXML_COMPACT'), 'Checking that the libxml version is at least 2.6.21', 'Upgrade your php-xml module with a newer libxml', false);
+check(function_exists('token_get_all'), 'Checking that the token_get_all() function is available', 'Install and enable the Tokenizer extension (highly recommended)', false);
+check(function_exists('mb_strlen'), 'Checking that the mb_strlen() function is available', 'Install and enable the mbstring extension', false);
+check(function_exists('iconv'), 'Checking that the iconv() function is available', 'Install and enable the iconv extension', false);
+check(function_exists('utf8_decode'), 'Checking that the utf8_decode() is available', 'Install and enable the XML extension', false);
+check(function_exists('posix_isatty'), 'Checking that the posix_isatty() is available', 'Install and enable the php_posix extension (used to colorized the CLI output)', false);
+check(class_exists('Locale'), 'Checking that the intl extension is available', 'Install and enable the intl extension (used for validators)', false);
+
+$accelerator =
+ (function_exists('apc_store') && ini_get('apc.enabled'))
+ ||
+ function_exists('eaccelerator_put') && ini_get('eaccelerator.enable')
+ ||
+ function_exists('xcache_set')
+;
+check($accelerator, 'Checking that a PHP accelerator is installed', 'Install a PHP accelerator like APC (highly recommended)', false);
+
+check(!ini_get('short_open_tag'), 'Checking that php.ini has short_open_tag set to off', 'Set short_open_tag to off in php.ini', false);
+check(!ini_get('magic_quotes_gpc'), 'Checking that php.ini has magic_quotes_gpc set to off', 'Set magic_quotes_gpc to off in php.ini', false);
+check(!ini_get('register_globals'), 'Checking that php.ini has register_globals set to off', 'Set register_globals to off in php.ini', false);
+check(!ini_get('session.auto_start'), 'Checking that php.ini has session.auto_start set to off', 'Set session.auto_start to off in php.ini', false);
+
+echo_title("Optional checks (Doctrine)");
+
+check(class_exists('PDO'), 'Checking that PDO is installed', 'Install PDO (mandatory for Doctrine)', false);
+if (class_exists('PDO')) {
+ $drivers = PDO::getAvailableDrivers();
+ check(count($drivers), 'Checking that PDO has some drivers installed: '.implode(', ', $drivers), 'Install PDO drivers (mandatory for Doctrine)');
+}
+
+/**
+ * Checks a configuration.
+ */
+function check($boolean, $message, $help = '', $fatal = false)
+{
+ echo $boolean ? " OK " : sprintf("\n\n[[%s]] ", $fatal ? ' ERROR ' : 'WARNING');
+ echo sprintf("$message%s\n", $boolean ? '' : ': FAILED');
+
+ if (!$boolean) {
+ echo " *** $help ***\n";
+ if ($fatal) {
+ die("You must fix this problem before resuming the check.\n");
+ }
+ }
+}
+
+function echo_title($title)
+{
+ echo "\n** $title **\n\n";
+}
diff --git a/app/config/config.yml b/app/config/config.yml
new file mode 100644
index 00000000..09a61dbe
--- /dev/null
+++ b/app/config/config.yml
@@ -0,0 +1,57 @@
+imports:
+ - { resource: parameters.ini }
+ - { resource: security.yml }
+
+framework:
+ secret: %secret%
+ charset: UTF-8
+ router: { resource: "%kernel.root_dir%/config/routing.yml" }
+ form: true
+ csrf_protection: true
+ validation: { enable_annotations: true }
+ templating: { engines: ['twig'] } #assets_version: SomeVersionScheme
+ session:
+ default_locale: %locale%
+ lifetime: 3600
+ auto_start: true
+
+# Twig Configuration
+twig:
+ debug: %kernel.debug%
+ strict_variables: %kernel.debug%
+ extensions: [twig.extension.text, twig.extension.debug]
+
+# Assetic Configuration
+assetic:
+ debug: %kernel.debug%
+ use_controller: false
+ filters:
+ cssrewrite: ~
+ closure:
+ jar: %kernel.root_dir%/java/compiler.jar
+ yui_css:
+ jar: %kernel.root_dir%/java/yuicompressor-2.4.2.jar
+
+# Doctrine Configuration
+doctrine:
+ dbal:
+ driver: %database_driver%
+ host: %database_host%
+ dbname: %database_name%
+ user: %database_user%
+ password: %database_password%
+ charset: UTF8
+ orm:
+ auto_generate_proxy_classes: %kernel.debug%
+ auto_mapping: true
+
+# Swiftmailer Configuration
+swiftmailer:
+ transport: %mailer_transport%
+ host: %mailer_host%
+ username: %mailer_user%
+ password: %mailer_password%
+
+jms_security_extra:
+ secure_controllers: true
+ secure_all_services: false
diff --git a/app/config/config_dev.yml b/app/config/config_dev.yml
new file mode 100644
index 00000000..229fa7b5
--- /dev/null
+++ b/app/config/config_dev.yml
@@ -0,0 +1,23 @@
+imports:
+ - { resource: config.yml }
+
+framework:
+ router: { resource: "%kernel.root_dir%/config/routing_dev.yml" }
+ profiler: { only_exceptions: false }
+
+web_profiler:
+ toolbar: false
+ intercept_redirects: false
+
+monolog:
+ handlers:
+ main:
+ type: stream
+ path: %kernel.logs_dir%/%kernel.environment%.log
+ level: debug
+ firephp:
+ type: firephp
+ level: info
+
+#assetic:
+# use_controller: true
diff --git a/app/config/config_prod.yml b/app/config/config_prod.yml
new file mode 100644
index 00000000..4a364960
--- /dev/null
+++ b/app/config/config_prod.yml
@@ -0,0 +1,18 @@
+imports:
+ - { resource: config.yml }
+
+#doctrine:
+# metadata_cache_driver: apc
+# result_cache_driver: apc
+# query_cache_driver: apc
+
+monolog:
+ handlers:
+ main:
+ type: fingers_crossed
+ action_level: error
+ handler: nested
+ nested:
+ type: stream
+ path: %kernel.logs_dir%/%kernel.environment%.log
+ level: debug
diff --git a/app/config/config_test.yml b/app/config/config_test.yml
new file mode 100644
index 00000000..7dba2fbf
--- /dev/null
+++ b/app/config/config_test.yml
@@ -0,0 +1,14 @@
+imports:
+ - { resource: config_dev.yml }
+
+framework:
+ test: ~
+ session:
+ storage_id: session.storage.filesystem
+
+web_profiler:
+ toolbar: false
+ intercept_redirects: false
+
+swiftmailer:
+ disable_delivery: true
diff --git a/app/config/parameters.ini b/app/config/parameters.ini
new file mode 100644
index 00000000..05d2e289
--- /dev/null
+++ b/app/config/parameters.ini
@@ -0,0 +1,18 @@
+; These parameters can be imported into other config files
+; by enclosing the key with % (like %database_user%)
+; Comments start with ';', as in php.ini
+[parameters]
+ database_driver = pdo_mysql
+ database_host = localhost
+ database_name = packagist
+ database_user = root
+ database_password =
+
+ mailer_transport = smtp
+ mailer_host = localhost
+ mailer_user =
+ mailer_password =
+
+ locale = en
+
+ secret = 84f4c65b9cde3417ecaeedc4fb57742c
diff --git a/app/config/routing.yml b/app/config/routing.yml
new file mode 100644
index 00000000..3f26d066
--- /dev/null
+++ b/app/config/routing.yml
@@ -0,0 +1,3 @@
+_packagist:
+ resource: "@PackagistWebBundle/Controller"
+ type: annotation
diff --git a/app/config/routing_dev.yml b/app/config/routing_dev.yml
new file mode 100644
index 00000000..eb4766e6
--- /dev/null
+++ b/app/config/routing_dev.yml
@@ -0,0 +1,14 @@
+#_assetic:
+# resource: .
+# type: assetic
+
+_wdt:
+ resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml"
+ prefix: /_wdt
+
+_profiler:
+ resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml"
+ prefix: /_profiler
+
+_main:
+ resource: routing.yml
\ No newline at end of file
diff --git a/app/config/security.yml b/app/config/security.yml
new file mode 100644
index 00000000..432c0f75
--- /dev/null
+++ b/app/config/security.yml
@@ -0,0 +1,41 @@
+security:
+ encoders:
+ Symfony\Component\Security\Core\User\User: plaintext
+
+ role_hierarchy:
+ ROLE_ADMIN: ROLE_USER
+ ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
+
+ providers:
+ in_memory:
+ users:
+ user: { password: userpass, roles: [ 'ROLE_USER' ] }
+ admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
+
+ firewalls:
+ profiler:
+ pattern: ^/_profiler
+ security: false
+
+ wdt:
+ pattern: ^/_wdt
+ security: false
+
+ login:
+ pattern: ^/demo/secured/login$
+ security: false
+
+ secured_area:
+ pattern: ^/demo/secured/
+ form_login:
+ check_path: /demo/secured/login_check
+ login_path: /demo/secured/login
+ logout:
+ path: /demo/secured/logout
+ target: /demo/
+ #anonymous: ~
+ #http_basic:
+ # realm: "Secured Demo Area"
+
+ access_control:
+ #- { path: /login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
diff --git a/app/console b/app/console
new file mode 100755
index 00000000..32104712
--- /dev/null
+++ b/app/console
@@ -0,0 +1,16 @@
+#!/usr/bin/env php
+getParameterOption(array('--env', '-e'), 'dev');
+$debug = !$input->hasParameterOption(array('--no-debug', ''));
+
+$kernel = new AppKernel($env, $debug);
+$application = new Application($kernel);
+$application->run();
diff --git a/app/java/compiler.jar b/app/java/compiler.jar
new file mode 100644
index 00000000..09ac825b
Binary files /dev/null and b/app/java/compiler.jar differ
diff --git a/app/java/yuicompressor-2.4.2.jar b/app/java/yuicompressor-2.4.2.jar
new file mode 100644
index 00000000..c29470bd
Binary files /dev/null and b/app/java/yuicompressor-2.4.2.jar differ
diff --git a/app/phpunit.xml.dist b/app/phpunit.xml.dist
new file mode 100644
index 00000000..1e31086d
--- /dev/null
+++ b/app/phpunit.xml.dist
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+ ../src/*/*Bundle/Tests
+ ../src/*/Bundle/*Bundle/Tests
+
+
+
+
+
+
+
+ ../src
+
+ ../src/*/*Bundle/Resources
+ ../src/*/*Bundle/Tests
+ ../src/*/Bundle/*Bundle/Resources
+ ../src/*/Bundle/*Bundle/Tests
+
+
+
+
+
diff --git a/bin/.htaccess b/bin/.htaccess
new file mode 100644
index 00000000..3418e55a
--- /dev/null
+++ b/bin/.htaccess
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/bin/build.sh b/bin/build.sh
new file mode 100755
index 00000000..b8e62fb5
--- /dev/null
+++ b/bin/build.sh
@@ -0,0 +1,99 @@
+#!/bin/sh
+
+# This file is part of the Symfony Standard Edition.
+#
+# (c) Fabien Potencier
+#
+# For the full copyright and license information, please view the LICENSE
+# file that was distributed with this source code.
+
+DIR=`php -r "echo realpath(dirname(\\$_SERVER['argv'][0]));"`
+cd $DIR
+VERSION=`cat VERSION`
+
+if [ ! -d "$DIR/build" ]; then
+ mkdir -p $DIR/build
+fi
+
+$DIR/bin/build_bootstrap.php
+$DIR/app/console assets:install web/
+
+# Without vendors
+rm -rf /tmp/Symfony
+mkdir /tmp/Symfony
+cp -r app /tmp/Symfony/
+cp -r bin /tmp/Symfony/
+cp -r src /tmp/Symfony/
+cp -r web /tmp/Symfony/
+cp -r README.rst /tmp/Symfony/
+cp -r LICENSE /tmp/Symfony/
+cp -r VERSION /tmp/Symfony/
+cd /tmp/Symfony
+sudo rm -rf app/cache/* app/logs/* .git*
+chmod 777 app/cache app/logs
+
+# DS_Store cleanup
+find . -name .DS_Store | xargs rm -rf -
+
+cd ..
+# avoid the creation of ._* files
+export COPY_EXTENDED_ATTRIBUTES_DISABLE=true
+export COPYFILE_DISABLE=true
+tar zcpf $DIR/build/Symfony_Standard_$VERSION.tgz Symfony
+sudo rm -f $DIR/build/Symfony_Standard_$VERSION.zip
+zip -rq $DIR/build/Symfony_Standard_$VERSION.zip Symfony
+
+# With vendors
+cd $DIR
+rm -rf /tmp/vendor
+mkdir /tmp/vendor
+TARGET=/tmp/vendor
+
+if [ ! -d "$DIR/vendor" ]; then
+ echo "The master vendor directory does not exist"
+ exit
+fi
+
+cp -r $DIR/vendor/* $TARGET/
+
+# Assetic
+cd $TARGET/assetic && rm -rf phpunit.xml* README* tests
+
+# Doctrine ORM
+cd $TARGET/doctrine && rm -rf UPGRADE* build* bin tests tools lib/vendor
+
+# Doctrine DBAL
+cd $TARGET/doctrine-dbal && rm -rf bin build* tests lib/vendor
+
+# Doctrine Common
+cd $TARGET/doctrine-common && rm -rf build* tests lib/vendor
+
+# Swiftmailer
+cd $TARGET/swiftmailer && rm -rf CHANGES README* build* docs notes test-suite tests create_pear_package.php package*
+
+# Symfony
+cd $TARGET/symfony && rm -rf README.md phpunit.xml* tests *.sh vendor
+
+# Twig
+cd $TARGET/twig && rm -rf AUTHORS CHANGELOG README.markdown bin doc package.xml.tpl phpunit.xml* test
+
+# Twig Extensions
+cd $TARGET/twig-extensions && rm -rf README doc phpunit.xml* test
+
+# Monolog
+cd $TARGET/monolog && rm -rf README.markdown phpunit.xml* tests
+
+# Metadata
+cd $TARGET/metadata && rm -rf README.rst phpunit.xml* tests
+
+# cleanup
+find $TARGET -name .git | xargs rm -rf -
+find $TARGET -name .gitignore | xargs rm -rf -
+find $TARGET -name .gitmodules | xargs rm -rf -
+find $TARGET -name .svn | xargs rm -rf -
+
+cd /tmp/
+mv /tmp/vendor /tmp/Symfony/
+tar zcpf $DIR/build/Symfony_Standard_Vendors_$VERSION.tgz Symfony
+sudo rm -f $DIR/build/Symfony_Standard_Vendors_$VERSION.zip
+zip -rq $DIR/build/Symfony_Standard_Vendors_$VERSION.zip Symfony
diff --git a/bin/build_bootstrap b/bin/build_bootstrap
new file mode 100755
index 00000000..2912a07e
--- /dev/null
+++ b/bin/build_bootstrap
@@ -0,0 +1,92 @@
+#!/usr/bin/env php
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once __DIR__.'/../vendor/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Component\ClassLoader\UniversalClassLoader;
+use Symfony\Component\ClassLoader\ClassCollectionLoader;
+
+$loader = new UniversalClassLoader();
+$loader->registerNamespaces(array('Symfony' => __DIR__.'/../vendor/symfony/src'));
+$loader->register();
+
+$file = __DIR__.'/../app/bootstrap.php.cache';
+if (file_exists($file)) {
+ unlink($file);
+}
+
+ClassCollectionLoader::load(array(
+ 'Symfony\\Component\\DependencyInjection\\ContainerInterface',
+ 'Symfony\\Component\\DependencyInjection\\Container',
+ 'Symfony\\Component\\DependencyInjection\\ContainerAwareInterface',
+ 'Symfony\\Component\\DependencyInjection\\ContainerAware',
+
+ 'Symfony\\Component\\HttpKernel\\Bundle\\BundleInterface',
+ 'Symfony\\Component\\HttpKernel\\Bundle\\Bundle',
+ 'Symfony\\Component\\HttpKernel\\Debug\\ErrorHandler',
+ 'Symfony\\Component\\HttpKernel\\HttpKernelInterface',
+ 'Symfony\\Component\\HttpKernel\\HttpKernel',
+ 'Symfony\\Component\\HttpKernel\\KernelInterface',
+ 'Symfony\\Component\\HttpKernel\\Kernel',
+
+ 'Symfony\\Component\\HttpFoundation\\ParameterBag',
+ 'Symfony\\Component\\HttpFoundation\\FileBag',
+ 'Symfony\\Component\\HttpFoundation\\ServerBag',
+ 'Symfony\\Component\\HttpFoundation\\HeaderBag',
+ 'Symfony\\Component\\HttpFoundation\\Request',
+ 'Symfony\\Component\\HttpFoundation\\ApacheRequest',
+
+ 'Symfony\\Component\\ClassLoader\\ClassCollectionLoader',
+ 'Symfony\\Component\\ClassLoader\\UniversalClassLoader',
+ 'Symfony\\Component\\ClassLoader\\MapFileClassLoader',
+
+ 'Symfony\\Component\\Config\\ConfigCache',
+), dirname($file), basename($file, '.php.cache'), false, false, '.php.cache');
+
+file_put_contents($file, "
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$rootDir = dirname(__DIR__);
+$vendorDir = $rootDir.'/vendor';
+
+array_shift($argv);
+if (!isset($argv[0])) {
+ die(<< Installing/Updating $name\n";
+
+ if (!is_dir($installDir)) {
+ system(sprintf('git clone %s "%s"', $url, $installDir));
+ }
+
+ system(sprintf('cd "%s" && git fetch origin && git reset --hard %s', $installDir, $rev));
+}
+
+// update?
+if ('update' === $command) {
+ $deps = array();
+ foreach (file($rootDir.'/deps') as $line) {
+ if (!trim($line)) {
+ continue;
+ }
+ $parts = array_values(array_filter(explode(' ', trim($line))));
+ if (3 !== count($parts)) {
+ die(sprintf('The deps file is not valid (near "%s")', $line));
+ }
+ list($name, $path, $url) = $parts;
+
+ ob_start();
+ system('cd "'.$vendorDir.'/'.$path.'/'.$name.'"; git log -n 1 --format=%H');
+ $deps[] = trim($name.' '.ob_get_clean());
+ }
+ file_put_contents($rootDir.'/deps.lock', implode("\n", $deps));
+}
+
+// php on windows can't use the shebang line from system()
+$interpreter = PHP_OS == 'WINNT' ? 'php.exe' : '';
+
+// Update the bootstrap files
+system(sprintf('%s "%s/bin/build_bootstrap"', $interpreter, $rootDir));
+
+// Update assets
+system(sprintf('%s "%s/app/console" assets:install "%s/web/"', $interpreter, $rootDir, $rootDir));
+
+// Remove the cache
+system(sprintf('%s "%s/app/console" cache:clear --no-warmup', $interpreter, $rootDir));
diff --git a/src/.htaccess b/src/.htaccess
new file mode 100644
index 00000000..3418e55a
--- /dev/null
+++ b/src/.htaccess
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/src/Packagist/WebBundle/Command/UpdatePackagesCommand.php b/src/Packagist/WebBundle/Command/UpdatePackagesCommand.php
new file mode 100644
index 00000000..12ac2de8
--- /dev/null
+++ b/src/Packagist/WebBundle/Command/UpdatePackagesCommand.php
@@ -0,0 +1,62 @@
+
+ * Nils Adermann
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Command;
+
+use Symfony\Bundle\FrameworkBundle\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\HttpKernel\KernelInterface;
+use Symfony\Component\Finder\Finder;
+
+/**
+ * @author Jordi Boggiano
+ */
+class UpdatePackagesCommand extends Command
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('pkg:update-packages')
+ ->setDefinition(array(
+ ))
+ ->setDescription('Updates packages')
+ ->setHelp(<<container->get('doctrine')->getEntityManager();
+
+ $qb = $em->createQueryBuilder();
+ $qb->select('p')
+ ->from('Packagist\WebBundle\Entity\Package', 'p')
+ ->where('p.status = ?1')
+ ->andWhere('p.lastUpdate IS NULL')
+ ->setParameter(1, 'active');
+
+ foreach ($qb->getQuery()->getResult() as $package) {
+ //$package->lastUpdate = new \DateTime;
+ //$em->flush();
+ }
+ }
+}
diff --git a/src/Packagist/WebBundle/Controller/ApiController.php b/src/Packagist/WebBundle/Controller/ApiController.php
new file mode 100644
index 00000000..9f6b3c9a
--- /dev/null
+++ b/src/Packagist/WebBundle/Controller/ApiController.php
@@ -0,0 +1,49 @@
+
+ * Nils Adermann
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Symfony\Component\HttpFoundation\Response;
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
+
+/**
+ * @author Jordi Boggiano
+ */
+class ApiController extends Controller
+{
+ /**
+ * @Template()
+ * @Route("/packages.json", name="packages")
+ */
+ public function packagesAction()
+ {
+ $version = $this->get('request')->query->get('version');
+
+ $packages = $this->get('doctrine')
+ ->getRepository('Packagist\WebBundle\Entity\Package')
+ ->findAll();
+
+ $data = '{';
+ $cnt = count($packages);
+ foreach ($packages as $idx => $package) {
+ $data .= '"'.$package->getName().'":'.$package->toJson();
+ if ($cnt > $idx+1) {
+ $data .= ',';
+ }
+ }
+ $data .= '}';
+
+ return new Response($data, 200, array('Content-Type' => 'application/json'));
+ }
+}
diff --git a/src/Packagist/WebBundle/Controller/WebController.php b/src/Packagist/WebBundle/Controller/WebController.php
new file mode 100644
index 00000000..9b3fa74b
--- /dev/null
+++ b/src/Packagist/WebBundle/Controller/WebController.php
@@ -0,0 +1,125 @@
+
+ * Nils Adermann
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Packagist\WebBundle\Entity\Package;
+use Packagist\WebBundle\Entity\Version;
+use Packagist\WebBundle\Form\PackageType;
+use Packagist\WebBundle\Form\VersionType;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
+
+/**
+ * @author Jordi Boggiano
+ */
+class WebController extends Controller
+{
+ /**
+ * @Template()
+ * @Route("/", name="home")
+ */
+ public function indexAction()
+ {
+ $packages = $this->get('doctrine')
+ ->getRepository('Packagist\WebBundle\Entity\Package')
+ ->findAll();
+
+ return array('packages' => $packages, 'page' => 'home');
+ }
+
+ /**
+ * @Template()
+ * @Route("/submit", name="submit")
+ */
+ public function submitPackageAction()
+ {
+ $package = new Package;
+ $form = $this->get('form.factory')->create(new PackageType, $package);
+
+ $request = $this->get('request');
+ if ($request->getMethod() == 'POST') {
+ $form->bindRequest($request);
+ if ($form->isValid()) {
+ try {
+ $em = $this->get('doctrine')->getEntityManager();
+ $em->persist($package);
+ $em->flush();
+
+ $this->get('session')->setFlash('success', $package->getName().' has been added to the package list, now go ahead and add a release!');
+ return new RedirectResponse($this->generateUrl('submit_version', array('package' => $package->getName())));
+ } catch (\PDOExceptionx $e) {
+ $this->get('session')->setFlash('error', $package->getName().' could not be saved in our database, most likely the name is already in use.');
+ }
+ }
+ }
+
+ return array('form' => $form->createView(), 'page' => 'submit');
+ }
+
+ /**
+ * @Template()
+ * @Route("/submit/{package}", name="submit_version")
+ */
+ public function submitVersionAction($package)
+ {
+ $em = $this->get('doctrine')->getEntityManager();
+
+ $pkg = $this->get('doctrine')->getRepository('Packagist\WebBundle\Entity\Package')
+ ->findOneByName($package);
+
+ if (!$pkg) {
+ throw new NotFoundHttpException('Package '.$package.' not found.');
+ }
+
+ // TODO populate with the latest version's data
+ $version = new Version;
+ $version->setEntityManager($em);
+ $version->setName($pkg->getName());
+ $version->setDescription($pkg->getDescription());
+ $form = $this->get('form.factory')->create(new VersionType, $version);
+
+ $request = $this->get('request');
+ if ($request->getMethod() == 'POST') {
+ $form->bindRequest($request);
+
+ if ($form->isValid()) {
+ try {
+ // TODO check if this is the latest version to move the latest dist-tags reference, and update the package's description perhaps
+ $pkg->addVersions($version);
+ $version->setPackage($pkg);
+ $em->persist($version);
+ $em->flush();
+
+ $this->get('session')->setFlash('success', $pkg->getName().'\'s version '.$version->getVersion().' has been added.');
+ return new RedirectResponse($this->generateUrl('home'));
+ } catch (\PDOException $e) {
+ $this->get('session')->setFlash('error', $pkg->getName().'\'s version '.$version->getVersion().' could not be saved in our database, most likely it already exists.');
+ }
+ }
+ }
+
+ return array('form' => $form->createView(), 'package' => $pkg, 'page' => 'submit');
+ }
+
+ /**
+ * @Template()
+ * @Route("/about", name="about")
+ */
+ public function aboutAction()
+ {
+ return array();
+ }
+}
diff --git a/src/Packagist/WebBundle/Entity/Package.php b/src/Packagist/WebBundle/Entity/Package.php
new file mode 100644
index 00000000..ba9da853
--- /dev/null
+++ b/src/Packagist/WebBundle/Entity/Package.php
@@ -0,0 +1,201 @@
+
+ * Nils Adermann
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * @ORM\Entity
+ * @ORM\Table(
+ * name="package",
+ * uniqueConstraints={@ORM\UniqueConstraint(name="name_idx",columns={"name"})}
+ * )
+ * @author Jordi Boggiano
+ */
+class Package
+{
+ /**
+ * @ORM\Id
+ * @ORM\Column(type="integer")
+ * @ORM\GeneratedValue(strategy="AUTO")
+ */
+ private $id;
+
+ /**
+ * Unique package name
+ *
+ * @ORM\Column
+ * @Assert\NotBlank()
+ */
+ private $name;
+
+ /**
+ * @ORM\Column(type="text", nullable="true")
+ */
+ private $description;
+
+ /**
+ * @ORM\OneToMany(targetEntity="Packagist\WebBundle\Entity\Version",mappedBy="package")
+ */
+ private $versions;
+
+// /**
+// * @ORM\ManyToMany(targetEntity="User")
+// */
+// private $maintainers;
+
+ // dist-tags / rel or runtime?
+
+ /**
+ * @ORM\Column(type="datetime")
+ */
+ private $createdAt;
+
+ /**
+ * @ORM\Column(type="datetime", nullable="true")
+ */
+ private $updatedAt;
+
+ public function __construct()
+ {
+ $this->versions = new \Doctrine\Common\Collections\ArrayCollection();
+ $this->createdAt = new \DateTime;
+ }
+
+ public function toJson()
+ {
+ $versions = array();
+ foreach ($this->versions as $version) {
+ $versions[$version->getVersion()] = $version->toArray();
+ }
+ $data = array(
+ 'name' => $this->name,
+ 'description' => $this->description,
+ 'dist-tags' => array(),
+ 'maintainers' => array(),
+ 'versions' => $versions,
+ );
+ return json_encode($data);
+ }
+
+ /**
+ * Get id
+ *
+ * @return string $id
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Set name
+ *
+ * @param string $name
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * Get name
+ *
+ * @return string $name
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Set description
+ *
+ * @param text $description
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+ }
+
+ /**
+ * Get description
+ *
+ * @return text $description
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Set createdAt
+ *
+ * @param datetime $createdAt
+ */
+ public function setCreatedAt($createdAt)
+ {
+ $this->createdAt = $createdAt;
+ }
+
+ /**
+ * Get createdAt
+ *
+ * @return datetime $createdAt
+ */
+ public function getCreatedAt()
+ {
+ return $this->createdAt;
+ }
+
+ /**
+ * Add versions
+ *
+ * @param Packagist\WebBundle\Entity\Version $versions
+ */
+ public function addVersions(\Packagist\WebBundle\Entity\Version $versions)
+ {
+ $this->versions[] = $versions;
+ }
+
+ /**
+ * Get versions
+ *
+ * @return string $versions
+ */
+ public function getVersions()
+ {
+ return $this->versions;
+ }
+
+ /**
+ * Set updatedAt
+ *
+ * @param datetime $updatedAt
+ */
+ public function setUpdatedAt($updatedAt)
+ {
+ $this->updatedAt = $updatedAt;
+ }
+
+ /**
+ * Get updatedAt
+ *
+ * @return datetime $updatedAt
+ */
+ public function getUpdatedAt()
+ {
+ return $this->updatedAt;
+ }
+}
\ No newline at end of file
diff --git a/src/Packagist/WebBundle/Entity/Tag.php b/src/Packagist/WebBundle/Entity/Tag.php
new file mode 100644
index 00000000..d498f2b2
--- /dev/null
+++ b/src/Packagist/WebBundle/Entity/Tag.php
@@ -0,0 +1,109 @@
+
+ * Nils Adermann
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * @ORM\Entity
+ * @ORM\Table(name="tag")
+ * @author Jordi Boggiano
+ */
+class Tag
+{
+ /**
+ * @ORM\Id
+ * @ORM\Column(type="integer")
+ * @ORM\GeneratedValue(strategy="AUTO")
+ */
+ private $id;
+
+ /**
+ * @ORM\Column
+ * @Assert\NotBlank()
+ */
+ private $name;
+
+ /**
+ * @ORM\ManyToMany(targetEntity="Packagist\WebBundle\Entity\Version", mappedBy="tags")
+ */
+ private $versions;
+
+ public function __construct($name = null)
+ {
+ $this->name = $name;
+ }
+
+ public static function getByName($em, $name, $create = false)
+ {
+ try {
+ $qb = $em->createQueryBuilder();
+ $qb->select('t')
+ ->from(__CLASS__, 't')
+ ->where('t.name = ?1')
+ ->setMaxResults(1)
+ ->setParameter(1, $name);
+ return $qb->getQuery()->getSingleResult();
+ } catch (\Doctrine\ORM\NoResultException $e) {
+ }
+ $tag = new self($name);
+ $em->persist($tag);
+ return $tag;
+ }
+
+ public function setId($id)
+ {
+ $this->id = $id;
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Add versions
+ *
+ * @param Packagist\WebBundle\Entity\Version $versions
+ */
+ public function addVersions(\Packagist\WebBundle\Entity\Version $versions)
+ {
+ $this->versions[] = $versions;
+ }
+
+ /**
+ * Get versions
+ *
+ * @return Doctrine\Common\Collections\Collection $versions
+ */
+ public function getVersions()
+ {
+ return $this->versions;
+ }
+
+ public function __toString()
+ {
+ return $this->name;
+ }
+}
\ No newline at end of file
diff --git a/src/Packagist/WebBundle/Entity/Version.php b/src/Packagist/WebBundle/Entity/Version.php
new file mode 100644
index 00000000..940e1c6a
--- /dev/null
+++ b/src/Packagist/WebBundle/Entity/Version.php
@@ -0,0 +1,451 @@
+
+ * Nils Adermann
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * @ORM\Entity
+ * @ORM\Table(
+ * name="package_version",
+ * uniqueConstraints={@ORM\UniqueConstraint(name="pkg_ver_idx",columns={"package_id","version"})}
+ * )
+ * @author Jordi Boggiano
+ */
+class Version
+{
+ /**
+ * @ORM\Id
+ * @ORM\Column(type="integer")
+ * @ORM\GeneratedValue(strategy="AUTO")
+ */
+ private $id;
+
+ /**
+ * @ORM\Column
+ * @Assert\NotBlank()
+ */
+ private $name;
+
+ /**
+ * @ORM\Column(type="text", nullable="true")
+ */
+ private $description;
+
+ /**
+ * @ORM\ManyToMany(targetEntity="Packagist\WebBundle\Entity\Tag", inversedBy="versions")
+ * @ORM\JoinTable(name="version_tag",
+ * joinColumns={@ORM\JoinColumn(name="version_id", referencedColumnName="id")},
+ * inverseJoinColumns={@ORM\JoinColumn(name="tag_id", referencedColumnName="id")}
+ * )
+ */
+ private $tags;
+
+ /**
+ * @ORM\ManyToOne(targetEntity="Packagist\WebBundle\Entity\Package", fetch="EAGER", inversedBy="versions")
+ * @Assert\Type(type="Packagist\WebBundle\Entity\Package")
+ */
+ private $package;
+
+ /**
+ * @ORM\Column(nullable="true")
+ * @Assert\Url()
+ */
+ private $homepage;
+
+ /**
+ * @ORM\Column
+ * @Assert\NotBlank()
+ */
+ private $version;
+
+ /**
+ * @ORM\Column(nullable="true")
+ */
+ private $license;
+
+// /**
+// * @ORM\ManyToMany(targetEntity="User")
+// */
+// private $authors;
+
+ /**
+ * JSON object of source spec
+ *
+ * @ORM\Column(type="text")
+ * @Assert\NotBlank()
+ */
+ private $source;
+
+ /**
+ * JSON object of requirements
+ *
+ * @ORM\Column(type="text", name="requires")
+ * @Assert\NotBlank()
+ */
+ private $require;
+
+// dist (later)
+
+ /**
+ * @ORM\Column(type="datetime")
+ */
+ private $createdAt;
+
+ /**
+ * @ORM\Column(type="datetime")
+ */
+ private $updatedAt;
+
+ /**
+ * @ORM\Column(type="datetime")
+ * @Assert\NotBlank()
+ */
+ private $releasedAt;
+
+ public function __construct()
+ {
+ $this->tags = new \Doctrine\Common\Collections\ArrayCollection();
+ $this->createdAt = new \DateTime;
+ $this->updatedAt = new \DateTime;
+ }
+
+ public function toArray()
+ {
+ $tags = array();
+ foreach ($this->tags as $tag) {
+ $tags[] = $tag->getName();
+ }
+ return array(
+ 'name' => $this->name,
+ 'description' => $this->description,
+ 'keywords' => $tags,
+ 'homepage' => $this->homepage,
+ 'version' => $this->version,
+ 'license' => $this->license,
+ 'authors' => array(),
+ 'require' => $this->getRequire(),
+ 'source' => $this->getSource(),
+ 'time' => $this->releasedAt->format('Y-m-d\TH:i:s'),
+ 'dist' => array(),
+ );
+ }
+
+ /**
+ * Get id
+ *
+ * @return string $id
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Set name
+ *
+ * @param string $name
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * Get name
+ *
+ * @return string $name
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Set description
+ *
+ * @param text $description
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+ }
+
+ /**
+ * Get description
+ *
+ * @return text $description
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Set homepage
+ *
+ * @param string $homepage
+ */
+ public function setHomepage($homepage)
+ {
+ $this->homepage = $homepage;
+ }
+
+ /**
+ * Get homepage
+ *
+ * @return string $homepage
+ */
+ public function getHomepage()
+ {
+ return $this->homepage;
+ }
+
+ /**
+ * Set version
+ *
+ * @param string $version
+ */
+ public function setVersion($version)
+ {
+ $this->version = ltrim($version, 'vV.');
+ }
+
+ /**
+ * Get version
+ *
+ * @return string $version
+ */
+ public function getVersion()
+ {
+ return $this->version;
+ }
+
+ /**
+ * Set license
+ *
+ * @param string $license
+ */
+ public function setLicense($license)
+ {
+ $this->license = $license;
+ }
+
+ /**
+ * Get license
+ *
+ * @return string $license
+ */
+ public function getLicense()
+ {
+ return $this->license;
+ }
+
+ /**
+ * Set source
+ *
+ * @param text $source
+ */
+ public function setSource($source)
+ {
+ if (preg_match('#^([a-z-]+) (\S+)$#', $source, $m)) {
+ $this->source = json_encode(array('type' => $m[1], 'url' => $m[2]));
+ }
+ }
+
+ /**
+ * Get source
+ *
+ * @return text $source
+ */
+ public function getSource()
+ {
+ return json_decode($this->source);
+ }
+
+ /**
+ * Set require
+ *
+ * @param text $require
+ */
+ public function setRequire($require)
+ {
+ if (preg_match_all('#^(\S+) (\S+)\r?\n?$#m', $require, $m)) {
+ $requires = array();
+ foreach ($m[1] as $idx => $package) {
+ $requires[$package] = $m[2][$idx];
+ }
+ $this->require = json_encode($requires);
+ }
+ }
+
+ /**
+ * Get require
+ *
+ * @return text $require
+ */
+ public function getRequire()
+ {
+ return json_decode($this->require);
+ }
+
+ /**
+ * Set createdAt
+ *
+ * @param datetime $createdAt
+ */
+ public function setCreatedAt($createdAt)
+ {
+ $this->createdAt = $createdAt;
+ }
+
+ /**
+ * Get createdAt
+ *
+ * @return datetime $createdAt
+ */
+ public function getCreatedAt()
+ {
+ return $this->createdAt;
+ }
+
+ /**
+ * Set releasedAt
+ *
+ * @param datetime $releasedAt
+ */
+ public function setReleasedAt($releasedAt)
+ {
+ $this->releasedAt = $releasedAt;
+ }
+
+ /**
+ * Get releasedAt
+ *
+ * @return datetime $releasedAt
+ */
+ public function getReleasedAt()
+ {
+ return $this->releasedAt;
+ }
+
+ /**
+ * Set package
+ *
+ * @param Packagist\WebBundle\Entity\Package $package
+ */
+ public function setPackage(\Packagist\WebBundle\Entity\Package $package)
+ {
+ $this->package = $package;
+ }
+
+ /**
+ * Get package
+ *
+ * @return Packagist\WebBundle\Entity\Package $package
+ */
+ public function getPackage()
+ {
+ return $this->package;
+ }
+
+ /**
+ * Add tags
+ *
+ * @param Packagist\WebBundle\Entity\Tag $tags
+ */
+ public function addTags(\Packagist\WebBundle\Entity\Tag $tags)
+ {
+ $this->tags[] = $tags;
+ }
+
+ /**
+ * Get tags
+ *
+ * @return Doctrine\Common\Collections\Collection $tags
+ */
+ public function getTags()
+ {
+ return $this->tags;
+ }
+
+ public function setTagsText($text)
+ {
+ $tags = array();
+ if (trim($text)) {
+ $tags = preg_split('#[\s,]+#', trim($text));
+ $tags = array_map(function($el) {
+ return trim(ltrim($el, '#'), '"\'');
+ }, $tags);
+ $uniqueTags = array();
+ foreach ($tags as $tag) {
+ if ($tag && !isset($uniqueTags[strtolower($tag)])) {
+ $uniqueTags[strtolower($tag)] = $tag;
+ }
+ }
+ $tags = array_values($uniqueTags);
+ }
+
+ foreach ($this->tags as $k => $tag) {
+ if (false !== ($idx = array_search($tag->getName(), $tags))) {
+ unset($tags[$idx]);
+ } else {
+ unset($this->tags[$k]);
+ }
+ }
+
+ foreach ($tags as $tag) {
+ $this->addTags($this->getTagEntity($tag));
+ }
+ }
+
+ public function setEntityManager($em)
+ {
+ $this->em = $em;
+ }
+
+ protected function getTagEntity($name)
+ {
+ return Tag::getByName($this->em, $name, true);
+ }
+
+ public function getTagsText()
+ {
+ $tags = array();
+ foreach ($this->tags as $tag) {
+ $tags[] = $tag->getName();
+ }
+ return implode(', ', $tags);
+ }
+
+ /**
+ * Set updatedAt
+ *
+ * @param datetime $updatedAt
+ */
+ public function setUpdatedAt($updatedAt)
+ {
+ $this->updatedAt = $updatedAt;
+ }
+
+ /**
+ * Get updatedAt
+ *
+ * @return datetime $updatedAt
+ */
+ public function getUpdatedAt()
+ {
+ return $this->updatedAt;
+ }
+}
\ No newline at end of file
diff --git a/src/Packagist/WebBundle/Form/PackageType.php b/src/Packagist/WebBundle/Form/PackageType.php
new file mode 100644
index 00000000..405faa18
--- /dev/null
+++ b/src/Packagist/WebBundle/Form/PackageType.php
@@ -0,0 +1,35 @@
+
+ * Nils Adermann
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Form;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilder;
+
+/**
+ * @author Jordi Boggiano
+ */
+class PackageType extends AbstractType
+{
+ public function buildForm(FormBuilder $builder, array $options)
+ {
+ $builder->add('name');
+ $builder->add('description', null, array('required' => false));
+ }
+
+ public function getDefaultOptions(array $options)
+ {
+ return array(
+ 'data_class' => 'Packagist\WebBundle\Entity\Package',
+ );
+ }
+}
diff --git a/src/Packagist/WebBundle/Form/VersionType.php b/src/Packagist/WebBundle/Form/VersionType.php
new file mode 100644
index 00000000..363db07b
--- /dev/null
+++ b/src/Packagist/WebBundle/Form/VersionType.php
@@ -0,0 +1,46 @@
+
+ * Nils Adermann
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Form;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilder;
+use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
+
+/**
+ * @author Jordi Boggiano
+ */
+class VersionType extends AbstractType
+{
+ public function buildForm(FormBuilder $builder, array $options)
+ {
+ $builder->add('description');
+ $builder->add('version', null);
+ $builder->add('homepage', 'url', array('required' => false));
+ $builder->add('tagsText', 'text');
+ $builder->add('license', null, array('required' => false));
+ $builder->add('source', 'text', array('required' => false));
+ $builder->add('require', null, array('required' => false));
+ $builder->add('releasedAt', 'datetime', array('date_widget' => 'text', 'time_widget' => 'text'));
+ $builder->add(
+ $builder->create('releasedAt', 'text')
+ ->appendClientTransformer(new DateTimeToStringTransformer(null, null, 'Y-m-d H:i:s'))
+ );
+ }
+
+ public function getDefaultOptions(array $options)
+ {
+ return array(
+ 'data_class' => 'Packagist\WebBundle\Entity\Version',
+ );
+ }
+}
diff --git a/src/Packagist/WebBundle/PackagistWebBundle.php b/src/Packagist/WebBundle/PackagistWebBundle.php
new file mode 100644
index 00000000..f911a4f3
--- /dev/null
+++ b/src/Packagist/WebBundle/PackagistWebBundle.php
@@ -0,0 +1,22 @@
+
+ * Nils Adermann
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * @author Jordi Boggiano
+ */
+class PackagistWebBundle extends Bundle
+{
+}
diff --git a/src/Packagist/WebBundle/Resources/config/routing.yml b/src/Packagist/WebBundle/Resources/config/routing.yml
new file mode 100644
index 00000000..404c3bd0
--- /dev/null
+++ b/src/Packagist/WebBundle/Resources/config/routing.yml
@@ -0,0 +1,3 @@
+#homepage:
+# pattern: /
+# defaults: { _controller: PackagistWebBundle:Default:index }
diff --git a/src/Packagist/WebBundle/Resources/public/css/main.css b/src/Packagist/WebBundle/Resources/public/css/main.css
new file mode 100644
index 00000000..6b6e0559
--- /dev/null
+++ b/src/Packagist/WebBundle/Resources/public/css/main.css
@@ -0,0 +1,281 @@
+/* HTML5 ✰ Boilerplate */
+
+html, body, div, span, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp,
+small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+
+blockquote, q { quotes: none; }
+blockquote:before, blockquote:after,
+q:before, q:after { content: ''; content: none; }
+ins { background-color: #ff9; color: #000; text-decoration: none; }
+mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; }
+del { text-decoration: line-through; }
+abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; }
+table { border-collapse: collapse; border-spacing: 0; }
+hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
+input, select { vertical-align: middle; }
+
+body { font:13px/1.231 sans-serif; *font-size:small; }
+select, input, textarea, button { font:99% sans-serif; }
+pre, code, kbd, samp { font-family: monospace, sans-serif; }
+
+html { overflow-y: scroll; }
+a:hover, a:active { outline: none; }
+ul, ol { margin-left: 2em; }
+ol { list-style-type: decimal; }
+nav ul, nav li { margin: 0; list-style:none; list-style-image: none; }
+small { font-size: 85%; }
+strong, th { font-weight: bold; }
+td { vertical-align: top; }
+
+sub, sup { font-size: 75%; line-height: 0; position: relative; }
+sup { top: -0.5em; }
+sub { bottom: -0.25em; }
+
+pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; padding: 15px; }
+textarea { overflow: auto; }
+.ie6 legend, .ie7 legend { margin-left: -7px; }
+input[type="radio"] { vertical-align: text-bottom; }
+input[type="checkbox"] { vertical-align: bottom; }
+.ie7 input[type="checkbox"] { vertical-align: baseline; }
+.ie6 input { vertical-align: text-bottom; }
+label, input[type="button"], input[type="submit"], input[type="image"], button { cursor: pointer; }
+button, input, select, textarea { margin: 0; }
+.no-boxshadow input:invalid, .no-boxshadow textarea:invalid { background-color: #f0dddd; }
+
+::-moz-selection{ background: #ffba53; color:#000; text-shadow: none; }
+::selection { background:#ffba53; color:#000; text-shadow: none; }
+a:link { -webkit-tap-highlight-color: #ffba53; }
+
+button { width: auto; overflow: visible; }
+.ie7 img { -ms-interpolation-mode: bicubic; }
+
+body, select, input, textarea { color: #444; }
+h1, h2, h3, h4, h5, h6 { font-weight: bold; }
+
+/*
+ // ========================================== \\
+ || ||
+ || Your styles ! ||
+ || ||
+ \\ ========================================== //
+*/
+
+body {
+ background: #888;
+ font-size: 15px;
+ font-family: "PT Sans", sans-serif;
+ color: #555;
+}
+
+a, a:active, a:visited {
+ color: #fb9700;
+ text-decoration: none;
+}
+a:hover {
+ color: #c67700;
+}
+
+.container {
+ width: 900px;
+ background: #fff;
+ margin: auto;
+ padding: 20px 40px 40px;
+}
+
+header h1 {
+ font-size: 50px;
+ margin-top: 0;
+ font-family: "Neuton", serif;
+}
+
+header h2 {
+ font-size: 30px;
+ margin: 10px 0;
+}
+
+header p {
+ font-size: 20px;
+}
+
+header a {
+ text-shadow: 0 1px 0 #bf7300;
+}
+
+header a:hover {
+ text-shadow: 0 1px 0 #663e00;
+}
+
+header {
+ margin-bottom: 20px;
+ font-size: 15px;
+}
+
+.flash-message {
+ font-size: 20px;
+ margin: 20px 0;
+}
+
+.flash-message.success {
+ color: #519f1c;
+}
+.flash-message.error {
+ color: #a21a1a;
+}
+
+.betawarn {
+ border: 1px solid #cc0;
+ background: #ffa;
+ padding: 10px;
+ border-radius: 5px;
+}
+
+.submit, .submit:active, .submit:visited, input[type="submit"] {
+ font-size: 22px;
+ font-family: "Neuton";
+ float: right;
+ background: #64c523;
+ display: block;
+ padding: 9px 20px 12px;
+ color: #fff;
+ margin-top: 10px;
+ text-decoration: none;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+ border: 1px solid #519f1c;
+ box-shadow: 0 0 5px rgba(0, 0, 0, .2);
+}
+
+.submit:hover {
+ color: #fff;
+ background: #53a51d;
+}
+
+.main h1 {
+ font-size: 30px;
+}
+
+.main h2 {
+ font-size: 23px;
+}
+
+label {
+ display: block;
+ margin: 20px 0 10px;
+}
+
+input, textarea {
+ width: 400px;
+}
+
+textarea {
+ resize: vertical;
+}
+
+input[type="submit"] {
+ width: 406px;
+ float: none;
+}
+
+form ul {
+ color: #c00;
+ list-style: none;
+ margin: 10px 0;
+}
+
+.package {
+ margin: 15px 0;
+}
+.package h2 {
+ float: left;
+ font-size: 25px;
+ margin-bottom: 5px;
+}
+.package .summary {
+ font-weight: normal;
+ font-size: 20px;
+ position: relative;
+ left: 10px;
+ top: 5px;
+}
+.package .description {
+ clear: left;
+}
+.package .links a {
+ display: block;
+}
+
+pre {
+ background: #ddd;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+ display: block;
+ padding: 5px;
+ margin: 10px 0;
+}
+
+/*
+ // ========================================== \\
+ || ||
+ || Finito ! ||
+ || ||
+ \\ ========================================== //
+*/
+
+.ir { display: block; text-indent: -999em; overflow: hidden; background-repeat: no-repeat; text-align: left; direction: ltr; }
+.hidden { display: none; visibility: hidden; }
+.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
+.visuallyhidden.focusable:active,
+.visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }
+.invisible { visibility: hidden; }
+.clearfix:before, .clearfix:after { content: "\0020"; display: block; height: 0; overflow: hidden; }
+.clearfix:after { clear: both; }
+.clearfix { zoom: 1; }
+
+@media all and (orientation:portrait) {
+
+}
+
+@media all and (orientation:landscape) {
+
+}
+
+@media screen and (max-device-width: 480px) {
+
+ /* html { -webkit-text-size-adjust:none; -ms-text-size-adjust:none; } */
+}
+
+@media print {
+ * { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important;
+ -ms-filter: none !important; }
+ a, a:visited { color: #444 !important; text-decoration: underline; }
+ a[href]:after { content: " (" attr(href) ")"; }
+ abbr[title]:after { content: " (" attr(title) ")"; }
+ .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }
+ pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
+ thead { display: table-header-group; }
+ tr, img { page-break-inside: avoid; }
+ @page { margin: 0.5cm; }
+ p, h2, h3 { orphans: 3; widows: 3; }
+ h2, h3{ page-break-after: avoid; }
+}
\ No newline at end of file
diff --git a/src/Packagist/WebBundle/Resources/public/js/main.js b/src/Packagist/WebBundle/Resources/public/js/main.js
new file mode 100644
index 00000000..e69de29b
diff --git a/src/Packagist/WebBundle/Resources/views/Web/index.html.twig b/src/Packagist/WebBundle/Resources/views/Web/index.html.twig
new file mode 100644
index 00000000..9bb7abf2
--- /dev/null
+++ b/src/Packagist/WebBundle/Resources/views/Web/index.html.twig
@@ -0,0 +1,19 @@
+{% extends "PackagistWebBundle::layout.html.twig" %}
+
+{% block content %}
+
Packagist is the main Composer repository. It aggregates all sorts of PHP libraries that are installable with Composer. Browse packages below and if you have some open-source lib submit it!