diff --git a/libraries/src/MVC/Controller/ApiController.php b/libraries/src/MVC/Controller/ApiController.php index 557209af4e55e..681438ece2c93 100644 --- a/libraries/src/MVC/Controller/ApiController.php +++ b/libraries/src/MVC/Controller/ApiController.php @@ -19,6 +19,7 @@ use Joomla\CMS\MVC\Model\ListModel; use Joomla\CMS\MVC\Model\State; use Joomla\CMS\MVC\View\JsonApiView; +use Joomla\CMS\Response\JsonResponse; use Joomla\Input\Input; use Joomla\Registry\Registry; use Tobscure\JsonApi\Exception\InvalidParameterException; @@ -304,6 +305,23 @@ public function delete($id = null) if ($model->getError() !== false) { throw new \RuntimeException($model->getError(), 500); } + + // If the model has set a 409 status code in the session, we return a 409 http status codee + if ($this->app->getSession()->get('http_status_code_409', false)) { + $this->app->getSession()->clear('http_status_code_409'); + $this->app->setHeader('status', 409, true); + $this->app->setHeader('Content-Type', 'application/json'); + $this->app->sendHeaders(); + $body = [ + 'status' => 'Conflict', + 'code' => 409, + 'message' => 'Resource not in state that can be deleted, must be trashed before it can be deleted', + ]; + echo new JsonResponse($body); + $this->app->close(); + } else { + throw new \RuntimeException(Text::_('JLIB_APPLICATION_ERROR_DELETE'), 500); + } } $this->app->setHeader('status', 204); diff --git a/libraries/src/MVC/Model/AdminModel.php b/libraries/src/MVC/Model/AdminModel.php index e451ebccf39a9..78e57662704f0 100644 --- a/libraries/src/MVC/Model/AdminModel.php +++ b/libraries/src/MVC/Model/AdminModel.php @@ -953,14 +953,30 @@ public function delete(&$pks) return false; } + if (Factory::getApplication()->isClient('api')) { + $session = Factory::getApplication()->getSession(); + $session->set('http_status_code_409', true); + } + Log::add(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), Log::WARNING, 'jerror'); return false; } } else { - $this->setError($table->getError()); + $error = $this->getError(); + if ($error) { + $this->setError($table->getError()); - return false; + return false; + } + if (Factory::getApplication()->isClient('api')) { + $session = Factory::getApplication()->getSession(); + $session->set('http_status_code_409', true); + } + + Log::add(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), Log::WARNING, 'jerror'); + + return true; } } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 7840bbd8a9d78..0d1c784fef2ce 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -13104,7 +13104,7 @@ parameters: Catch thrown Exceptions instead of getError$# ''' identifier: method.deprecated - count: 1 + count: 2 path: libraries/src/MVC/Model/AdminModel.php - diff --git a/tests/System/integration/api/com_banners/Banners.cy.js b/tests/System/integration/api/com_banners/Banners.cy.js index 6619b1ed4ee6f..e7c8d2b524ac5 100644 --- a/tests/System/integration/api/com_banners/Banners.cy.js +++ b/tests/System/integration/api/com_banners/Banners.cy.js @@ -48,4 +48,28 @@ describe('Test that banners API endpoint', () => { cy.db_createBanner({ name: 'automated test banner', state: -2 }) .then((banner) => cy.api_delete(`/banners/${banner.id}`)); }); + + it('check correct response for delete a not existent contact', () => { + cy.api_delete('/banners/9999') + .then((result) => expect(result.status).to.eq(204)); + }); + + it('cannot delete a banner that is not trashed', () => { + cy.db_createBanner({ name: 'automated test banner' }) + .then((banner) => { + cy.api_getBearerToken().then((token) => { + cy.request({ + method: 'DELETE', + url: `/api/index.php/v1/banners/${banner.id}`, + headers: { + Authorization: `Bearer ${token}`, + }, + failOnStatusCode: false + }).then((response) => { + expect(response.status).to.equal(409); + expect(response.body.data.message).to.include('must be trashed before it can be deleted'); + }); + }); + }); + }); });