Skip to content

Commit

Permalink
fix samples accessible when product is out of stock
Browse files Browse the repository at this point in the history
  • Loading branch information
engcom-Charlie committed Jun 26, 2020
1 parent def5104 commit f9d4e0a
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 27 deletions.
103 changes: 76 additions & 27 deletions app/code/Magento/Downloadable/Controller/Download/Sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,71 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

declare(strict_types=1);

namespace Magento\Downloadable\Controller\Download;

use Magento\Downloadable\Controller\Download;
use Magento\Downloadable\Helper\Download as DownloadHelper;
use Magento\Downloadable\Helper\File;
use Magento\Downloadable\Model\RelatedProductRetriever;
use Magento\Downloadable\Model\Sample as SampleModel;
use Magento\Downloadable\Model\SampleFactory;
use Magento\Framework\App\Action\Context;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\CatalogInventory\Api\StockConfigurationInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\App\ResponseInterface;

/**
* Class Sample executes download sample action.
*
* @SuppressWarnings(PHPMD.AllPurposeAction)
*/
class Sample extends \Magento\Downloadable\Controller\Download
class Sample extends Download
{
/**
* @var RelatedProductRetriever
*/
private $relatedProductRetriever;

/**
* @var File
*/
private $file;

/**
* @var SampleFactory
*/
private $sampleFactory;

/**
* @var StockConfigurationInterface
*/
private $stockConfiguration;

/**
* @param Context $context
* @param RelatedProductRetriever $relatedProductRetriever
* @param File|null $file
* @param SampleFactory|null $sampleFactory
* @param StockConfigurationInterface|null $stockConfiguration
*/
public function __construct(
Context $context,
RelatedProductRetriever $relatedProductRetriever
RelatedProductRetriever $relatedProductRetriever,
?File $file = null,
?SampleFactory $sampleFactory = null,
?StockConfigurationInterface $stockConfiguration = null
) {
parent::__construct($context);

$this->relatedProductRetriever = $relatedProductRetriever;
$this->file = $file ?: ObjectManager::getInstance()->get(File::class);
$this->sampleFactory = $sampleFactory ?: ObjectManager::getInstance()->get(SampleFactory::class);
$this->stockConfiguration = $stockConfiguration
?: ObjectManager::getInstance()->get(StockConfigurationInterface::class);
}

/**
Expand All @@ -47,43 +79,60 @@ public function execute()
{
$sampleId = $this->getRequest()->getParam('sample_id', 0);
/** @var SampleModel $sample */
$sample = $this->_objectManager->create(SampleModel::class);
$sample = $this->sampleFactory->create();
$sample->load($sampleId);
if ($sample->getId() && $this->isProductSalable($sample)) {
$resource = '';
$resourceType = '';
if ($sample->getSampleType() == DownloadHelper::LINK_TYPE_URL) {
$resource = $sample->getSampleUrl();
$resourceType = DownloadHelper::LINK_TYPE_URL;
} elseif ($sample->getSampleType() == DownloadHelper::LINK_TYPE_FILE) {
/** @var \Magento\Downloadable\Helper\File $helper */
$helper = $this->_objectManager->get(\Magento\Downloadable\Helper\File::class);
$resource = $helper->getFilePath($sample->getBasePath(), $sample->getSampleFile());
$resourceType = DownloadHelper::LINK_TYPE_FILE;
}
try {
$this->_processDownload($resource, $resourceType);
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit(0);
} catch (\Exception $e) {
$this->messageManager->addError(
__('Sorry, there was an error getting requested content. Please contact the store owner.')
);
}
if ($this->isCanDownload($sample)) {
$this->download($sample);
}

return $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl());
}

/**
* Check is related product salable.
* Is sample can be downloaded
*
* @param SampleModel $sample
* @return bool
*/
private function isProductSalable(SampleModel $sample): bool
private function isCanDownload(SampleModel $sample): bool
{
$product = $this->relatedProductRetriever->getProduct((int) $sample->getProductId());
return $product ? $product->isSalable() : false;
if ($product && $sample->getId()) {
$isProductEnabled = (int) $product->getStatus() === Status::STATUS_ENABLED;

return $product->isSalable() || $this->stockConfiguration->isShowOutOfStock() && $isProductEnabled;
}

return false;
}

/**
* Download process
*
* @param SampleModel $sample
* @return void
*/
private function download(SampleModel $sample): void
{
$resource = '';
$resourceType = '';

if ($sample->getSampleType() === DownloadHelper::LINK_TYPE_URL) {
$resource = $sample->getSampleUrl();
$resourceType = DownloadHelper::LINK_TYPE_URL;
} elseif ($sample->getSampleType() === DownloadHelper::LINK_TYPE_FILE) {
$resource = $this->file->getFilePath($sample->getBasePath(), $sample->getSampleFile());
$resourceType = DownloadHelper::LINK_TYPE_FILE;
}

try {
$this->_processDownload($resource, $resourceType);
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit(0);
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(
__('Sorry, there was an error getting requested content. Please contact the store owner.')
);
}
}
}
11 changes: 11 additions & 0 deletions app/code/Magento/Downloadable/Test/Mftf/Data/ProductData.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,15 @@
<requiredEntity type="downloadable_link">downloadableLink1</requiredEntity>
<requiredEntity type="downloadable_link">downloadableLink2</requiredEntity>
</entity>
<entity name="DownloadableProductWithoutLinksOutOfStock" type="product">
<data key="sku" unique="suffix">downloadableproduct</data>
<data key="type_id">downloadable</data>
<data key="attribute_set_id">4</data>
<data key="name" unique="suffix">DownloadableProduct</data>
<data key="price">99.99</data>
<data key="quantity">50</data>
<data key="status">1</data>
<data key="is_in_stock">0</data>
<data key="urlKey" unique="suffix">downloadableproduct</data>
</entity>
</entities>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->

<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
<test name="VerifyOutOfStockDownloadableProductSamplesAreAccessibleTest">
<annotations>
<features value="Downloadable"/>
<stories value="Downloadable product"/>
<title value="Samples of Downloadable Products are accessible, if product is out of stock"/>
<description value="Samples of Downloadable Products are accessible, if product is out of stock"/>
<severity value="MAJOR"/>
<group value="downloadable"/>
<group value="catalog"/>
</annotations>
<before>
<!-- Enable show out of stock product -->
<magentoCLI stepKey="enableShowOutOfStockProduct" command="config:set cataloginventory/options/show_out_of_stock 1"/>

<!-- Add downloadable domains -->
<magentoCLI stepKey="addDownloadableDomain" command="downloadable:domains:add example.com static.magento.com"/>

<!-- Create category -->
<createData entity="_defaultCategory" stepKey="createCategory"/>

<!-- Create downloadable product -->
<createData entity="DownloadableProductWithoutLinksOutOfStock" stepKey="createProduct">
<requiredEntity createDataKey="createCategory"/>
</createData>

<!-- Add downloadable link -->
<createData entity="downloadableLink1" stepKey="addDownloadableLink">
<requiredEntity createDataKey="createProduct"/>
</createData>

<!-- Add downloadable sample -->
<createData entity="DownloadableSample" stepKey="addDownloadableSample">
<requiredEntity createDataKey="createProduct"/>
</createData>
</before>
<after>
<!-- Disable show out of stock product -->
<magentoCLI stepKey="enableShowOutOfStockProduct" command="config:set cataloginventory/options/show_out_of_stock 0"/>

<!-- Remove downloadable domains -->
<magentoCLI stepKey="removeDownloadableDomain" command="downloadable:domains:remove example.com static.magento.com"/>

<!-- Delete product -->
<deleteData createDataKey="createProduct" stepKey="deleteDownloadableProduct"/>

<!-- Delete category -->
<deleteData createDataKey="createCategory" stepKey="deleteCategory"/>

<!-- Admin logout -->
<actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/>
</after>

<!-- Open Downloadable product from precondition on Storefront -->
<actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openStorefrontProductPage">
<argument name="productUrl" value="$createProduct.custom_attributes[url_key]$"/>
</actionGroup>

<!-- Sample url is accessible -->
<actionGroup ref="AssertStorefrontSeeElementActionGroup" stepKey="seeDownloadableSample">
<argument name="selector" value="{{StorefrontDownloadableProductSection.downloadableSampleLabel(DownloadableSample.title)}}"/>
</actionGroup>
<click selector="{{StorefrontDownloadableProductSection.downloadableSampleLabel(DownloadableSample.title)}}" stepKey="clickDownloadableSample"/>
<switchToNextTab stepKey="switchToSampleTab"/>
<wait time="2" stepKey="waitToMakeSureThereWillBeNoRedirectToHomePage"/>
<seeInCurrentUrl url="downloadable/download/sample/sample_id/" stepKey="amOnSampleDownloadPage"/>
<closeTab stepKey="closeSampleTab"/>
</test>
</tests>

0 comments on commit f9d4e0a

Please sign in to comment.