Merge branch 'master' into feature_posts

This commit is contained in:
Alexey Skobkin 2015-06-02 10:56:29 +03:00
commit ca28ebd67d
13 changed files with 349 additions and 213 deletions

54
README.md Normal file
View file

@ -0,0 +1,54 @@
# Point Tools
Point Tools - это сервис предоставляющий дополнительные функции для блогов [Point.im](https://point.im/).
# Установка
Установка сервиса довольно проста:
## Получение исходников
```shell
git clone https://skobkin@bitbucket.org/skobkin/point-tools.git
cd point-tools
```
## Выставление прав
Выставьте права на запись для директорий `app/cache` и `app/logs`.
## Установка зависимостей
```shell
# В dev-среде:
composer install
# В prod-среде
composer install --no-dev --optimize-autoloader
```
После установки зависимостей у вас будут запрошены реквизиты доступа к БД PostgreSQL и данные необходимые для функционирования сервиса.
## Инициализация БД
```shell
php app/console doctrine:migrations:migrate
```
## Установка ресурсов
```shell
php app/console assets:install web --symlink
```
## Добавление задания в CRON
```shell
crontab -e
```
Вставьте в ваш файл crontab конфиг задания:
```crontab
# point.skobk.in
*/10 * * * * /usr/bin/php /path/to/point-tools/app/console point:update:subscriptions --env=prod
```

View file

@ -27,6 +27,9 @@
<li><a href="{{ path('index') }}"><span class="glyphicon glyphicon-home"></span> {{ 'Main'|trans }}</a></li> <li><a href="{{ path('index') }}"><span class="glyphicon glyphicon-home"></span> {{ 'Main'|trans }}</a></li>
<li><a href="{{ path('users_top') }}"><span class="glyphicon glyphicon-stats"></span> {{ 'Top'|trans }}</a></li> <li><a href="{{ path('users_top') }}"><span class="glyphicon glyphicon-stats"></span> {{ 'Top'|trans }}</a></li>
</ul> </ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="https://bitbucket.org/skobkin/point-tools/issues?status=new&status=open" target="_blank"><span class="glyphicon glyphicon-envelope"></span> {{ 'Report a bug'|trans }}</a></li>
</ul>
{% endblock %} {% endblock %}
</div> </div>
{%- endblock -%} {%- endblock -%}
@ -42,11 +45,16 @@
{% block footer %} {% block footer %}
<div class="row"> <div class="row">
<div class="copyright col-sm-6 col-xs-12"> <div class="copyright col-xs-8">
<p> <p>
&copy; 2015{% if 2015 != 'now'|date('Y') %}-{{ 'now'|date('Y') }}{% endif %} &copy; 2015{% if 2015 != 'now'|date('Y') %}-{{ 'now'|date('Y') }}{% endif %}
<a href="https://skobk.in/" target="_blank">Alexey Skobkin</a> aka <a href="https://skobkin-ru.point.im/" target="_blank">@skobkin-ru</a> <a href="https://skobk.in/" target="_blank">Alexey Skobkin</a> aka <a href="https://skobkin-ru.point.im/" target="_blank">@skobkin-ru</a>
</p> </p>
</div> </div>
<div class="powered-by col-xs-4">
<p class="pull-right">
<a href="https://bitbucket.org/skobkin/point-tools" target="_blank"><span class="glyphicon glyphicon-download-alt"></span> {{ 'Source code'|trans }}</a>
</p>
</div>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -542,11 +542,22 @@ class SymfonyRequirements extends RequirementCollection
/* optional recommendations follow */ /* optional recommendations follow */
$this->addRecommendation( if (file_exists(__DIR__.'/../vendor/composer')) {
file_get_contents(__FILE__) === file_get_contents(__DIR__.'/../vendor/sensio/distribution-bundle/Sensio/Bundle/DistributionBundle/Resources/skeleton/app/SymfonyRequirements.php'), require_once __DIR__.'/../vendor/autoload.php';
'Requirements file should be up-to-date',
'Your requirements file is outdated. Run composer install and re-check your configuration.' try {
); $r = new \ReflectionClass('Sensio\Bundle\DistributionBundle\SensioDistributionBundle');
$contents = file_get_contents(dirname($r->getFileName()).'/Resources/skeleton/app/SymfonyRequirements.php');
} catch (\ReflectionException $e) {
$contents = '';
}
$this->addRecommendation(
file_get_contents(__FILE__) === $contents,
'Requirements file should be up-to-date',
'Your requirements file is outdated. Run composer install and re-check your configuration.'
);
}
$this->addRecommendation( $this->addRecommendation(
version_compare($installedPhpVersion, '5.3.4', '>='), version_compare($installedPhpVersion, '5.3.4', '>='),

View file

@ -5,7 +5,7 @@ imports:
framework: framework:
#esi: ~ #esi: ~
#translator: { fallbacks: ["%locale%"] } translator: { fallbacks: ["%locale%"] }
secret: "%secret%" secret: "%secret%"
router: router:
resource: "%kernel.root_dir%/config/routing.yml" resource: "%kernel.root_dir%/config/routing.yml"

View file

@ -16,6 +16,7 @@ parameters:
point_api_base_url: https://point.im/api/ point_api_base_url: https://point.im/api/
point_use_https: true point_use_https: true
point_login: point-tools point_login: point-tools
point_id: 435
locale: en locale: en

224
composer.lock generated
View file

@ -1,23 +1,23 @@
{ {
"_readme": [ "_readme": [
"This file locks the dependencies of your project to a known state", "This file locks the dependencies of your project to a known state",
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "6f8a78a0b471fceb335f2e83e43985ef", "hash": "6f8a78a0b471fceb335f2e83e43985ef",
"packages": [ "packages": [
{ {
"name": "doctrine/annotations", "name": "doctrine/annotations",
"version": "v1.2.3", "version": "v1.2.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/annotations.git", "url": "https://github.com/doctrine/annotations.git",
"reference": "eeda578cbe24a170331a1cfdf78be723412df7a4" "reference": "b5202eb9e83f8db52e0e58867e0a46e63be8332e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/eeda578cbe24a170331a1cfdf78be723412df7a4", "url": "https://api.github.com/repos/doctrine/annotations/zipball/b5202eb9e83f8db52e0e58867e0a46e63be8332e",
"reference": "eeda578cbe24a170331a1cfdf78be723412df7a4", "reference": "b5202eb9e83f8db52e0e58867e0a46e63be8332e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -72,20 +72,20 @@
"docblock", "docblock",
"parser" "parser"
], ],
"time": "2014-12-20 20:49:38" "time": "2014-12-23 22:40:37"
}, },
{ {
"name": "doctrine/cache", "name": "doctrine/cache",
"version": "v1.4.0", "version": "v1.4.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/cache.git", "url": "https://github.com/doctrine/cache.git",
"reference": "2346085d2b027b233ae1d5de59b07440b9f288c8" "reference": "c9eadeb743ac6199f7eec423cb9426bc518b7b03"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/2346085d2b027b233ae1d5de59b07440b9f288c8", "url": "https://api.github.com/repos/doctrine/cache/zipball/c9eadeb743ac6199f7eec423cb9426bc518b7b03",
"reference": "2346085d2b027b233ae1d5de59b07440b9f288c8", "reference": "c9eadeb743ac6199f7eec423cb9426bc518b7b03",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -96,13 +96,13 @@
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": ">=3.7", "phpunit/phpunit": ">=3.7",
"predis/predis": "~0.8", "predis/predis": "~1.0",
"satooshi/php-coveralls": "~0.6" "satooshi/php-coveralls": "~0.6"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.4.x-dev" "dev-master": "1.5.x-dev"
} }
}, },
"autoload": { "autoload": {
@ -142,25 +142,28 @@
"cache", "cache",
"caching" "caching"
], ],
"time": "2015-01-15 20:38:55" "time": "2015-04-15 00:11:59"
}, },
{ {
"name": "doctrine/collections", "name": "doctrine/collections",
"version": "v1.2", "version": "v1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/collections.git", "url": "https://github.com/doctrine/collections.git",
"reference": "b99c5c46c87126201899afe88ec490a25eedd6a2" "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/collections/zipball/b99c5c46c87126201899afe88ec490a25eedd6a2", "url": "https://api.github.com/repos/doctrine/collections/zipball/6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
"reference": "b99c5c46c87126201899afe88ec490a25eedd6a2", "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3.2" "php": ">=5.3.2"
}, },
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
@ -177,17 +180,6 @@
"MIT" "MIT"
], ],
"authors": [ "authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
},
{ {
"name": "Roman Borschel", "name": "Roman Borschel",
"email": "roman@code-factory.org" "email": "roman@code-factory.org"
@ -196,11 +188,17 @@
"name": "Benjamin Eberlei", "name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de" "email": "kontakt@beberlei.de"
}, },
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{ {
"name": "Johannes Schmitt", "name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com", "email": "schmittjoh@gmail.com"
"homepage": "https://github.com/schmittjoh",
"role": "Developer of wrapped JMSSerializerBundle"
} }
], ],
"description": "Collections Abstraction library", "description": "Collections Abstraction library",
@ -210,20 +208,20 @@
"collections", "collections",
"iterator" "iterator"
], ],
"time": "2014-02-03 23:07:43" "time": "2015-04-14 22:21:58"
}, },
{ {
"name": "doctrine/common", "name": "doctrine/common",
"version": "v2.4.2", "version": "v2.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/common.git", "url": "https://github.com/doctrine/common.git",
"reference": "5db6ab40e4c531f14dad4ca96a394dfce5d4255b" "reference": "cd8daf2501e10c63dced7b8b9b905844316ae9d3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/common/zipball/5db6ab40e4c531f14dad4ca96a394dfce5d4255b", "url": "https://api.github.com/repos/doctrine/common/zipball/cd8daf2501e10c63dced7b8b9b905844316ae9d3",
"reference": "5db6ab40e4c531f14dad4ca96a394dfce5d4255b", "reference": "cd8daf2501e10c63dced7b8b9b905844316ae9d3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -240,7 +238,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "2.4.x-dev" "dev-master": "2.6.x-dev"
} }
}, },
"autoload": { "autoload": {
@ -253,17 +251,6 @@
"MIT" "MIT"
], ],
"authors": [ "authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
},
{ {
"name": "Roman Borschel", "name": "Roman Borschel",
"email": "roman@code-factory.org" "email": "roman@code-factory.org"
@ -272,11 +259,17 @@
"name": "Benjamin Eberlei", "name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de" "email": "kontakt@beberlei.de"
}, },
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{ {
"name": "Johannes Schmitt", "name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com", "email": "schmittjoh@gmail.com"
"homepage": "https://github.com/schmittjoh",
"role": "Developer of wrapped JMSSerializerBundle"
} }
], ],
"description": "Common Library for Doctrine projects", "description": "Common Library for Doctrine projects",
@ -288,7 +281,7 @@
"persistence", "persistence",
"spl" "spl"
], ],
"time": "2014-05-21 19:28:51" "time": "2015-04-02 19:55:44"
}, },
{ {
"name": "doctrine/dbal", "name": "doctrine/dbal",
@ -355,16 +348,16 @@
}, },
{ {
"name": "doctrine/doctrine-bundle", "name": "doctrine/doctrine-bundle",
"version": "v1.4.0", "version": "v1.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/DoctrineBundle.git", "url": "https://github.com/doctrine/DoctrineBundle.git",
"reference": "1986ff3a945b584c6505d07eae92d77e41131078" "reference": "0b9e27037c4fdbad515ee5ec89842e9091a6480f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/1986ff3a945b584c6505d07eae92d77e41131078", "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/0b9e27037c4fdbad515ee5ec89842e9091a6480f",
"reference": "1986ff3a945b584c6505d07eae92d77e41131078", "reference": "0b9e27037c4fdbad515ee5ec89842e9091a6480f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -372,6 +365,7 @@
"doctrine/doctrine-cache-bundle": "~1.0", "doctrine/doctrine-cache-bundle": "~1.0",
"jdorn/sql-formatter": "~1.1", "jdorn/sql-formatter": "~1.1",
"php": ">=5.3.2", "php": ">=5.3.2",
"symfony/console": "~2.3",
"symfony/doctrine-bridge": "~2.2", "symfony/doctrine-bridge": "~2.2",
"symfony/framework-bundle": "~2.3" "symfony/framework-bundle": "~2.3"
}, },
@ -390,7 +384,7 @@
"type": "symfony-bundle", "type": "symfony-bundle",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.4.x-dev" "dev-master": "1.5.x-dev"
} }
}, },
"autoload": { "autoload": {
@ -428,7 +422,7 @@
"orm", "orm",
"persistence" "persistence"
], ],
"time": "2015-02-28 11:04:45" "time": "2015-05-28 12:27:15"
}, },
{ {
"name": "doctrine/doctrine-cache-bundle", "name": "doctrine/doctrine-cache-bundle",
@ -521,19 +515,19 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git",
"reference": "6a1bd731dbdd4ad952a3b246a8f38c9c12f52e62" "reference": "1e8cd4415bd2f893eb828216b529a75e8b61d579"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/6a1bd731dbdd4ad952a3b246a8f38c9c12f52e62", "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/1e8cd4415bd2f893eb828216b529a75e8b61d579",
"reference": "6a1bd731dbdd4ad952a3b246a8f38c9c12f52e62", "reference": "1e8cd4415bd2f893eb828216b529a75e8b61d579",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"doctrine/doctrine-bundle": "~1.0", "doctrine/doctrine-bundle": "~1.0",
"doctrine/migrations": "~1.0@dev", "doctrine/migrations": "~1.0@dev",
"php": ">=5.3.2", "php": ">=5.3.2",
"symfony/framework-bundle": "~2.1" "symfony/framework-bundle": "~2.3|~3.0"
}, },
"type": "symfony-bundle", "type": "symfony-bundle",
"extra": { "extra": {
@ -571,7 +565,7 @@
"migrations", "migrations",
"schema" "schema"
], ],
"time": "2015-02-16 13:24:46" "time": "2015-05-06 08:32:15"
}, },
{ {
"name": "doctrine/inflector", "name": "doctrine/inflector",
@ -700,21 +694,28 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/migrations.git", "url": "https://github.com/doctrine/migrations.git",
"reference": "65978aa4e9ffca3bb632225ad8c6320077d80d85" "reference": "abb87d84ed21fd30c27bd3b52252a495a36d32fb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/migrations/zipball/65978aa4e9ffca3bb632225ad8c6320077d80d85", "url": "https://api.github.com/repos/doctrine/migrations/zipball/abb87d84ed21fd30c27bd3b52252a495a36d32fb",
"reference": "65978aa4e9ffca3bb632225ad8c6320077d80d85", "reference": "abb87d84ed21fd30c27bd3b52252a495a36d32fb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"doctrine/dbal": "~2.0", "doctrine/dbal": "~2.0",
"php": ">=5.3.2" "php": ">=5.3.2",
"symfony/console": "~2.3",
"symfony/yaml": "~2.3"
},
"conflict": {
"doctrine/orm": "<2.4"
}, },
"require-dev": { "require-dev": {
"symfony/console": "2.*", "doctrine/coding-standard": "dev-master",
"symfony/yaml": "2.*" "doctrine/orm": "2.*",
"phpunit/phpunit": "~4.0",
"satooshi/php-coveralls": "0.6.*"
}, },
"suggest": { "suggest": {
"symfony/console": "to run the migration from the console" "symfony/console": "to run the migration from the console"
@ -750,7 +751,7 @@
"database", "database",
"migrations" "migrations"
], ],
"time": "2015-03-23 09:47:20" "time": "2015-05-26 15:30:26"
}, },
{ {
"name": "doctrine/orm", "name": "doctrine/orm",
@ -1281,17 +1282,17 @@
}, },
{ {
"name": "sensio/distribution-bundle", "name": "sensio/distribution-bundle",
"version": "v3.0.20", "version": "v3.0.25",
"target-dir": "Sensio/Bundle/DistributionBundle", "target-dir": "Sensio/Bundle/DistributionBundle",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sensiolabs/SensioDistributionBundle.git", "url": "https://github.com/sensiolabs/SensioDistributionBundle.git",
"reference": "48c76189fb0a76a20a4a67a750b513ed06074b55" "reference": "01931139b0f067a4016d5d56e82c2b3086533b89"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sensiolabs/SensioDistributionBundle/zipball/48c76189fb0a76a20a4a67a750b513ed06074b55", "url": "https://api.github.com/repos/sensiolabs/SensioDistributionBundle/zipball/01931139b0f067a4016d5d56e82c2b3086533b89",
"reference": "48c76189fb0a76a20a4a67a750b513ed06074b55", "reference": "01931139b0f067a4016d5d56e82c2b3086533b89",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1337,21 +1338,20 @@
"configuration", "configuration",
"distribution" "distribution"
], ],
"time": "2015-03-26 11:09:50" "time": "2015-05-29 22:35:41"
}, },
{ {
"name": "sensio/framework-extra-bundle", "name": "sensio/framework-extra-bundle",
"version": "v3.0.6", "version": "v3.0.8",
"target-dir": "Sensio/Bundle/FrameworkExtraBundle",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git", "url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git",
"reference": "1c3ed356bd1ff67cd71806efbb71511644035c85" "reference": "a30fc18bf147bc25faf6b1d54bf55cfad4b63cba"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/1c3ed356bd1ff67cd71806efbb71511644035c85", "url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/a30fc18bf147bc25faf6b1d54bf55cfad4b63cba",
"reference": "1c3ed356bd1ff67cd71806efbb71511644035c85", "reference": "a30fc18bf147bc25faf6b1d54bf55cfad4b63cba",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1364,6 +1364,7 @@
}, },
"suggest": { "suggest": {
"symfony/expression-language": "", "symfony/expression-language": "",
"symfony/psr-http-message-bridge": "To use the PSR-7 converters",
"symfony/security-bundle": "" "symfony/security-bundle": ""
}, },
"type": "symfony-bundle", "type": "symfony-bundle",
@ -1373,8 +1374,8 @@
} }
}, },
"autoload": { "autoload": {
"psr-0": { "psr-4": {
"Sensio\\Bundle\\FrameworkExtraBundle": "" "Sensio\\Bundle\\FrameworkExtraBundle\\": ""
} }
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
@ -1392,20 +1393,20 @@
"annotations", "annotations",
"controllers" "controllers"
], ],
"time": "2015-03-24 15:12:07" "time": "2015-05-29 18:27:23"
}, },
{ {
"name": "sensiolabs/security-checker", "name": "sensiolabs/security-checker",
"version": "v2.0.1", "version": "v2.0.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sensiolabs/security-checker.git", "url": "https://github.com/sensiolabs/security-checker.git",
"reference": "134cecf1c61256bd8e973e11376891a724543820" "reference": "2c2a71f1c77d9765c12638c4724d9ca23658a810"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sensiolabs/security-checker/zipball/134cecf1c61256bd8e973e11376891a724543820", "url": "https://api.github.com/repos/sensiolabs/security-checker/zipball/2c2a71f1c77d9765c12638c4724d9ca23658a810",
"reference": "134cecf1c61256bd8e973e11376891a724543820", "reference": "2c2a71f1c77d9765c12638c4724d9ca23658a810",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1437,7 +1438,7 @@
} }
], ],
"description": "A security checker for your composer.lock", "description": "A security checker for your composer.lock",
"time": "2015-01-26 16:25:19" "time": "2015-05-28 14:22:40"
}, },
{ {
"name": "swiftmailer/swiftmailer", "name": "swiftmailer/swiftmailer",
@ -1678,12 +1679,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/symfony.git", "url": "https://github.com/symfony/symfony.git",
"reference": "6ce03d3942ae65b9bcbc2afbec800ea1cf8361d8" "reference": "7493c2bef54fb818c5304bdd9d2194890b839422"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/symfony/zipball/6ce03d3942ae65b9bcbc2afbec800ea1cf8361d8", "url": "https://api.github.com/repos/symfony/symfony/zipball/7493c2bef54fb818c5304bdd9d2194890b839422",
"reference": "6ce03d3942ae65b9bcbc2afbec800ea1cf8361d8", "reference": "7493c2bef54fb818c5304bdd9d2194890b839422",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1747,7 +1748,6 @@
"ircmaxell/password-compat": "~1.0", "ircmaxell/password-compat": "~1.0",
"monolog/monolog": "~1.11", "monolog/monolog": "~1.11",
"ocramius/proxy-manager": "~0.4|~1.0", "ocramius/proxy-manager": "~0.4|~1.0",
"propel/propel1": "~1.6",
"symfony/phpunit-bridge": "self.version" "symfony/phpunit-bridge": "self.version"
}, },
"type": "library", "type": "library",
@ -1757,14 +1757,14 @@
} }
}, },
"autoload": { "autoload": {
"psr-0": { "psr-4": {
"Symfony\\Bridge\\Doctrine\\": "src/", "Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/",
"Symfony\\Bridge\\Monolog\\": "src/", "Symfony\\Bridge\\Monolog\\": "src/Symfony/Bridge/Monolog/",
"Symfony\\Bridge\\ProxyManager\\": "src/", "Symfony\\Bridge\\ProxyManager\\": "src/Symfony/Bridge/ProxyManager/",
"Symfony\\Bridge\\Swiftmailer\\": "src/", "Symfony\\Bridge\\Swiftmailer\\": "src/Symfony/Bridge/Swiftmailer/",
"Symfony\\Bridge\\Twig\\": "src/", "Symfony\\Bridge\\Twig\\": "src/Symfony/Bridge/Twig/",
"Symfony\\Bundle\\": "src/", "Symfony\\Bundle\\": "src/Symfony/Bundle/",
"Symfony\\Component\\": "src/" "Symfony\\Component\\": "src/Symfony/Component/"
}, },
"classmap": [ "classmap": [
"src/Symfony/Component/HttpFoundation/Resources/stubs", "src/Symfony/Component/HttpFoundation/Resources/stubs",
@ -1779,21 +1779,21 @@
"MIT" "MIT"
], ],
"authors": [ "authors": [
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
},
{ {
"name": "Fabien Potencier", "name": "Fabien Potencier",
"email": "fabien@symfony.com" "email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
} }
], ],
"description": "The Symfony PHP framework", "description": "The Symfony PHP framework",
"homepage": "http://symfony.com", "homepage": "https://symfony.com",
"keywords": [ "keywords": [
"framework" "framework"
], ],
"time": "2015-03-29 09:44:52" "time": "2015-05-30 17:16:04"
}, },
{ {
"name": "twig/extensions", "name": "twig/extensions",
@ -1849,20 +1849,20 @@
}, },
{ {
"name": "twig/twig", "name": "twig/twig",
"version": "v1.18.0", "version": "v1.18.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/twigphp/Twig.git", "url": "https://github.com/twigphp/Twig.git",
"reference": "4cf7464348e7f9893a93f7096a90b73722be99cf" "reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/4cf7464348e7f9893a93f7096a90b73722be99cf", "url": "https://api.github.com/repos/twigphp/Twig/zipball/9f70492f44398e276d1b81c1b43adfe6751c7b7f",
"reference": "4cf7464348e7f9893a93f7096a90b73722be99cf", "reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.2.4" "php": ">=5.2.7"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@ -1902,7 +1902,7 @@
"keywords": [ "keywords": [
"templating" "templating"
], ],
"time": "2015-01-25 17:32:08" "time": "2015-04-19 08:30:27"
} }
], ],
"packages-dev": [ "packages-dev": [

View file

@ -44,8 +44,14 @@ class UpdateSubscriptionsCommand extends ContainerAwareCommand
/** @var SubscriptionsManager $subscriptionsManager */ /** @var SubscriptionsManager $subscriptionsManager */
$subscriptionsManager = $this->getContainer()->get('skobkin_point_tools.subscriptions_manager'); $subscriptionsManager = $this->getContainer()->get('skobkin_point_tools.subscriptions_manager');
$serviceUserName = $this->getContainer()->getParameter('point_login'); try {
$serviceUser = $this->getContainer()->get('doctrine.orm.entity_manager')->getRepository('SkobkinPointToolsBundle:User')->findOneBy(['login' => $serviceUserName]); $serviceUserId = $this->getContainer()->getParameter('point_id');
} catch (\InvalidArgumentException $e) {
$log->alert('Could not get point_id parameter from config file', ['exception_message' => $e->getMessage()]);
return false;
}
$serviceUser = $this->getContainer()->get('doctrine.orm.entity_manager')->getRepository('SkobkinPointToolsBundle:User')->find($serviceUserId);
if (!$serviceUser) { if (!$serviceUser) {
$log->info('Service user not found'); $log->info('Service user not found');
@ -59,16 +65,24 @@ class UpdateSubscriptionsCommand extends ContainerAwareCommand
} }
try { try {
$serviceSubscribers = $api->getUserSubscribersByLogin($serviceUserName); $serviceSubscribers = $api->getUserSubscribersById($serviceUserId);
} catch (\Exception $e) { } catch (\Exception $e) {
// @todo fallback to the local subscribers list
$output->writeln('Error while getting service subscribers'); $output->writeln('Error while getting service subscribers');
$log->error('Error while getting service subscribers.' . PHP_EOL . $log->error('Error while getting service subscribers.', ['user_login' => $serviceUser->getLogin(), 'user_id' => $serviceUser->getId(), 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
$e->getMessage() . PHP_EOL .
$e->getFile() . ':' . $e->getLine()
);
return false; $serviceSubscribers = [];
foreach ($serviceUser->getSubscribers() as $subscription) {
$serviceSubscribers[] = $subscription->getSubscriber();
}
$output->writeln('Fallback to local list');
$log->error('Fallback to local list');
if (!count($serviceSubscribers)) {
$log->info('No local subscribers. Finishing.');
return false;
}
} }
if ($output->isVerbose()) { if ($output->isVerbose()) {
@ -79,10 +93,7 @@ class UpdateSubscriptionsCommand extends ContainerAwareCommand
try { try {
$subscriptionsManager->updateUserSubscribers($serviceUser, $serviceSubscribers); $subscriptionsManager->updateUserSubscribers($serviceUser, $serviceSubscribers);
} catch (\Exception $e) { } catch (\Exception $e) {
$log->error('Error while updating service subscribers' . PHP_EOL . $log->error('Error while updating service subscribers', ['user_login' => $serviceUser->getLogin(), 'user_id' => $serviceUser->getId(), 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
$e->getMessage() . PHP_EOL .
$e->getFile() . ':' . $e->getLine()
);
return false; return false;
} }
@ -97,13 +108,10 @@ class UpdateSubscriptionsCommand extends ContainerAwareCommand
$log->info('Processing @' . $user->getLogin()); $log->info('Processing @' . $user->getLogin());
try { try {
$userCurrentSubscribers = $api->getUserSubscribersByLogin($user->getLogin()); $userCurrentSubscribers = $api->getUserSubscribersById($user->getId());
} catch (\Exception $e) { } catch (\Exception $e) {
$output->writeln(' Error while getting subscribers. Skipping.'); $output->writeln(' Error while getting subscribers. Skipping.');
$log->error('Error while getting subscribers.' . PHP_EOL . $log->error('Error while getting subscribers.', ['user_login' => $user->getLogin(), 'user_id' => $user->getId(), 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
$e->getMessage() . PHP_EOL .
$e->getFile() . ':' . $e->getLine()
);
continue; continue;
} }
@ -116,10 +124,7 @@ class UpdateSubscriptionsCommand extends ContainerAwareCommand
// Updating user subscribers // Updating user subscribers
$subscriptionsManager->updateUserSubscribers($user, $userCurrentSubscribers); $subscriptionsManager->updateUserSubscribers($user, $userCurrentSubscribers);
} catch (\Exception $e) { } catch (\Exception $e) {
$log->error('Error while updating user subscribers' . PHP_EOL . $log->error('Error while updating user subscribers', ['user_login' => $user->getLogin(), 'user_id' => $user->getId(), 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
$e->getMessage() . PHP_EOL .
$e->getFile() . ':' . $e->getLine()
);
} }
// @todo move to the config // @todo move to the config

View file

@ -184,7 +184,7 @@ class User
/** /**
* Get subscribers * Get subscribers
* *
* @return ArrayCollection * @return Subscription[]|ArrayCollection
*/ */
public function getSubscribers() public function getSubscribers()
{ {

View file

@ -38,6 +38,10 @@ body > .container {
margin-top: 30px; margin-top: 30px;
} }
.user-subscriptions-log {
margin-top: 30px;
}
h4.panel-title a { h4.panel-title a {
text-decoration: none; text-decoration: none;
} }

View file

@ -0,0 +1,32 @@
# Russian language for Point tools
# Шапка
Toggle navigation: Переключить навигацию
Main: Главная
Top: Топ
Report a bug: Сообщить об ошибке
# Подвал
Source code: Исходный код
# Главная
All users: Всего пользователей
Subscribed users: Подписчиков сервиса
24 hours events: Событий за сутки
Username: Имя пользователя
Search: Поиск
# Страница пользователя
Subscribers: Подписчики
Subscriptions log: Лог подписок
User: Пользователь
Action: Действие
Date: Дата
No subscribers data found: Информация о подписчиках отсутствует
No log data found: Лог отсутствует
# Топ пользователей
Top users: Популярные пользователи
Subscribers count: Подписчиков

View file

@ -3,30 +3,30 @@
{% block content %} {% block content %}
<div class="well well-lg"> <div class="well well-lg">
{# @todo rewrite to Symfony forms #} {# @todo rewrite to Symfony forms #}
<form class="form-inline" method="post" action="{{ url('user_search') }}"> <form class="form-inline" method="post" action="{{ path('user_search') }}">
<div class="form-group"> <div class="form-group">
<label class="sr-only" for="index-input-username">Username</label> <label class="sr-only" for="index-input-username">{{ 'Username'|trans }}</label>
<div class="input-group"> <div class="input-group">
<div class="input-group-addon">@</div> <div class="input-group-addon">@</div>
<input name="login" type="text" class="form-control" id="index-input-username" placeholder="username"> <input name="login" type="text" class="form-control" id="index-input-username" placeholder="username">
</div> </div>
</div> </div>
<button type="submit" class="btn btn-primary">Search</button> <button type="submit" class="btn btn-primary">{{ 'Search'|trans }}</button>
</form> </form>
</div> </div>
<div class="container service-stats"> <div class="container service-stats">
<div class="row"> <div class="row">
<div class="col-xs-2"><span class="glyphicon glyphicon-user"></span> {{ 'All users'|trans }}</div> <div class="col-xs-8 col-sm-3"><span class="glyphicon glyphicon-user"></span> {{ 'All users'|trans }}</div>
<div class="col-xs-2">{{ users_count }}</div> <div class="col-xs-4 col-sm-2">{{ users_count }}</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-2"><span class="glyphicon glyphicon-user"></span> {{ 'Subscribed users'|trans }}</div> <div class="col-xs-8 col-sm-3"><span class="glyphicon glyphicon-user"></span> {{ 'Subscribed users'|trans }}</div>
<div class="col-xs-2"><a href="{{ url('user_show', {'login': service_login}) }}">{{ subscribers_count }}</a></div> <div class="col-xs-4 col-sm-2"><a href="{{ url('user_show', {'login': service_login}) }}">{{ subscribers_count }}</a></div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-2"><span class="glyphicon glyphicon-list"></span> {{ 'Last events'|trans }}</div> <div class="col-xs-8 col-sm-3"><span class="glyphicon glyphicon-list"></span> {{ '24 hours events'|trans }}</div>
<div class="col-xs-2">{{ events_count }}</div> <div class="col-xs-4 col-sm-2">{{ events_count }}</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -9,68 +9,77 @@
</h1> </h1>
<div class="user-subscribers"> <div class="user-subscribers">
<div class="panel-group" id="accordion-subscribers"> {% if subscribers|length > 0 %}
<div class="panel panel-default"> <div class="panel-group" id="accordion-subscribers">
<div class="panel-heading"id="headingOne"> <div class="panel panel-default">
<h4 class="panel-title"> <div class="panel-heading" id="heading-subscribers">
<a data-toggle="collapse" data-parent="#accordion-subscribers" aria-expanded="true" href="#collapse-subscribers"> <h4 class="panel-title">
<span class="glyphicon glyphicon-collapse-down"></span> {{ 'Subscribers'|trans }} <a data-toggle="collapse" data-parent="#accordion-subscribers" aria-expanded="false" href="#collapse-subscribers">
</a> <span class="glyphicon glyphicon-collapse-down"></span> {{ 'Subscribers'|trans }}
</h4> </a>
</div> </h4>
<div id="collapse-subscribers" class="panel-collapse collapse in"> </div>
<div class="panel-body"> <div id="collapse-subscribers" class="panel-collapse collapse" aria-labelledby="heading-subscribers">
<ul class="users mosaic"> <div class="panel-body">
{% for user in subscribers %} <ul class="users mosaic">
<li><a href="{{ url('user_show', {login: user.login}) }}">@{{ user.login }}</a></li> {% for user in subscribers %}
{% endfor %} <li><a href="{{ url('user_show', {login: user.login}) }}">@{{ user.login }}</a></li>
</ul> {% endfor %}
</ul>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> {% else %}
<div class="alert alert-warning" role="alert">{{ 'No subscribers data found'|trans }}</div>
{% endif %}
</div> </div>
<div class="user-subscribers"> <div class="user-subscriptions-log">
<div class="panel-group" id="accordion-log"> {% if log|length > 0 %}
<div class="panel panel-default"> <div class="panel-group" id="accordion-log">
<div class="panel-heading" id="headingOne"> <div class="panel panel-default">
<h4 class="panel-title"> <div class="panel-heading" id="heading-subscriptions-log">
<a data-toggle="collapse" data-parent="#accordion-log" aria-expanded="true" href="#collapse-log"> <h4 class="panel-title">
<span class="glyphicon glyphicon-collapse-down"></span> {{ 'Subscriptions log'|trans }} <a data-toggle="collapse" data-parent="#accordion-log" aria-expanded="true" href="#collapse-log">
</a> <span class="glyphicon glyphicon-collapse-down"></span> {{ 'Subscriptions log'|trans }}
</h4> </a>
</div> </h4>
<div id="collapse-log" class="panel-collapse collapse in"> </div>
<div class="panel-body"> <div id="collapse-log" class="panel-collapse collapse in" aria-labelledby="heading-subscriptions-log">
<table class="table table-striped"> <div class="panel-body">
<thead> <table class="table table-striped">
<tr> <thead>
<td>{{ 'User'|trans }}</td>
<td>{{ 'Action'|trans }}</td>
<td>{{ 'Date'|trans }}</td>
</tr>
</thead>
<tbody>
{% for event in log %}
<tr> <tr>
<td> <td>{{ 'User'|trans }}</td>
<a href="{{ url('user_show', {login: event.subscriber.login}) }}">@{{ event.subscriber.login }}</a> <td>{{ 'Action'|trans }}</td>
</td> <td>{{ 'Date'|trans }}</td>
<td>
<span class="glyphicon {% if event.action == 'subscribe' %}glyphicon-plus{% elseif event.action == 'unsubscribe' %}glyphicon-minus{% endif %}"></span>
</td>
<td>
{# Use DateTime helper: https://sonata-project.org/bundles/intl/master/doc/reference/datetime.html #}
{{ event.date|date('H:i:s d F Y') }}
</td>
</tr> </tr>
{% endfor %} </thead>
</tbody> <tbody>
</table> {% for event in log %}
<tr>
<td>
<a href="{{ url('user_show', {login: event.subscriber.login}) }}">@{{ event.subscriber.login }}</a>
</td>
<td>
<span class="glyphicon {% if event.action == 'subscribe' %}glyphicon-plus{% elseif event.action == 'unsubscribe' %}glyphicon-minus{% endif %}"></span>
</td>
<td>
{# Use DateTime helper: https://sonata-project.org/bundles/intl/master/doc/reference/datetime.html #}
{{ event.date|date('d F Y H:i:s') }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> {% else %}
<div class="alert alert-warning" role="alert">{{ 'No log data found'|trans }}</div>
{% endif %}
</div> </div>
{% endblock %} {% endblock %}

View file

@ -18,6 +18,7 @@ class SubscriptionsManager
protected $em; protected $em;
// @todo Add logger
public function __construct(EntityManagerInterface $entityManager) public function __construct(EntityManagerInterface $entityManager)
{ {
$this->em = $entityManager; $this->em = $entityManager;
@ -38,6 +39,14 @@ class SubscriptionsManager
$oldSubscribersList[] = $subscription->getSubscriber(); $oldSubscribersList[] = $subscription->getSubscriber();
} }
$isFirstTime = false;
// Preventing to add garbage subscriptions for first processing
// @todo improve algorithm
if ((count($oldSubscribersList) === 0) && (count($newSubscribersList) > 1)) {
$isFirstTime = true;
}
unset($tmpOldSubscribers); unset($tmpOldSubscribers);
$subscribedList = $this->getUsersListsDiff($newSubscribersList, $oldSubscribersList); $subscribedList = $this->getUsersListsDiff($newSubscribersList, $oldSubscribersList);
@ -53,17 +62,20 @@ class SubscriptionsManager
$user->addSubscriber($subscription); $user->addSubscriber($subscription);
$logEvent = new SubscriptionEvent(); // If it's not first processing
$logEvent if (!$isFirstTime) {
->setSubscriber($subscribedUser) $logEvent = new SubscriptionEvent();
->setAuthor($user) $logEvent
->setAction(SubscriptionEvent::ACTION_SUBSCRIBE) ->setSubscriber($subscribedUser)
; ->setAuthor($user)
->setAction(SubscriptionEvent::ACTION_SUBSCRIBE);
$user->addNewSubscriberEvent($logEvent); $user->addNewSubscriberEvent($logEvent);
$this->em->persist($logEvent);
}
$this->em->persist($subscription); $this->em->persist($subscription);
$this->em->persist($logEvent);
} }
unset($subscribedList); unset($subscribedList);
@ -81,7 +93,7 @@ class SubscriptionsManager
$logEvent = new SubscriptionEvent(); $logEvent = new SubscriptionEvent();
$logEvent $logEvent
->setSubscriber($unsubscribedUser) ->setSubscriber($unsubscribedUser)
->setAction($user) ->setAuthor($user)
->setAction(SubscriptionEvent::ACTION_UNSUBSCRIBE) ->setAction(SubscriptionEvent::ACTION_UNSUBSCRIBE)
; ;