Completed
Push — master ( 02d35f...e51675 )
by Sam
12s
created

ContentfulSyncController::handleIncomingWebhook()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 41
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 41
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 27
nc 7
nop 1
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($this->getResourceId($resource));
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, $this->getResourceId($resource));
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 ResourceInterface $resource
126
     *
127
     * @return string
128
     */
129
    private function getResourceId(ResourceInterface $resource): string
130
    {
131
        return $resource->getSystemProperties()->getId();
132
    }
133
134
    /**
135
     * @param Request $request
136
     *
137
     * @return string
138
     */
139
    private function getContentfulTopic(Request $request): string
140
    {
141
        return $request->header('X-Contentful-Topic', '');
142
    }
143
}
144