Hardcoded URL's removed everywhere in favor of dynamically generated based on container parameters. Router now can generate absolute URL even when not processing HTTP request. Avatar-related functions moved from UserApi to PointUrlExtension.

This commit is contained in:
Alexey Skobkin 2017-01-11 21:03:32 +03:00
parent d6bd2ddd73
commit bc363c03e7
19 changed files with 141 additions and 151 deletions

View file

@ -7,6 +7,10 @@ imports:
# http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: ru
# Defining default router parameters to be able to generate correct full URL's when not processing HTTP request
router.request_context.host: "%point_tools_domain%"
router.request_context.scheme: "%point_tools_scheme%"
router.request_context.base_url: "%point_tools_base_url%"
framework:
#esi: ~

View file

@ -11,8 +11,15 @@ parameters:
mailer_user: ~
mailer_password: ~
point_base_url: https://point.im/
point_api_base_url: https://point.im/api/
point_tools_domain: point.skobk.in
point_tools_scheme: https
# Path to public root (e.g. 'path/to/app')
point_tools_base_url: ''
point_domain: point.im
point_scheme: https
point_base_url: '%point_scheme%://%point_domain%/'
point_api_base_url: '%point_base_url%/api/'
# Delay between calls when updating users subscribers (in microseconds)
point_api_delay: 500000
point_use_https: true

View file

@ -6,7 +6,6 @@ use Doctrine\ORM\EntityManager;
use Skobkin\Bundle\PointToolsBundle\DTO\DailyEvents;
use Skobkin\Bundle\PointToolsBundle\DTO\TopUserDTO;
use Skobkin\Bundle\PointToolsBundle\Entity\User;
use Skobkin\Bundle\PointToolsBundle\Service\UserApi;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Ob\HighchartsBundle\Highcharts\Highchart;
use Symfony\Component\HttpFoundation\Request;
@ -37,14 +36,11 @@ class UserController extends Controller
10
);
$userApi = $this->get('app.point.api_user');
return $this->render('SkobkinPointToolsBundle:User:show.html.twig', [
'user' => $user,
'subscribers' => $em->getRepository('SkobkinPointToolsBundle:User')->findUserSubscribersById($user->getId()),
'subscriptions_log' => $subscriberEventsPagination,
'rename_log' => $em->getRepository('SkobkinPointToolsBundle:UserRenameEvent')->findBy(['user' => $user], ['date' => 'DESC'], 10),
'avatar_url' => $userApi->getAvatarUrl($user, UserApi::AVATAR_SIZE_LARGE),
]);
}

View file

@ -12,6 +12,10 @@ use Doctrine\ORM\Mapping as ORM;
*/
class User
{
const AVATAR_SIZE_SMALL = '24';
const AVATAR_SIZE_MEDIUM = '40';
const AVATAR_SIZE_LARGE = '80';
/**
* @var int
*

View file

@ -175,9 +175,12 @@ services:
# Twig extensions
app.twig.point_users_extension:
class: Skobkin\Bundle\PointToolsBundle\Twig\PointUserExtension
class: Skobkin\Bundle\PointToolsBundle\Twig\PointUrlExtension
public: false
arguments: ['@app.point.api_user']
arguments:
- '%point_domain%'
- '%point_scheme%'
- '%point_base_url%'
tags:
- { name: twig.extension }

View file

@ -43,7 +43,7 @@
</div>
</div>
<div class="row">
<div class="col-xs-12"><a href="https://point.im/{{ post.id }}" class="post">#{{ post.id }}</a></div>
<div class="col-xs-12"><a href="{{ post.id|point_post_url }}" class="post">#{{ post.id }}</a></div>
</div>
{% if post.comments|length > 0 %}

View file

@ -10,4 +10,4 @@
/stats - Show some statistics about service
/help shows this message
Visit [Point Tools](https://point.skobk.in/) for more info.
Visit [Point Tools]({{ url('index') }}) for more info.

View file

@ -5,7 +5,7 @@
{% for event in events %}
{% set sub_login = event.subscriber.login %}
{% set author_login = event.author.login %}
{{ event.date|date('d M H:i') }} [@{{ sub_login }}]({{ sub_login|point_user_url(true) }}){% if subscription == event.action %} -> {% else %} X {% endif %}[@{{ author_login }}]({{ author_login|point_user_url(true) }})
{{ event.date|date('d M H:i') }} [@{{ sub_login }}]({{ sub_login|point_user_url }}){% if subscription == event.action %} -> {% else %} X {% endif %}[@{{ author_login }}]({{ author_login|point_user_url }})
{% endfor %}
See more events on [Point Tools](https://point.skobk.in/) site.
See more events on [Point Tools]({{ url('index') }}) site.

View file

@ -5,8 +5,7 @@
{# @var event \Skobkin\Bundle\PointToolsBundle\Entity\SubscriptionEvent #}
{% for event in events %}
{% set sub_login = event.subscriber.login %}
{{ event.date|date('d M y H:i') }} {% if subscription == event.action %} + {% else %} - {% endif %} [@{{ sub_login }}]({{ sub_login|point_user_url(true) }})
{{ event.date|date('d M y H:i') }} {% if subscription == event.action %} + {% else %} - {% endif %} [@{{ sub_login }}]({{ sub_login|point_user_url }})
{% endfor %}
{# @todo remove hardcoded URL #}
See more events on [Point Tools](https://point.skobk.in{{ path('user_show', {'login': user.login}) }}) site.
See more events on [Point Tools]({{ url('user_show', {'login': user.login}) }}) site.

View file

@ -1,7 +1,7 @@
{# @var account \Skobkin\Bundle\PointToolsBundle\Entity\Telegram\Account #}
*Your current settings:*
Account /link status: {% if account.user %}linked to [@{{ account.user.login }}]({{ account.user.login|point_user_url(true) }}){% else %}Not linked{% endif %}
Account /link status: {% if account.user %}linked to [@{{ account.user.login }}]({{ account.user.login|point_user_url }}){% else %}Not linked{% endif %}
User renaming notifications: {% if account.renameNotification %}enabled{% else %}disabled{% endif %}

View file

@ -6,4 +6,4 @@ Telegram users: {{ telegram_accounts }}
Telegram linked users: {{ telegram_linked_accounts }}
24 hours events: {{ today_events }}
Visit [Point Tools](https://point.skobk.in/) for more info.
Visit [Point Tools]({{ url('statistics') }}) for more info.

View file

@ -7,5 +7,4 @@
No subscribers
{% endif %}
{# @todo remove hardcoded URL #}
See more events on [Point Tools](https://point.skobk.in{{ path('user_show', {'login': user.login}) }}) site.
See more events on [Point Tools]({{ url('user_show', {'login': user.login}) }}) site.

View file

@ -5,16 +5,15 @@
{% if subscribed|length > 0 %}
New subscribers:
{% for subscriber in subscribed %}
[@{{ subscriber.login }}]({{ subscriber.login|point_user_url(true) }})
[@{{ subscriber.login }}]({{ subscriber.login|point_user_url }})
{% endfor %}
{% endif %}
{% if unsubscribed|length > 0 %}
Lost subscribers:
{% for subscriber in unsubscribed %}
[@{{ subscriber.login }}]({{ subscriber.login|point_user_url(true) }})
[@{{ subscriber.login }}]({{ subscriber.login|point_user_url }})
{% endfor %}
{% endif %}
{# @todo remove hardcoded URL #}
See full subscribers history on [Point Tools](https://point.skobk.in{{ path('user_show', {'login': user.login}) }}) site.
See full subscribers history on [Point Tools]({{ url('user_show', {'login': user.login}) }}) site.

View file

@ -4,5 +4,5 @@
{% for event in events %}
{% set login_old = event.oldLogin %}
{% set login_new = event.user.login %}
@{{ login_old }} -> [@{{ login_new }}]({{ login_new|point_user_url(true) }})
@{{ login_old }} -> [@{{ login_new }}]({{ login_new|point_user_url }})
{% endfor %}

View file

@ -4,7 +4,8 @@
{% block content %}
<h1 class="user-login">
<img src="{{ avatar_url }}">
{# TODO: Add class with image size #}
<img src="{{ user.login|point_avatar_large }}">
<a href="{{ user.login|point_user_blog_url }}" target="_blank">{{ user.login }}</a>
</h1>

View file

@ -20,15 +20,6 @@ use Symfony\Component\HttpFoundation\Response;
*/
class UserApi extends AbstractApi
{
const AVATAR_SIZE_SMALL = '24';
const AVATAR_SIZE_MEDIUM = '40';
const AVATAR_SIZE_LARGE = '80';
/**
* @var string Base URL for user avatars
*/
protected $avatarsBaseUrl = '//point.im/avatar/';
/**
* @var EntityManager
*/
@ -50,6 +41,7 @@ class UserApi extends AbstractApi
$this->em = $entityManager;
$this->serializer = $serializer;
// @todo refactor
$this->userRepository = $this->em->getRepository('SkobkinPointToolsBundle:User');
}
@ -355,34 +347,4 @@ class UserApi extends AbstractApi
return $resultUsers;
}
/**
* Creates URL of avatar with specified size by User object
*
* @param User $user
* @param string $size
*
* @return string
*/
public function getAvatarUrl(User $user, string $size): string
{
return $this->getAvatarUrlByLogin($user->getLogin(), $size);
}
/**
* Creates URL of avatar with specified size by login string
*
* @param string $login
* @param string $size
*
* @return string
*/
public function getAvatarUrlByLogin(string $login, string $size): string
{
if (!in_array($size, [self::AVATAR_SIZE_SMALL, self::AVATAR_SIZE_MEDIUM, self::AVATAR_SIZE_LARGE], true)) {
throw new \InvalidArgumentException('Avatar size must be one of restricted variants. See UserApi class AVATAR_SIZE_* constants.');
}
return $this->avatarsBaseUrl.urlencode($login).'/'.$size;
}
}

View file

@ -0,0 +1,100 @@
<?php
namespace Skobkin\Bundle\PointToolsBundle\Twig;
use Skobkin\Bundle\PointToolsBundle\Entity\User;
class PointUrlExtension extends \Twig_Extension
{
/**
* @var string
*/
private $pointDomain;
/**
* @var string
*/
private $pointScheme;
/**
* @var string
*/
private $pointBaseUrl;
public function __construct(string $pointDomain, string $pointScheme, string $pointBaseUrl)
{
$this->pointDomain = $pointDomain;
$this->pointScheme = $pointScheme;
$this->pointBaseUrl = $pointBaseUrl;
}
public function getFunctions()
{
return [
new \Twig_SimpleFunction('point_avatar', [$this, 'avatarFunction']),
new \Twig_SimpleFunction('point_avatar_small', [$this, 'avatarSmallFunction']),
new \Twig_SimpleFunction('point_avatar_medium', [$this, 'avatarMediumFunction']),
new \Twig_SimpleFunction('point_avatar_large', [$this, 'avatarLargeFunction']),
new \Twig_SimpleFunction('point_user_url', [$this, 'userUrl']),
new \Twig_SimpleFunction('point_user_blog_url', [$this, 'userBlogUrl']),
new \Twig_SimpleFunction('point_post_url', [$this, 'postUrl']),
];
}
public function getFilters()
{
return [
new \Twig_SimpleFilter('point_avatar', [$this, 'avatarFunction']),
new \Twig_SimpleFilter('point_avatar_small', [$this, 'avatarSmallFunction']),
new \Twig_SimpleFilter('point_avatar_medium', [$this, 'avatarMediumFunction']),
new \Twig_SimpleFilter('point_avatar_large', [$this, 'avatarLargeFunction']),
new \Twig_SimpleFilter('point_user_url', [$this, 'pointUserUrl']),
new \Twig_SimpleFilter('point_user_blog_url', [$this, 'userBlogUrl']),
new \Twig_SimpleFilter('point_post_url', [$this, 'postUrl']),
];
}
public function avatarSmallFunction(string $login): string
{
return $this->avatarFunction($login, User::AVATAR_SIZE_SMALL);
}
public function avatarMediumFunction(string $login): string
{
return $this->avatarFunction($login, User::AVATAR_SIZE_MEDIUM);
}
public function avatarLargeFunction(string $login): string
{
return $this->avatarFunction($login, User::AVATAR_SIZE_LARGE);
}
public function avatarFunction(string $login, $size): string
{
return $this->getAvatarUrlByLogin($login, $size);
}
public function userUrl(string $login): string
{
return sprintf('%s://%s.%s/', $this->pointScheme, $login, $this->pointDomain);
}
public function userBlogUrl(string $login): string
{
return sprintf('%s://%s.%s/blog/', $this->pointScheme, $login, $this->pointDomain);
}
public function postUrl(string $postId): string
{
return sprintf('%s://%s/%s', $this->pointScheme, $this->pointDomain, $postId);
}
private function getAvatarUrlByLogin(string $login, string $size): string
{
if (!in_array($size, [User::AVATAR_SIZE_SMALL, User::AVATAR_SIZE_MEDIUM, User::AVATAR_SIZE_LARGE], true)) {
throw new \InvalidArgumentException('Avatar size must be one of restricted variants. See User::AVATAR_SIZE_* constants.');
}
return sprintf('%s://%s/avatar/%s/%s', $this->pointScheme, $this->pointDomain, urlencode($login), $size);
}
}

View file

@ -1,86 +0,0 @@
<?php
namespace Skobkin\Bundle\PointToolsBundle\Twig;
use Skobkin\Bundle\PointToolsBundle\Service\UserApi;
class PointUserExtension extends \Twig_Extension
{
const POINT_HOST = 'point.im';
/**
* @var UserApi
*/
private $userApi;
public function __construct(UserApi $userApi)
{
$this->userApi = $userApi;
}
public function getFunctions()
{
return [
new \Twig_SimpleFunction('point_avatar', [$this, 'pointAvatarFunction']),
new \Twig_SimpleFunction('point_avatar_small', [$this, 'pointAvatarSmallFunction']),
new \Twig_SimpleFunction('point_avatar_medium', [$this, 'pointAvatarMediumFunction']),
new \Twig_SimpleFunction('point_avatar_large', [$this, 'pointAvatarLargeFunction']),
new \Twig_SimpleFunction('point_user_url', [$this, 'pointUserUrl']),
new \Twig_SimpleFunction('point_user_blog_url', [$this, 'pointUserBlogUrl']),
];
}
public function getFilters()
{
return [
new \Twig_SimpleFilter('point_avatar', [$this, 'pointAvatarFunction']),
new \Twig_SimpleFilter('point_avatar_small', [$this, 'pointAvatarSmallFunction']),
new \Twig_SimpleFilter('point_avatar_medium', [$this, 'pointAvatarMediumFunction']),
new \Twig_SimpleFilter('point_avatar_large', [$this, 'pointAvatarLargeFunction']),
new \Twig_SimpleFilter('point_user_url', [$this, 'pointUserUrl']),
new \Twig_SimpleFilter('point_user_blog_url', [$this, 'pointUserBlogUrl']),
];
}
public function pointAvatarSmallFunction(string $login): string
{
return $this->pointAvatarFunction($login, UserApi::AVATAR_SIZE_SMALL);
}
public function pointAvatarMediumFunction(string $login): string
{
return $this->pointAvatarFunction($login, UserApi::AVATAR_SIZE_MEDIUM);
}
public function pointAvatarLargeFunction(string $login): string
{
return $this->pointAvatarFunction($login, UserApi::AVATAR_SIZE_LARGE);
}
public function pointAvatarFunction(string $login, $size): string
{
return $this->userApi->getAvatarUrlByLogin($login, $size);
}
/**
* @param string $login
* @param bool $forceHttps
*
* @return string
*/
public function pointUserUrl(string $login, bool $forceHttps = false): string
{
return sprintf('%s//%s.%s/', $forceHttps ? 'https:' : '', $login, self::POINT_HOST);
}
/**
* @param string $login
* @param bool $forceHttps
*
* @return string
*/
public function pointUserBlogUrl(string $login, bool $forceHttps = false): string
{
return sprintf('%s//%s.%s/blog/', $forceHttps ? 'https:' : '', $login, self::POINT_HOST);
}
}

View file

@ -61,8 +61,10 @@ class UserControllerTest extends WebTestCase
'testuser page has no avatar'
);
$pointScheme = static::createClient()->getContainer()->getParameter('point_scheme');
$this->assertEquals(
'//point.im/avatar/testuser/80',
$pointScheme.'://point.im/avatar/testuser/80',
$userAvatar->attr('src'),
'testuser avatar image source is not correct'
);