├── .gitignore ├── .php_cs ├── .php_cs.cache ├── .travis.yml ├── INSTALLATION.md ├── LICENSE ├── README.md ├── app ├── AppCache.php ├── AppKernel.php ├── Resources │ ├── FOSUserBundle │ │ └── views │ │ │ └── Security │ │ │ └── login.html.twig │ ├── TwigBundle │ │ └── views │ │ │ └── Exception │ │ │ ├── error404.html.twig │ │ │ └── error500.html.twig │ ├── public │ │ ├── css │ │ │ └── packy.css │ │ └── js │ │ │ └── packy.js │ └── views │ │ ├── base.html.twig │ │ ├── base_clean.html.twig │ │ ├── form.html.twig │ │ ├── macro.html.twig │ │ └── menu.html.twig ├── autoload.php ├── config │ ├── config.yml │ ├── config_dev.yml │ ├── config_prod.yml │ ├── config_test.yml │ ├── parameters.yml.dist │ ├── routing.yml │ ├── routing_dev.yml │ ├── security.yml │ └── services.yml └── migrations │ ├── Version20150414184644.php │ ├── Version20150414194738.php │ ├── Version20150414194741.php │ ├── Version20150827220301.php │ └── Version20170712084447.php ├── bin └── console ├── composer.json ├── composer.lock ├── grumphp.yml ├── package.json ├── phpcs.ruleset.xml ├── src └── AppBundle │ ├── AppBundle.php │ ├── Command │ ├── InstallCommand.php │ ├── PackageUpdateCommand.php │ ├── ProjectUpdateCommand.php │ └── ReinstallCommand.php │ ├── Controller │ ├── ProfileController.php │ ├── ProjectController.php │ └── UserController.php │ ├── DependencyInjection │ ├── AppExtension.php │ └── Compiler │ │ ├── DependencyManagerCompilerPass.php │ │ ├── PackageManagerCompilerPass.php │ │ └── RepositoryManagerCompilerPass.php │ ├── DependencyManager │ ├── Composer.php │ ├── DependencyManager.php │ ├── DependencyManagers.php │ ├── Npm.php │ └── Pip.php │ ├── Entity │ ├── Dependency.php │ ├── Package.php │ ├── Project.php │ └── User.php │ ├── Form │ └── Type │ │ ├── ChangePasswordType.php │ │ ├── ProjectFormType.php │ │ └── UserFormType.php │ ├── Menu │ ├── Builder.php │ └── Voter │ │ └── RouteVoter.php │ ├── PackageManager │ ├── PackageManager.php │ ├── PackageManagers.php │ ├── Packagist.php │ ├── Pypi.php │ └── Registry.php │ ├── Repository │ ├── DependencyRepository.php │ ├── PackageRepository.php │ ├── ProjectRepository.php │ └── UserRepository.php │ ├── RepositoryManager │ ├── Bitbucket.php │ ├── Github.php │ ├── Gitlab.php │ ├── RepositoryManager.php │ └── RepositoryManagers.php │ ├── Resources │ ├── config │ │ ├── doctrine │ │ │ ├── Dependency.orm.yml │ │ │ ├── Package.orm.yml │ │ │ ├── Project.orm.yml │ │ │ └── User.orm.yml │ │ ├── routing.yml │ │ ├── routing │ │ │ ├── profile.yml │ │ │ ├── project.yml │ │ │ └── user.yml │ │ ├── service │ │ │ ├── dependency_managers.yml │ │ │ ├── package_managers.yml │ │ │ ├── repository.yml │ │ │ ├── repository_managers.yml │ │ │ └── service.yml │ │ └── validation.yml │ └── views │ │ ├── Profile │ │ └── change_password.html.twig │ │ ├── Project │ │ ├── analyze.html.twig │ │ ├── form.html.twig │ │ └── overview.html.twig │ │ └── User │ │ ├── form.html.twig │ │ └── overview.html.twig │ └── Service │ └── VersionFormatter.php ├── var ├── cache │ └── .gitkeep ├── logs │ └── .gitkeep └── sessions │ └── .gitkeep ├── web ├── .htaccess ├── app.php ├── app_dev.php ├── favicon.ico └── robots.txt ├── webpack.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /.web-server-pid 2 | /app/config/parameters.yml 3 | /build/ 4 | /phpunit.xml 5 | /var/* 6 | !/var/cache 7 | /var/cache/* 8 | !var/cache/.gitkeep 9 | !/var/logs 10 | /var/logs/* 11 | !var/logs/.gitkeep 12 | !/var/sessions 13 | /var/sessions/* 14 | !var/sessions/.gitkeep 15 | /vendor/ 16 | /web/bundles/ 17 | /node_modules/ 18 | Capfile 19 | /app/config/deploy.rb 20 | .idea/ 21 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | in(__DIR__ . '/src') 5 | ; 6 | 7 | return PhpCsFixer\Config::create() 8 | ->setRules([ 9 | '@PSR2' => true, 10 | '@Symfony' => true, 11 | '@Symfony:risky' => true, 12 | 'array_syntax' => ['syntax' => 'short'], 13 | 'blank_line_after_opening_tag' => false, 14 | 'class_definition' => ['singleLine' => false], 15 | 'concat_space' => ['spacing' => 'one'], 16 | 'mb_str_functions' => true, 17 | 'no_unused_imports' => true, 18 | 'ordered_class_elements' => true, 19 | 'ordered_imports' => ['sortAlgorithm' => 'alpha'], 20 | 'phpdoc_no_empty_return' => false, 21 | ]) 22 | ->setRiskyAllowed(true) 23 | ->setFinder($finder) 24 | ; 25 | -------------------------------------------------------------------------------- /.php_cs.cache: -------------------------------------------------------------------------------- 1 | {"php":"7.1.2","version":"2.3.2:v2.3.2#597745f744bcce1aed59dfd1bb4603de2a06cda9","rules":{"blank_line_after_namespace":true,"braces":{"allow_single_line_closure":true},"class_definition":{"singleLine":false},"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_constants":true,"lowercase_keywords":true,"method_argument_space":true,"no_closing_tag":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":true,"single_import_per_statement":true,"single_line_after_imports":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":true,"encoding":true,"full_opening_tag":true,"binary_operator_spaces":{"align_double_arrow":false,"align_equals":false},"blank_line_before_return":true,"cast_spaces":true,"concat_space":{"spacing":"one"},"declare_equal_normalize":true,"function_typehint_space":true,"hash_to_slash_comment":true,"include":true,"lowercase_cast":true,"magic_constant_casing":true,"method_separation":true,"native_function_casing":true,"new_with_braces":true,"no_blank_lines_after_class_opening":true,"no_blank_lines_after_phpdoc":true,"no_empty_comment":true,"no_empty_phpdoc":true,"no_empty_statement":true,"no_extra_consecutive_blank_lines":{"tokens":["curly_brace_block","extra","parenthesis_brace_block","square_brace_block","throw","use"]},"no_leading_import_slash":true,"no_leading_namespace_whitespace":true,"no_mixed_echo_print":{"use":"echo"},"no_multiline_whitespace_around_double_arrow":true,"no_short_bool_cast":true,"no_singleline_whitespace_before_semicolons":true,"no_spaces_around_offset":true,"no_trailing_comma_in_list_call":true,"no_trailing_comma_in_singleline_array":true,"no_unneeded_control_parentheses":true,"no_unused_imports":true,"no_whitespace_before_comma_in_array":true,"no_whitespace_in_blank_line":true,"normalize_index_brace":true,"object_operator_without_whitespace":true,"php_unit_fqcn_annotation":true,"phpdoc_align":true,"phpdoc_annotation_without_dot":true,"phpdoc_indent":true,"phpdoc_inline_tag":true,"phpdoc_no_access":true,"phpdoc_no_alias_tag":true,"phpdoc_no_package":true,"phpdoc_no_useless_inheritdoc":true,"phpdoc_return_self_reference":true,"phpdoc_scalar":true,"phpdoc_separation":true,"phpdoc_single_line_var_spacing":true,"phpdoc_summary":true,"phpdoc_to_comment":true,"phpdoc_trim":true,"phpdoc_types":true,"phpdoc_var_without_name":true,"pre_increment":true,"protected_to_private":true,"return_type_declaration":true,"self_accessor":true,"short_scalar_cast":true,"single_blank_line_before_namespace":true,"single_quote":true,"space_after_semicolon":true,"standardize_not_equals":true,"ternary_operator_spaces":true,"trailing_comma_in_multiline_array":true,"trim_array_spaces":true,"unary_operator_spaces":true,"whitespace_after_comma_in_array":true,"dir_constant":true,"ereg_to_preg":true,"function_to_constant":true,"is_null":true,"modernize_types_casting":true,"no_alias_functions":true,"non_printable_character":true,"php_unit_construct":true,"php_unit_dedicate_assert":true,"psr4":true,"silenced_deprecation_error":true,"array_syntax":{"syntax":"short"},"mb_str_functions":true,"ordered_class_elements":true,"ordered_imports":{"sortAlgorithm":"alpha"}},"hashes":{"src\/\/AppBundle\/Analyzer\/AnalyzerFactory.php":175953298,"src\/\/AppBundle\/Analyzer\/AnalyzerInterface.php":3692825834,"src\/\/AppBundle\/Analyzer\/ComposerAnalyzer.php":627921770,"src\/\/AppBundle\/Analyzer\/GenericAnalyzer.php":2065276909,"src\/\/AppBundle\/Analyzer\/NpmAnalyzer.php":640811879,"src\/\/AppBundle\/Analyzer\/PipAnalyzer.php":513704983,"src\/\/AppBundle\/AppBundle.php":585545203,"src\/\/AppBundle\/Command\/InstallCommand.php":4270481875,"src\/\/AppBundle\/Command\/PackageUpdateCommand.php":1492287218,"src\/\/AppBundle\/Command\/ProjectUpdateCommand.php":176818330,"src\/\/AppBundle\/Command\/ReinstallCommand.php":2743311376,"src\/\/AppBundle\/Controller\/ProfileController.php":3074672258,"src\/\/AppBundle\/Controller\/ProjectController.php":1618887373,"src\/\/AppBundle\/Controller\/UserController.php":1610100230,"src\/\/AppBundle\/DependencyInjection\/AppExtension.php":3394005274,"src\/\/AppBundle\/DependencyInjection\/Compiler\/FetcherCompilerPass.php":90043247,"src\/\/AppBundle\/Entity\/Dependency.php":3242902625,"src\/\/AppBundle\/Entity\/Package.php":3092259190,"src\/\/AppBundle\/Entity\/Project.php":433111830,"src\/\/AppBundle\/Entity\/User.php":2171921688,"src\/\/AppBundle\/Fetcher\/AbstractFetcher.php":626918637,"src\/\/AppBundle\/Fetcher\/ComposerFetcher.php":3579430318,"src\/\/AppBundle\/Fetcher\/FetcherInterface.php":569812645,"src\/\/AppBundle\/Fetcher\/Fetchers.php":3076414014,"src\/\/AppBundle\/Fetcher\/NpmFetcher.php":1110549934,"src\/\/AppBundle\/Fetcher\/PipFetcher.php":276571500,"src\/\/AppBundle\/Form\/Type\/ChangePasswordType.php":551509831,"src\/\/AppBundle\/Form\/Type\/ProjectFormType.php":1765003039,"src\/\/AppBundle\/Form\/Type\/UserFormType.php":1175908207,"src\/\/AppBundle\/Manager\/AdapterFactory.php":1535403116,"src\/\/AppBundle\/Manager\/AdapterInterface.php":3926076575,"src\/\/AppBundle\/Manager\/BitbucketAdapter.php":3719422151,"src\/\/AppBundle\/Manager\/GithubAdapter.php":3106698339,"src\/\/AppBundle\/Manager\/GitlabAdapter.php":3062094415,"src\/\/AppBundle\/Menu\/Builder.php":2726949383,"src\/\/AppBundle\/Menu\/Voter\/RouteVoter.php":264807107,"src\/\/AppBundle\/Repository\/DependencyRepository.php":9256868,"src\/\/AppBundle\/Repository\/PackageRepository.php":1521133676,"src\/\/AppBundle\/Repository\/ProjectRepository.php":2108230989,"src\/\/AppBundle\/Repository\/UserRepository.php":1290641377,"src\/\/AppBundle\/Service\/VersionFormatter.php":812087240}} -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.0 5 | - 7.1 6 | 7 | branches: 8 | only: 9 | - master 10 | 11 | before_script: 12 | - cp app/config/parameters.yml.dist app/config/parameters.yml 13 | - composer self-update 14 | - composer install --no-interaction --dev 15 | - php bin/console doctrine:database:create --env=test > /dev/null 16 | - php bin/console doctrine:schema:create --env=test > /dev/null 17 | 18 | script: 19 | # - phpunit --coverage-text --coverage-clover ./clover.xml 20 | # - wget https://scrutinizer-ci.com/ocular.phar 21 | # - php ocular.phar code-coverage:upload --format=php-clover ./clover.xml 22 | - find -L 'src' -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l 23 | - php bin/console lint:yaml src app 24 | - php bin/console lint:twig src app 25 | - php bin/console doctrine:schema:validate 26 | - php vendor/bin/php-cs-fixer --dry-run fix src/ 27 | - php vendor/bin/phpstan analyse src --level 1 28 | -------------------------------------------------------------------------------- /INSTALLATION.md: -------------------------------------------------------------------------------- 1 | Production Installation 2 | ===== 3 | - Point Apache/NGINX to web/app.php 4 | - install npm dependencies `npm install` 5 | - run `./node_modules/.bin/encore prod` to get assets 6 | - Run `composer install` to install php dependencies 7 | - Run `php bin/console packy:install --env=prod` to install Packy 8 | - Set a cronjob for `php bin/console packy:project:update --env=prod` and `bin/console packy:package:update --env=prod` 9 | 10 | Development Installation 11 | ===== 12 | - Point Apache/NGINX to web/ 13 | - install npm dependencies `npm install` 14 | - run `./node_modules/.bin/encore dev` to get assets 15 | - Run `composer install` to install php dependencies 16 | - Make sure a database connection has been set in `app/config/parameters.yml` 17 | - Run `php bin/console packy:install` 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Packy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Packy 2 | ==== 3 | 4 | [![Author](http://img.shields.io/badge/author-@ptnijssen-blue.svg?style=flat-square)](https://twitter.com/ptnijssen) 5 | [![Build Status](https://img.shields.io/travis/peternijssen/packy/master.svg?style=flat-square)](https://travis-ci.org/peternijssen/packy) 6 | [![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/peternijssen/packy.svg?style=flat-square)](https://scrutinizer-ci.com/g/peternijssen/packy/code-structure) 7 | [![Quality Score](https://img.shields.io/scrutinizer/g/peternijssen/packy.svg?style=flat-square)](https://scrutinizer-ci.com/g/peternijssen/packy) 8 | [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) 9 | [![Packagist Version](https://img.shields.io/packagist/v/peternijssen/packy.svg?style=flat-square)](https://packagist.org/packages/peternijssen/packy) 10 | [![Total Downloads](https://img.shields.io/packagist/dt/peternijssen/packy.svg?style=flat-square)](https://packagist.org/packages/peternijssen/packy) 11 | [![SensioLabsInsight](https://insight.sensiolabs.com/projects/d43bceaf-afaa-48fd-99ce-52cb437e5d73/mini.png)](https://insight.sensiolabs.com/projects/d43bceaf-afaa-48fd-99ce-52cb437e5d73) 12 | 13 | **Description** 14 | 15 | Packy is an open source tool to validate if your dependencies are up 2 date. 16 | 17 | **Current analyzers** 18 | - Composer 19 | - Npm 20 | - Pip 21 | - Yarn 22 | 23 | **Current managers** 24 | - Github 25 | 26 | **In development** 27 | - Bitbucket 28 | - Gitlab 29 | 30 | Screenshots 31 | ===== 32 | 33 | ![Packy](http://i60.tinypic.com/2mgtxdj.png) 34 | 35 | ![Packy](http://i61.tinypic.com/x4q4ao.png) 36 | 37 | ![Packy](http://i61.tinypic.com/2zqv695.png) 38 | 39 | 40 | Usage 41 | ===== 42 | 43 | You can use packy by logging in with your created admin account. After logging in, you can create a project. To check the project for it's dependencies and to check if the dependencies are up 2 date, run `bin/console packy:project:update`. 44 | If you only want to check if there are new versions of packages, you can run `bin/console packy:package:update` 45 | 46 | 47 | Contributing 48 | ===== 49 | 50 | Thanks for considering to contribute. You can contribute by creating pull requests or report issues. 51 | 52 | Translating 53 | ===== 54 | 55 | Currently, no language files have been created. Feel free to help out. When done, translating Packy will become possible. 56 | 57 | Authors 58 | ===== 59 | 60 | Packy was originally created by [Peter Nijssen](https://www.peternijssen.nl). 61 | See the list of [contributors](https://github.com/peternijssen/packy/graphs/contributors). 62 | 63 | The theme is named [AdminLTE](https://github.com/almasaeed2010/AdminLTE) and is created by [Almsaeed Studio](http://www.almsaeedstudio.com/). 64 | -------------------------------------------------------------------------------- /app/AppCache.php: -------------------------------------------------------------------------------- 1 | getEnvironment(), array('dev', 'test'))) { 27 | $bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle(); 28 | $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); 29 | $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); 30 | $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); 31 | } 32 | 33 | return $bundles; 34 | } 35 | 36 | public function getRootDir() 37 | { 38 | return __DIR__; 39 | } 40 | 41 | public function getCacheDir() 42 | { 43 | return dirname(__DIR__).'/var/cache/'.$this->getEnvironment(); 44 | } 45 | 46 | public function getLogDir() 47 | { 48 | return dirname(__DIR__).'/var/logs'; 49 | } 50 | 51 | public function registerContainerConfiguration(LoaderInterface $loader) 52 | { 53 | $loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml'); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Security/login.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '::base_clean.html.twig' %} 2 | 3 | {% block content %} 4 | 5 |
6 | 9 |
10 | 11 |
12 | {% if error %} 13 |
14 | 15 | 16 | {{ error.messageKey|trans(error.messageData, 'security') }} 17 |
18 | {% endif %} 19 |
20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 |
28 |
29 |
30 | 31 |
32 |
33 | 34 | 35 |
36 |
37 |
38 | {% endblock %} 39 | -------------------------------------------------------------------------------- /app/Resources/TwigBundle/views/Exception/error404.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '::base.html.twig' %} 2 | 3 | {% block title %}An Error Occurred: {{ status_text }}{% endblock %} 4 | 5 | {% block content %} 6 |
7 |

404

8 |
9 |

Oops! Page not found.

10 |

11 | We could not find the page you were looking for. 12 | Meanwhile, you may return to the homepage. 13 |

14 |
15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /app/Resources/TwigBundle/views/Exception/error500.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '::base.html.twig' %} 2 | 3 | {% block title %}An Error Occurred: {{ status_text }}{% endblock %} 4 | 5 | {% block content %} 6 |
7 |

500

8 |
9 |

Oops! Something went wrong.

10 |

11 | We will work on fixing that right away. 12 | Meanwhile, you may return to the homepage. 13 |

14 |
15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /app/Resources/public/css/packy.css: -------------------------------------------------------------------------------- 1 | .nav-tabs-custom > .nav-tabs > li.active { 2 | border-top-color: #605ca8; 3 | } 4 | 5 | .dropdown-menu > li > a.delete:hover { 6 | background-color: #dd4b39; 7 | color: #FFFFFF; 8 | } 9 | 10 | .main-footer a { 11 | color: #000; 12 | } 13 | 14 | .box.box-solid.box-purple { 15 | border: 1px solid #605ca8; 16 | } 17 | 18 | .box.box-purple { 19 | border-top-color: #605ca8; 20 | } 21 | 22 | .box.box-solid.box-purple>.box-header { 23 | color: #FFF; 24 | background-color: #605ca8; 25 | } -------------------------------------------------------------------------------- /app/Resources/public/js/packy.js: -------------------------------------------------------------------------------- 1 | import '../css/packy.css'; 2 | 3 | // require jQuery normally 4 | const $ = require('jquery'); 5 | 6 | // create global $ and jQuery variables 7 | global.$ = global.jQuery = $; 8 | 9 | 10 | const Highcharts = require('highcharts'); 11 | require('highcharts/modules/exporting')(Highcharts); 12 | 13 | global.Highcharts = Highcharts; 14 | -------------------------------------------------------------------------------- /app/Resources/views/base.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}Packy{% endblock %} 6 | {% block stylesheets %} 7 | 8 | 9 | {% endblock %} 10 | 11 | 12 | 13 | 14 |
15 |
16 | 19 | 64 |
65 |
66 | 72 | 73 |
74 |
75 | {% block headerContent %} 76 | {% endblock %} 77 |
78 | 79 |
80 | {% block content %} 81 | {% endblock %} 82 |
83 |
84 | 85 | 91 |
92 |
93 | 94 | {% block javascripts %} 95 | 96 | 97 | 98 | 124 | {% endblock %} 125 | 126 | 127 | -------------------------------------------------------------------------------- /app/Resources/views/base_clean.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}Packy{% endblock %} 6 | {% block stylesheets %} 7 | 8 | 9 | {% endblock %} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {% block content %} 18 | {% endblock %} 19 | 20 | {% block javascripts %} 21 | 22 | 23 | 24 | {% endblock %} 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/Resources/views/form.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "bootstrap_3_layout.html.twig" %} 2 | 3 | {% block form_row %} 4 | {% spaceless %} 5 |
6 | {{ form_label(form) }} 7 | {{ form_widget(form) }} 8 | {{ form_errors(form) }} 9 |
10 | {% endspaceless %} 11 | {% endblock form_row %} 12 | 13 | {% block form_widget_simple %} 14 | {% spaceless %} 15 | {% set type = type|default('text') %} 16 | {% set attr = attr|merge({ 'class': (attr.class|default('') ~ ' form-control')|trim }) %} 17 | 18 | {% endspaceless %} 19 | {% endblock form_widget_simple %} 20 | 21 | {% block choice_widget_collapsed %} 22 | {% spaceless %} 23 | {% set attr = attr|merge({ 'class': (attr.class|default('') ~ ' form-control')|trim }) %} 24 | 25 | 39 | {% endspaceless %} 40 | {% endblock choice_widget_collapsed %} 41 | 42 | {% block choice_widget_options %} 43 | {% spaceless %} 44 | {% for group_label, choice in options %} 45 | {% if choice is iterable %} 46 | 47 | {% set options = choice %} 48 | {{ block('choice_widget_options') }} 49 | 50 | {% else %} 51 | 52 | {% endif %} 53 | {% endfor %} 54 | {% endspaceless %} 55 | {% endblock choice_widget_options %} 56 | 57 | {% block textarea_widget %} 58 | {% spaceless %} 59 | {% set attr = attr|merge({ 'class': (attr.class|default('') ~ ' form-control')|trim }) %} 60 | 61 | {% endspaceless %} 62 | {% endblock textarea_widget %} 63 | 64 | {% block form_errors %} 65 | {% spaceless %} 66 | {% if errors|length > 0 %} 67 | {% for error in errors %} 68 | 69 | {% endfor %} 70 | {% endif %} 71 | {% endspaceless %} 72 | {% endblock form_errors %} 73 | -------------------------------------------------------------------------------- /app/Resources/views/macro.html.twig: -------------------------------------------------------------------------------- 1 | {% macro statusLabel(version, status) %} 2 | {% if status == 'stable' %} 3 | {{ version }} 4 | {% elseif status == 'outdated' %} 5 | {{ version }} 6 | {% elseif status == 'unstable' %} 7 | {{ version }} 8 | {% endif %} 9 | {% endmacro %} 10 | -------------------------------------------------------------------------------- /app/Resources/views/menu.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'knp_menu.html.twig' %} 2 | 3 | {% block linkElement %} 4 | {% import 'knp_menu.html.twig' as knp_menu %} 5 | 6 | {% if item.extras.icon is defined %}{% endif %} 7 | {{ block('label') }} 8 | {% if item.hasChildren() %} 9 | 10 | {% endif %} 11 | 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /app/autoload.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('CREATE TABLE project ( 22 | id INT AUTO_INCREMENT NOT NULL, 23 | name VARCHAR(150) NOT NULL, 24 | description LONGTEXT DEFAULT NULL, 25 | repository_url VARCHAR(255) NOT NULL, 26 | repository_type VARCHAR(50) NOT NULL, 27 | vendor_name VARCHAR(50) NOT NULL, 28 | package_name VARCHAR(50) NOT NULL, 29 | created_at DATETIME NOT NULL, 30 | updated_at DATETIME NOT NULL, 31 | deleted_at DATETIME DEFAULT NULL, 32 | PRIMARY KEY(id) 33 | ) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'); 34 | } 35 | 36 | /** 37 | * @param Schema $schema 38 | */ 39 | public function down(Schema $schema) 40 | { 41 | // this down() migration is auto-generated, please modify it to your needs 42 | $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 43 | 44 | $this->addSql('DROP TABLE project'); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/migrations/Version20150414194738.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('CREATE TABLE user ( 22 | id INT AUTO_INCREMENT NOT NULL, 23 | first_name VARCHAR(255) DEFAULT NULL, 24 | last_name VARCHAR(255) DEFAULT NULL, 25 | username VARCHAR(255) NOT NULL, 26 | username_canonical VARCHAR(255) NOT NULL, 27 | email VARCHAR(255) NOT NULL, 28 | email_canonical VARCHAR(255) NOT NULL, 29 | enabled TINYINT(1) NOT NULL, 30 | salt VARCHAR(255) NOT NULL, 31 | password VARCHAR(255) NOT NULL, 32 | last_login DATETIME DEFAULT NULL, 33 | locked TINYINT(1) NOT NULL, 34 | expired TINYINT(1) NOT NULL, 35 | expires_at DATETIME DEFAULT NULL, 36 | confirmation_token VARCHAR(255) DEFAULT NULL, 37 | password_requested_at DATETIME DEFAULT NULL, 38 | roles LONGTEXT NOT NULL COMMENT \'(DC2Type:array)\', 39 | credentials_expired TINYINT(1) NOT NULL, 40 | credentials_expire_at DATETIME DEFAULT NULL, 41 | created_at DATETIME NOT NULL, 42 | updated_at DATETIME NOT NULL, 43 | deleted_at DATETIME DEFAULT NULL, 44 | UNIQUE INDEX UNIQ_8D93D64992FC23A8 (username_canonical), 45 | UNIQUE INDEX UNIQ_8D93D649A0D96FBF (email_canonical), 46 | PRIMARY KEY(id) 47 | ) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'); 48 | } 49 | 50 | /** 51 | * @param Schema $schema 52 | */ 53 | public function down(Schema $schema) 54 | { 55 | // this down() migration is auto-generated, please modify it to your needs 56 | $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 57 | 58 | $this->addSql('DROP TABLE user'); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/migrations/Version20150414194741.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('CREATE TABLE dependency ( 22 | id INT AUTO_INCREMENT NOT NULL, 23 | project_id INT DEFAULT NULL, 24 | package_id INT DEFAULT NULL, 25 | raw_version LONGTEXT DEFAULT NULL, 26 | current_version LONGTEXT DEFAULT NULL, 27 | created_at DATETIME NOT NULL, 28 | updated_at DATETIME NOT NULL, 29 | INDEX IDX_2F585505166D1F9C (project_id), 30 | INDEX IDX_2F585505F44CABFF (package_id), 31 | PRIMARY KEY(id) 32 | ) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'); 33 | 34 | $this->addSql('CREATE TABLE package ( 35 | id INT AUTO_INCREMENT NOT NULL, 36 | name VARCHAR(255) NOT NULL, 37 | manager VARCHAR(255) NOT NULL, 38 | latest_version LONGTEXT DEFAULT NULL, 39 | last_checked_at DATETIME DEFAULT NULL, 40 | created_at DATETIME NOT NULL, 41 | updated_at DATETIME NOT NULL, PRIMARY KEY(id) 42 | ) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'); 43 | 44 | $this->addSql('ALTER TABLE dependency ADD CONSTRAINT FK_2F585505166D1F9C FOREIGN KEY (project_id) REFERENCES project (id)'); 45 | $this->addSql('ALTER TABLE dependency ADD CONSTRAINT FK_2F585505F44CABFF FOREIGN KEY (package_id) REFERENCES package (id)'); 46 | } 47 | 48 | /** 49 | * @param Schema $schema 50 | */ 51 | public function down(Schema $schema) 52 | { 53 | // this down() migration is auto-generated, please modify it to your needs 54 | $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 55 | 56 | $this->addSql('ALTER TABLE dependency DROP FOREIGN KEY FK_2F585505166D1F9C'); 57 | $this->addSql('ALTER TABLE dependency DROP FOREIGN KEY FK_2F585505F44CABFF'); 58 | $this->addSql('DROP TABLE dependency'); 59 | $this->addSql('DROP TABLE package'); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/migrations/Version20150827220301.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('ALTER TABLE project ADD branch VARCHAR(50) NOT NULL'); 22 | } 23 | 24 | /** 25 | * @param Schema $schema 26 | */ 27 | public function down(Schema $schema) 28 | { 29 | // this down() migration is auto-generated, please modify it to your needs 30 | $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 31 | 32 | $this->addSql('ALTER TABLE project DROP COLUMN branch'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/migrations/Version20170712084447.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('ALTER TABLE project CHANGE repository_type repository_type VARCHAR(25) NOT NULL'); 22 | $this->addSql('ALTER TABLE user DROP locked, DROP expired, DROP expires_at, DROP credentials_expired, DROP credentials_expire_at, CHANGE username username VARCHAR(180) NOT NULL, CHANGE username_canonical username_canonical VARCHAR(180) NOT NULL, CHANGE email email VARCHAR(180) NOT NULL, CHANGE email_canonical email_canonical VARCHAR(180) NOT NULL, CHANGE salt salt VARCHAR(255) DEFAULT NULL, CHANGE confirmation_token confirmation_token VARCHAR(180) DEFAULT NULL'); 23 | $this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D649C05FB297 ON user (confirmation_token)'); 24 | } 25 | 26 | /** 27 | * @param Schema $schema 28 | */ 29 | public function down(Schema $schema) 30 | { 31 | // this down() migration is auto-generated, please modify it to your needs 32 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 33 | 34 | $this->addSql('ALTER TABLE project CHANGE repository_type repository_type VARCHAR(50) NOT NULL COLLATE utf8_unicode_ci'); 35 | $this->addSql('DROP INDEX UNIQ_8D93D649C05FB297 ON user'); 36 | $this->addSql('ALTER TABLE user ADD locked INT NOT NULL, ADD expired TINYINT(1) NOT NULL, ADD expires_at DATETIME DEFAULT NULL, ADD credentials_expired TINYINT(1) NOT NULL, ADD credentials_expire_at DATETIME DEFAULT NULL, CHANGE username username VARCHAR(255) NOT NULL COLLATE utf8_unicode_ci, CHANGE username_canonical username_canonical VARCHAR(255) NOT NULL COLLATE utf8_unicode_ci, CHANGE email email VARCHAR(255) NOT NULL COLLATE utf8_unicode_ci, CHANGE email_canonical email_canonical VARCHAR(255) NOT NULL COLLATE utf8_unicode_ci, CHANGE salt salt VARCHAR(255) NOT NULL COLLATE utf8_unicode_ci, CHANGE confirmation_token confirmation_token VARCHAR(255) DEFAULT NULL COLLATE utf8_unicode_ci'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | getParameterOption(['--env', '-e'], getenv('SYMFONY_ENV') ?: 'dev'); 19 | $debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(['--no-debug', '']) && $env !== 'prod'; 20 | 21 | if ($debug) { 22 | Debug::enable(); 23 | } 24 | 25 | $kernel = new AppKernel($env, $debug); 26 | $application = new Application($kernel); 27 | $application->run($input); 28 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "peternijssen/packy", 3 | "license": "MIT", 4 | "description": "Packy is an open source tool to validate if your dependencies are up 2 date. Packy is based on the Symfony framework.", 5 | "keywords": ["dependencies", "composer", "yarn", "npm", "pip"], 6 | "type": "project", 7 | "authors": [ 8 | { 9 | "name": "Peter Nijssen", 10 | "email": "peter@peternijssen.nl", 11 | "homepage": "https://www.peternijssen.nl" 12 | } 13 | ], 14 | "autoload": { 15 | "psr-4": { 16 | "": "src" 17 | }, 18 | "classmap": [ 19 | "app/AppKernel.php", 20 | "app/AppCache.php" 21 | ] 22 | }, 23 | "autoload-dev": { 24 | "psr-4": { 25 | "Tests\\": "tests/" 26 | }, 27 | "files": [ 28 | "vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php" 29 | ] 30 | }, 31 | "require": { 32 | "php": ">=7.0", 33 | "symfony/symfony": "3.3.*", 34 | "symfony/swiftmailer-bundle": "^2.3.10", 35 | "symfony/monolog-bundle": "^3.1.0", 36 | "doctrine/orm": "^2.5", 37 | "doctrine/doctrine-bundle": "^1.6", 38 | "doctrine/doctrine-cache-bundle": "^1.2", 39 | "doctrine/doctrine-migrations-bundle": "1.1.*", 40 | "sensio/distribution-bundle": "^5.0.19", 41 | "sensio/framework-extra-bundle": "^3.0.2", 42 | "incenteev/composer-parameter-handler": "~2.0", 43 | "stof/doctrine-extensions-bundle": "dev-master", 44 | "guzzlehttp/guzzle": "^6.0", 45 | "knplabs/knp-menu-bundle": "^2.1", 46 | "friendsofsymfony/user-bundle": "^2.0", 47 | "ornicar/gravatar-bundle": "^1.1", 48 | "knplabs/github-api": "^1.7", 49 | "m4tthumphrey/php-gitlab-api": "^8.0", 50 | "gentle/bitbucket-api": "^1.0", 51 | "twig/twig": "^2.0", 52 | "twig/extensions": "1.*", 53 | "composer/semver": "^1.4" 54 | }, 55 | "require-dev": { 56 | "sensio/generator-bundle": "^3.0", 57 | "symfony/phpunit-bridge": "^3.0", 58 | "phpro/grumphp": "^0.8", 59 | "roave/security-advisories": "dev-master", 60 | "sensiolabs/security-checker": "~3.0", 61 | "friendsofphp/php-cs-fixer": "^2.2", 62 | "phpstan/phpstan": "^0.7", 63 | "phpstan/phpstan-doctrine": "^0.7", 64 | "squizlabs/php_codesniffer": "^2.8", 65 | "escapestudios/symfony2-coding-standard": "^2.10" 66 | }, 67 | "scripts": { 68 | "symfony-scripts": [ 69 | "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters", 70 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache" 71 | ], 72 | "post-install-cmd": [ 73 | "@symfony-scripts" 74 | ], 75 | "post-update-cmd": [ 76 | "@symfony-scripts" 77 | ] 78 | }, 79 | "minimum-stability": "stable", 80 | "extra": { 81 | "symfony-app-dir": "app", 82 | "symfony-bin-dir": "bin", 83 | "symfony-var-dir": "var", 84 | "symfony-web-dir": "web", 85 | "symfony-tests-dir": "tests", 86 | "symfony-assets-install": "relative", 87 | "incenteev-parameters": { 88 | "file": "app/config/parameters.yml" 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /grumphp.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | git_dir: . 3 | bin_dir: ./vendor/bin 4 | stop_on_failure: false 5 | ascii: 6 | failed: grumphp-grumpy.txt 7 | succeeded: grumphp-happy.txt 8 | tasks: 9 | git_blacklist: 10 | keywords: 11 | - "die(" 12 | - "var_dump(" 13 | - "exit;" 14 | - "dump(" 15 | composer: ~ 16 | jsonlint: ~ 17 | xmllint: ~ 18 | yamllint: ~ 19 | extensions: [] 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@symfony/webpack-encore": "^0.9.1", 4 | "admin-lte": "^2.3.11", 5 | "bootstrap-sass": "^3.3.7", 6 | "font-awesome": "^4.7.0", 7 | "highcharts": "^5.0.12", 8 | "jquery": "^3.2.1", 9 | "node-sass": "^4.5.3", 10 | "sass-loader": "^6.0.6", 11 | "tether": "^1.4.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /phpcs.ruleset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | */scripts/* 4 | */tests/* 5 | */vendor/* 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/AppBundle/AppBundle.php: -------------------------------------------------------------------------------- 1 | addCompilerPass(new DependencyManagerCompilerPass()); 27 | $container->addCompilerPass(new RepositoryManagerCompilerPass()); 28 | $container->addCompilerPass(new PackageManagerCompilerPass()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/AppBundle/Command/InstallCommand.php: -------------------------------------------------------------------------------- 1 | setName('packy:install') 28 | ->setDescription('Install packy'); 29 | } 30 | 31 | /** 32 | * Execute the command. 33 | * 34 | * @param InputInterface $input 35 | * @param OutputInterface $output 36 | * 37 | * @throws \Exception 38 | */ 39 | protected function execute(InputInterface $input, OutputInterface $output) 40 | { 41 | $command = $this->getApplication()->find('doctrine:database:create'); 42 | $arguments = [ 43 | 'command' => 'doctrine:database:create', 44 | '--if-not-exists' => true, 45 | '--quiet' => true, 46 | ]; 47 | $input = new ArrayInput($arguments); 48 | $input->setInteractive(false); 49 | $command->run($input, $output); 50 | 51 | $command = $this->getApplication()->find('doctrine:migrations:migrate'); 52 | $arguments = [ 53 | 'command' => 'doctrine:migrations:migrate', 54 | '--quiet' => true, 55 | ]; 56 | $input = new ArrayInput($arguments); 57 | $input->setInteractive(false); 58 | $command->run($input, $output); 59 | 60 | $userCommand = $this->getApplication()->find('fos:user:create'); 61 | $arguments = [ 62 | 'command' => 'fos:user:create', 63 | '--super-admin' => true, 64 | ]; 65 | $input = new ArrayInput($arguments); 66 | $userCommand->run($input, $output); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/AppBundle/Command/PackageUpdateCommand.php: -------------------------------------------------------------------------------- 1 | setName('packy:package:update') 27 | ->setDescription('Update the version of the package'); 28 | } 29 | 30 | /** 31 | * Execute the command. 32 | * 33 | * @param InputInterface $input 34 | * @param OutputInterface $output 35 | * 36 | * @throws \Exception 37 | */ 38 | protected function execute(InputInterface $input, OutputInterface $output) 39 | { 40 | $packageRepository = $this->getContainer()->get('packy.repository.package'); 41 | $packageManagers = $this->getContainer()->get('packy.package_managers'); 42 | $packages = $packageRepository->findAll(); 43 | 44 | foreach ($packages as $package) { 45 | $packageManager = $packageManagers->get($package->getManager()); 46 | $package = $packageManager->analyzePackage($package); 47 | $packageRepository->update($package); 48 | $output->writeln('Package ' . $package->getName() . ' updated!'); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/AppBundle/Command/ProjectUpdateCommand.php: -------------------------------------------------------------------------------- 1 | setName('packy:project:update') 29 | ->setDescription('Update the dependencies of projects'); 30 | } 31 | 32 | /** 33 | * Execute the command. 34 | * 35 | * @param InputInterface $input 36 | * @param OutputInterface $output 37 | * 38 | * @throws \Exception 39 | */ 40 | protected function execute(InputInterface $input, OutputInterface $output) 41 | { 42 | $projectRepository = $this->getContainer()->get('packy.repository.project'); 43 | $packageRepository = $this->getContainer()->get('packy.repository.package'); 44 | $repositoryManagers = $this->getContainer()->get('packy.repository_managers'); 45 | $dependencyManagers = $this->getContainer()->get('packy.dependency_managers'); 46 | $packageManagers = $this->getContainer()->get('packy.package_managers'); 47 | $versionFormatter = $this->getContainer()->get('packy.service.version_formatter'); 48 | 49 | $projects = $projectRepository->findAll(); 50 | 51 | foreach ($projects as $project) { 52 | $repository = $repositoryManagers->get($project->getRepositoryType()); 53 | 54 | foreach ($dependencyManagers->getAll() as $dependencyManager) { 55 | $dependencies = $dependencyManager->fetchDependencies($repository, $project); 56 | 57 | foreach ($dependencies as $name => $version) { 58 | $package = $packageRepository->findOne($name, $dependencyManager->getName()); 59 | if (null === $package) { 60 | $package = new Package(); 61 | $package->setName($name); 62 | $package->setManager($dependencyManager->getName()); 63 | $packageRepository->create($package); 64 | } 65 | 66 | $packageManager = $packageManagers->get($package->getManager()); 67 | 68 | $package = $packageManager->analyzePackage($package); 69 | $packageRepository->update($package); 70 | 71 | $dependency = new Dependency(); 72 | $dependency->setPackage($package); 73 | $dependency->setRawVersion($version); 74 | $dependency->setCurrentVersion($versionFormatter->normalizeVersion($version)); 75 | $project->addDependency($dependency); 76 | } 77 | } 78 | 79 | $projectRepository->update($project); 80 | 81 | $output->writeln('Project ' . $project->getName() . ' updated!'); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/AppBundle/Command/ReinstallCommand.php: -------------------------------------------------------------------------------- 1 | setName('packy:reinstall') 29 | ->setDescription('Reinstall packy'); 30 | } 31 | 32 | /** 33 | * Execute the command. 34 | * 35 | * @param InputInterface $input 36 | * @param OutputInterface $output 37 | * 38 | * @throws \Exception 39 | */ 40 | protected function execute(InputInterface $input, OutputInterface $output) 41 | { 42 | $helper = $this->getHelper('question'); 43 | $question = new ConfirmationQuestion( 44 | 'Do you really want to reinstall packy? All data will be lost. (y/n) ', 45 | false 46 | ); 47 | 48 | if (!$helper->ask($input, $output, $question)) { 49 | return; 50 | } 51 | 52 | $command = $this->getApplication()->find('doctrine:database:drop'); 53 | $arguments = [ 54 | 'command' => 'doctrine:database:drop', 55 | '--force' => true, 56 | '--quiet' => true, 57 | ]; 58 | 59 | $input = new ArrayInput($arguments); 60 | $input->setInteractive(false); 61 | $command->run($input, $output); 62 | 63 | $installCommand = $this->getApplication()->find('packy:install'); 64 | $arguments = [ 65 | 'command' => 'packy:install', 66 | ]; 67 | $installInput = new ArrayInput($arguments); 68 | $installCommand->run($installInput, $output); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/AppBundle/Controller/ProfileController.php: -------------------------------------------------------------------------------- 1 | getUser(); 31 | $profileForm = $this->createForm(ChangePasswordType::class, $user); 32 | 33 | if ($request->isMethod('POST')) { 34 | $profileForm->handleRequest($request); 35 | if ($profileForm->isValid()) { 36 | if (0 !== mb_strlen($user->getPlainPassword())) { 37 | $encoder = $this->container->get('security.password_encoder'); 38 | $user->setPassword($encoder->encodePassword($user, $user->getPlainPassword())); 39 | $user->eraseCredentials(); 40 | } 41 | 42 | $userRepository = $this->get('packy.repository.user'); 43 | $userRepository->update($user); 44 | 45 | return $this->redirect($this->generateUrl('packy_project_overview')); 46 | } 47 | } 48 | 49 | return $this->render( 50 | 'AppBundle:Profile:change_password.html.twig', 51 | [ 52 | 'user' => $user, 53 | 'profileForm' => $profileForm->createView(), 54 | ] 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/AppBundle/Controller/ProjectController.php: -------------------------------------------------------------------------------- 1 | get('packy.repository.project'); 32 | $projects = $projectRepository->findAll(); 33 | 34 | return $this->render( 35 | 'AppBundle:Project:overview.html.twig', 36 | [ 37 | 'projects' => $projects, 38 | ] 39 | ); 40 | } 41 | 42 | /** 43 | * Add project. 44 | * 45 | * @param Request $request A Request instance 46 | * 47 | * @return Response A Response instance 48 | */ 49 | public function addAction(Request $request) 50 | { 51 | $project = new Project(); 52 | $projectForm = $this->createForm(ProjectFormType::class, $project); 53 | 54 | if ($request->isMethod('POST')) { 55 | $projectForm->handleRequest($request); 56 | if ($projectForm->isValid()) { 57 | $projectManager = $this->get('packy.repository.project'); 58 | $projectManager->create($project); 59 | 60 | return $this->redirect($this->generateUrl('packy_project_overview')); 61 | } 62 | } 63 | 64 | return $this->render( 65 | 'AppBundle:Project:form.html.twig', 66 | [ 67 | 'project' => $project, 68 | 'projectForm' => $projectForm->createView(), 69 | ] 70 | ); 71 | } 72 | 73 | /** 74 | * @ParamConverter("project", class="AppBundle:Project", options={"id" = "projectId"}) 75 | * 76 | * Analyze project 77 | * 78 | * @param Project $project 79 | * 80 | * @return Response A Response instance 81 | */ 82 | public function analyzeAction(Project $project) 83 | { 84 | $dependencyRepository = $this->get('packy.repository.dependency'); 85 | 86 | $dependencyManagers = $this->get('packy.dependency_managers'); 87 | $dependencyManagers = $dependencyManagers->getAll(); 88 | 89 | //@TODO: Refactor 90 | $vendors = []; 91 | foreach ($dependencyManagers as $manager) { 92 | $name = $manager->getName(); 93 | $dependencies = $dependencyRepository->findAllByManager($project, $name); 94 | if (!empty($dependencies)) { 95 | $vendors[$name] = $dependencies; 96 | } 97 | } 98 | 99 | //@TODO: BIG Refactor 100 | $stats = [ 101 | 'outdated' => [], 102 | 'unstable' => [], 103 | 'stable' => [], 104 | ]; 105 | 106 | foreach ($vendors as $name => $dependencies) { 107 | foreach ($stats as &$stat) { 108 | $stat[$name] = 0; 109 | } 110 | 111 | unset($stat); 112 | 113 | foreach ($stats as $type => $stat) { 114 | foreach ($dependencies as $dependency) { 115 | if ($dependency->getStatus() == $type) { 116 | $stats[$type][$name] += 1; 117 | } 118 | } 119 | } 120 | } 121 | 122 | return $this->render( 123 | 'AppBundle:Project:analyze.html.twig', 124 | [ 125 | 'project' => $project, 126 | 'vendors' => $vendors, 127 | 'stats' => $stats, 128 | ] 129 | ); 130 | } 131 | 132 | /** 133 | * @ParamConverter("project", class="AppBundle:Project", options={"id" = "projectId"}) 134 | * 135 | * Edit project 136 | * 137 | * @param Request $request A Request instance 138 | * @param Project $project 139 | * 140 | * @return Response A Response instance 141 | */ 142 | public function editAction(Request $request, Project $project) 143 | { 144 | $projectForm = $this->createForm(ProjectFormType::class, $project); 145 | 146 | if ($request->isMethod('POST')) { 147 | $projectForm->handleRequest($request); 148 | if ($projectForm->isValid()) { 149 | $projectRepository = $this->get('packy.repository.project'); 150 | $projectRepository->update($project); 151 | 152 | return $this->redirect($this->generateUrl('packy_project_overview')); 153 | } 154 | } 155 | 156 | return $this->render( 157 | 'AppBundle:Project:form.html.twig', 158 | [ 159 | 'project' => $project, 160 | 'projectForm' => $projectForm->createView(), 161 | ] 162 | ); 163 | } 164 | 165 | /** 166 | * @ParamConverter("project", class="AppBundle:Project", options={"id" = "projectId"}) 167 | * 168 | * Delete project 169 | * 170 | * @param Project $project 171 | * 172 | * @return RedirectResponse A Response instance 173 | */ 174 | public function deleteAction(Project $project) 175 | { 176 | $projectRepository = $this->get('packy.repository.project'); 177 | $projectRepository->delete($project); 178 | 179 | return $this->redirect($this->generateUrl('packy_project_overview')); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/AppBundle/Controller/UserController.php: -------------------------------------------------------------------------------- 1 | get('packy.repository.user'); 32 | $users = $userRepository->findAll(); 33 | 34 | return $this->render( 35 | 'AppBundle:User:overview.html.twig', 36 | [ 37 | 'users' => $users, 38 | ] 39 | ); 40 | } 41 | 42 | /** 43 | * Add user. 44 | * 45 | * @param Request $request A Request instance 46 | * 47 | * @return Response A Response instance 48 | */ 49 | public function addAction(Request $request) 50 | { 51 | $user = new User(); 52 | $userForm = $this->createForm(UserFormType::class, $user); 53 | 54 | if ($request->isMethod('POST')) { 55 | $userForm->handleRequest($request); 56 | if ($userForm->isValid()) { 57 | $user->setEnabled(true); 58 | 59 | $userRepository = $this->get('packy.repository.user'); 60 | $userRepository->create($user); 61 | 62 | return $this->redirect($this->generateUrl('packy_user_overview')); 63 | } 64 | } 65 | 66 | return $this->render( 67 | 'AppBundle:User:form.html.twig', 68 | [ 69 | 'user' => $user, 70 | 'userForm' => $userForm->createView(), 71 | ] 72 | ); 73 | } 74 | 75 | /** 76 | * @ParamConverter("user", class="AppBundle:User", options={"id" = "userId"}) 77 | * 78 | * Edit user 79 | * 80 | * @param Request $request A Request instance 81 | * @param User $user 82 | * 83 | * @return Response A Response instance 84 | */ 85 | public function editAction(Request $request, User $user) 86 | { 87 | $userForm = $this->createForm(UserFormType::class, $user); 88 | 89 | if ($request->isMethod('POST')) { 90 | $userForm->handleRequest($request); 91 | if ($userForm->isValid()) { 92 | $userRepository = $this->get('packy.repository.user'); 93 | $userRepository->update($user); 94 | 95 | return $this->redirect($this->generateUrl('packy_user_overview')); 96 | } 97 | } 98 | 99 | return $this->render( 100 | 'AppBundle:User:form.html.twig', 101 | [ 102 | 'user' => $user, 103 | 'userForm' => $userForm->createView(), 104 | ] 105 | ); 106 | } 107 | 108 | /** 109 | * @ParamConverter("user", class="AppBundle:User", options={"id" = "userId"}) 110 | * 111 | * Delete user 112 | * 113 | * @param User $user 114 | * 115 | * @return RedirectResponse A Response instance 116 | */ 117 | public function deleteAction(User $user) 118 | { 119 | $userRepository = $this->get('packy.repository.user'); 120 | $userRepository->delete($user); 121 | 122 | return $this->redirect($this->generateUrl('packy_user_overview')); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/AppBundle/DependencyInjection/AppExtension.php: -------------------------------------------------------------------------------- 1 | load('service/dependency_managers.yml'); 28 | $loader->load('service/package_managers.yml'); 29 | $loader->load('service/repository.yml'); 30 | $loader->load('service/repository_managers.yml'); 31 | $loader->load('service/service.yml'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/AppBundle/DependencyInjection/Compiler/DependencyManagerCompilerPass.php: -------------------------------------------------------------------------------- 1 | has('packy.dependency_managers')) { 28 | return; 29 | } 30 | 31 | $definition = $container->findDefinition('packy.dependency_managers'); 32 | 33 | $taggedServices = $container->findTaggedServiceIds('packy_dependency_manager'); 34 | 35 | foreach ($taggedServices as $id => $tags) { 36 | foreach ($tags as $attributes) { 37 | $definition->addMethodCall('add', [new Reference($id), $attributes["alias"]]); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/AppBundle/DependencyInjection/Compiler/PackageManagerCompilerPass.php: -------------------------------------------------------------------------------- 1 | has('packy.package_managers')) { 28 | return; 29 | } 30 | 31 | $definition = $container->findDefinition('packy.package_managers'); 32 | 33 | $taggedServices = $container->findTaggedServiceIds('packy_package_manager'); 34 | 35 | foreach ($taggedServices as $id => $tags) { 36 | foreach ($tags as $attributes) { 37 | $definition->addMethodCall('add', [new Reference($id), $attributes["alias"]]); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/AppBundle/DependencyInjection/Compiler/RepositoryManagerCompilerPass.php: -------------------------------------------------------------------------------- 1 | has('packy.repository_managers')) { 28 | return; 29 | } 30 | 31 | $definition = $container->findDefinition('packy.repository_managers'); 32 | 33 | $taggedServices = $container->findTaggedServiceIds('packy_repository_manager'); 34 | 35 | foreach ($taggedServices as $id => $tags) { 36 | foreach ($tags as $attributes) { 37 | $definition->addMethodCall('add', [new Reference($id), $attributes["alias"]]); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/AppBundle/DependencyManager/Composer.php: -------------------------------------------------------------------------------- 1 | packageFileName = 'composer.lock'; 30 | } 31 | 32 | /** 33 | * Fetch the dependencies. 34 | * 35 | * @param RepositoryManager $repositoryManager 36 | * @param Project $project 37 | * 38 | * @return array 39 | */ 40 | public function fetchDependencies(RepositoryManager $repositoryManager, Project $project): array 41 | { 42 | $fileContent = $repositoryManager->getFileContents($project, $this->packageFileName); 43 | 44 | if (is_array($fileContent)) { 45 | $dependencies = []; 46 | if (array_key_exists('packages', $fileContent)) { 47 | foreach ($fileContent['packages'] as $package) { 48 | $dependencies[$package['name']] = $package['version']; 49 | } 50 | } 51 | 52 | if (array_key_exists('packages-dev', $fileContent)) { 53 | foreach ($fileContent['packages'] as $package) { 54 | $dependencies[$package['name']] = $package['version']; 55 | } 56 | } 57 | 58 | return $dependencies; 59 | } 60 | 61 | return []; 62 | } 63 | 64 | /** 65 | * Get the name of the fetcher. 66 | * 67 | * @return string 68 | */ 69 | public function getName(): string 70 | { 71 | return 'composer'; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/AppBundle/DependencyManager/DependencyManager.php: -------------------------------------------------------------------------------- 1 | dependencyManagers = []; 27 | } 28 | 29 | /** 30 | * @param DependencyManager $manager 31 | * @param string $alias 32 | */ 33 | public function add(DependencyManager $manager, string $alias) 34 | { 35 | $this->dependencyManagers[$alias] = $manager; 36 | } 37 | 38 | /** 39 | * @return DependencyManager[] 40 | */ 41 | public function getAll(): array 42 | { 43 | return $this->dependencyManagers; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/AppBundle/DependencyManager/Npm.php: -------------------------------------------------------------------------------- 1 | packageFileName = 'package-lock.json'; 30 | } 31 | 32 | /** 33 | * Fetch the dependencies. 34 | * 35 | * @param RepositoryManager $repositoryManager 36 | * @param Project $project 37 | * 38 | * @return array 39 | */ 40 | public function fetchDependencies(RepositoryManager $repositoryManager, Project $project): array 41 | { 42 | $fileContent = $repositoryManager->getFileContents($project, $this->packageFileName); 43 | 44 | if (is_array($fileContent)) { 45 | $dependencies = []; 46 | if (array_key_exists('dependencies', $fileContent)) { 47 | foreach ($fileContent['dependencies'] as $name => $package) { 48 | $dependencies[$name] = $package['version']; 49 | } 50 | } 51 | 52 | if (array_key_exists('devDependencies', $fileContent)) { 53 | foreach ($fileContent['devDependencies'] as $name => $package) { 54 | $dependencies[$name] = $package['version']; 55 | } 56 | } 57 | 58 | return $dependencies; 59 | } 60 | 61 | return []; 62 | } 63 | 64 | /** 65 | * Get the name of the fetcher. 66 | * 67 | * @return string 68 | */ 69 | public function getName(): string 70 | { 71 | return 'npm'; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/AppBundle/DependencyManager/Pip.php: -------------------------------------------------------------------------------- 1 | packageFileName = 'requirements.txt'; 30 | } 31 | 32 | /** 33 | * Fetch the dependencies. 34 | * 35 | * @param RepositoryManager $repositoryManager 36 | * @param Project $project 37 | * 38 | * @return array 39 | */ 40 | public function fetchDependencies(RepositoryManager $repositoryManager, Project $project): array 41 | { 42 | $fileContent = $repositoryManager->getFileContents($project, $this->packageFileName); 43 | 44 | if (is_array($fileContent) && !empty($fileContent)) { 45 | $lines = explode("\n", $fileContent); 46 | 47 | $dependencies = []; 48 | foreach ($lines as $line) { 49 | $chunks = explode('==', $line); 50 | if (count($chunks) == 2) { 51 | $dependencies[$chunks[0]] = $chunks[1]; 52 | } 53 | } 54 | 55 | return $dependencies; 56 | } 57 | 58 | return []; 59 | } 60 | 61 | /** 62 | * Get the name of the fetcher. 63 | * 64 | * @return string 65 | */ 66 | public function getName(): string 67 | { 68 | return 'pip'; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/AppBundle/Entity/Dependency.php: -------------------------------------------------------------------------------- 1 | id; 61 | } 62 | 63 | /** 64 | * Set rawVersion. 65 | * 66 | * @param string $rawVersion 67 | */ 68 | public function setRawVersion(string $rawVersion) 69 | { 70 | $this->rawVersion = $rawVersion; 71 | } 72 | 73 | /** 74 | * Get rawVersion. 75 | * 76 | * @return string 77 | */ 78 | public function getRawVersion(): string 79 | { 80 | return $this->rawVersion; 81 | } 82 | 83 | /** 84 | * Set currentVersion. 85 | * 86 | * @param string $currentVersion 87 | */ 88 | public function setCurrentVersion(string $currentVersion) 89 | { 90 | $this->currentVersion = $currentVersion; 91 | } 92 | 93 | /** 94 | * Get currentVersion. 95 | * 96 | * @return string 97 | */ 98 | public function getCurrentVersion(): string 99 | { 100 | return $this->currentVersion; 101 | } 102 | 103 | /** 104 | * Set project. 105 | * 106 | * @param Project $project 107 | */ 108 | public function setProject(Project $project = null) 109 | { 110 | $this->project = $project; 111 | } 112 | 113 | /** 114 | * Get project. 115 | * 116 | * @return Project 117 | */ 118 | public function getProject(): ?Project 119 | { 120 | return $this->project; 121 | } 122 | 123 | /** 124 | * Set package. 125 | * 126 | * @param Package $package 127 | */ 128 | public function setPackage(Package $package = null) 129 | { 130 | $this->package = $package; 131 | } 132 | 133 | /** 134 | * Get package. 135 | * 136 | * @return Package 137 | */ 138 | public function getPackage(): ?Package 139 | { 140 | return $this->package; 141 | } 142 | 143 | /** 144 | * Get status. 145 | * 146 | * @return string 147 | */ 148 | public function getStatus(): string 149 | { 150 | if (preg_match('/[a-zA-Z]+$/', $this->getRawVersion())) { 151 | return 'unstable'; 152 | } 153 | 154 | if (Comparator::greaterThanOrEqualTo($this->getCurrentVersion(), $this->package->getLatestVersion())) { 155 | return 'stable'; 156 | } 157 | 158 | return 'outdated'; 159 | } 160 | 161 | /** 162 | * Set createdAt. 163 | * 164 | * @param \DateTimeInterface $createdAt 165 | */ 166 | public function setCreatedAt(\DateTimeInterface $createdAt) 167 | { 168 | $this->createdAt = $createdAt; 169 | } 170 | 171 | /** 172 | * Get createdAt. 173 | * 174 | * @return \DateTimeInterface 175 | */ 176 | public function getCreatedAt(): \DateTimeInterface 177 | { 178 | return $this->createdAt; 179 | } 180 | 181 | /** 182 | * Set updatedAt. 183 | * 184 | * @param \DateTimeInterface $updatedAt 185 | */ 186 | public function setUpdatedAt(\DateTimeInterface $updatedAt) 187 | { 188 | $this->updatedAt = $updatedAt; 189 | } 190 | 191 | /** 192 | * Get updatedAt. 193 | * 194 | * @return \DateTimeInterface 195 | */ 196 | public function getUpdatedAt(): \DateTimeInterface 197 | { 198 | return $this->updatedAt; 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /src/AppBundle/Entity/Package.php: -------------------------------------------------------------------------------- 1 | dependencies = new ArrayCollection(); 65 | } 66 | 67 | /** 68 | * Get id. 69 | * 70 | * @return int 71 | */ 72 | public function getId(): int 73 | { 74 | return $this->id; 75 | } 76 | 77 | /** 78 | * Set name. 79 | * 80 | * @param string $name 81 | */ 82 | public function setName(string $name) 83 | { 84 | $this->name = $name; 85 | } 86 | 87 | /** 88 | * Get name. 89 | * 90 | * @return string 91 | */ 92 | public function getName(): string 93 | { 94 | return $this->name; 95 | } 96 | 97 | /** 98 | * Set manager. 99 | * 100 | * @param string $manager 101 | */ 102 | public function setManager(string $manager) 103 | { 104 | $this->manager = $manager; 105 | } 106 | 107 | /** 108 | * Get manager. 109 | * 110 | * @return string 111 | */ 112 | public function getManager(): string 113 | { 114 | return $this->manager; 115 | } 116 | 117 | /** 118 | * Set latestVersion. 119 | * 120 | * @param string $latestVersion 121 | */ 122 | public function setLatestVersion(string $latestVersion) 123 | { 124 | $this->latestVersion = $latestVersion; 125 | } 126 | 127 | /** 128 | * Get latestVersion. 129 | * 130 | * @return string|null 131 | */ 132 | public function getLatestVersion(): ?string 133 | { 134 | return $this->latestVersion; 135 | } 136 | 137 | /** 138 | * Set $lastCheckAt. 139 | * 140 | * @param \DateTimeInterface $lastCheckAt 141 | */ 142 | public function setLastCheckAt(\DateTimeInterface $lastCheckAt) 143 | { 144 | $this->lastCheckAt = $lastCheckAt; 145 | } 146 | 147 | /** 148 | * Get lastCheckAt. 149 | * 150 | * @return \DateTimeInterface 151 | */ 152 | public function getLastCheckAt(): \DateTimeInterface 153 | { 154 | return $this->lastCheckAt; 155 | } 156 | 157 | /** 158 | * Set createdAt. 159 | * 160 | * @param \DateTimeInterface $createdAt 161 | */ 162 | public function setCreatedAt(\DateTimeInterface $createdAt) 163 | { 164 | $this->createdAt = $createdAt; 165 | } 166 | 167 | /** 168 | * Get createdAt. 169 | * 170 | * @return \DateTimeInterface 171 | */ 172 | public function getCreatedAt(): \DateTimeInterface 173 | { 174 | return $this->createdAt; 175 | } 176 | 177 | /** 178 | * Set updatedAt. 179 | * 180 | * @param \DateTimeInterface $updatedAt 181 | */ 182 | public function setUpdatedAt(\DateTimeInterface $updatedAt) 183 | { 184 | $this->updatedAt = $updatedAt; 185 | } 186 | 187 | /** 188 | * Get updatedAt. 189 | * 190 | * @return \DateTimeInterface 191 | */ 192 | public function getUpdatedAt(): \DateTimeInterface 193 | { 194 | return $this->updatedAt; 195 | } 196 | 197 | /** 198 | * Add dependencies. 199 | * 200 | * @param Dependency $dependencies 201 | */ 202 | public function addDependency(Dependency $dependencies) 203 | { 204 | $this->dependencies[] = $dependencies; 205 | } 206 | 207 | /** 208 | * Remove dependencies. 209 | * 210 | * @param Dependency $dependencies 211 | */ 212 | public function removeDependency(Dependency $dependencies) 213 | { 214 | $this->dependencies->removeElement($dependencies); 215 | } 216 | 217 | /** 218 | * Get dependencies. 219 | * 220 | * @return Collection 221 | */ 222 | public function getDependencies(): Collection 223 | { 224 | return $this->dependencies; 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/AppBundle/Entity/Project.php: -------------------------------------------------------------------------------- 1 | dependencies = new ArrayCollection(); 85 | } 86 | 87 | /** 88 | * Get id. 89 | * 90 | * @return int 91 | */ 92 | public function getId(): int 93 | { 94 | return $this->id; 95 | } 96 | 97 | /** 98 | * Set name. 99 | * 100 | * @param string $name 101 | */ 102 | public function setName(string $name) 103 | { 104 | $this->name = $name; 105 | } 106 | 107 | /** 108 | * Get name. 109 | * 110 | * @return string 111 | */ 112 | public function getName(): string 113 | { 114 | return $this->name; 115 | } 116 | 117 | /** 118 | * Set description. 119 | * 120 | * @param string $description 121 | */ 122 | public function setDescription(string $description) 123 | { 124 | $this->description = $description; 125 | } 126 | 127 | /** 128 | * Get description. 129 | * 130 | * @return string 131 | */ 132 | public function getDescription(): string 133 | { 134 | return $this->description; 135 | } 136 | 137 | /** 138 | * Set repositoryUrl. 139 | * 140 | * @param string $repositoryUrl 141 | */ 142 | public function setRepositoryUrl(string $repositoryUrl) 143 | { 144 | $this->repositoryUrl = $repositoryUrl; 145 | } 146 | 147 | /** 148 | * Get repositoryUrl. 149 | * 150 | * @return string 151 | */ 152 | public function getRepositoryUrl(): string 153 | { 154 | return $this->repositoryUrl; 155 | } 156 | 157 | /** 158 | * Add dependencies. 159 | * 160 | * @TODO: Refactor 161 | * 162 | * @param Dependency $dependency 163 | */ 164 | public function addDependency(Dependency $dependency) 165 | { 166 | $dependency->setProject($this); 167 | 168 | foreach ($this->dependencies as $k => $dep) { 169 | if ($dep->getPackage()->getName() == $dependency->getPackage()->getName()) { 170 | $dep->setCurrentVersion($dependency->getCurrentVersion()); 171 | $dep->setRawVersion($dependency->getRawVersion()); 172 | $dep->setRawVersion($dependency->getRawVersion()); 173 | 174 | return $this; 175 | } 176 | } 177 | 178 | $this->dependencies[] = $dependency; 179 | } 180 | 181 | /** 182 | * Remove dependencies. 183 | * 184 | * @param Dependency $dependency 185 | */ 186 | public function removeDependency(Dependency $dependency) 187 | { 188 | $this->dependencies->removeElement($dependency); 189 | } 190 | 191 | /** 192 | * Get dependencies. 193 | * 194 | * @return Collection 195 | */ 196 | public function getDependencies(): Collection 197 | { 198 | return $this->dependencies; 199 | } 200 | 201 | /** 202 | * Set repositoryType. 203 | * 204 | * @param string $repositoryType 205 | */ 206 | public function setRepositoryType(string $repositoryType) 207 | { 208 | $this->repositoryType = $repositoryType; 209 | } 210 | 211 | /** 212 | * Get repositoryType. 213 | * 214 | * @return string 215 | */ 216 | public function getRepositoryType(): string 217 | { 218 | return $this->repositoryType; 219 | } 220 | 221 | /** 222 | * Set vendorName. 223 | * 224 | * @param string $vendorName 225 | */ 226 | public function setVendorName($vendorName) 227 | { 228 | $this->vendorName = $vendorName; 229 | } 230 | 231 | /** 232 | * Get vendorName. 233 | * 234 | * @return string 235 | */ 236 | public function getVendorName(): string 237 | { 238 | return $this->vendorName; 239 | } 240 | 241 | /** 242 | * Set packageName. 243 | * 244 | * @param string $packageName 245 | */ 246 | public function setPackageName(string $packageName) 247 | { 248 | $this->packageName = $packageName; 249 | } 250 | 251 | /** 252 | * Get packageName. 253 | * 254 | * @return string 255 | */ 256 | public function getPackageName(): string 257 | { 258 | return $this->packageName; 259 | } 260 | 261 | /** 262 | * Set branch. 263 | * 264 | * @param string $branch 265 | */ 266 | public function setBranch(string $branch) 267 | { 268 | $this->branch = $branch; 269 | } 270 | 271 | /** 272 | * Get branch. 273 | * 274 | * @return string 275 | */ 276 | public function getBranch(): string 277 | { 278 | return $this->branch; 279 | } 280 | 281 | /** 282 | * Get the total stats. 283 | * 284 | * @todo: Refactor into a service 285 | * 286 | * @return array 287 | */ 288 | public function getTotalStats(): array 289 | { 290 | $stats = ['unstable' => 0, 'stable' => 0, 'outdated' => 0]; 291 | 292 | foreach ($this->getDependencies() as $dependency) { 293 | $stats[$dependency->getStatus()] += 1; 294 | } 295 | 296 | return $stats; 297 | } 298 | 299 | /** 300 | * Set createdAt. 301 | * 302 | * @param \DateTimeInterface $createdAt 303 | */ 304 | public function setCreatedAt(\DateTimeInterface $createdAt) 305 | { 306 | $this->createdAt = $createdAt; 307 | } 308 | 309 | /** 310 | * Get createdAt. 311 | * 312 | * @return \DateTimeInterface 313 | */ 314 | public function getCreatedAt(): \DateTimeInterface 315 | { 316 | return $this->createdAt; 317 | } 318 | 319 | /** 320 | * Set updatedAt. 321 | * 322 | * @param \DateTimeInterface $updatedAt 323 | * 324 | * @return Project 325 | */ 326 | public function setUpdatedAt(\DateTimeInterface $updatedAt) 327 | { 328 | $this->updatedAt = $updatedAt; 329 | } 330 | 331 | /** 332 | * Get updatedAt. 333 | * 334 | * @return \DateTimeInterface 335 | */ 336 | public function getUpdatedAt(): \DateTimeInterface 337 | { 338 | return $this->updatedAt; 339 | } 340 | 341 | /** 342 | * Set deletedAt. 343 | * 344 | * @param \DateTimeInterface $deletedAt 345 | */ 346 | public function setDeletedAt(\DateTimeInterface $deletedAt = null) 347 | { 348 | $this->deletedAt = $deletedAt; 349 | } 350 | 351 | /** 352 | * Get deletedAt. 353 | * 354 | * @return \DateTimeInterface|null 355 | */ 356 | public function getDeletedAt(): ?\DateTimeInterface 357 | { 358 | return $this->deletedAt; 359 | } 360 | } 361 | -------------------------------------------------------------------------------- /src/AppBundle/Entity/User.php: -------------------------------------------------------------------------------- 1 | id; 64 | } 65 | 66 | /** 67 | * Get first name of user. 68 | * 69 | * @return string 70 | */ 71 | public function getFirstName() 72 | { 73 | return $this->firstName; 74 | } 75 | 76 | /** 77 | * Set user first name. 78 | * 79 | * @param string $firstName 80 | * 81 | * @return User 82 | */ 83 | public function setFirstName($firstName) 84 | { 85 | $this->firstName = $firstName; 86 | 87 | return $this; 88 | } 89 | 90 | /** 91 | * Get last name of user. 92 | * 93 | * @return string 94 | */ 95 | public function getLastName() 96 | { 97 | return $this->lastName; 98 | } 99 | 100 | /** 101 | * Set user last name. 102 | * 103 | * @param string $lastName 104 | * 105 | * @return User 106 | */ 107 | public function setLastName($lastName) 108 | { 109 | $this->lastName = $lastName; 110 | 111 | return $this; 112 | } 113 | 114 | /** 115 | * Get the name of a user. 116 | * 117 | * @return string 118 | */ 119 | public function getName() 120 | { 121 | return $this->getFirstName() . ' ' . $this->getLastName(); 122 | } 123 | 124 | /** 125 | * Get creation date. 126 | * 127 | * @return \DateTime 128 | */ 129 | public function getCreatedAt() 130 | { 131 | return $this->createdAt; 132 | } 133 | 134 | /** 135 | * Get update date. 136 | * 137 | * @return \DateTime 138 | */ 139 | public function getUpdatedAt() 140 | { 141 | return $this->updatedAt; 142 | } 143 | 144 | /** 145 | * Get deletion date. 146 | * 147 | * @return \DateTime 148 | */ 149 | public function getDeletedAt() 150 | { 151 | return $this->deletedAt; 152 | } 153 | 154 | /** 155 | * Set deletion date. 156 | * 157 | * @param \DateTime $deletedAt 158 | */ 159 | public function setDeletedAt(\DateTime $deletedAt = null) 160 | { 161 | $this->deletedAt = $deletedAt; 162 | } 163 | 164 | /** 165 | * Set createdAt. 166 | * 167 | * @param \DateTime $createdAt 168 | * 169 | * @return User 170 | */ 171 | public function setCreatedAt($createdAt) 172 | { 173 | $this->createdAt = $createdAt; 174 | 175 | return $this; 176 | } 177 | 178 | /** 179 | * Set updatedAt. 180 | * 181 | * @param \DateTime $updatedAt 182 | * 183 | * @return User 184 | */ 185 | public function setUpdatedAt($updatedAt) 186 | { 187 | $this->updatedAt = $updatedAt; 188 | 189 | return $this; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/AppBundle/Form/Type/ChangePasswordType.php: -------------------------------------------------------------------------------- 1 | add('name') 28 | ->add('description') 29 | ->add('repositoryType', ChoiceType::class, [ 30 | 'choices' => ['Github' => 'github'/*, 'gitlab' => 'gitlab', 'Bitbucket' => 'bitbucket'*/], 31 | ]) 32 | ->add('repositoryUrl') 33 | ->add('vendorName') 34 | ->add('packageName') 35 | ->add('branch'); 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function configureOptions(OptionsResolver $resolver) 42 | { 43 | $resolver->setDefaults( 44 | [ 45 | 'data_class' => 'AppBundle\Entity\Project', 46 | ] 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/AppBundle/Form/Type/UserFormType.php: -------------------------------------------------------------------------------- 1 | add('firstname') 29 | ->add('lastname') 30 | ->add('email') 31 | ->add('roles', CollectionType::class, [ 32 | 'entry_type' => ChoiceType::class, 33 | 'entry_options' => [ 34 | 'choices' => [ 35 | 'Admin' => 'ROLE_ADMIN', 36 | 'Developer' => 'ROLE_DEVELOPER', 37 | 'Viewer' => 'ROLE_VIEWER', 38 | ], 39 | 'choices_as_values' => true, 40 | 'label' => false, 41 | ], 42 | ]); 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | public function configureOptions(OptionsResolver $resolver) 49 | { 50 | $resolver->setDefaults( 51 | [ 52 | 'data_class' => 'AppBundle\Entity\User', 53 | ] 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/AppBundle/Menu/Builder.php: -------------------------------------------------------------------------------- 1 | factory = $factory; 39 | $this->security = $security; 40 | } 41 | 42 | /** 43 | * Create the side menu. 44 | * 45 | * @return ItemInterface 46 | */ 47 | public function createSideMenu() 48 | { 49 | $menu = $this->factory->createItem('root'); 50 | $menu->setChildrenAttribute('class', 'sidebar-menu'); 51 | 52 | $menu->addChild( 53 | 'Projects', 54 | [ 55 | 'route' => 'packy_project_overview', 56 | 'extras' => [ 57 | 'icon' => 'fa-tasks fa-fw', 58 | ], 59 | ] 60 | ); 61 | 62 | if ($this->security->isGranted('ROLE_ADMIN')) { 63 | $menu->addChild( 64 | 'Users', 65 | [ 66 | 'route' => 'packy_user_overview', 67 | 'extras' => [ 68 | 'icon' => 'fa-users fa-fw', 69 | ], 70 | ] 71 | ); 72 | } 73 | 74 | return $menu; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/AppBundle/Menu/Voter/RouteVoter.php: -------------------------------------------------------------------------------- 1 | requestStack = $requestStack; 33 | } 34 | 35 | /** 36 | * match item to route. 37 | * 38 | * @param ItemInterface $item 39 | * 40 | * @return null|bool true if the item is current, null if not 41 | */ 42 | public function matchItem(ItemInterface $item) 43 | { 44 | if (null === $this->requestStack->getCurrentRequest()) { 45 | return null; 46 | } 47 | 48 | $route = $this->requestStack->getCurrentRequest()->attributes->get('_route'); 49 | if (null === $route) { 50 | return null; 51 | } 52 | 53 | $routes = (array) $item->getExtra('routes', []); 54 | 55 | foreach ($routes as $itemRoute) { 56 | if (isset($itemRoute['route'])) { 57 | if (is_string($itemRoute['route'])) { 58 | $itemRoute = [ 59 | 'route' => $itemRoute['route'], 60 | 'pattern' => '/' . $itemRoute['route'] . '/', 61 | ]; 62 | 63 | if ($this->isMatchingRoute($itemRoute)) { 64 | return true; 65 | } 66 | } 67 | } 68 | } 69 | 70 | return null; 71 | } 72 | 73 | /** 74 | * Check if we can match a route. 75 | * 76 | * @param array $itemRoute An array with the route and the route pattern 77 | * 78 | * @return bool true if a match was found, false if not 79 | */ 80 | private function isMatchingRoute(array $itemRoute) 81 | { 82 | $route = $this->requestStack->getCurrentRequest()->attributes->get('_route'); 83 | $route = $this->getBaseRoute($route); 84 | 85 | if (!empty($itemRoute['route'])) { 86 | if ($this->getBaseRoute($itemRoute['route']) === $route) { 87 | return true; 88 | } 89 | } 90 | 91 | return false; 92 | } 93 | 94 | /** 95 | * Get the base of the route. 96 | * 97 | * @param $route 98 | * 99 | * @return string 100 | */ 101 | private function getBaseRoute($route) 102 | { 103 | $chunks = explode('_', $route); 104 | 105 | return implode('_', array_slice($chunks, 0, 2)); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/AppBundle/PackageManager/PackageManager.php: -------------------------------------------------------------------------------- 1 | packageManagers = []; 27 | } 28 | 29 | /** 30 | * @param PackageManager $manager 31 | * @param string $alias 32 | */ 33 | public function add(PackageManager $manager, string $alias) 34 | { 35 | $this->packageManagers[$alias] = $manager; 36 | } 37 | 38 | /** 39 | * @param string $alias 40 | * 41 | * @return PackageManager 42 | */ 43 | public function get(string $alias): PackageManager 44 | { 45 | return $this->packageManagers[$alias]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/AppBundle/PackageManager/Packagist.php: -------------------------------------------------------------------------------- 1 | get( 33 | $this->packageVendor . $package->getName() . '.json', 34 | [ 35 | 'exceptions' => false, 36 | ] 37 | ); 38 | 39 | if ($response->getStatusCode() == 200) { 40 | $data = $this->parseJson((string) $response->getBody()); 41 | 42 | $newestVersion = $this->getLatestVersion(array_keys($data['package']['versions'])); 43 | $package->setLatestVersion($newestVersion); 44 | $package->setLastCheckAt(new \DateTime()); 45 | } 46 | 47 | return $package; 48 | } 49 | 50 | /** 51 | * Parse JSON data. 52 | * 53 | * @param string $data 54 | * 55 | * @return mixed 56 | */ 57 | private function parseJson($data) 58 | { 59 | $parsedData = json_decode($data, true); 60 | if ($parsedData === false) { 61 | throw new \RuntimeException('Unable to parse json file'); 62 | } 63 | 64 | return $parsedData; 65 | } 66 | 67 | /** 68 | * Find latest version. 69 | * 70 | * @param array $versions 71 | * 72 | * @return string 73 | */ 74 | private function getLatestVersion($versions = []) 75 | { 76 | $latestVersion = '0.0.0'; 77 | foreach ($versions as $version) { 78 | $version = ltrim($version, 'v'); 79 | if (preg_match('/^[0-9.]+$/', $version)) { 80 | if (version_compare($latestVersion, $version) >= 0) { 81 | continue; 82 | } 83 | $latestVersion = $version; 84 | } 85 | } 86 | 87 | return $latestVersion; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/AppBundle/PackageManager/Pypi.php: -------------------------------------------------------------------------------- 1 | get( 33 | $this->packageVendor . $package->getName() . '/json', 34 | [ 35 | 'exceptions' => false, 36 | ] 37 | ); 38 | 39 | if ($response->getStatusCode() == 200) { 40 | $data = $this->parseJson((string) $response->getBody()); 41 | 42 | $newestVersion = $data['info']['version']; 43 | $package->setLatestVersion($newestVersion); 44 | $package->setLastCheckAt(new \DateTime()); 45 | } 46 | 47 | return $package; 48 | } 49 | 50 | /** 51 | * Parse JSON data. 52 | * 53 | * @param string $data 54 | * 55 | * @return mixed 56 | */ 57 | private function parseJson($data) 58 | { 59 | $parsedData = json_decode($data, true); 60 | if ($parsedData === false) { 61 | throw new \RuntimeException('Unable to parse json file'); 62 | } 63 | 64 | return $parsedData; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/AppBundle/PackageManager/Registry.php: -------------------------------------------------------------------------------- 1 | get( 33 | $this->packageVendor . $package->getName(), 34 | [ 35 | 'exceptions' => false, 36 | ] 37 | ); 38 | 39 | if ($response->getStatusCode() == 200) { 40 | $data = $this->parseJson((string) $response->getBody()); 41 | 42 | $newestVersion = $data['dist-tags']['latest']; 43 | $package->setLatestVersion($newestVersion); 44 | $package->setLastCheckAt(new \DateTime()); 45 | } 46 | 47 | return $package; 48 | } 49 | 50 | /** 51 | * Parse JSON data. 52 | * 53 | * @param string $data 54 | * 55 | * @return mixed 56 | */ 57 | private function parseJson($data) 58 | { 59 | $parsedData = json_decode($data, true); 60 | if ($parsedData === false) { 61 | throw new \RuntimeException('Unable to parse json file'); 62 | } 63 | 64 | return $parsedData; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/AppBundle/Repository/DependencyRepository.php: -------------------------------------------------------------------------------- 1 | objectManager = $objectManager; 49 | } 50 | 51 | /** 52 | * Find all dependencies for a certain manager. 53 | * 54 | * @param Project $project 55 | * @param string $sortField 56 | * @param string $sortOrder 57 | * 58 | * @return array 59 | */ 60 | public function findAllByProject(Project $project, $sortField = 'pa.name', $sortOrder = 'ASC') 61 | { 62 | return $this->getQueryBuilder() 63 | ->leftJoin(self::ENTITY_ALIAS . '.project', 'p') 64 | ->leftJoin(self::ENTITY_ALIAS . '.package', 'pa') 65 | ->where('p = :project') 66 | ->setParameter('project', $project) 67 | ->orderBy($sortField, $sortOrder) 68 | ->getQuery() 69 | ->getResult(); 70 | } 71 | 72 | /** 73 | * Find all dependencies for a certain project and manager. 74 | * 75 | * @param Project $project 76 | * @param string $manager 77 | * @param string $sortField 78 | * @param string $sortOrder 79 | * 80 | * @return array 81 | */ 82 | public function findAllByManager(Project $project, $manager, $sortField = 'pa.name', $sortOrder = 'ASC') 83 | { 84 | return $this->getQueryBuilder() 85 | ->leftJoin(self::ENTITY_ALIAS . '.project', 'p') 86 | ->leftJoin(self::ENTITY_ALIAS . '.package', 'pa') 87 | ->where('p = :project') 88 | ->andWhere('pa.manager = :manager') 89 | ->setParameter('project', $project) 90 | ->setParameter('manager', $manager) 91 | ->orderBy($sortField, $sortOrder) 92 | ->getQuery() 93 | ->getResult(); 94 | } 95 | 96 | /** 97 | * get QueryBuilder. 98 | * 99 | * @return QueryBuilder 100 | */ 101 | public function getQueryBuilder() 102 | { 103 | return $this->objectManager 104 | ->getRepository(self::ENTITY_CLASS) 105 | ->createQueryBuilder(self::ENTITY_ALIAS); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/AppBundle/Repository/PackageRepository.php: -------------------------------------------------------------------------------- 1 | objectManager = $objectManager; 49 | } 50 | 51 | /** 52 | * Find all packages. 53 | * 54 | * @param string $sortField 55 | * @param string $sortOrder 56 | * 57 | * @return array 58 | */ 59 | public function findAll($sortField = 'createdAt', $sortOrder = 'DESC') 60 | { 61 | return $this->getQueryBuilder() 62 | ->orderBy(self::ENTITY_ALIAS . '.' . $sortField, $sortOrder) 63 | ->getQuery() 64 | ->getResult(); 65 | } 66 | 67 | /** 68 | * Return one package. 69 | * 70 | * @param string $name 71 | * @param string $manager 72 | * 73 | * @return mixed 74 | * 75 | * @throws \Doctrine\ORM\NonUniqueResultException 76 | */ 77 | public function findOne($name, $manager) 78 | { 79 | return $this->getQueryBuilder() 80 | ->where(self::ENTITY_ALIAS . '.name = :name') 81 | ->andWhere(self::ENTITY_ALIAS . '.manager = :manager') 82 | ->setParameter(':name', $name) 83 | ->setParameter(':manager', $manager) 84 | ->getQuery() 85 | ->getOneOrNullResult(); 86 | } 87 | 88 | /** 89 | * Create a package. 90 | * 91 | * @param Package $package 92 | */ 93 | public function create(Package $package) 94 | { 95 | $this->objectManager->persist($package); 96 | $this->objectManager->flush(); 97 | } 98 | 99 | /** 100 | * Update a package. 101 | * 102 | * @param Package $package 103 | */ 104 | public function update(Package $package) 105 | { 106 | $this->objectManager->persist($package); 107 | $this->objectManager->flush(); 108 | } 109 | 110 | /** 111 | * Delete a package. 112 | * 113 | * @param Package $package 114 | */ 115 | public function delete(Package $package) 116 | { 117 | $this->objectManager->remove($package); 118 | $this->objectManager->flush(); 119 | } 120 | 121 | /** 122 | * get QueryBuilder. 123 | * 124 | * @return QueryBuilder 125 | */ 126 | public function getQueryBuilder() 127 | { 128 | return $this->objectManager 129 | ->getRepository(self::ENTITY_CLASS) 130 | ->createQueryBuilder(self::ENTITY_ALIAS); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/AppBundle/Repository/ProjectRepository.php: -------------------------------------------------------------------------------- 1 | objectManager = $objectManager; 49 | } 50 | 51 | /** 52 | * Find all projects. 53 | * 54 | * @param string $sortField 55 | * @param string $sortOrder 56 | * 57 | * @return Project[] 58 | */ 59 | public function findAll($sortField = 'createdAt', $sortOrder = 'DESC') 60 | { 61 | return $this->getQueryBuilder() 62 | ->orderBy(self::ENTITY_ALIAS . '.' . $sortField, $sortOrder) 63 | ->getQuery() 64 | ->getResult(); 65 | } 66 | 67 | /** 68 | * Create a project. 69 | * 70 | * @param Project $project 71 | */ 72 | public function create(Project $project) 73 | { 74 | $this->objectManager->persist($project); 75 | $this->objectManager->flush(); 76 | } 77 | 78 | /** 79 | * Update a project. 80 | * 81 | * @param Project $project 82 | */ 83 | public function update(Project $project) 84 | { 85 | $this->objectManager->persist($project); 86 | $this->objectManager->flush(); 87 | } 88 | 89 | /** 90 | * Delete a project. 91 | * 92 | * @param Project $project 93 | */ 94 | public function delete(Project $project) 95 | { 96 | $this->objectManager->remove($project); 97 | $this->objectManager->flush(); 98 | } 99 | 100 | /** 101 | * get QueryBuilder. 102 | * 103 | * @return QueryBuilder 104 | */ 105 | public function getQueryBuilder() 106 | { 107 | return $this->objectManager 108 | ->getRepository(self::ENTITY_CLASS) 109 | ->createQueryBuilder(self::ENTITY_ALIAS); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/AppBundle/Repository/UserRepository.php: -------------------------------------------------------------------------------- 1 | objectManager = $objectManager; 49 | } 50 | 51 | /** 52 | * Find all users. 53 | * 54 | * @param string $sortField 55 | * @param string $sortOrder 56 | * 57 | * @return array 58 | */ 59 | public function findAll($sortField = 'createdAt', $sortOrder = 'DESC') 60 | { 61 | return $this->getQueryBuilder() 62 | ->orderBy(self::ENTITY_ALIAS . '.' . $sortField, $sortOrder) 63 | ->getQuery() 64 | ->getResult(); 65 | } 66 | 67 | /** 68 | * Create an user. 69 | * 70 | * @param User $user 71 | */ 72 | public function create(User $user) 73 | { 74 | $this->objectManager->persist($user); 75 | $this->objectManager->flush(); 76 | } 77 | 78 | /** 79 | * Update an user. 80 | * 81 | * @param User $user 82 | */ 83 | public function update(User $user) 84 | { 85 | $this->objectManager->persist($user); 86 | $this->objectManager->flush(); 87 | } 88 | 89 | /** 90 | * Delete an user. 91 | * 92 | * @param User $user 93 | */ 94 | public function delete(User $user) 95 | { 96 | $this->objectManager->remove($user); 97 | $this->objectManager->flush(); 98 | } 99 | 100 | /** 101 | * Return a new query builder. 102 | * 103 | * @return QueryBuilder 104 | */ 105 | public function getQueryBuilder() 106 | { 107 | return $this->objectManager 108 | ->getRepository(self::ENTITY_CLASS) 109 | ->createQueryBuilder(self::ENTITY_ALIAS); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/AppBundle/RepositoryManager/Bitbucket.php: -------------------------------------------------------------------------------- 1 | client = new \Bitbucket\API\Repositories\Src(); 29 | //$this->client ->setCredentials( new Bitbucket\API\Authentication\Basic($bb_user, $bb_pass) ); 30 | } 31 | 32 | /** 33 | * Get the file contents. 34 | * 35 | * 36 | * @param Project $project 37 | * @param string $file 38 | * 39 | * @return array 40 | */ 41 | public function getFileContents(Project $project, string $file): array 42 | { 43 | $response = $this->client->raw( 44 | $project->getVendorName(), 45 | $project->getPackageName(), 46 | $project->getBranch(), 47 | $file 48 | ); 49 | 50 | return $this->parseJson($response->getContent()); 51 | } 52 | 53 | /** 54 | * Parse JSON data. 55 | * 56 | * @param string $data 57 | * 58 | * @return mixed 59 | */ 60 | private function parseJson($data) 61 | { 62 | $parsedData = json_decode($data, true); 63 | if ($parsedData === false) { 64 | throw new \RuntimeException('Unable to parse json file'); 65 | } 66 | 67 | return $parsedData; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/AppBundle/RepositoryManager/Github.php: -------------------------------------------------------------------------------- 1 | client = new \Github\Client(); 29 | } 30 | 31 | /** 32 | * Get the file contents. 33 | * 34 | * 35 | * @param Project $project 36 | * @param string $file 37 | * 38 | * @return array 39 | */ 40 | public function getFileContents(Project $project, string $file): array 41 | { 42 | try { 43 | $fileContent = $this->client->api('repo')->contents()->download( 44 | $project->getVendorName(), 45 | $project->getPackageName(), 46 | $file, 47 | $project->getBranch() 48 | ); 49 | 50 | return $this->parseJson($fileContent); 51 | } catch (\Github\Exception\RuntimeException $e) { 52 | return []; 53 | } 54 | } 55 | 56 | /** 57 | * Parse JSON data. 58 | * 59 | * @param string $data 60 | * 61 | * @return mixed 62 | */ 63 | private function parseJson($data) 64 | { 65 | $parsedData = json_decode($data, true); 66 | if ($parsedData === false) { 67 | throw new \RuntimeException('Unable to parse json file'); 68 | } 69 | 70 | return $parsedData; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/AppBundle/RepositoryManager/Gitlab.php: -------------------------------------------------------------------------------- 1 | client = new \Gitlab\Client(''); 29 | $this->client->authenticate('', \Gitlab\Client::AUTH_URL_TOKEN); 30 | } 31 | 32 | /** 33 | * Get the file contents. 34 | * 35 | * @param Project $project 36 | * @param string $file 37 | * 38 | * @return array 39 | */ 40 | public function getFileContents(Project $project, string $file): array 41 | { 42 | try { 43 | $fileContent = $this->client->api('repositories')->getFile( 44 | $project->getVendorName() . '/' . $project->getPackageName(), 45 | $file, 46 | $project->getBranch() 47 | ); 48 | 49 | return $this->parseJson($fileContent); 50 | } catch (\Gitlab\Exception\RuntimeException $e) { 51 | return []; 52 | } 53 | } 54 | 55 | /** 56 | * Parse JSON data. 57 | * 58 | * @param string $data 59 | * 60 | * @return mixed 61 | */ 62 | private function parseJson($data) 63 | { 64 | if ($data === false) { 65 | throw new \RuntimeException('Unable to parse json file'); 66 | } 67 | 68 | if (array_key_exists('content', $data)) { 69 | return json_decode(base64_decode($data['content']), true); 70 | } 71 | 72 | return ''; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/AppBundle/RepositoryManager/RepositoryManager.php: -------------------------------------------------------------------------------- 1 | repositoryManagers = []; 27 | } 28 | 29 | /** 30 | * @param RepositoryManager $manager 31 | * @param string $alias 32 | */ 33 | public function add(RepositoryManager $manager, string $alias) 34 | { 35 | $this->repositoryManagers[$alias] = $manager; 36 | } 37 | 38 | /** 39 | * @param string $alias 40 | * 41 | * @return RepositoryManager 42 | */ 43 | public function get(string $alias): RepositoryManager 44 | { 45 | return $this->repositoryManagers[$alias]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/doctrine/Dependency.orm.yml: -------------------------------------------------------------------------------- 1 | AppBundle\Entity\Dependency: 2 | type: entity 3 | table: dependency 4 | 5 | manyToOne: 6 | project: 7 | targetEntity: Project 8 | inversedBy: dependencies 9 | joinColumn: 10 | name: project_id 11 | referencedColumnName: id 12 | cascade: ["persist"] 13 | package: 14 | targetEntity: Package 15 | inversedBy: dependencies 16 | joinColumn: 17 | name: package_id 18 | referencedColumnName: id 19 | cascade: ["persist"] 20 | fetch: EAGER 21 | id: 22 | id: 23 | type: integer 24 | generator: { strategy: AUTO } 25 | 26 | fields: 27 | rawVersion: 28 | type: text 29 | nullable: true 30 | column: raw_version 31 | currentVersion: 32 | type: text 33 | nullable: true 34 | column: current_version 35 | createdAt: 36 | type: datetime 37 | column: created_at 38 | gedmo: 39 | timestampable: 40 | on: create 41 | updatedAt: 42 | type: datetime 43 | column: updated_at 44 | gedmo: 45 | timestampable: 46 | on: update 47 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/doctrine/Package.orm.yml: -------------------------------------------------------------------------------- 1 | AppBundle\Entity\Package: 2 | type: entity 3 | table: package 4 | 5 | oneToMany: 6 | dependencies: 7 | targetEntity: Dependency 8 | mappedBy: package 9 | cascade: ["persist", "merge", "remove"] 10 | 11 | id: 12 | id: 13 | type: integer 14 | generator: { strategy: AUTO } 15 | 16 | fields: 17 | name: 18 | type: string 19 | length: 255 20 | manager: 21 | type: string 22 | length: 255 23 | latestVersion: 24 | type: text 25 | nullable: true 26 | column: latest_version 27 | lastCheckAt: 28 | type: datetime 29 | nullable: true 30 | column: last_checked_at 31 | createdAt: 32 | type: datetime 33 | column: created_at 34 | gedmo: 35 | timestampable: 36 | on: create 37 | updatedAt: 38 | type: datetime 39 | column: updated_at 40 | gedmo: 41 | timestampable: 42 | on: update 43 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/doctrine/Project.orm.yml: -------------------------------------------------------------------------------- 1 | AppBundle\Entity\Project: 2 | type: entity 3 | table: project 4 | 5 | gedmo: 6 | soft_deleteable: 7 | field_name: deletedAt 8 | time_aware: true 9 | 10 | oneToMany: 11 | dependencies: 12 | targetEntity: Dependency 13 | mappedBy: project 14 | cascade: ["persist", "merge", "remove"] 15 | 16 | id: 17 | id: 18 | type: integer 19 | generator: { strategy: AUTO } 20 | 21 | fields: 22 | name: 23 | type: string 24 | length: 150 25 | description: 26 | type: text 27 | nullable: true 28 | repositoryType: 29 | type: string 30 | length: 25 31 | column: repository_type 32 | repositoryUrl: 33 | type: string 34 | length: 255 35 | column: repository_url 36 | vendorName: 37 | type: string 38 | length: 50 39 | column: vendor_name 40 | packageName: 41 | type: string 42 | length: 50 43 | column: package_name 44 | branch: 45 | type: string 46 | length: 50 47 | column: branch 48 | createdAt: 49 | type: datetime 50 | column: created_at 51 | gedmo: 52 | timestampable: 53 | on: create 54 | updatedAt: 55 | type: datetime 56 | column: updated_at 57 | gedmo: 58 | timestampable: 59 | on: update 60 | deletedAt: 61 | type: datetime 62 | column: deleted_at 63 | nullable: true 64 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/doctrine/User.orm.yml: -------------------------------------------------------------------------------- 1 | AppBundle\Entity\User: 2 | type: entity 3 | table: user 4 | 5 | gedmo: 6 | soft_deleteable: 7 | field_name: deletedAt 8 | time_aware: true 9 | 10 | id: 11 | id: 12 | type: integer 13 | generator: { strategy: AUTO } 14 | 15 | fields: 16 | firstName: 17 | type: string 18 | nullable: true 19 | column: first_name 20 | lastName: 21 | type: string 22 | nullable: true 23 | column: last_name 24 | createdAt: 25 | type: datetime 26 | column: created_at 27 | gedmo: 28 | timestampable: 29 | on: create 30 | updatedAt: 31 | type: datetime 32 | column: updated_at 33 | gedmo: 34 | timestampable: 35 | on: update 36 | deletedAt: 37 | type: datetime 38 | column: deleted_at 39 | nullable: true 40 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/routing.yml: -------------------------------------------------------------------------------- 1 | packy_projects: 2 | resource: "@AppBundle/Resources/config/routing/project.yml" 3 | prefix: /projects 4 | packy_profile: 5 | resource: "@AppBundle/Resources/config/routing/profile.yml" 6 | prefix: /profile 7 | packy_users: 8 | resource: "@AppBundle/Resources/config/routing/user.yml" 9 | prefix: /admin/users 10 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/routing/profile.yml: -------------------------------------------------------------------------------- 1 | packy_profile_change_password: 2 | path: /change-password 3 | defaults: { _controller: AppBundle:Profile:changePassword } 4 | methods: [GET, POST] 5 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/routing/project.yml: -------------------------------------------------------------------------------- 1 | packy_project_overview: 2 | path: /overview 3 | defaults: { _controller: AppBundle:Project:overview } 4 | methods: [GET] 5 | packy_project_add: 6 | path: /projects/add 7 | defaults: { _controller: AppBundle:Project:add } 8 | methods: [GET, POST] 9 | packy_project_analyze: 10 | path: /projects/{projectId}/analyze 11 | defaults: { _controller: AppBundle:Project:analyze } 12 | methods: [GET] 13 | requirements: 14 | projectId: \d+ 15 | packy_project_edit: 16 | path: /projects/{projectId}/edit 17 | defaults: { _controller: AppBundle:Project:edit } 18 | methods: [GET, POST] 19 | requirements: 20 | projectId: \d+ 21 | packy_project_delete: 22 | path: /projects/{projectId}/delete 23 | defaults: { _controller: AppBundle:Project:delete } 24 | methods: [DELETE] 25 | requirements: 26 | projectId: \d+ 27 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/routing/user.yml: -------------------------------------------------------------------------------- 1 | packy_user_overview: 2 | path: /overview 3 | defaults: { _controller: AppBundle:User:overview } 4 | methods: [GET] 5 | packy_user_add: 6 | path: /add 7 | defaults: { _controller: AppBundle:User:add } 8 | methods: [GET, POST] 9 | packy_user_edit: 10 | path: /{userId}/edit 11 | defaults: { _controller: AppBundle:User:edit } 12 | methods: [GET, POST] 13 | requirements: 14 | userId: \d+ 15 | packy_user_delete: 16 | path: /{userId}/delete 17 | defaults: { _controller: AppBundle:User:delete } 18 | methods: [DELETE] 19 | requirements: 20 | userId: \d+ 21 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/service/dependency_managers.yml: -------------------------------------------------------------------------------- 1 | services: 2 | packy.dependency_managers: 3 | class: AppBundle\DependencyManager\DependencyManagers 4 | 5 | packy.dependency_manager.composer: 6 | class: AppBundle\DependencyManager\Composer 7 | tags: 8 | - { name: packy_dependency_manager, alias: composer } 9 | 10 | packy.dependency_manager.npm: 11 | class: AppBundle\DependencyManager\Npm 12 | tags: 13 | - { name: packy_dependency_manager, alias: npm } 14 | 15 | packy.dependency_manager.pip: 16 | class: AppBundle\DependencyManager\Pip 17 | tags: 18 | - { name: packy_dependency_manager, alias: pip } 19 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/service/package_managers.yml: -------------------------------------------------------------------------------- 1 | services: 2 | packy.package_managers: 3 | class: AppBundle\PackageManager\PackageManagers 4 | 5 | packy.package_manager.packagist: 6 | class: AppBundle\PackageManager\Packagist 7 | tags: 8 | - { name: packy_package_manager, alias: composer } 9 | 10 | packy.package_manager.pypi: 11 | class: AppBundle\PackageManager\Pypi 12 | tags: 13 | - { name: packy_package_manager, alias: pip } 14 | 15 | packy.package_manager.registry: 16 | class: AppBundle\PackageManager\Registry 17 | tags: 18 | - { name: packy_package_manager, alias: npm } 19 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/service/repository.yml: -------------------------------------------------------------------------------- 1 | services: 2 | packy.repository.project: 3 | class: AppBundle\Repository\ProjectRepository 4 | arguments: 5 | - "@doctrine.orm.entity_manager" 6 | 7 | packy.repository.package: 8 | class: AppBundle\Repository\PackageRepository 9 | arguments: 10 | - "@doctrine.orm.entity_manager" 11 | 12 | packy.repository.dependency: 13 | class: AppBundle\Repository\DependencyRepository 14 | arguments: 15 | - "@doctrine.orm.entity_manager" 16 | 17 | packy.repository.user: 18 | class: AppBundle\Repository\UserRepository 19 | arguments: 20 | - "@doctrine.orm.entity_manager" 21 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/service/repository_managers.yml: -------------------------------------------------------------------------------- 1 | services: 2 | packy.repository_managers: 3 | class: AppBundle\RepositoryManager\RepositoryManagers 4 | 5 | packy.repository_manager.composer: 6 | class: AppBundle\RepositoryManager\Bitbucket 7 | tags: 8 | - { name: packy_repository_manager, alias: bitbucket } 9 | 10 | packy.repository_manager.npm: 11 | class: AppBundle\RepositoryManager\Github 12 | tags: 13 | - { name: packy_repository_manager, alias: github } 14 | 15 | packy.repository_manager.pip: 16 | class: AppBundle\RepositoryManager\Gitlab 17 | tags: 18 | - { name: packy_repository_manager, alias: gitlab } 19 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/service/service.yml: -------------------------------------------------------------------------------- 1 | services: 2 | packy.service.version_formatter: 3 | class: AppBundle\Service\VersionFormatter 4 | 5 | packy.menu.voter.route_voter: 6 | class: AppBundle\Menu\Voter\RouteVoter 7 | arguments: 8 | - "@request_stack" 9 | tags: 10 | - { name: knp_menu.voter } 11 | 12 | packy.menu.builder: 13 | class: AppBundle\Menu\Builder 14 | arguments: 15 | - "@knp_menu.factory" 16 | - "@security.authorization_checker" 17 | tags: 18 | - { name: knp_menu.menu_builder, method: createSideMenu, alias: side_menu } 19 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/config/validation.yml: -------------------------------------------------------------------------------- 1 | AppBundle\Entity\Project: 2 | properties: 3 | name: 4 | - NotBlank: ~ 5 | repositoryType: 6 | - NotBlank: ~ 7 | repositoryUrl: 8 | - NotBlank: ~ 9 | - Url: ~ 10 | vendorName: 11 | - NotBlank: ~ 12 | packageName: 13 | - NotBlank: ~ 14 | 15 | AppBundle\Entity\User: 16 | properties: 17 | firstName: 18 | - NotBlank: ~ 19 | lastName: 20 | - NotBlank: ~ 21 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/views/Profile/change_password.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '::base.html.twig' %} 2 | 3 | {% block title %} 4 | {{ parent() }} | Users 5 | {% endblock %} 6 | 7 | {% block headerContent %} 8 |

9 | Profile 10 | 11 | Change password 12 | 13 |

14 | 20 | {% endblock %} 21 | 22 | {% block content %} 23 |
24 |
25 |
26 | {{ form_start(profileForm, { 'attr': { 'id': 'main-form'}}) }} 27 |
28 | 29 |
30 |
31 | {{ form_widget(profileForm) }} 32 |
33 | 36 | {{ form_end(profileForm, {'render_rest': false}) }} 37 |
38 |
39 |
40 | {% endblock %} 41 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/views/Project/analyze.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '::base.html.twig' %} 2 | {% import "::macro.html.twig" as macro %} 3 | 4 | 5 | {% block title %} 6 | {{ parent() }} | Projects 7 | {% endblock %} 8 | 9 | {% block stylesheets %} 10 | {{ parent() }} 11 | 12 | {% endblock %} 13 | 14 | {% block headerContent %} 15 |

16 | Projects 17 | Analyze {{ project.name }} 18 |

19 | 23 | {% endblock %} 24 | 25 | {% block content %} 26 |
27 |
28 | 60 |
61 | 62 |
63 |
64 |
65 |
66 | 67 |
68 |

69 | Status overview 70 |

71 |
72 |
73 |
74 | 75 |
76 |
77 |
78 |
79 |
80 | {% endblock %} 81 | 82 | {% block javascripts %} 83 | {{ parent() }} 84 | 85 | 153 | {% endblock %} 154 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/views/Project/form.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '::base.html.twig' %} 2 | 3 | {% block title %} 4 | {{ parent() }} | Projects 5 | {% endblock %} 6 | 7 | {% block headerContent %} 8 |

9 | Projects 10 | 11 | {% if project.id is null %} 12 | Add project 13 | {% else %} 14 | Edit {{ project.name }} 15 | {% endif %} 16 | 17 |

18 | 28 | {% endblock %} 29 | 30 | {% block content %} 31 |
32 |
33 |
34 | {{ form_start(projectForm, { 'attr': { 'id': 'main-form'}}) }} 35 |
36 | 37 |
38 |
39 | {{ form_widget(projectForm) }} 40 |
41 | 44 | {{ form_end(projectForm, {'render_rest': false}) }} 45 |
46 |
47 |
48 | {% endblock %} 49 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/views/Project/overview.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block headerContent %} 4 |

5 | Projects 6 | Overview 7 |

8 | 9 | 12 | {% endblock %} 13 | 14 | {% block content %} 15 |
16 |
17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {% if is_granted('ROLE_DEVELOPER') %} 29 | 30 | 31 | 32 | {% endif %} 33 | {% if projects is empty %} 34 | 35 | 36 | 37 | {% endif %} 38 | {% for project in projects %} 39 | 40 | 41 | 50 | 65 | 66 | {% endfor %} 67 | 68 |
Project nameStatsOptions
Add project
No projects found!
{{ project.name }} 42 | {% set stat = project.getTotalStats() %} 43 | {{ stat['stable'] }} 44 |   45 | {{ stat['unstable'] }} 46 |   47 | {{ stat['outdated'] }} 48 | 49 | 51 |
52 | 55 | 63 |
64 |
69 |
70 |
71 |
72 |
73 | {% endblock %} 74 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/views/User/form.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '::base.html.twig' %} 2 | 3 | {% block title %} 4 | {{ parent() }} | Users 5 | {% endblock %} 6 | 7 | {% block headerContent %} 8 |

9 | Users 10 | 11 | {% if user.id is null %} 12 | Add user 13 | {% else %} 14 | Edit {{ user.name }} 15 | {% endif %} 16 | 17 |

18 | 28 | {% endblock %} 29 | 30 | {% block content %} 31 |
32 |
33 |
34 | {{ form_start(userForm, { 'attr': { 'id': 'main-form'}}) }} 35 |
36 | 37 |
38 |
39 | {{ form_widget(userForm) }} 40 |
41 | 44 | {{ form_end(userForm, {'render_rest': false}) }} 45 |
46 |
47 |
48 | {% endblock %} 49 | -------------------------------------------------------------------------------- /src/AppBundle/Resources/views/User/overview.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block headerContent %} 4 |

5 | Users 6 | Overview 7 |

8 | 9 | 12 | {% endblock %} 13 | 14 | {% block content %} 15 |
16 |
17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | {% if users is empty %} 32 | 33 | 34 | 35 | {% endif %} 36 | {% for user in users %} 37 | 38 | 39 | 40 | 55 | 56 | {% endfor %} 57 | 58 |
NameUsernameOptions
Add user
No users found!
{{ user.name }}{{ user.username }} 41 |
42 | 45 | 53 |
54 |
59 |
60 |
61 |
62 |
63 | {% endblock %} 64 | -------------------------------------------------------------------------------- /src/AppBundle/Service/VersionFormatter.php: -------------------------------------------------------------------------------- 1 | determineVersionValue($versionRange); 30 | if (version_compare($normalizedVersion, $nowVersion) < 0) { 31 | $normalizedVersion = $nowVersion; 32 | } 33 | } 34 | } else { 35 | $normalizedVersion = $this->determineVersionValue($rawVersion); 36 | } 37 | 38 | // Remove any characters which don't belong in an actual version number 39 | $normalizedVersion = preg_replace('/[^0-9.]/', '', $normalizedVersion); 40 | 41 | return $normalizedVersion; 42 | } 43 | 44 | /** 45 | * Determine version value and handle wildcards and comparison operator. 46 | * 47 | * @param string $rawVersion 48 | * 49 | * @return string $version 50 | */ 51 | private function determineVersionValue($rawVersion) 52 | { 53 | $version = str_replace(['*', ' '], ['999', ''], $rawVersion); 54 | if (preg_match('/^([\~\>\<\=\!]+)([0-9\.]+)$/', $version, $m) && count($m) == 3) { 55 | $operator = $m[1]; 56 | $version = $m[2]; 57 | $versionAnnotations = explode('.', $version); 58 | if (count($versionAnnotations) == 3) { 59 | list($major, $minor, $patch) = $versionAnnotations; 60 | } else { 61 | switch (count($versionAnnotations)) { 62 | case 2: 63 | list($major, $minor) = $versionAnnotations; 64 | $patch = 999; 65 | break; 66 | 67 | default: 68 | $major = $versionAnnotations; 69 | $minor = 999; 70 | $patch = 999; 71 | break; 72 | } 73 | } 74 | if (mb_strpos($operator, '>') !== false || mb_strpos($operator, '!') !== false || mb_strpos($operator, '~') !== false) { 75 | $version = $major . '.999.999'; 76 | } elseif (mb_strpos($operator, '<') !== false) { 77 | if ($major == 0 && $minor > 0) { 78 | $version = $major . '.' . (((int) $minor) - 1) . '.999'; 79 | } elseif ($patch == 0) { 80 | $version = (((int) $major) - 1) . '.999.999'; 81 | } else { 82 | $version = $major . '.0.0'; 83 | } 84 | } 85 | } 86 | 87 | return $version; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /var/cache/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peternijssen/packy/28b78e419e398a44dde82ec7c197c005cc63eba1/var/cache/.gitkeep -------------------------------------------------------------------------------- /var/logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peternijssen/packy/28b78e419e398a44dde82ec7c197c005cc63eba1/var/logs/.gitkeep -------------------------------------------------------------------------------- /var/sessions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peternijssen/packy/28b78e419e398a44dde82ec7c197c005cc63eba1/var/sessions/.gitkeep -------------------------------------------------------------------------------- /web/.htaccess: -------------------------------------------------------------------------------- 1 | # Use the front controller as index file. It serves as a fallback solution when 2 | # every other rewrite/redirect fails (e.g. in an aliased environment without 3 | # mod_rewrite). Additionally, this reduces the matching process for the 4 | # start page (path "/") because otherwise Apache will apply the rewriting rules 5 | # to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl). 6 | DirectoryIndex app.php 7 | 8 | # Disabling MultiViews prevents unwanted negotiation, e.g. "/app" should not resolve 9 | # to the front controller "/app.php" but be rewritten to "/app.php/app". 10 | 11 | Options -MultiViews 12 | 13 | 14 | 15 | RewriteEngine On 16 | 17 | # Determine the RewriteBase automatically and set it as environment variable. 18 | # If you are using Apache aliases to do mass virtual hosting or installed the 19 | # project in a subdirectory, the base path will be prepended to allow proper 20 | # resolution of the app.php file and to redirect to the correct URI. It will 21 | # work in environments without path prefix as well, providing a safe, one-size 22 | # fits all solution. But as you do not need it in this case, you can comment 23 | # the following 2 lines to eliminate the overhead. 24 | RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$ 25 | RewriteRule ^(.*) - [E=BASE:%1] 26 | 27 | # Sets the HTTP_AUTHORIZATION header removed by apache 28 | RewriteCond %{HTTP:Authorization} . 29 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 30 | 31 | # Redirect to URI without front controller to prevent duplicate content 32 | # (with and without `/app.php`). Only do this redirect on the initial 33 | # rewrite by Apache and not on subsequent cycles. Otherwise we would get an 34 | # endless redirect loop (request -> rewrite to front controller -> 35 | # redirect -> request -> ...). 36 | # So in case you get a "too many redirects" error or you always get redirected 37 | # to the start page because your Apache does not expose the REDIRECT_STATUS 38 | # environment variable, you have 2 choices: 39 | # - disable this feature by commenting the following 2 lines or 40 | # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the 41 | # following RewriteCond (best solution) 42 | RewriteCond %{ENV:REDIRECT_STATUS} ^$ 43 | RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L] 44 | 45 | # If the requested filename exists, simply serve it. 46 | # We only want to let Apache serve files and not directories. 47 | RewriteCond %{REQUEST_FILENAME} -f 48 | RewriteRule .? - [L] 49 | 50 | # Rewrite all other queries to the front controller. 51 | RewriteRule .? %{ENV:BASE}/app.php [L] 52 | 53 | 54 | 55 | 56 | # When mod_rewrite is not available, we instruct a temporary redirect of 57 | # the start page to the front controller explicitly so that the website 58 | # and the generated links can still be used. 59 | RedirectMatch 302 ^/$ /app.php/ 60 | # RedirectTemp cannot be used instead 61 | 62 | 63 | -------------------------------------------------------------------------------- /web/app.php: -------------------------------------------------------------------------------- 1 | handle($request); 8 | $response->send(); 9 | $kernel->terminate($request, $response); 10 | -------------------------------------------------------------------------------- /web/app_dev.php: -------------------------------------------------------------------------------- 1 | handle($request); 27 | $response->send(); 28 | $kernel->terminate($request, $response); 29 | 30 | -------------------------------------------------------------------------------- /web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peternijssen/packy/28b78e419e398a44dde82ec7c197c005cc63eba1/web/favicon.ico -------------------------------------------------------------------------------- /web/robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | # www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449 3 | 4 | User-agent: * 5 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | // webpack.config.js 2 | var Encore = require('@symfony/webpack-encore'); 3 | 4 | Encore 5 | .setOutputPath('web/build/') 6 | .setPublicPath('/build') 7 | .cleanupOutputBeforeBuild() 8 | .addEntry('app', './app/Resources/public/js/packy.js') 9 | .addEntry('highcharts', [ 10 | 'highcharts', 11 | 'highcharts/css/highcharts.css', 12 | ]) 13 | .createSharedEntry('vendor', [ 14 | 'jquery', 15 | 'tether', 16 | 'bootstrap-sass', 17 | 'admin-lte', 18 | 'highcharts', 19 | 'bootstrap-sass/assets/stylesheets/_bootstrap.scss', 20 | 'font-awesome/css/font-awesome.css', 21 | 'admin-lte/dist/css/AdminLTE.css', 22 | 'admin-lte/dist/css/skins/skin-purple.css' 23 | ]) 24 | .enableSassLoader({ 25 | resolve_url_loader: false 26 | }) 27 | .autoProvidejQuery() 28 | .enableSourceMaps(!Encore.isProduction()) 29 | .enableVersioning() 30 | ; 31 | 32 | // export the final configuration 33 | module.exports = Encore.getWebpackConfig(); 34 | --------------------------------------------------------------------------------