Completed
Pull Request — master (#12)
by Sam
09:38
created

ContentfulSyncController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 2
1
<?php
2
3
namespace Digia\Lumen\ContentfulSync\Http\Controllers;
4
5
use Contentful\Core\Resource\ResourceInterface;
6
use Contentful\Delivery\SystemProperties;
7
use Digia\Lumen\ContentfulSync\Contracts\ContentfulSyncServiceContract;
8
use Digia\Lumen\ContentfulSync\Exceptions\ContentfulSyncException;
9
use Digia\Lumen\ContentfulSync\Http\Middleware\NewRelicMiddleware;
10
use Illuminate\Http\Request;
11
use Illuminate\Http\Response;
12
use Laravel\Lumen\Routing\Controller;
13
use Nord\Lumen\Contentful\ContentfulServiceContract;
14
15
/**
16
 * Handles incoming webhooks from Contentful
17
 *
18
 * @package Digia\Lumen\ContentfulSync\Http\Controllers
19
 */
20
class ContentfulSyncController extends Controller
21
{
22
23
    protected const TOPIC_CONTENT_MANAGEMENT_ASSET_PUBLISH   = 'ContentManagement.Asset.publish';
24
    protected const TOPIC_CONTENT_MANAGEMENT_ASSET_UNPUBLISH = 'ContentManagement.Asset.unpublish';
25
    protected const TOPIC_CONTENT_MANAGEMENT_ASSET_DELETE    = 'ContentManagement.Asset.delete';
26
    protected const TOPIC_CONTENT_MANAGEMENT_ENTRY_PUBLISH   = 'ContentManagement.Entry.publish';
27
    protected const TOPIC_CONTENT_MANAGEMENT_ENTRY_UNPUBLISH = 'ContentManagement.Entry.unpublish';
28
    protected const TOPIC_CONTENT_MANAGEMENT_ENTRY_DELETE    = 'ContentManagement.Entry.delete';
29
30
    /**
31
     * @var ContentfulServiceContract
32
     */
33
    private $contentfulService;
34
35
    /**
36
     * @var ContentfulSyncServiceContract
37
     */
38
    private $contentfulSyncService;
39
40
    /**
41
     * ContentfulSyncController constructor.
42
     *
43
     * @param ContentfulServiceContract     $contentfulService
44
     * @param ContentfulSyncServiceContract $contentfulSyncService
45
     */
46
    public function __construct(
47
        ContentfulServiceContract $contentfulService,
48
        ContentfulSyncServiceContract $contentfulSyncService
49
    ) {
50
        $this->contentfulService     = $contentfulService;
51
        $this->contentfulSyncService = $contentfulSyncService;
52
    }
53
54
    /**
55
     * @param Request $request
56
     *
57
     * @return Response
58
     *
59
     * @throws \InvalidArgumentException if the space or environment ID is invalid
60
     * @throws ContentfulSyncException if the webhook cannot be handled
61
     */
62
    public function handleIncomingWebhook(Request $request): Response
63
    {
64
        $requestContent = (string)$request->getContent();
65
66
        // Parse the payload into a Contentful SDK resource object
67
        $resource = $this->contentfulService->getClient()->parseJson($requestContent);
68
69
        // Instrument the request so the middleware can do its job
70
        $contentfulTopic = $this->getContentfulTopic($request);
71
        $request->attributes->set(NewRelicMiddleware::ATTRIBUTE_TOPIC, $contentfulTopic);
72
73
        // Handle different topics differently
74
        switch ($contentfulTopic) {
75
            case self::TOPIC_CONTENT_MANAGEMENT_ASSET_PUBLISH:
76
                $this->contentfulSyncService->publishAsset($requestContent);
77
                break;
78
            case self::TOPIC_CONTENT_MANAGEMENT_ASSET_UNPUBLISH:
79
            case self::TOPIC_CONTENT_MANAGEMENT_ASSET_DELETE:
80
                $this->contentfulSyncService->deleteAsset($resource->getId());
0 ignored issues
show
Bug introduced by
The method getId does only exist in Contentful\Core\Resource\ResourceInterface, but not in Contentful\Core\Resource\ResourceArray.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
81
                break;
82
            case self::TOPIC_CONTENT_MANAGEMENT_ENTRY_PUBLISH:
83
                $contentType = $this->getResourceContentType($resource);
84
85
                $request->attributes->set(NewRelicMiddleware::ATTRIBUTE_CONTENT_TYPE, $contentType);
86
87
                $this->contentfulSyncService->publishEntry($contentType, $requestContent);
88
                break;
89
            case self::TOPIC_CONTENT_MANAGEMENT_ENTRY_UNPUBLISH:
90
            case self::TOPIC_CONTENT_MANAGEMENT_ENTRY_DELETE:
91
                $contentType = $this->getResourceContentType($resource);
92
93
                $request->attributes->set(NewRelicMiddleware::ATTRIBUTE_CONTENT_TYPE, $contentType);
94
95
                $this->contentfulSyncService->deleteEntry($contentType, $resource->getId());
96
                break;
97
            default:
98
                throw new ContentfulSyncException(sprintf('Unknown topic "%s"', $contentfulTopic));
99
        }
100
101
        return new Response();
102
    }
103
104
    /**
105
     * @param ResourceInterface $resource
106
     *
107
     * @return string
108
     *
109
     * @throws \InvalidArgumentException
110
     */
111
    private function getResourceContentType(ResourceInterface $resource): string
112
    {
113
        /** @var SystemProperties $systemProperties */
114
        $systemProperties = $resource->getSystemProperties();
115
        $contentType      = $systemProperties->getContentType();
116
117
        if ($contentType === null) {
118
            throw new \InvalidArgumentException('Resource does not have a content type');
119
        }
120
121
        return $contentType->getId();
122
    }
123
124
    /**
125
     * @param Request $request
126
     *
127
     * @return string
128
     */
129
    private function getContentfulTopic(Request $request): string
130
    {
131
        return $request->header('X-Contentful-Topic', '');
132
    }
133
}
134