diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 6da4321..22b9bf5 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -37,7 +37,7 @@ jobs:
NC3_BUILD_DIR: "/opt/nc3"
NC3_DOCKER_DIR: "/opt/docker"
NC3_GIT_URL: "git://github.com/NetCommons3/NetCommons3.git"
- NC3_GIT_BRANCH: "master"
+ NC3_GIT_BRANCH: "availability"
PLUGIN_BUILD_DIR: ${{ github.workspace }}
PHP_VERSION: ${{ matrix.php }}
MYSQL_VERSION: ${{ matrix.mysql }}
diff --git a/Controller/LikesController.php b/Controller/LikesController.php
index 57bfe2d..97622f9 100644
--- a/Controller/LikesController.php
+++ b/Controller/LikesController.php
@@ -4,6 +4,7 @@
*
* @author Noriko Arai
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @link http://www.netcommons.org NetCommons Project
* @license http://www.netcommons.org/license.txt NetCommons License
* @copyright Copyright 2014, NetCommons Project
@@ -15,6 +16,7 @@
* Likes Controller
*
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @package NetCommons\Likes\Controller
*/
class LikesController extends LikesAppController {
@@ -26,6 +28,7 @@ class LikesController extends LikesAppController {
*/
public $uses = array(
'Likes.Like',
+ 'Likes.LikesUser',
);
/**
@@ -35,15 +38,63 @@ class LikesController extends LikesAppController {
*/
public function beforeFilter() {
parent::beforeFilter();
- $this->Auth->allow('like');
+ $this->Auth->allow('load');
+ $this->Auth->allow('save');
}
/**
- * like
+ * load
*
* @return void
*/
- public function like() {
+ public function load() {
+ $likes = [];
+ $condsStrs = explode(',', $this->request->query('like_conds_strs'));
+
+ $likesUserConditions = [];
+ if (Current::read('User.id')) {
+ $likesUserConditions['user_id'] = Current::read('User.id');
+ } else {
+ $likesUserConditions['session_key'] = $this->Session->id();
+ }
+
+ foreach ($condsStrs as $condsStr) {
+ $conds = explode('-', $condsStr);
+ $like = $this->Like->find('first', [
+ 'fields' => [
+ 'id',
+ 'like_count',
+ 'unlike_count',
+ ],
+ 'conditions' => [
+ 'plugin_key' => $conds[0],
+ 'block_key' => $conds[1],
+ 'content_key' => $conds[2],
+ ],
+ 'recursive' => -1,
+ ]);
+ if (! empty($like)) {
+ $like = $like['Like'];
+ $likesUserConditions['like_id'] = $like['id'];
+ $like['disabled'] = $this->LikesUser->find('count', [
+ 'conditions' => $likesUserConditions,
+ 'recursive' => -1,
+ ]);
+ unset($like['id']);
+ $likes[$condsStr] = $like;
+ }
+ }
+
+ $this->set('likes', $likes);
+ $this->set('_serialize', ['likes']);
+ }
+
+/**
+ * save
+ *
+ * @return void
+ */
+ public function save() {
if (! $this->request->is('post')) {
return $this->throwBadRequest();
}
diff --git a/Model/LikesAppModel.php b/Model/LikesAppModel.php
index 1d3dc29..93ab7c8 100644
--- a/Model/LikesAppModel.php
+++ b/Model/LikesAppModel.php
@@ -4,6 +4,7 @@
*
* @author Noriko Arai
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @link http://www.netcommons.org NetCommons Project
* @license http://www.netcommons.org/license.txt NetCommons License
* @copyright Copyright 2014, NetCommons Project
@@ -19,4 +20,10 @@
*/
class LikesAppModel extends AppModel {
+/**
+ * CDNを無効にする
+ *
+ * @var bool
+ */
+ public $invalidateCDN = false;
}
diff --git a/Test/Case/Controller/LikesControllerTest.php b/Test/Case/Controller/LikesControllerTest.php
index f46c1e0..159863c 100644
--- a/Test/Case/Controller/LikesControllerTest.php
+++ b/Test/Case/Controller/LikesControllerTest.php
@@ -4,6 +4,7 @@
*
* @author Noriko Arai
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @link http://www.netcommons.org NetCommons Project
* @license http://www.netcommons.org/license.txt NetCommons License
* @copyright Copyright 2014, NetCommons Project
@@ -15,6 +16,7 @@
* LikesController Test Case
*
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @package NetCommons\Likes\Test\Case\Controller
* @SuppressWarnings(PHPMD.LongVariable)
*/
@@ -109,7 +111,7 @@ public function testLikeGet($urlOptions, $assert, $exception = null, $return = '
$url = Hash::merge(array(
'plugin' => $this->plugin,
'controller' => $this->_controller,
- 'action' => 'like',
+ 'action' => 'save',
), $urlOptions);
$this->_testGetAction($url, $assert, $exception, $return);
@@ -151,7 +153,7 @@ public function dataProviderLikeGet() {
* @return void
*/
public function testLikePost($data, $urlOptions, $exception = null, $return = 'json') {
- $this->_testPostAction('post', $data, Hash::merge(array('action' => 'like'), $urlOptions), $exception, $return);
+ $this->_testPostAction('post', $data, Hash::merge(array('action' => 'save'), $urlOptions), $exception, $return);
}
/**
@@ -193,7 +195,7 @@ public function dataProviderLikePost() {
public function testLikeExists() {
$data = $this->dataProviderLikePost()[2]['data'];
- $this->_testPostAction('post', $data, array('action' => 'like'), null, 'json');
+ $this->_testPostAction('post', $data, array('action' => 'save'), null, 'json');
$this->generateNc(Inflector::camelize($this->_controller));
@@ -201,7 +203,7 @@ public function testLikeExists() {
TestAuthGeneral::login($this);
$this->_mockForReturnTrue('Likes.Like', 'saveLike', 0);
- $this->_testPostAction('post', $data, array('action' => 'like'), null, 'json');
+ $this->_testPostAction('post', $data, array('action' => 'save'), null, 'json');
}
}
diff --git a/Test/Case/Model/Like/ExistsLikeTest.php b/Test/Case/Model/Like/ExistsLikeTest.php
index eb602d0..4dde930 100644
--- a/Test/Case/Model/Like/ExistsLikeTest.php
+++ b/Test/Case/Model/Like/ExistsLikeTest.php
@@ -1,11 +1,12 @@
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @link http://www.netcommons.org NetCommons Project
* @license http://www.netcommons.org/license.txt NetCommons License
* @copyright Copyright 2014, NetCommons Project
@@ -14,9 +15,10 @@
App::uses('NetCommonsModelTestCase', 'NetCommons.TestSuite');
/**
- * Like::ExistLike()のテスト
+ * Like::existsLike()のテスト
*
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @package NetCommons\Likes\Test\Case\Model\Like
*/
class LikeExistsLikeTest extends NetCommonsModelTestCase {
@@ -56,7 +58,7 @@ class LikeExistsLikeTest extends NetCommonsModelTestCase {
* existsLikeのテスト
*
* @param array $contentKey キー情報
- * @param string $expected 期待値
+ * @param bool $expected 期待値
* @param int $userId ユーザーID
* @dataProvider dataProviderExistsLike
* @return void
@@ -85,9 +87,9 @@ public function testExistsLike($contentKey, $expected, $userId = 0) {
*/
public function dataProviderExistsLike() {
return array(
- array('aaa', 0),
- array('testcontent', 0),
- array('testcontent', 1, 1),
+ array('aaa', false),
+ array('testcontent', false),
+ array('testcontent', true, 1),
);
}
diff --git a/Test/Case/View/Helper/ButtonsTest.php b/Test/Case/View/Helper/ButtonsTest.php
index 837c65b..baf1f6e 100644
--- a/Test/Case/View/Helper/ButtonsTest.php
+++ b/Test/Case/View/Helper/ButtonsTest.php
@@ -65,11 +65,11 @@ public function tearDown() {
public function testButtons($model, $setting, $content) {
$result = $this->Like->buttons('Content', $setting, $content);
- if ($content['Content']['status'] === WorkflowComponent::STATUS_PUBLISHED && $setting['use_like'] === 1) {
- $this->assertContains('assertNotContains('assertContains('assertNotContains('assertContains('glyphicon glyphicon-thumbs-up', $result);
} else {
diff --git a/Test/Case/View/Helper/DisplayTest.php b/Test/Case/View/Helper/DisplayTest.php
index 5b67d22..3970143 100644
--- a/Test/Case/View/Helper/DisplayTest.php
+++ b/Test/Case/View/Helper/DisplayTest.php
@@ -4,6 +4,7 @@
*
* @author Noriko Arai
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @link http://www.netcommons.org NetCommons Project
* @license http://www.netcommons.org/license.txt NetCommons License
* @copyright Copyright 2014, NetCommons Project
@@ -17,6 +18,7 @@
* Display for LikeHelper Test Case
*
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @package NetCommons\Likes\Test\Case\View\Helper
*/
class LikeHelperDisplayTest extends NetCommonsCakeTestCase {
@@ -61,7 +63,7 @@ public function tearDown() {
* @return void
*/
public function testDisplay($setting, $content) {
- $result = $this->Like->display($setting, $content);
+ $result = $this->Like->display('Video', $setting, $content);
if ($setting['use_like'] === 1) {
$this->assertContains('glyphicon glyphicon-thumbs-up', $result);
diff --git a/View/Elements/like_button.ctp b/View/Elements/like_button.ctp
index 91171fb..ba3b013 100644
--- a/View/Elements/like_button.ctp
+++ b/View/Elements/like_button.ctp
@@ -3,26 +3,31 @@
* Like button view template
*
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @link http://www.netcommons.org NetCommons Project
* @license http://www.netcommons.org/license.txt NetCommons License
* @copyright Copyright 2014, NetCommons Project
*/
?>
-
-
- {{options.likeCount}}
-
- {{options.unlikeCount}}
-
-
-
-
-
- {{options.likeCount}}
-
- {{options.unlikeCount}}
-
+
+
+ ng-click="save()">
+
+
+
+
+
+
+
+
+ >
+
+
+
+
+
+
+
+
diff --git a/View/Helper/LikeHelper.php b/View/Helper/LikeHelper.php
index 58af0d9..e27f8af 100644
--- a/View/Helper/LikeHelper.php
+++ b/View/Helper/LikeHelper.php
@@ -4,6 +4,7 @@
*
* @author Noriko Arai
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @link http://www.netcommons.org NetCommons Project
* @license http://www.netcommons.org/license.txt NetCommons License
* @copyright Copyright 2014, NetCommons Project
@@ -22,6 +23,7 @@ class_exists('Like');
* * イイネ!、ヤダネ!ボタン表示:[buttonsメソッド](#buttons)
*
* @author Shohei Nakajima
+ * @author Kazunori Sakamoto
* @package NetCommons\Likes\View\Helper
*/
class LikeHelper extends AppHelper {
@@ -31,13 +33,14 @@ class LikeHelper extends AppHelper {
*
* @var array
*/
- public $helpers = array(
+ public $helpers = [
'Html',
'Form',
+ 'NetCommons.CDNCache',
'NetCommons.NetCommonsForm',
'NetCommons.NetCommonsHtml',
'NetCommons.Token',
- );
+ ];
/**
* Before render callback. beforeRender is called before the view file is rendered.
@@ -138,33 +141,43 @@ public function setting($likeFieldName, $unlikeFieldName, $attributes = array())
* #### Sample code
* ##### template file(ctp file)
* ```
- * Like->display($bbsSetting, $bbsArticle); ?>
+ * Like->display('BbsArticle', $bbsSetting, $bbsArticle); ?>
* ```
*
+ * @param array $model String of model name
* @param array $setting Array of use like setting data.
* @param array $content Array of content data with like count.
* @param array $attributes Array of attributes and HTML arguments.
* @return string HTML tags
*/
- public function display($setting, $content, $attributes = array()) {
+ public function display($model, $setting, $content, $attributes = array()) {
$output = '';
+ $condsStr = $this->_View->request->params['plugin'] . '-' .
+ Current::read('Block.key') . '-' . ($content[$model]['key'] ?? '');
+
+ $like = $this->__getInitialLike($content);
+
//いいね
if (isset($setting['use_like']) && $setting['use_like']) {
- $element = ' ';
- $element .= (int)Hash::get($content, 'Like.like_count');
+ $element = '';
+ $element .= ' ';
+ $element .= '' . $like['like_count'] . '';
+ $element .= '';
$output .= $this->Html->div(
- array('like-icon', 'text-muted'), $element, $attributes
- );
+ array('like-icon', 'text-muted'), $element, $attributes
+ );
}
//わるいね
if (isset($setting['use_unlike']) && $setting['use_unlike']) {
- $element = ' ';
- $element .= (int)Hash::get($content, 'Like.unlike_count');
+ $element = '';
+ $element .= ' ';
+ $element .= '' . $like['unlike_count'] . '';
+ $element .= '';
$output .= $this->Html->div(
- array('like-icon', 'text-muted'), $element, $attributes
- );
+ array('like-icon', 'text-muted'), $element, $attributes
+ );
}
return $output;
@@ -193,13 +206,12 @@ public function display($setting, $content, $attributes = array()) {
public function buttons($model, $setting, $content, $attributes = array()) {
$output = '';
- if (! Hash::get($setting, 'use_like') && ! Hash::get($setting, 'use_like')) {
+ if (! Hash::get($setting, 'use_like') && ! Hash::get($setting, 'use_unlike')) {
return $output;
}
- if (isset($content['LikesUser']['id']) ||
- $content[$model]['status'] !== WorkflowComponent::STATUS_PUBLISHED) {
- return $this->display($setting, $content, $attributes);
+ if ($content[$model]['status'] !== WorkflowComponent::STATUS_PUBLISHED) {
+ return $this->display($model, $setting, $content, $attributes);
}
if (! isset($content['Like']['id'])) {
@@ -217,51 +229,53 @@ public function buttons($model, $setting, $content, $attributes = array()) {
);
}
- $data = array(
- 'Frame' => array('id' => Current::read('Frame.id')),
- 'Like' => array(
+ $data = [
+ 'Frame' => ['id' => Current::read('Frame.id')],
+ 'Like' => [
'plugin_key' => Hash::get($content, 'Like.plugin_key'),
'block_key' => Hash::get($content, 'Like.block_key'),
'content_key' => Hash::get($content, 'Like.content_key'),
- ),
- 'LikesUser' => array(
+ ],
+ 'LikesUser' => [
'like_id' => Hash::get($content, 'LikesUser.like_id'),
'user_id' => Hash::get($content, 'LikesUser.user_id'),
'is_liked' => Hash::get($content, 'LikesUser.is_liked'),
- ),
- );
- $options = array(
- 'likeCount' => (int)Hash::get($content, 'Like.like_count'),
- 'unlikeCount' => (int)Hash::get($content, 'Like.unlike_count'),
- 'disabled' => false
- );
+ ],
+ ];
$tokenFields = Hash::flatten($data);
$hiddenFields = $tokenFields;
unset($hiddenFields['LikesUser.is_liked']);
$hiddenFields = array_keys($hiddenFields);
- $cunnentData = $this->_View->request->data;
+ $currentData = $this->_View->request->data;
$this->_View->request->data = $data;
- $tokens = $this->Token->getToken('Like', '/likes/likes/like.json', $tokenFields, $hiddenFields);
- $data += $tokens;
+ $token = $this->Token->getToken(
+ 'LikeSave', '/likes/likes/save.json', $tokenFields, $hiddenFields
+ );
+ $data += $token;
+
+ $this->_View->request->data = $currentData;
+
+ $like = $content['Like'];
+ $condsStr = $like['plugin_key'] . '-' . $like['block_key'] . '-' . $like['content_key'];
- $this->_View->request->data = $cunnentData;
+ $like = $this->__getInitialLike($content);
$output .= '';
+ 'ng-init="initialize(' . h(json_encode($data)) . ')">';
//いいね
if (Hash::get($setting, 'use_like')) {
- $output .= $this->Html->div(array('like-icon'),
- $this->_View->element('Likes.like_button', ['isLiked' => Like::IS_LIKE]), $attributes);
+ $output .= $this->Html->div(array('like-icon'), $this->_View->element('Likes.like_button',
+ ['condsStr' => $condsStr, 'like' => $like, 'isLiked' => Like::IS_LIKE]), $attributes);
}
//わるいね
if (Hash::get($setting, 'use_unlike')) {
- $output .= $this->Html->div(array('like-icon'),
- $this->_View->element('Likes.like_button', ['isLiked' => Like::IS_UNLIKE]), $attributes);
+ $output .= $this->Html->div(array('like-icon'), $this->_View->element('Likes.like_button',
+ ['condsStr' => $condsStr, 'like' => $like, 'isLiked' => Like::IS_UNLIKE]), $attributes);
}
$output .= '
';
@@ -269,4 +283,25 @@ public function buttons($model, $setting, $content, $attributes = array()) {
return $output;
}
+/**
+ * Ajaxの実行前に表示すべきいいね情報を返します。
+ *
+ * @param array $content Array of content data with like count.
+ * @return array
+ */
+ private function __getInitialLike($content) {
+ if ($this->CDNCache->isCacheable()) {
+ return [
+ 'like_count' => '-',
+ 'unlike_count' => '-',
+ 'disabled' => true,
+ ];
+ }
+ $like = $content['Like'];
+ return [
+ 'like_count' => Hash::get($like, 'like_count', 0),
+ 'unlike_count' => Hash::get($like, 'unlike_count', 0),
+ 'disabled' => $content['LikesUser']['is_liked'],
+ ];
+ }
}
diff --git a/webroot/js/likes.js b/webroot/js/likes.js
index bd2708c..f896df6 100644
--- a/webroot/js/likes.js
+++ b/webroot/js/likes.js
@@ -1,6 +1,7 @@
/**
* @fileoverview Likes Javascript
* @author nakajimashouhei@gmail.com (Shohei Nakajima)
+ * @author exkazuu@willbooster.com (Kazunori Sakamoto)
*/
@@ -11,39 +12,38 @@
* @param {function('$http', '$q')} Controller
*/
NetCommonsApp.factory('LikesSave', ['$http', '$q', 'NC3_URL', function($http, $q, NC3_URL) {
- return function(post) {
-
+ return function(data) {
var deferred = $q.defer();
var promise = deferred.promise;
$http.get(NC3_URL + '/net_commons/net_commons/csrfToken.json')
.then(function(response) {
var token = response.data;
- post._Token.key = token.data._Token.key;
+ data._Token.key = token.data._Token.key;
- //POSTリクエスト
+ // POSTリクエスト
$http.post(
- NC3_URL + '/likes/likes/like.json',
- $.param({_method: 'POST', data: post}),
- {cache: false,
- headers:
- {'Content-Type': 'application/x-www-form-urlencoded'}
+ NC3_URL + '/likes/likes/save.json',
+ $.param({_method: 'POST', data: data}),
+ {
+ cache: false,
+ headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}
).then(
- function(response) {
- //success condition
+ function(response) {
+ // success condition
var data = response.data;
deferred.resolve(data);
},
- function(response) {
- //error condition
+ function(response) {
+ // error condition
var data = response.data;
var status = response.status;
deferred.reject(data, status);
});
},
function(response) {
- //Token error condition
+ // Token error condition
var data = response.data;
var status = response.status;
deferred.reject(data, status);
@@ -79,16 +79,6 @@ NetCommonsApp.controller('Likes', ['$scope', 'LikesSave', function($scope, Likes
*/
$scope.data = null;
- /**
- * Options parameters
- * - disabled
- * - likeCounts
- * - unlikeCounts
- *
- * @type {object}
- */
- $scope.options = null;
-
/**
* initialize
* - disabled
@@ -97,10 +87,8 @@ NetCommonsApp.controller('Likes', ['$scope', 'LikesSave', function($scope, Likes
*
* @return {void}
*/
- $scope.initialize = function(data, options) {
+ $scope.initialize = function(data) {
$scope.data = data;
- $scope.options = options;
- $scope.options.disabled = false;
};
/**
@@ -108,27 +96,28 @@ NetCommonsApp.controller('Likes', ['$scope', 'LikesSave', function($scope, Likes
*
* @return {void}
*/
- $scope.save = function(isLiked) {
- $scope.data['LikesUser']['is_liked'] = isLiked;
- if ($scope.options.disabled) {
- return;
- }
- $scope.options.disabled = true;
- $scope.sending = true;
+ $scope.save = function(isLiked, condsStr) {
+ var queryPrefix = '.' + condsStr;
+ var aDisplay = $(queryPrefix + ' > a').css('display');
+ var spanDisplay = $(queryPrefix + ' > span').css('display');
+
+ $(queryPrefix + ' > a').css('display', 'none');
+ $(queryPrefix + ' > span').css('display', '');
+ $scope.data.LikesUser.is_liked = isLiked;
LikesSave($scope.data)
- .success(function(data) {
- $scope.sending = false;
- //success condition
+ .success(function() {
+ var $counts;
if (isLiked) {
- $scope.options['likeCount'] = $scope.options['likeCount'] + 1;
+ $counts = $(queryPrefix + ' .like-count');
} else {
- $scope.options['unlikeCount'] = $scope.options['unlikeCount'] + 1;
+ $counts = $(queryPrefix + ' .unlike-count');
}
+ $counts.each(function() { $(this).text(Number($(this).text()) + 1); });
})
- .error(function(data, status) {
- //error condition
- $scope.sending = false;
+ .error(function() {
+ $(queryPrefix + ' > a').css('display', aDisplay);
+ $(queryPrefix + ' > span').css('display', spanDisplay);
});
};
}]);