You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
287 lines
8.3 KiB
287 lines
8.3 KiB
<?php |
|
|
|
namespace Drupal\islandora\Controller; |
|
|
|
use Drupal\Core\Access\AccessResult; |
|
use Drupal\Core\Controller\ControllerBase; |
|
use Drupal\Core\Database\Connection; |
|
use Drupal\Core\Routing\RouteMatch; |
|
use Drupal\Core\Session\AccountInterface; |
|
use Drupal\media\Entity\Media; |
|
use Drupal\media\MediaInterface; |
|
use Drupal\media\MediaTypeInterface; |
|
use Drupal\node\NodeInterface; |
|
use Drupal\taxonomy\TermInterface; |
|
use Drupal\islandora\IslandoraUtils; |
|
use Drupal\islandora\MediaSource\MediaSourceService; |
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
|
use Symfony\Component\HttpFoundation\Request; |
|
use Symfony\Component\HttpFoundation\Response; |
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; |
|
use Symfony\Component\HttpKernel\Exception\HttpException; |
|
|
|
/** |
|
* Controller for MediaSource. |
|
* |
|
* @package Drupal\islandora\Controller |
|
*/ |
|
class MediaSourceController extends ControllerBase { |
|
|
|
/** |
|
* Service for business logic. |
|
* |
|
* @var \Drupal\islandora\MediaSource\MediaSourceService |
|
*/ |
|
protected $service; |
|
|
|
/** |
|
* Database connection. |
|
* |
|
* @var \Drupal\Core\Database\Connection |
|
*/ |
|
protected $database; |
|
|
|
/** |
|
* Islandora utils. |
|
* |
|
* @var \Drupal\islandora\IslandoraUtils |
|
*/ |
|
protected $utils; |
|
|
|
/** |
|
* MediaSourceController constructor. |
|
* |
|
* @param \Drupal\islandora\MediaSource\MediaSourceService $service |
|
* Service for business logic. |
|
* @param \Drupal\Core\Database\Connection $database |
|
* Database connection. |
|
* @param \Drupal\islandora\IslandoraUtils $utils |
|
* Islandora utils. |
|
*/ |
|
public function __construct( |
|
MediaSourceService $service, |
|
Connection $database, |
|
IslandoraUtils $utils |
|
) { |
|
$this->service = $service; |
|
$this->database = $database; |
|
$this->utils = $utils; |
|
} |
|
|
|
/** |
|
* Controller's create method for dependecy injection. |
|
* |
|
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container |
|
* The App Container. |
|
* |
|
* @return \Drupal\islandora\Controller\MediaSourceController |
|
* Controller instance. |
|
*/ |
|
public static function create(ContainerInterface $container) { |
|
return new static( |
|
$container->get('islandora.media_source_service'), |
|
$container->get('database'), |
|
$container->get('islandora.utils') |
|
); |
|
} |
|
|
|
/** |
|
* Updates a source file for a Media. |
|
* |
|
* @param \Drupal\media\MediaInterface $media |
|
* The media whose source file you want to update. |
|
* @param \Symfony\Component\HttpFoundation\Request $request |
|
* The request object. |
|
* |
|
* @return \Symfony\Component\HttpFoundation\Response |
|
* 204 on success. |
|
* |
|
* @throws \Symfony\Component\HttpKernel\Exception\HttpException |
|
*/ |
|
public function put(MediaInterface $media, Request $request) { |
|
$content_type = $request->headers->get('Content-Type', ""); |
|
|
|
if (empty($content_type)) { |
|
throw new BadRequestHttpException("Missing Content-Type header"); |
|
} |
|
|
|
// Since we update both the Media and its File, do this in a transaction. |
|
$transaction = $this->database->startTransaction(); |
|
|
|
try { |
|
|
|
$this->service->updateSourceField( |
|
$media, |
|
$request->getContent(TRUE), |
|
$content_type |
|
); |
|
|
|
return new Response("", 204); |
|
} |
|
catch (HttpException $e) { |
|
$transaction->rollBack(); |
|
throw $e; |
|
} |
|
catch (\Exception $e) { |
|
$transaction->rollBack(); |
|
throw new HttpException(500, $e->getMessage()); |
|
} |
|
} |
|
|
|
/** |
|
* Adds a Media to a Node using the specified field. |
|
* |
|
* @param \Drupal\node\NodeInterface $node |
|
* The Node to which you want to add a Media. |
|
* @param \Drupal\media\MediaTypeInterface $media_type |
|
* Media type for new media. |
|
* @param \Drupal\taxonomy\TermInterface $taxonomy_term |
|
* Term from the 'Behavior' vocabulary to give to new media. |
|
* @param \Symfony\Component\HttpFoundation\Request $request |
|
* The request object. |
|
* |
|
* @return \Symfony\Component\HttpFoundation\Response |
|
* 201 on success with a Location link header. |
|
* |
|
* @throws \Symfony\Component\HttpKernel\Exception\HttpException |
|
*/ |
|
public function putToNode( |
|
NodeInterface $node, |
|
MediaTypeInterface $media_type, |
|
TermInterface $taxonomy_term, |
|
Request $request |
|
) { |
|
$content_type = $request->headers->get('Content-Type', ""); |
|
|
|
if (empty($content_type)) { |
|
throw new BadRequestHttpException("Missing Content-Type header"); |
|
} |
|
|
|
$content_location = $request->headers->get('Content-Location', ""); |
|
|
|
// Since we create both a Media and its File, |
|
// start a transaction. |
|
$transaction = $this->database->startTransaction(); |
|
|
|
try { |
|
$media = $this->service->putToNode( |
|
$node, |
|
$media_type, |
|
$taxonomy_term, |
|
$request->getContent(TRUE), |
|
$content_type, |
|
$content_location |
|
); |
|
|
|
// We return the media if it was newly created. |
|
if ($media) { |
|
$response = new Response("", 201); |
|
$response->headers->set("Location", $this->utils->getEntityUrl($media)); |
|
} |
|
else { |
|
$response = new Response("", 204); |
|
} |
|
return $response; |
|
} |
|
catch (HttpException $e) { |
|
$transaction->rollBack(); |
|
throw $e; |
|
} |
|
catch (\Exception $e) { |
|
$transaction->rollBack(); |
|
throw new HttpException(500, $e->getMessage()); |
|
} |
|
} |
|
|
|
/** |
|
* Checks for permissions to update a node and create media. |
|
* |
|
* @param \Drupal\Core\Session\AccountInterface $account |
|
* Account for user making the request. |
|
* @param \Drupal\Core\Routing\RouteMatch $route_match |
|
* Route match to get Node from url params. |
|
* |
|
* @return \Drupal\Core\Access\AccessResultInterface |
|
* Access result. |
|
*/ |
|
public function putToNodeAccess(AccountInterface $account, RouteMatch $route_match) { |
|
// We'd have 404'd already if node didn't exist, so no need to check. |
|
// Just hack it out of the route match. |
|
$node = $route_match->getParameter('node'); |
|
return AccessResult::allowedIf($node->access('update', $account) && $account->hasPermission('create media')); |
|
} |
|
|
|
/** |
|
* Adds file to existing media. |
|
* |
|
* @param Drupal\media\Entity\Media\Media $media |
|
* The media to which file is added. |
|
* @param string $destination_field |
|
* The name of the media field to add file reference. |
|
* @param \Symfony\Component\HttpFoundation\Request $request |
|
* The request object. |
|
* |
|
* @return \Symfony\Component\HttpFoundation\Response |
|
* 201 on success with a Location link header. |
|
* |
|
* @throws \Drupal\Core\Entity\EntityStorageException |
|
* @throws \Drupal\Core\TypedData\Exception\ReadOnlyException |
|
*/ |
|
public function attachToMedia( |
|
Media $media, |
|
string $destination_field, |
|
Request $request |
|
) { |
|
$content_location = $request->headers->get('Content-Location', ""); |
|
if (empty($content_location)) { |
|
throw new BadRequestHttpException("Missing Content-Location header"); |
|
} |
|
|
|
$content_type = $request->headers->get('Content-Type', ""); |
|
if (empty($content_type)) { |
|
throw new BadRequestHttpException("Missing Content-Type header"); |
|
} |
|
|
|
// Since we create both a Media and its File, |
|
// start a transaction. |
|
$transaction = $this->database->startTransaction(); |
|
|
|
try { |
|
$this->service->putToMedia( |
|
$media, |
|
$destination_field, |
|
$request->getContent(TRUE), |
|
$content_type, |
|
$content_location |
|
); |
|
// Should only see this with a GET request for testing. |
|
return new Response("<h1>Complete</h1>"); |
|
} |
|
catch (HttpException $e) { |
|
$transaction->rollBack(); |
|
throw $e; |
|
} |
|
catch (\Exception $e) { |
|
$transaction->rollBack(); |
|
throw new HttpException(500, $e->getMessage()); |
|
} |
|
} |
|
|
|
/** |
|
* Checks for permissions to update a node and update media. |
|
* |
|
* @param \Drupal\Core\Session\AccountInterface $account |
|
* Account for user making the request. |
|
* @param \Drupal\Core\Routing\RouteMatch $route_match |
|
* Route match to get Node from url params. |
|
* |
|
* @return \Drupal\Core\Access\AccessResultInterface |
|
* Access result. |
|
*/ |
|
public function attachToMediaAccess(AccountInterface $account, RouteMatch $route_match) { |
|
$media = $route_match->getParameter('media'); |
|
$node = $this->utils->getParentNode($media); |
|
return AccessResult::allowedIf($node->access('update', $account) && $account->hasPermission('create media')); |
|
} |
|
|
|
}
|
|
|