Completed
Push — master ( b130be...d8cd50 )
by MusikAnimal
02:24
created

EditCounterController::setUpEditCounter()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.5125
c 0
b 0
f 0
cc 5
eloc 14
nc 4
nop 3
1
<?php
2
/**
3
 * This file contains only the EditCounterController class.
4
 */
5
6
namespace AppBundle\Controller;
7
8
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
9
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
10
use Symfony\Component\HttpFoundation\Request;
11
use Symfony\Component\HttpFoundation\Response;
12
use Symfony\Component\HttpFoundation\RedirectResponse;
13
use Symfony\Component\HttpFoundation\JsonResponse;
14
use Xtools\EditCounter;
15
use Xtools\EditCounterRepository;
16
use Xtools\Page;
17
use Xtools\Project;
18
use Xtools\ProjectRepository;
19
use Xtools\User;
20
use Xtools\UserRepository;
21
22
/**
23
 * Class EditCounterController
24
 */
25
class EditCounterController extends Controller
26
{
27
28
    /** @var User The user being queried. */
29
    protected $user;
30
31
    /** @var Project The project being queried. */
32
    protected $project;
33
34
    /** @var EditCounter The edit-counter, that does all the work. */
35
    protected $editCounter;
36
37
    /**
38
     * Get the tool's shortname.
39
     * @return string
40
     */
41
    public function getToolShortname()
42
    {
43
        return 'ec';
44
    }
45
46
    /**
47
     * Every action in this controller (other than 'index') calls this first.
48
     * If a response is returned, the calling action is expected to return it.
49
     * @param string|bool $project The project name.
50
     * @param string|bool $username The username.
51
     * @param string $key API key, as given in the reuqest. Omit this for actions
52
     *   that are public (only /api/ec actions should pass this in).
53
     * @return null|RedirectResponse
54
     */
55
    protected function setUpEditCounter($project = false, $username = false, $key = null)
56
    {
57
        if ($key && $key !== $this->container->getParameter('secret')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $key of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
58
            throw $this->createAccessDeniedException('This endpoint is for internal use only.');
59
        }
60
61
        $this->project = ProjectRepository::getProject($project, $this->container);
0 ignored issues
show
Bug introduced by
It seems like $project defined by parameter $project on line 55 can also be of type boolean; however, Xtools\ProjectRepository::getProject() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
62
        $this->user = UserRepository::getUser($username, $this->container);
1 ignored issue
show
Bug introduced by
It seems like $username defined by parameter $username on line 55 can also be of type boolean; however, Xtools\UserRepository::getUser() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
Compatibility introduced by
$this->container of type object<Symfony\Component...ion\ContainerInterface> is not a sub-type of object<Symfony\Component...ncyInjection\Container>. It seems like you assume a concrete implementation of the interface Symfony\Component\Depend...tion\ContainerInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
63
64
        // Don't continue if the user doesn't exist.
65
        if (!$this->user->existsOnProject($this->project)) {
66
            $this->addFlash('notice', 'user-not-found');
67
            return $this->redirectToRoute('ec', ['project' => $project]);
68
        }
69
70
        // Get an edit-counter if we don't already have it set.
71
        if ($this->editCounter instanceof EditCounter) {
72
            return;
73
        }
74
        $editCounterRepo = new EditCounterRepository();
75
        $editCounterRepo->setContainer($this->container);
1 ignored issue
show
Compatibility introduced by
$this->container of type object<Symfony\Component...ion\ContainerInterface> is not a sub-type of object<Symfony\Component...ncyInjection\Container>. It seems like you assume a concrete implementation of the interface Symfony\Component\Depend...tion\ContainerInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
76
        $this->editCounter = new EditCounter($this->project, $this->user);
77
        $this->editCounter->setRepository($editCounterRepo);
78
    }
79
80
    /**
81
     * The initial GET request that displays the search form.
82
     *
83
     * @Route("/ec", name="ec")
84
     * @Route("/ec", name="EditCounter")
85
     * @Route("/ec/", name="EditCounterSlash")
86
     * @Route("/ec/index.php", name="EditCounterIndexPhp")
87
     * @Route("/ec/{project}", name="EditCounterProject")
88
     *
89
     * @param Request $request
90
     * @param string|null $project
91
     * @return RedirectResponse|Response
92
     */
93
    public function indexAction(Request $request, $project = null)
94
    {
95
        $queryProject = $request->query->get('project');
96
        $username = $request->query->get('username', $request->query->get('user'));
97
98
        if (($project || $queryProject) && $username) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $project of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
99
            $routeParams = ['project' => ($project ?: $queryProject), 'username' => $username];
100
            return $this->redirectToRoute('EditCounterResult', $routeParams);
101
        } elseif (!$project && $queryProject) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $project of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
102
            return $this->redirectToRoute('EditCounterProject', ['project' => $queryProject]);
103
        }
104
105
        $project = ProjectRepository::getProject($project, $this->container);
106
        if (!$project->exists()) {
107
            $project = ProjectRepository::getDefaultProject($this->container);
108
        }
109
110
        // Otherwise fall through.
111
        return $this->render('editCounter/index.html.twig', [
112
            'xtPageTitle' => 'tool-ec',
113
            'xtSubtitle' => 'tool-ec-desc',
114
            'xtPage' => 'ec',
115
            'project' => $project,
116
        ]);
117
    }
118
119
    /**
120
     * Display all results.
121
     * @Route("/ec/{project}/{username}", name="EditCounterResult")
122
     * @param Request $request
123
     * @param string $project
124
     * @param string $username
125
     * @return Response
126
     */
127
    public function resultAction(Request $request, $project, $username)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
128
    {
129
        $ret = $this->setUpEditCounter($project, $username);
130
        if ($ret instanceof RedirectResponse) {
131
            return $ret;
132
        }
133
134
        // Asynchronously collect some of the data that will be shown.
135
        // If multithreading is turned off, the normal getters in the views will
136
        // collect the necessary data synchronously.
137
        if ($this->container->getParameter('app.multithread')) {
138
            $this->editCounter->prepareData($this->container);
0 ignored issues
show
Unused Code introduced by
The call to EditCounter::prepareData() has too many arguments starting with $this->container.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
139
        }
140
141
        // FIXME: is this needed? It shouldn't ever be a subrequest here in the resultAction.
142
        $isSubRequest = $this->container->get('request_stack')->getParentRequest() !== null;
143
144
        return $this->render('editCounter/result.html.twig', [
145
            'xtTitle' => $this->user->getUsername() . ' - ' . $this->project->getTitle(),
146
            'xtPage' => 'ec',
147
            'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..'),
148
            'is_sub_request' => $isSubRequest,
149
            'user' => $this->user,
150
            'project' => $this->project,
151
            'ec' => $this->editCounter,
152
        ]);
153
    }
154
155
    /**
156
     * Display the general statistics section.
157
     * @Route("/ec-generalstats/{project}/{username}", name="EditCounterGeneralStats")
158
     * @param string $project
159
     * @param string $username
160
     * @return Response
161
     */
162 View Code Duplication
    public function generalStatsAction($project, $username)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
163
    {
164
        $ret = $this->setUpEditCounter($project, $username);
165
        if ($ret instanceof RedirectResponse) {
166
            return $ret;
167
        }
168
169
        $isSubRequest = $this->get('request_stack')->getParentRequest() !== null;
170
        return $this->render('editCounter/general_stats.html.twig', [
171
            'xtTitle' => $this->user->getUsername(),
172
            'xtPage' => 'ec',
173
            'is_sub_request' => $isSubRequest,
174
            'user' => $this->user,
175
            'project' => $this->project,
176
            'ec' => $this->editCounter,
177
        ]);
178
    }
179
180
    /**
181
     * Display the namespace totals section.
182
     * @Route("/ec-namespacetotals/{project}/{username}", name="EditCounterNamespaceTotals")
183
     * @param Request $request
184
     * @param string $project
185
     * @param string $username
186
     * @return Response
187
     */
188 View Code Duplication
    public function namespaceTotalsAction(Request $request, $project, $username)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
189
    {
190
        $ret = $this->setUpEditCounter($project, $username);
191
        if ($ret instanceof RedirectResponse) {
192
            return $ret;
193
        }
194
195
        $isSubRequest = $this->get('request_stack')->getParentRequest() !== null;
196
        return $this->render('editCounter/namespace_totals.html.twig', [
197
            'xtTitle' => $this->user->getUsername(),
198
            'xtPage' => 'ec',
199
            'is_sub_request' => $isSubRequest,
200
            'user' => $this->user,
201
            'project' => $this->project,
202
            'ec' => $this->editCounter,
203
        ]);
204
    }
205
206
    /**
207
     * Display the timecard section.
208
     * @Route("/ec-timecard/{project}/{username}", name="EditCounterTimecard")
209
     * @param string $project
210
     * @param string $username
211
     * @return Response
212
     */
213 View Code Duplication
    public function timecardAction($project, $username)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
214
    {
215
        $ret = $this->setUpEditCounter($project, $username);
216
        if ($ret instanceof RedirectResponse) {
217
            return $ret;
218
        }
219
220
        $isSubRequest = $this->get('request_stack')->getParentRequest() !== null;
221
        $optedInPage = $this->project
1 ignored issue
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Xtools\Repository as the method getPage() does only exist in the following sub-classes of Xtools\Repository: Xtools\ProjectRepository. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
222
            ->getRepository()
223
            ->getPage($this->project, $this->project->userOptInPage($this->user));
224
        return $this->render('editCounter/timecard.html.twig', [
225
            'xtTitle' => $this->user->getUsername(),
226
            'xtPage' => 'ec',
227
            'is_sub_request' => $isSubRequest,
228
            'user' => $this->user,
229
            'project' => $this->project,
230
            'ec' => $this->editCounter,
231
            'opted_in_page' => $optedInPage,
232
        ]);
233
    }
234
235
    /**
236
     * Display the year counts section.
237
     * @Route("/ec-yearcounts/{project}/{username}", name="EditCounterYearCounts")
238
     * @param string $project
239
     * @param string $username
240
     * @return Response
241
     */
242 View Code Duplication
    public function yearcountsAction($project, $username)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
243
    {
244
        $ret = $this->setUpEditCounter($project, $username);
245
        if ($ret instanceof RedirectResponse) {
246
            return $ret;
247
        }
248
249
        $isSubRequest = $this->container->get('request_stack')->getParentRequest() !== null;
250
        return $this->render('editCounter/yearcounts.html.twig', [
251
            'xtTitle' => $this->user->getUsername(),
252
            'xtPage' => 'ec',
253
            'is_sub_request' => $isSubRequest,
254
            'user' => $this->user,
255
            'project' => $this->project,
256
            'ec' => $this->editCounter,
257
        ]);
258
    }
259
260
    /**
261
     * Display the month counts section.
262
     * @Route("/ec-monthcounts/{project}/{username}", name="EditCounterMonthCounts")
263
     * @param Request $request
264
     * @param string $project
265
     * @param string $username
266
     * @return Response
267
     */
268 View Code Duplication
    public function monthcountsAction(Request $request, $project, $username)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
269
    {
270
        $ret = $this->setUpEditCounter($project, $username);
271
        if ($ret instanceof RedirectResponse) {
272
            return $ret;
273
        }
274
275
        $isSubRequest = $this->container->get('request_stack')->getParentRequest() !== null;
276
        $optedInPage = $this->project
1 ignored issue
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Xtools\Repository as the method getPage() does only exist in the following sub-classes of Xtools\Repository: Xtools\ProjectRepository. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
277
            ->getRepository()
278
            ->getPage($this->project, $this->project->userOptInPage($this->user));
279
        return $this->render('editCounter/monthcounts.html.twig', [
280
            'xtTitle' => $this->user->getUsername(),
281
            'xtPage' => 'ec',
282
            'is_sub_request' => $isSubRequest,
283
            'user' => $this->user,
284
            'project' => $this->project,
285
            'ec' => $this->editCounter,
286
            'opted_in_page' => $optedInPage,
287
        ]);
288
    }
289
290
    /**
291
     * Display the latest global edits section.
292
     * @Route("/ec-latestglobal/{project}/{username}", name="EditCounterLatestGlobal")
293
     * @param Request $request The HTTP request.
294
     * @param string $project The project name.
295
     * @param string $username The username.
296
     * @return Response
297
     */
298 View Code Duplication
    public function latestglobalAction(Request $request, $project, $username)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
299
    {
300
        $ret = $this->setUpEditCounter($project, $username);
301
        if ($ret instanceof RedirectResponse) {
302
            return $ret;
303
        }
304
305
        $isSubRequest = $request->get('htmlonly')
306
                        || $this->container->get('request_stack')->getParentRequest() !== null;
307
        return $this->render('editCounter/latest_global.html.twig', [
308
            'xtTitle' => $this->user->getUsername(),
309
            'xtPage' => 'ec',
310
            'is_sub_request' => $isSubRequest,
311
            'user' => $this->user,
312
            'project' => $this->project,
313
            'ec' => $this->editCounter,
314
        ]);
315
    }
316
317
318
    /**
319
     * Below are internal API endpoints for the Edit Counter.
320
     * All only respond with JSON and only to requests passing in the value
321
     * of the 'secret' parameter. This should not be used in JavaScript or clientside
322
     * applications, rather only used internally.
323
     */
324
325
    /**
326
     * Get (most) of the general statistics as JSON.
327
     * @Route("/api/ec/pairdata/{project}/{username}/{key}", name="EditCounterApiPairData")
328
     * @param Request $request
329
     * @param string $project
330
     * @param string $username
331
     * @param string $key API key.
332
     * @return JsonResponse
333
     */
334 View Code Duplication
    public function pairDataApiAction(Request $request, $project, $username, $key)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
335
    {
336
        $ret = $this->setUpEditCounter($project, $username, $key);
337
        if ($ret instanceof RedirectResponse) {
338
            return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $ret; (Symfony\Component\HttpFoundation\RedirectResponse) is incompatible with the return type documented by AppBundle\Controller\Edi...ller::pairDataApiAction of type Symfony\Component\HttpFoundation\JsonResponse.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
339
        }
340
341
        return new JsonResponse(
342
            $this->editCounter->getPairData(),
343
            Response::HTTP_OK
344
        );
345
    }
346
347
    /**
348
     * Get various log counts for the user as JSON.
349
     * @Route("/api/ec/logcounts/{project}/{username}/{key}", name="EditCounterApiLogCounts")
350
     * @param Request $request
351
     * @param string $project
352
     * @param string $username
353
     * @param string $key API key.
354
     * @return JsonResponse
355
     */
356 View Code Duplication
    public function logCountsApiAction(Request $request, $project, $username, $key)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
357
    {
358
        $ret = $this->setUpEditCounter($project, $username, $key);
359
        if ($ret instanceof RedirectResponse) {
360
            return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $ret; (Symfony\Component\HttpFoundation\RedirectResponse) is incompatible with the return type documented by AppBundle\Controller\Edi...ler::logCountsApiAction of type Symfony\Component\HttpFoundation\JsonResponse.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
361
        }
362
363
        return new JsonResponse(
364
            $this->editCounter->getLogCounts(),
365
            Response::HTTP_OK
366
        );
367
    }
368
369
    /**
370
     * Get edit sizes for the user as JSON.
371
     * @Route("/api/ec/editsizes/{project}/{username}/{key}", name="EditCounterApiEditSizes")
372
     * @param Request $request
373
     * @param string $project
374
     * @param string $username
375
     * @param string $key API key.
376
     * @return JsonResponse
377
     */
378 View Code Duplication
    public function editSizesApiAction(Request $request, $project, $username, $key)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
379
    {
380
        $ret = $this->setUpEditCounter($project, $username, $key);
381
        if ($ret instanceof RedirectResponse) {
382
            return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $ret; (Symfony\Component\HttpFoundation\RedirectResponse) is incompatible with the return type documented by AppBundle\Controller\Edi...ler::editSizesApiAction of type Symfony\Component\HttpFoundation\JsonResponse.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
383
        }
384
385
        return new JsonResponse(
386
            $this->editCounter->getEditSizeData(),
387
            Response::HTTP_OK
388
        );
389
    }
390
391
    /**
392
     * Get the namespace totals for the user as JSON.
393
     * @Route("/api/ec/namespacetotals/{project}/{username}/{key}", name="EditCounterApiNamespaceTotals")
394
     * @param Request $request
395
     * @param string $project
396
     * @param string $username
397
     * @param string $key API key.
398
     * @return Response
399
     */
400 View Code Duplication
    public function namespaceTotalsApiAction(Request $request, $project, $username, $key)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
401
    {
402
        $ret = $this->setUpEditCounter($project, $username, $key);
403
        if ($ret instanceof RedirectResponse) {
404
            return $ret;
405
        }
406
407
        return new JsonResponse(
408
            $this->editCounter->namespaceTotals(),
409
            Response::HTTP_OK
410
        );
411
    }
412
413
    /**
414
     * Display or fetch the month counts for the user.
415
     * @Route("/api/ec/monthcounts/{project}/{username}/{key}", name="EditCounterApiMonthCounts")
416
     * @param Request $request
417
     * @param string $project
418
     * @param string $username
419
     * @param string $key API key.
420
     * @return Response
421
     */
422 View Code Duplication
    public function monthcountsApiAction(Request $request, $project, $username, $key)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
423
    {
424
        $ret = $this->setUpEditCounter($project, $username, $key);
425
        if ($ret instanceof RedirectResponse) {
426
            return $ret;
427
        }
428
429
        return new JsonResponse(
430
            $this->editCounter->monthCounts(),
431
            Response::HTTP_OK
432
        );
433
    }
434
}
435