Commit 39829c19 by halweg

feat : review模块点赞

parent 9c30de29
......@@ -23,6 +23,8 @@ class Images extends \Magento\Framework\View\Element\Template
private $reviewId;
private $productId;
/**
* @var int
*/
......@@ -73,6 +75,17 @@ class Images extends \Magento\Framework\View\Element\Template
return $this;
}
public function setProductId($productId): Images
{
$this->productId = $productId;
return $this;
}
public function getProductId()
{
return $this->productId;
}
public function getCollection() {
/** @var Collection $collection */
$collection = $this->collectionFactory->create()
......
......@@ -11,6 +11,8 @@ use Joshine\Review\Block\Components\Pager;
class ListView extends \Magento\Review\Block\Product\View\ListView
{
const VOTED_CLASS_NAME = 'active';
/**
* @var \Magento\Review\Model\Review\SummaryFactory
*/
......@@ -25,15 +27,32 @@ class ListView extends \Magento\Review\Block\Product\View\ListView
private $reviewsColFactory;
private $voteRepository;
private $vote;
private $formKey;
/**
* @var \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress
*/
private $remoteAddress;
public function __construct(
DataObjectFactory $dataObjectFactory,
SummaryFactory $summaryModFactory,
\Magento\Framework\Data\Form\FormKey $formKey,
\Magento\Framework\HTTP\PhpEnvironment\RemoteAddress $remoteAddress,
\Joshine\Review\Model\Repository\VoteRepository $voteRepository,
\Magento\Review\Model\ResourceModel\Review\CollectionFactory $reviewsColFactory,
\Magento\Catalog\Block\Product\Context $context, \Magento\Framework\Url\EncoderInterface $urlEncoder, \Magento\Framework\Json\EncoderInterface $jsonEncoder, \Magento\Framework\Stdlib\StringUtils $string, \Magento\Catalog\Helper\Product $productHelper, \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig, \Magento\Framework\Locale\FormatInterface $localeFormat, \Magento\Customer\Model\Session $customerSession, ProductRepositoryInterface $productRepository, \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, \Magento\Review\Model\ResourceModel\Review\CollectionFactory $collectionFactory, array $data = [])
{
$this->summaryModFactory = $summaryModFactory;
$this->dataObjectFactory = $dataObjectFactory;
$this->reviewsColFactory = $reviewsColFactory;
$this->voteRepository = $voteRepository;
$this->formKey = $formKey;
$this->remoteAddress = $remoteAddress;
parent::__construct($context, $urlEncoder, $jsonEncoder, $string, $productHelper, $productTypeConfig, $localeFormat, $customerSession, $productRepository, $priceCurrency, $collectionFactory, $data);
}
......@@ -90,8 +109,15 @@ class ListView extends \Magento\Review\Block\Product\View\ListView
'2' => 0,
'1' => 0
];
foreach ($this->getReviewsCollection() as $item) {
$reviews = $this->reviewsColFactory->create()->addStoreFilter(
$this->_storeManager->getStore()->getId()
)->addStatusFilter(
\Magento\Review\Model\Review::STATUS_APPROVED
)->addEntityFilter(
'product',
$this->getProduct()->getId()
);
foreach ($reviews as $item) {
if($item->getSizeFits() != 0 ){
$key = $item->getSizeFits();
$result[$key] = $result[$key] + 1;
......@@ -140,4 +166,51 @@ class ListView extends \Magento\Review\Block\Product\View\ListView
return $this->getChildHtml('pager');
}
private function getVote($reviewId)
{
return $this->voteRepository->getVotesCount($reviewId);
}
public function getPlusReview($reviewId)
{
$vote = $this->getVote($reviewId);
return $vote['plus'];
}
/**
* @return string
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function getFormKey(): string
{
return $this->formKey->getFormKey();
}
/**
* @return string
*/
public function getPlusVotedClass($reviewId)
{
$result = '';
if ($this->isPlusVoted($reviewId)) {
$result = self::VOTED_CLASS_NAME;
}
return $result;
}
private function getVotedByIp($reviewId)
{
return $this->voteRepository->getVotesCount(
$reviewId,
$this->remoteAddress->getRemoteAddress()
);
}
public function isPlusVoted($reviewId)
{
$voted = $this->getVotedByIp($reviewId);
return $voted['plus'] > 0;
}
}
<?php
namespace Joshine\Review\Controller\Ajax;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Controller\Result\JsonFactory;
class Helpful extends \Magento\Framework\App\Action\Action
{
/**
* @var \Magento\Framework\Data\Form\FormKey\Validator
*/
private $formKeyValidator;
/**
* @var \Psr\Log\LoggerInterface
*/
private $logger;
/**
* @var \Magento\Framework\Json\EncoderInterface
*/
private $jsonEncoder;
/**
* @var \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress
*/
private $remoteAddress;
private $voteRepository;
private $voteFactory;
/**
* @var JsonFactory
*/
private $resultJsonFactory;
public function __construct(
Context $context,
\Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator,
\Psr\Log\LoggerInterface $logger,
\Magento\Framework\Json\EncoderInterface $jsonEncoder,
\Magento\Framework\HTTP\PhpEnvironment\RemoteAddress $remoteAddress,
\Joshine\Review\Model\VoteFactory $voteFactory,
\Joshine\Review\Model\Repository\VoteRepository $voteRepository,
JsonFactory $resultJsonFactory
) {
parent::__construct($context);
$this->formKeyValidator = $formKeyValidator;
$this->logger = $logger;
$this->jsonEncoder = $jsonEncoder;
$this->remoteAddress = $remoteAddress;
$this->voteRepository = $voteRepository;
$this->voteFactory = $voteFactory;
$this->resultJsonFactory = $resultJsonFactory;
}
/**
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Json|\Magento\Framework\Controller\ResultInterface
*/
public function execute()
{
$message = [
'error' => __('Sorry. There is a problem with your Vote Request.')
];
if ($this->getRequest()->isAjax()) {
try {
if (!$this->formKeyValidator->validate($this->getRequest())) {
throw new LocalizedException(
__('Form key is not valid. Please try to reload the page.')
);
}
$type = $this->getRequest()->getParam('type');
$reviewId = (int)$this->getRequest()->getParam('review');
if ($reviewId > 0 && in_array($type, ['plus', 'minus', 'update'])) {
$ip = $this->remoteAddress->getRemoteAddress();
if ($type != 'update') {
$type = ($type == 'plus') ? '1' : '0';
$model = $this->voteRepository->getByIdAndIp($reviewId, $ip);
$modelType = $model->getType();
if ($model->getVoteId()) {
$this->voteRepository->delete($model);
}
if ($modelType === null || $modelType != $type) {
$model = $this->voteFactory->create();
$model->setIp($ip);
$model->setReviewId($reviewId);
$model->setType($type);
$this->voteRepository->save($model);
}
}
$votesForReview = $this->voteRepository->getVotesCount($reviewId);
$voted = $this->voteRepository->getVotesCount($reviewId, $ip);
$message = [
'success' => __('Success.'),
'data' => $votesForReview,
'voted' => $voted
];
}
} catch (LocalizedException $e) {
$message = ['error' => $e->getMessage()];
} catch (\Exception $e) {
$this->logger->error($e->getMessage());
}
}
$resultPage = $this->resultJsonFactory->create();
$resultPage->setHttpResponseCode(200);
$resultPage->setData($message);
return $resultPage;
}
}
......@@ -53,11 +53,12 @@ class BlockHelper implements \Magento\Framework\Data\CollectionDataSourceInterfa
$this->urlBuilder = $urlBuilder;
$this->request = $request;
}
public function getReviewImagesHtml($reviewId, $addSizeStyles = true)
public function getReviewImagesHtml($reviewId, $productId)
{
$html = '';
$block = $this->blockFactory
->createBlock(Images::class)
->setProductId($productId)
->setReviewId($reviewId);
if ($block) {
$html = $block->toHtml();
......
<?php
namespace Joshine\Review\Model\Repository;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Exception\CouldNotDeleteException;
use Magento\Framework\Exception\CouldNotSaveException;
use Joshine\Review\Model\ResourceModel;
use Joshine\Review\Model\VoteFactory;
class VoteRepository
{
/**
* @var array
*/
private $vote = [];
/**
* @var ResourceModel\Vote
*/
private $voteResource;
/**
* @var VoteFactory
*/
private $voteFactory;
/**
* @var ResourceModel\Vote\CollectionFactory
*/
private $collectionFactory;
public function __construct(
\Joshine\Review\Model\ResourceModel\Vote $voteResource,
\Joshine\Review\Model\VoteFactory $voteFactory,
\Joshine\Review\Model\ResourceModel\Vote\CollectionFactory $collectionFactory
) {
$this->voteResource = $voteResource;
$this->voteFactory = $voteFactory;
$this->collectionFactory = $collectionFactory;
}
/**
* {@inheritdoc}
*/
public function save($vote)
{
if ($vote->getVoteId()) {
$vote = $this->get($vote->getVoteId())->addData($vote->getData());
}
try {
$this->voteResource->save($vote);
$this->vote[$vote->getVoteId()] = $vote;
} catch (\Exception $e) {
if ($vote->getVoteId()) {
throw new CouldNotSaveException(
__('Unable to save vote with ID %1. Error: %2', [$vote->getVoteId(), $e->getMessage()])
);
}
throw new CouldNotSaveException(__('Unable to save new vote. Error: %1', $e->getMessage()));
}
return $vote;
}
/**
* {@inheritdoc}
*/
public function get($voteId)
{
if (!isset($this->vote[$voteId])) {
$vote = $this->voteFactory->create();
$this->voteResource->load($vote, $voteId);
if (!$vote->getVoteId()) {
throw new NoSuchEntityException(__('Vote with specified ID "%1" not found.', $voteId));
}
$this->vote[$voteId] = $vote;
}
return $this->vote[$voteId];
}
public function getByIdAndIp($reviewId, $ip)
{
$vote = $this->voteFactory->create();
$collection = $this->collectionFactory->create()
->addFieldToFilter('review_id', $reviewId)
->addFieldToFilter('ip', $ip);
$collection->getSelect()->limit(1);
if ($collection->getSize() > 0) {
$vote = $collection->getFirstItem();
}
return $vote;
}
/**
* {@inheritdoc}
*/
public function delete($vote)
{
try {
$this->voteResource->delete($vote);
unset($this->vote[$vote->getId()]);
} catch (\Exception $e) {
if ($vote->getVoteId()) {
throw new CouldNotDeleteException(
__('Unable to remove vote with ID %1. Error: %2', [$vote->getVoteId(), $e->getMessage()])
);
}
throw new CouldNotDeleteException(__('Unable to remove vote. Error: %1', $e->getMessage()));
}
return true;
}
/**
* {@inheritdoc}
*/
public function deleteById($voteId)
{
$model = $this->get($voteId);
$this->delete($model);
return true;
}
/**
* @param $reviewId
* @param null $ip
* @return array
*/
public function getVotesCount($reviewId, $ip = null)
{
$result = [
'plus' => 0,
'minus' => 0
];
$collection = $this->collectionFactory->create()
->addFieldToFilter('review_id', $reviewId);
if ($ip) {
$collection->addFieldToFilter('ip', $ip);
}
foreach ($collection as $vote) {
if ($vote->getType() == '1') {
$result['plus'] = ++$result['plus'];
} else {
$result['minus'] = ++$result['minus'];
}
}
return $result;
}
public function getVoteModel()
{
return $this->voteFactory->create();
}
/**
* @return array
*/
public function getVoteIpKeys()
{
return $this->collectionFactory->create()->getVoteIpKeys();
}
}
<?php
namespace Joshine\Review\Model\ResourceModel;
class Vote extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
const TABLE_NAME = 'joshine_review_vote';
protected function _construct()
{
$this->_init(self::TABLE_NAME, 'vote_id');
}
}
<?php
namespace Joshine\Review\Model\ResourceModel\Vote;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
class Collection extends AbstractCollection
{
public function _construct()
{
$this->_init(
\Joshine\Review\Model\Vote::class,
\Joshine\Review\Model\ResourceModel\Vote::class
);
}
/**
* @return array
*/
public function getVoteIpKeys(): array
{
$this->getSelect()->columns('CONCAT(review_id,ip) as vote_key');
return $this->getColumnValues('vote_key');
}
}
<?php
namespace Joshine\Review\Model;
use Magento\Framework\Model\AbstractModel;
class Vote extends AbstractModel
{
const VOTE_ID = 'vote_id';
const REVIEW_ID = 'review_id';
const TYPE = 'type';
const IP = 'ip';
public function _construct()
{
$this->_init(\Joshine\Review\Model\ResourceModel\Vote::class);
}
/**
* Returns vote id field
*
* @return int|null
*/
public function getVoteId()
{
return $this->getData(self::VOTE_ID);
}
/**
* @param int $voteId
*
* @return $this
*/
public function setVoteId($voteId)
{
$this->setData(self::VOTE_ID, $voteId);
return $this;
}
/**
* Returns review id field
*
* @return int|null
*/
public function getReviewId()
{
return $this->getData(self::REVIEW_ID);
}
/**
* @param int $reviewId
*
* @return $this
*/
public function setReviewId($reviewId)
{
$this->setData(self::REVIEW_ID, $reviewId);
return $this;
}
/**
* Returns vote type
*
* @return int|null
*/
public function getType()
{
return $this->getData(self::TYPE);
}
/**
* @param int $type
*
* @return $this
*/
public function setType($type)
{
$this->setData(self::TYPE, $type);
return $this;
}
/**
* Returns vote type
*
* @return string|null
*/
public function getIp()
{
return $this->getData(self::IP);
}
/**
* @param string $ip
*
* @return $this
*/
public function setIp($ip)
{
$this->setData(self::IP, $ip);
return $this;
}
}
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="joshine_review" frontName="joshine_review">
<module name="Joshine_Review" />
</route>
</router>
</config>
......@@ -5,10 +5,12 @@ $collection = $block->getCollection();
<?php if ($collection->getSize()): ?>
<?php foreach ($collection as $item): ?>
<div class="joshine-review-pic-item joshine-col-xs-4">
<img class="review-image rounded"
src="<?= $block->getResizedImagePath($item) ?>"
/>
<div class="joshine-review-pic-item joshine-col-xs-4" data-amreview-js="slider-item" data-img-src="<?= $block->getFullImagePath($item) ?>"
data-product-id="<?= $block->getProductId() ?>"
data-reviews-id="<?= $block->getReviewId() ?>">
<img class="review-image rounded" src="<?= $block->getResizedImagePath($item) ?>"/>
</div>
<?php endforeach; ?>
<?php endif;?>
<div id="popup-mpdal" >
<style>
.joshine-model-warp .joshine-mask {
z-index: 1000;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0,0,0,.8);
}
</style>
<div class="joshine-model-warp joshine-hidden">
Place Your Contents Here
</div>
\ No newline at end of file
<div class="joshine-mask"></div>
</div>
......@@ -131,14 +131,16 @@ $t = [ 1 => __('Small') , 2 => __('True to Size') ,3 => __('Large')];
</div>
</div>
<div class="joshine-review-pics">
<?= /* @noEscape */ $helper->getReviewImagesHtml($review->getId()) ?>
<?= /* @noEscape */ $helper->getReviewImagesHtml($review->getId(), $block->getProductId()) ?>
</div>
</div>
<div class="joshine-review-list-item-right">
<div class="joshine-review-helpful joshine-font-c-darkgray joshine-font-text">
<span>helpful</span>
<span class="joshine-like"></span>
<span class="joshine-review-likes-count">3</span>
<span class="joshine-like <?= $block->getPlusVotedClass($review->getId()); ?>" data-review-id="<?= $review->getId(); ?>">
<input name="form_key" type="hidden" value="<?= /* @noEscape */ $block->getFormKey(); ?>" />
</span>
<span class="joshine-review-likes-count"><?= $block->getPlusReview($review->getId()); ?></span>
</div>
</div>
</div>
......@@ -216,8 +218,10 @@ $t = [ 1 => __('Small') , 2 => __('True to Size') ,3 => __('Large')];
</div>
<div class="joshine-pull-right">
<div class="joshine-review-helpful joshine-font-c-darkgray joshine-font-text">
<span class="joshine-like"></span>
<span class="joshine-review-likes-count">3</span>
<span class="joshine-like <?= $block->getPlusVotedClass($review->getId()); ?>" data-review-id="<?= $review->getId(); ?>">
<input name="form_key" type="hidden" value="<?= /* @noEscape */ $block->getFormKey(); ?>" />
</span>
<span class="joshine-review-likes-count" data-review-id="<?= $review->getId(); ?>"><?= $block->getPlusReview($review->getId()); ?></span>
</div>
</div>
</div>
......@@ -236,7 +240,7 @@ $t = [ 1 => __('Small') , 2 => __('True to Size') ,3 => __('Large')];
</div>
<div class="row joshine-review-pics">
<?= /* @noEscape */ $helper->getReviewImagesHtml($review->getId()) ?>
<?= /* @noEscape */ $helper->getReviewImagesHtml($review->getId(), $block->getProductId()) ?>
</div>
</div>
<hr>
......@@ -254,5 +258,41 @@ $t = [ 1 => __('Small') , 2 => __('True to Size') ,3 => __('Large')];
$(".joshine-review-add-btn").on('click',function () {
$(".block.review-add").removeClass('joshine-hidden');
});
$(".joshine-like").on('click', function() {
var element = $(this);
var formKey = $.mage.cookies.get('form_key');
if (formKey) {
element.find('input[name="form_key"]').val(formKey);
}
var type = element.hasClass('active') ? 'minus' : 'plus';
var reviewId = element.data('review-id');
var data = 'type='+ type +'&form_key=' + formKey + '&review=' + reviewId;
function refreshReviewVote(response)
{
if (!response.hasOwnProperty('success')) {
return;
}
if (type === 'plus') {
element.addClass('active')
}
if (type === 'minus') {
element.removeClass('active')
}
element.siblings('.joshine-review-likes-count').html(response.data.plus);
}
$.ajax({
url: '/joshine_review/ajax/helpful',
data: data,
type: 'GET',
dataType: 'json',
success: function (response) {
refreshReviewVote(response);
}
});
});
});
</script>
\ No newline at end of file
define(['jquery'], function ($) {
define(['jquery', 'Magento_Ui/js/modal/modal'], function ($) {
'use strict';
return {
_create : function () {
handleReviewsImgClick : function (element, event) {
$('.joshine-model-warp').removeClass('joshine-hidden');
},
handlePage : function (element, event) {
......@@ -25,14 +26,5 @@ define(['jquery'], function ($) {
pageLoad.loaderContext.html(data);
});
},
_dealClass : function (element, classNames) {
for (let className of classNames) {
element.siblings().removeClass(className)
}
for (let className of classNames) {
element.addClass(className)
}
}
}
});
\ No newline at end of file
......@@ -8,18 +8,15 @@ define([
_create: function () {
var self = this;
self._binding();
//组件初始化
self._componentLoad();
},
_componentLoad : function () {
},
_binding : function () {
$(document).on('click', '.joshine-pagination-btn', function(event){
handler.handlePage($(this), event);
});
/*$(document).on('click', '.joshine-review-pic-item', function (event) {
handler.handleReviewsImgClick($(this), event);
});*/
},
});
return $.mage.joshineReview
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment