Completed
Pull Request — master (#356)
by Christian
03:38
created

TwitterEmbedTweetBlockService::configureEditForm()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 53

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 53
rs 9.0254
c 0
b 0
f 0
cc 1
nc 1
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\SeoBundle\Block\Social;
15
16
use Guzzle\Http\Exception\CurlException;
17
use Sonata\BlockBundle\Block\BlockContextInterface;
18
use Sonata\BlockBundle\Block\Service\EditableBlockService;
19
use Sonata\BlockBundle\Form\Mapper\FormMapper;
20
use Sonata\BlockBundle\Meta\Metadata;
21
use Sonata\BlockBundle\Meta\MetadataInterface;
22
use Sonata\BlockBundle\Model\BlockInterface;
23
use Sonata\Form\Type\ImmutableArrayType;
24
use Sonata\Form\Validator\ErrorElement;
25
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
26
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
27
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
28
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
29
use Symfony\Component\Form\Extension\Core\Type\TextType;
30
use Symfony\Component\HttpFoundation\Response;
31
use Symfony\Component\OptionsResolver\OptionsResolver;
32
33
/**
34
 * This block service allows to embed a tweet by requesting the Twitter API.
35
 *
36
 * @see https://dev.twitter.com/docs/api/1/get/statuses/oembed
37
 *
38
 * @author Hugo Briand <[email protected]>
39
 */
40
class TwitterEmbedTweetBlockService extends BaseTwitterButtonBlockService implements EditableBlockService
41
{
42
    public const TWITTER_OEMBED_URI = 'https://api.twitter.com/1/statuses/oembed.json';
43
    public const TWEET_URL_PATTERN = '%^(https://)(www.)?(twitter.com/)(.*)(/status)(es)?(/)([0-9]*)$%i';
44
    public const TWEET_ID_PATTERN = '%^([0-9]*)$%';
45
46
    /**
47
     * {@inheritdoc}
48
     */
49
    public function execute(BlockContextInterface $blockContext, Response $response = null): Response
50
    {
51
        $tweet = $blockContext->getSetting('tweet');
52
53
        if (($uriMatched = preg_match(self::TWEET_URL_PATTERN, $tweet))
54
            || preg_match(self::TWEET_ID_PATTERN, $tweet)) {
55
            // We matched an URL or an ID, we'll need to ask the API
56
            if (false === class_exists('Guzzle\Http\Client')) {
57
                throw new \RuntimeException('The guzzle http client library is required to call the Twitter API. Make sure to add guzzle/guzzle to your composer.json.');
58
            }
59
60
            // TODO cache API result
61
            $client = new \Guzzle\Http\Client();
62
            $client->setConfig(['curl.options' => [CURLOPT_CONNECTTIMEOUT_MS => 1000]]);
63
64
            try {
65
                $request = $client->get($this->buildUri($uriMatched, $blockContext->getSettings()));
0 ignored issues
show
Documentation introduced by
$uriMatched is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
66
                $apiTweet = json_decode($request->send()->getBody(true), true);
67
68
                $tweet = $apiTweet['html'];
69
            } catch (CurlException $e) {
70
                // log error
71
            }
72
        }
73
74
        return $this->renderResponse($blockContext->getTemplate(), [
75
            'block' => $blockContext->getBlock(),
76
            'tweet' => $tweet,
77
        ], $response);
78
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function configureSettings(OptionsResolver $resolver): void
84
    {
85
        $resolver->setDefaults([
86
            'template' => '@SonataSeo/Block/block_twitter_embed.html.twig',
87
            'tweet' => '',
88
            'maxwidth' => null,
89
            'hide_media' => false,
90
            'hide_thread' => false,
91
            'omit_script' => false,
92
            'align' => 'none',
93
            'related' => null,
94
            'lang' => null,
95
        ]);
96
    }
97
98
    public function configureCreateForm(FormMapper $form, BlockInterface $block): void
99
    {
100
        $this->configureEditForm($form, $block);
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function configureEditForm(FormMapper $form, BlockInterface $block): void
107
    {
108
        $form->add('settings', ImmutableArrayType::class, [
109
            'keys' => [
110
                ['tweet', TextareaType::class, [
111
                    'required' => true,
112
                    'label' => 'form.label_tweet',
113
                    'sonata_help' => 'form.help_tweet',
114
                ]],
115
                ['maxwidth', IntegerType::class, [
116
                    'required' => false,
117
                    'label' => 'form.label_maxwidth',
118
                    'sonata_help' => 'form.help_maxwidth',
119
                ]],
120
                ['hide_media', CheckboxType::class, [
121
                    'required' => false,
122
                    'label' => 'form.label_hide_media',
123
                    'sonata_help' => 'form.help_hide_media',
124
                ]],
125
                ['hide_thread', CheckboxType::class, [
126
                    'required' => false,
127
                    'label' => 'form.label_hide_thread',
128
                    'sonata_help' => 'form.help_hide_thread',
129
                ]],
130
                ['omit_script', CheckboxType::class, [
131
                    'required' => false,
132
                    'label' => 'form.label_omit_script',
133
                    'sonata_help' => 'form.help_omit_script',
134
                ]],
135
                ['align', ChoiceType::class, [
136
                    'required' => false,
137
                    'choices' => [
138
                        'left' => 'form.label_align_left',
139
                        'right' => 'form.label_align_right',
140
                        'center' => 'form.label_align_center',
141
                        'none' => 'form.label_align_none',
142
                    ],
143
                    'label' => 'form.label_align',
144
                ]],
145
                ['related', TextType::class, [
146
                    'required' => false,
147
                    'label' => 'form.label_related',
148
                    'sonata_help' => 'form.help_related',
149
                ]],
150
                ['lang', ChoiceType::class, [
151
                    'required' => true,
152
                    'choices' => $this->languageList,
153
                    'label' => 'form.label_lang',
154
                ]],
155
            ],
156
            'translation_domain' => 'SonataSeoBundle',
157
        ]);
158
    }
159
160
    public function validate(ErrorElement $errorElement, BlockInterface $block): void
161
    {
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167
    public function getMetadata(): MetadataInterface
168
    {
169
        return new Metadata('sonata.seo.block.twitter.embed', null, null, 'SonataSeoBundle', [
170
            'class' => 'fa fa-twitter',
171
        ]);
172
    }
173
174
    /**
175
     * Returns supported API parameters from settings.
176
     *
177
     * @return array
178
     */
179
    protected function getSupportedApiParams()
180
    {
181
        return [
182
            'maxwidth',
183
            'hide_media',
184
            'hide_thread',
185
            'omit_script',
186
            'align',
187
            'related',
188
            'lang',
189
            'url',
190
            'id',
191
        ];
192
    }
193
194
    /**
195
     * Builds the API query URI based on $settings.
196
     *
197
     * @param bool $uriMatched
198
     *
199
     * @return string
200
     */
201
    protected function buildUri($uriMatched, array $settings)
202
    {
203
        $apiParams = $settings;
204
        $supportedParams = $this->getSupportedApiParams();
205
206
        if ($uriMatched) {
207
            // We matched the uri
208
            $apiParams['url'] = $settings['tweet'];
209
        } else {
210
            $apiParams['id'] = $settings['tweet'];
211
        }
212
213
        unset($apiParams['tweet']);
214
215
        $parameters = [];
216
        foreach ($apiParams as $key => $value) {
217
            if ($value && \in_array($key, $supportedParams, true)) {
218
                $parameters[] = $key.'='.$value;
219
            }
220
        }
221
222
        return sprintf('%s?%s', self::TWITTER_OEMBED_URI, implode('&', $parameters));
223
    }
224
}
225