mirror of
https://github.com/rr-/szurubooru.git
synced 2025-07-17 08:26:24 +00:00
Compare commits
77 Commits
Author | SHA1 | Date | |
---|---|---|---|
43334b33e1 | |||
839e97b1e2 | |||
8a33b9581d | |||
7067d8e13d | |||
5769034223 | |||
c0a5c800e0 | |||
b70231bd7e | |||
bc757dd883 | |||
924592675c | |||
a3aea27a13 | |||
3c54671aeb | |||
d8df51f0c0 | |||
b693a5f4b3 | |||
303f91e15c | |||
c350c47195 | |||
24ce67b4ff | |||
06d7c19556 | |||
728d1d65de | |||
4b27b8a85d | |||
bfe31d87a1 | |||
2fd371b10a | |||
f1647a5f7b | |||
cd688b25a3 | |||
a7c6e9f043 | |||
997c2a10ec | |||
95cf0ca37b | |||
116522498d | |||
01a84ee4e2 | |||
2458935fdf | |||
f2b1e3bedb | |||
77c51d9a8a | |||
d8d65ed24c | |||
58d3129548 | |||
0b032e7f94 | |||
4e6fe634e1 | |||
b14f02810e | |||
796c2d1b1f | |||
40197d6c39 | |||
736c0a66ff | |||
48230a64ad | |||
da6b37b14c | |||
4b4ccf365a | |||
2b0a4d1f76 | |||
2d1b5308f3 | |||
8fb1b87ae5 | |||
9621810332 | |||
bd33b09f7b | |||
3245c75187 | |||
e38152b921 | |||
2195b2c9a1 | |||
969f70318b | |||
06cc776438 | |||
76edbfeddb | |||
9de6e7e739 | |||
d8a4e1ec4e | |||
193d1c5f7a | |||
7ff961fc21 | |||
a11436aa8c | |||
a3b02adb7f | |||
40b16f586b | |||
602d7a1f45 | |||
333c538f1e | |||
7c182f57a0 | |||
2a7ca79b2d | |||
9e894bc41c | |||
cdd2726f30 | |||
029f0f00a4 | |||
c6fe7a4320 | |||
8bd4ae27c2 | |||
2a215ef51b | |||
6473ed74d3 | |||
44a4184eb8 | |||
847f248829 | |||
a0133ea632 | |||
0b15ca1b05 | |||
2996f27671 | |||
6a751ed0b2 |
@ -24,6 +24,10 @@ h3 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
#middle {
|
||||
padding: 0 2em;
|
||||
position: relative;
|
||||
|
@ -18,10 +18,12 @@
|
||||
#home .post .left {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
#home .post .right {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
#home .post-footer,
|
||||
@ -35,5 +37,7 @@
|
||||
|
||||
#home .version {
|
||||
opacity: .4;
|
||||
font-size: 12px;
|
||||
}
|
||||
#home .subheader, #home .post-footer {
|
||||
font-size: 85%;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@
|
||||
.post-small {
|
||||
position: relative;
|
||||
}
|
||||
.post-small a {
|
||||
.post-small .link {
|
||||
display: inline-block;
|
||||
margin: 0.2em;
|
||||
border: 1px solid #999;
|
||||
@ -82,20 +82,20 @@
|
||||
}
|
||||
|
||||
|
||||
.post-small a:focus,
|
||||
.post-small a:hover {
|
||||
.post-small .link:focus,
|
||||
.post-small .link:hover {
|
||||
background: #64C2ED;
|
||||
border-color: #64C2ED;
|
||||
box-shadow: 0 0 0 2px #64C2ED;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.post-small a:focus img:not(.loading),
|
||||
.post-small a:hover img:not(.loading) {
|
||||
.post-small .link:focus img:not(.loading),
|
||||
.post-small .link:hover img:not(.loading) {
|
||||
opacity: .8 !important;
|
||||
}
|
||||
|
||||
.post-small a .info {
|
||||
.post-small .link .info {
|
||||
display: none;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
@ -105,22 +105,22 @@
|
||||
background: #64C2ED;
|
||||
color: black;
|
||||
}
|
||||
.post-small a .info ul {
|
||||
.post-small .link .info ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.post-small a .info li {
|
||||
.post-small .link .info li {
|
||||
display: inline-block;
|
||||
margin: 0.1em 0.5em;
|
||||
padding: 0;
|
||||
}
|
||||
.post-small a:focus .info,
|
||||
.post-small a:hover .info {
|
||||
.post-small .link:focus .info,
|
||||
.post-small .link:hover .info {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.post-small:not(.post-type-image) a::before {
|
||||
.post-small:not(.post-type-image) .link::before {
|
||||
display: block;
|
||||
content: '';
|
||||
z-index: 2;
|
||||
@ -133,7 +133,7 @@
|
||||
border-left: 50px solid transparent;
|
||||
}
|
||||
|
||||
.post-small:not(.post-type-image) a::after {
|
||||
.post-small:not(.post-type-image) .link::after {
|
||||
display: block;
|
||||
content: '...';
|
||||
z-index: 3;
|
||||
@ -148,14 +148,14 @@
|
||||
color: white;
|
||||
font-size: 15px;
|
||||
}
|
||||
.post-small.post-type-youtube a::after {
|
||||
.post-small.post-type-youtube .link::after {
|
||||
font-size: 13px;
|
||||
content: 'youtube';
|
||||
}
|
||||
.post-small.post-type-video a::after {
|
||||
.post-small.post-type-video .link::after {
|
||||
content: 'video';
|
||||
}
|
||||
.post-small.post-type-flash a::after {
|
||||
.post-small.post-type-flash .link::after {
|
||||
content: 'flash';
|
||||
}
|
||||
|
||||
|
@ -157,12 +157,17 @@
|
||||
|
||||
#post-view #post-edit-target {
|
||||
padding: 1em;
|
||||
width: 50%;
|
||||
min-width: 30em;
|
||||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
box-shadow: 0 0 1em 0.5em rgba(255, 255, 255, 0.8);
|
||||
z-index: 2;
|
||||
display: none;
|
||||
}
|
||||
#post-edit-target .form-wrapper {
|
||||
min-width: 100%;
|
||||
}
|
||||
#post-view>* {
|
||||
z-index: -1;
|
||||
}
|
||||
@ -224,6 +229,7 @@
|
||||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||
font-size: 12pt;
|
||||
}
|
||||
.post-note .text-wrapper {
|
||||
position: absolute;
|
||||
|
@ -39,12 +39,14 @@
|
||||
|
||||
#user-list .user img {
|
||||
vertical-align: top;
|
||||
margin-right: 1em;
|
||||
display: block;
|
||||
}
|
||||
#user-list .user>a {
|
||||
display: block;
|
||||
#user-list .user .avatar {
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
#user-list .user .avatar a {
|
||||
display: block;
|
||||
}
|
||||
#user-list .user .details {
|
||||
float: left;
|
||||
|
@ -138,7 +138,7 @@
|
||||
<script type="text/javascript" src="/js/Presenters/PostPresenter.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/js/Presenters/GlobalCommentListPresenter.js"></script>
|
||||
<script type="text/javascript" src="/js/Presenters/PostCommentListPresenter.js"></script>
|
||||
<script type="text/javascript" src="/js/Presenters/CommentListPresenter.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/js/Presenters/TagListPresenter.js"></script>
|
||||
<script type="text/javascript" src="/js/Presenters/TagPresenter.js"></script>
|
||||
|
@ -73,7 +73,7 @@ App.API = function(_, jQuery, promise, appState) {
|
||||
|
||||
var xhr = null;
|
||||
var apiPromise = promise.make(function(resolve, reject) {
|
||||
xhr = jQuery.ajax({
|
||||
var options = {
|
||||
headers: {
|
||||
'X-Authorization-Token': appState.get('loginToken') || '',
|
||||
},
|
||||
@ -92,7 +92,13 @@ App.API = function(_, jQuery, promise, appState) {
|
||||
type: method,
|
||||
url: fullUrl,
|
||||
data: data,
|
||||
});
|
||||
cache: false,
|
||||
};
|
||||
if (data instanceof FormData) {
|
||||
options.processData = false;
|
||||
options.contentType = false;
|
||||
}
|
||||
xhr = jQuery.ajax(options);
|
||||
});
|
||||
apiPromise.xhr = xhr;
|
||||
return apiPromise;
|
||||
|
@ -70,7 +70,7 @@ App.BrowsingSettings = function(
|
||||
var formData = {
|
||||
browsingSettings: JSON.stringify(settings),
|
||||
};
|
||||
return api.put('/users/' + user.name, formData);
|
||||
return api.post('/users/' + user.name, formData);
|
||||
}
|
||||
|
||||
function save() {
|
||||
|
@ -17,12 +17,14 @@ App.Controls.AutoCompleteInput = function($input) {
|
||||
maxResults: 15,
|
||||
minLengthToArbitrarySearch: 3,
|
||||
onApply: null,
|
||||
onRender: null,
|
||||
additionalFilter: null,
|
||||
};
|
||||
var showTimeout = null;
|
||||
var cachedSource = null;
|
||||
var results = [];
|
||||
var activeResult = -1;
|
||||
var monitorInputHidingInterval = null;
|
||||
|
||||
if ($input.length === 0) {
|
||||
throw new Error('Input element was not found');
|
||||
@ -133,6 +135,7 @@ App.Controls.AutoCompleteInput = function($input) {
|
||||
|
||||
function hide() {
|
||||
$div.hide();
|
||||
window.clearInterval(monitorInputHidingInterval);
|
||||
}
|
||||
|
||||
function selectPrevious() {
|
||||
@ -222,12 +225,16 @@ App.Controls.AutoCompleteInput = function($input) {
|
||||
});
|
||||
$list.append($listItem);
|
||||
});
|
||||
if (options.onRender) {
|
||||
options.onRender($list);
|
||||
}
|
||||
refreshActiveResult();
|
||||
$div.css({
|
||||
left: ($input.offset().left) + 'px',
|
||||
top: ($input.offset().top + $input.outerHeight() - 2) + 'px',
|
||||
});
|
||||
$div.show();
|
||||
monitorInputHiding();
|
||||
}
|
||||
|
||||
function refreshActiveResult() {
|
||||
@ -237,5 +244,13 @@ App.Controls.AutoCompleteInput = function($input) {
|
||||
}
|
||||
}
|
||||
|
||||
function monitorInputHiding() {
|
||||
monitorInputHidingInterval = window.setInterval(function() {
|
||||
if (!$input.is(':visible')) {
|
||||
hide();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
return options;
|
||||
};
|
||||
|
@ -14,6 +14,14 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
var tagConfirmKeys = [KEY_RETURN, KEY_SPACE];
|
||||
var inputConfirmKeys = [KEY_RETURN];
|
||||
|
||||
var SOURCE_INITIAL_TEXT = 1;
|
||||
var SOURCE_AUTOCOMPLETION = 2;
|
||||
var SOURCE_PASTE = 3;
|
||||
var SOURCE_IMPLICATIONS = 4;
|
||||
var SOURCE_INPUT_BLUR = 5;
|
||||
var SOURCE_INPUT_ENTER = 6;
|
||||
var SOURCE_SUGGESTIONS = 7;
|
||||
|
||||
var tags = [];
|
||||
var options = {
|
||||
beforeTagAdded: null,
|
||||
@ -56,10 +64,10 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
$input.focus();
|
||||
});
|
||||
$input.attr('placeholder', $underlyingInput.attr('placeholder'));
|
||||
$suggestions.insertAfter($wrapper);
|
||||
$siblings.insertAfter($wrapper);
|
||||
$suggestions.insertAfter($wrapper);
|
||||
|
||||
processText($underlyingInput.val(), addTagDirectly);
|
||||
processText($underlyingInput.val(), SOURCE_INITIAL_TEXT);
|
||||
|
||||
$underlyingInput.val('');
|
||||
}
|
||||
@ -67,7 +75,7 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
function initAutoComplete() {
|
||||
var autoComplete = new App.Controls.AutoCompleteInput($input);
|
||||
autoComplete.onApply = function(text) {
|
||||
processText(text, addTag);
|
||||
processText(text, SOURCE_AUTOCOMPLETION);
|
||||
$input.val('');
|
||||
};
|
||||
autoComplete.additionalFilter = function(results) {
|
||||
@ -75,6 +83,14 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
return !_.contains(getTags(), resultItem[0]);
|
||||
});
|
||||
};
|
||||
autoComplete.onRender = function($list) {
|
||||
$list.find('li').each(function() {
|
||||
var $li = jQuery(this);
|
||||
if (isTaggedWith($li.attr('data-key'))) {
|
||||
$li.css('opacity', '0.5');
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
$input.bind('focus', function(e) {
|
||||
@ -83,7 +99,7 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
$input.bind('blur', function(e) {
|
||||
$wrapper.removeClass('focused');
|
||||
var tagName = $input.val();
|
||||
addTag(tagName);
|
||||
addTag(tagName, SOURCE_INPUT_BLUR);
|
||||
$input.val('');
|
||||
});
|
||||
|
||||
@ -101,7 +117,7 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
processTextWithoutLast(pastedText, addTag);
|
||||
processTextWithoutLast(pastedText, SOURCE_PASTE);
|
||||
});
|
||||
|
||||
$input.bind('keydown', function(e) {
|
||||
@ -114,7 +130,7 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
var tagName = $input.val();
|
||||
e.preventDefault();
|
||||
$input.val('');
|
||||
addTag(tagName);
|
||||
addTag(tagName, SOURCE_INPUT_ENTER);
|
||||
} else if (e.which === KEY_BACKSPACE && jQuery(this).val().length === 0) {
|
||||
e.preventDefault();
|
||||
removeLastTag();
|
||||
@ -127,19 +143,19 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
});
|
||||
}
|
||||
|
||||
function processText(text, callback) {
|
||||
function processText(text, source) {
|
||||
var tagNamesToAdd = explodeText(text);
|
||||
_.map(tagNamesToAdd, function(tagName) { callback(tagName); });
|
||||
_.map(tagNamesToAdd, function(tagName) { addTag(tagName, source); });
|
||||
}
|
||||
|
||||
function processTextWithoutLast(text, callback) {
|
||||
function processTextWithoutLast(text, source) {
|
||||
var tagNamesToAdd = explodeText(text);
|
||||
var lastTagName = tagNamesToAdd.pop();
|
||||
_.map(tagNamesToAdd, function(tagName) { callback(tagName); });
|
||||
_.map(tagNamesToAdd, function(tagName) { addTag(tagName, source); });
|
||||
$input.val(lastTagName);
|
||||
}
|
||||
|
||||
function addTag(tagName) {
|
||||
function addTag(tagName, source) {
|
||||
tagName = tagName.trim();
|
||||
if (tagName.length === 0) {
|
||||
return;
|
||||
@ -157,39 +173,53 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
if (isTaggedWith(tagName)) {
|
||||
flashTagRed(tagName);
|
||||
} else {
|
||||
beforeTagAdded(tagName);
|
||||
beforeTagAdded(tagName, source);
|
||||
|
||||
var exportedTag = getExportedTag(tagName);
|
||||
if (!exportedTag || !exportedTag.banned) {
|
||||
addTagDirectly(tagName);
|
||||
tags.push(tagName);
|
||||
var $elem = createListElement(tagName);
|
||||
$tagList.append($elem);
|
||||
}
|
||||
|
||||
afterTagAdded(tagName);
|
||||
afterTagAdded(tagName, source);
|
||||
}
|
||||
}
|
||||
|
||||
function addTagDirectly(tagName) {
|
||||
tags.push(tagName);
|
||||
var $elem = createListElement(tagName);
|
||||
$tagList.append($elem);
|
||||
function beforeTagRemoved(tagName) {
|
||||
if (typeof(options.beforeTagRemoved) === 'function') {
|
||||
options.beforeTagRemoved(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
function beforeTagAdded(tagName) {
|
||||
function afterTagRemoved(tagName) {
|
||||
refreshShownSiblings();
|
||||
}
|
||||
|
||||
function beforeTagAdded(tagName, source) {
|
||||
if (typeof(options.beforeTagAdded) === 'function') {
|
||||
options.beforeTagAdded(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
function afterTagAdded(tagName) {
|
||||
var tag = getExportedTag(tagName);
|
||||
if (tag) {
|
||||
_.each(tag.implications, function(impliedTagName) {
|
||||
addTag(impliedTagName);
|
||||
flashTagYellow(impliedTagName);
|
||||
});
|
||||
showOrHideSuggestions(tag.suggestions);
|
||||
} else {
|
||||
flashTagGreen(tagName);
|
||||
function afterTagAdded(tagName, source) {
|
||||
if (source === SOURCE_IMPLICATIONS) {
|
||||
flashTagYellow(tagName);
|
||||
} else if (source !== SOURCE_INITIAL_TEXT) {
|
||||
var tag = getExportedTag(tagName);
|
||||
if (tag) {
|
||||
_.each(tag.implications, function(impliedTagName) {
|
||||
if (!isTaggedWith(impliedTagName)) {
|
||||
addTag(impliedTagName, SOURCE_IMPLICATIONS);
|
||||
}
|
||||
});
|
||||
if (source !== SOURCE_IMPLICATIONS && source !== SOURCE_SUGGESTIONS) {
|
||||
showOrHideSuggestions(tagName);
|
||||
refreshShownSiblings();
|
||||
}
|
||||
} else {
|
||||
flashTagGreen(tagName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,10 +235,9 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
var oldTagNames = getTags();
|
||||
var newTagNames = _.without(oldTagNames, tagName);
|
||||
if (newTagNames.length !== oldTagNames.length) {
|
||||
if (typeof(options.beforeTagRemoved) === 'function') {
|
||||
options.beforeTagRemoved(tagName);
|
||||
}
|
||||
beforeTagRemoved(tagName);
|
||||
setTags(newTagNames);
|
||||
afterTagRemoved(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,7 +291,8 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
$tagLink.text(tagName);
|
||||
$tagLink.click(function(e) {
|
||||
e.preventDefault();
|
||||
showOrHideTagSiblings(tagName);
|
||||
showOrHideSiblings(tagName);
|
||||
showOrHideSuggestions(tagName);
|
||||
});
|
||||
$elem.append($tagLink);
|
||||
|
||||
@ -276,19 +306,13 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
return $elem;
|
||||
}
|
||||
|
||||
function showOrHideSuggestions(suggestedTagNames) {
|
||||
if (_.size(suggestedTagNames) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var suggestions = filterSuggestions(suggestedTagNames);
|
||||
if (suggestions.length > 0) {
|
||||
attachTagsToSuggestionList($suggestions.find('ul'), suggestions);
|
||||
$suggestions.slideDown('fast');
|
||||
}
|
||||
function showOrHideSuggestions(tagName) {
|
||||
var tag = getExportedTag(tagName);
|
||||
var suggestions = tag ? tag.suggestions : [];
|
||||
updateSuggestions($suggestions, suggestions);
|
||||
}
|
||||
|
||||
function showOrHideTagSiblings(tagName) {
|
||||
function showOrHideSiblings(tagName) {
|
||||
if ($siblings.data('lastTag') === tagName && $siblings.is(':visible')) {
|
||||
$siblings.slideUp('fast');
|
||||
$siblings.data('lastTag', null);
|
||||
@ -298,48 +322,58 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
promise.wait(getSiblings(tagName), promise.make(function(resolve, reject) {
|
||||
$siblings.slideUp('fast', resolve);
|
||||
})).then(function(siblings) {
|
||||
siblings = _.pluck(siblings, 'name');
|
||||
$siblings.data('lastTag', tagName);
|
||||
|
||||
if (!_.size(siblings)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var suggestions = filterSuggestions(_.pluck(siblings, 'name'));
|
||||
if (suggestions.length > 0) {
|
||||
attachTagsToSuggestionList($siblings.find('ul'), suggestions);
|
||||
$siblings.slideDown('fast');
|
||||
}
|
||||
$siblings.data('siblings', siblings);
|
||||
updateSuggestions($siblings, siblings);
|
||||
}).fail(function() {
|
||||
});
|
||||
}
|
||||
|
||||
function filterSuggestions(sourceTagNames) {
|
||||
var tagNames = _.filter(sourceTagNames.slice(), function(tagName) {
|
||||
return !isTaggedWith(tagName);
|
||||
});
|
||||
tagNames = tagNames.slice(0, 20);
|
||||
return tagNames;
|
||||
function refreshShownSiblings() {
|
||||
updateSuggestions($siblings, $siblings.data('siblings'));
|
||||
}
|
||||
|
||||
function attachTagsToSuggestionList($list, tagNames) {
|
||||
$list.empty();
|
||||
_.each(tagNames, function(tagName) {
|
||||
var $li = jQuery('<li>');
|
||||
var $a = jQuery('<a href="#/posts/query=' + tagName + '">');
|
||||
$a.text(tagName);
|
||||
$a.click(function(e) {
|
||||
e.preventDefault();
|
||||
addTag(tagName);
|
||||
$li.fadeOut('fast', function() {
|
||||
$li.remove();
|
||||
if ($list.children().length === 0) {
|
||||
$list.parent('div').slideUp('fast');
|
||||
}
|
||||
});
|
||||
function updateSuggestions($target, suggestedTagNames) {
|
||||
function filterSuggestions(sourceTagNames) {
|
||||
if (!sourceTagNames) {
|
||||
return [];
|
||||
}
|
||||
var tagNames = _.filter(sourceTagNames.slice(), function(tagName) {
|
||||
return !isTaggedWith(tagName);
|
||||
});
|
||||
$li.append($a);
|
||||
$list.append($li);
|
||||
});
|
||||
tagNames = tagNames.slice(0, 20);
|
||||
return tagNames;
|
||||
}
|
||||
|
||||
function attachTagsToSuggestionList($list, tagNames) {
|
||||
$list.empty();
|
||||
_.each(tagNames, function(tagName) {
|
||||
var $li = jQuery('<li>');
|
||||
var $a = jQuery('<a href="#/posts/query=' + tagName + '">');
|
||||
$a.text(tagName);
|
||||
$a.click(function(e) {
|
||||
e.preventDefault();
|
||||
addTag(tagName, SOURCE_SUGGESTIONS);
|
||||
$li.fadeOut('fast', function() {
|
||||
$li.remove();
|
||||
if ($list.children().length === 0) {
|
||||
$list.parent('div').slideUp('fast');
|
||||
}
|
||||
});
|
||||
});
|
||||
$li.append($a);
|
||||
$list.append($li);
|
||||
});
|
||||
}
|
||||
|
||||
var suggestions = filterSuggestions(suggestedTagNames);
|
||||
if (suggestions.length > 0) {
|
||||
attachTagsToSuggestionList($target.find('ul'), suggestions);
|
||||
$target.slideDown('fast');
|
||||
} else {
|
||||
$target.slideUp('fast');
|
||||
}
|
||||
}
|
||||
|
||||
function getSiblings(tagName) {
|
||||
@ -364,6 +398,7 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
function hideSuggestions() {
|
||||
$siblings.hide();
|
||||
$suggestions.hide();
|
||||
$siblings.data('siblings', []);
|
||||
}
|
||||
|
||||
_.extend(options, {
|
||||
|
@ -1,7 +1,7 @@
|
||||
var App = App || {};
|
||||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.PostCommentListPresenter = function(
|
||||
App.Presenters.CommentListPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
@ -26,14 +26,16 @@ App.Presenters.PostCommentListPresenter = function(
|
||||
privileges = {
|
||||
canListComments: auth.hasPrivilege(auth.privileges.listComments),
|
||||
canAddComments: auth.hasPrivilege(auth.privileges.addComments),
|
||||
editOwnComments: auth.hasPrivilege(auth.privileges.editOwnComments),
|
||||
editAllComments: auth.hasPrivilege(auth.privileges.editAllComments),
|
||||
deleteOwnComments: auth.hasPrivilege(auth.privileges.deleteOwnComments),
|
||||
deleteAllComments: auth.hasPrivilege(auth.privileges.deleteAllComments),
|
||||
canEditOwnComments: auth.hasPrivilege(auth.privileges.editOwnComments),
|
||||
canEditAllComments: auth.hasPrivilege(auth.privileges.editAllComments),
|
||||
canDeleteOwnComments: auth.hasPrivilege(auth.privileges.deleteOwnComments),
|
||||
canDeleteAllComments: auth.hasPrivilege(auth.privileges.deleteAllComments),
|
||||
canViewUsers: auth.hasPrivilege(auth.privileges.viewUsers),
|
||||
canViewPosts: auth.hasPrivilege(auth.privileges.viewPosts),
|
||||
};
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('post-comment-list'),
|
||||
util.promiseTemplate('comment-list'),
|
||||
util.promiseTemplate('comment-list-item'),
|
||||
util.promiseTemplate('comment-form'))
|
||||
.then(function(
|
||||
@ -101,10 +103,13 @@ App.Presenters.PostCommentListPresenter = function(
|
||||
var $item = jQuery('<li>' + templates.commentListItem({
|
||||
comment: comment,
|
||||
formatRelativeTime: util.formatRelativeTime,
|
||||
formatAbsoluteTime: util.formatAbsoluteTime,
|
||||
formatMarkdown: util.formatMarkdown,
|
||||
canVote: auth.isLoggedIn(),
|
||||
canEditComment: auth.isLoggedIn(comment.user.name) ? privileges.editOwnComments : privileges.editAllComments,
|
||||
canDeleteComment: auth.isLoggedIn(comment.user.name) ? privileges.deleteOwnComments : privileges.deleteAllComments,
|
||||
canEditComment: auth.isLoggedIn(comment.user.name) ? privileges.canEditOwnComments : privileges.canEditAllComments,
|
||||
canDeleteComment: auth.isLoggedIn(comment.user.name) ? privileges.canDeleteOwnComments : privileges.canDeleteAllComments,
|
||||
canViewUsers: privileges.canViewUsers,
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
util.loadImagesNicely($item.find('img'));
|
||||
$targetList.append($item);
|
||||
@ -227,4 +232,4 @@ App.Presenters.PostCommentListPresenter = function(
|
||||
|
||||
};
|
||||
|
||||
App.DI.register('postCommentListPresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'auth', 'topNavigationPresenter', 'messagePresenter'], App.Presenters.PostCommentListPresenter);
|
||||
App.DI.register('commentListPresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'auth', 'topNavigationPresenter', 'messagePresenter'], App.Presenters.CommentListPresenter);
|
@ -5,17 +5,23 @@ App.Presenters.GlobalCommentListPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
auth,
|
||||
promise,
|
||||
pagerPresenter,
|
||||
topNavigationPresenter) {
|
||||
|
||||
var $el;
|
||||
var privileges;
|
||||
var templates = {};
|
||||
|
||||
function init(params, loaded) {
|
||||
$el = jQuery('#content');
|
||||
topNavigationPresenter.select('comments');
|
||||
|
||||
privileges = {
|
||||
canViewPosts: auth.hasPrivilege(auth.privileges.viewPosts),
|
||||
};
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('global-comment-list'),
|
||||
util.promiseTemplate('global-comment-list-item'),
|
||||
@ -69,10 +75,11 @@ App.Presenters.GlobalCommentListPresenter = function(
|
||||
util: util,
|
||||
post: post,
|
||||
postTemplate: templates.post,
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
|
||||
util.loadImagesNicely($post.find('img'));
|
||||
var presenter = App.DI.get('postCommentListPresenter');
|
||||
var presenter = App.DI.get('commentListPresenter');
|
||||
|
||||
presenter.init({
|
||||
post: post,
|
||||
@ -95,4 +102,4 @@ App.Presenters.GlobalCommentListPresenter = function(
|
||||
|
||||
};
|
||||
|
||||
App.DI.register('globalCommentListPresenter', ['_', 'jQuery', 'util', 'promise', 'pagerPresenter', 'topNavigationPresenter'], App.Presenters.GlobalCommentListPresenter);
|
||||
App.DI.register('globalCommentListPresenter', ['_', 'jQuery', 'util', 'auth', 'promise', 'pagerPresenter', 'topNavigationPresenter'], App.Presenters.GlobalCommentListPresenter);
|
||||
|
@ -63,6 +63,7 @@ App.Presenters.HistoryPresenter = function(
|
||||
function renderHistory($page, historyItems) {
|
||||
$page.append(templates.history({
|
||||
formatRelativeTime: util.formatRelativeTime,
|
||||
formatAbsoluteTime: util.formatAbsoluteTime,
|
||||
history: historyItems}));
|
||||
}
|
||||
|
||||
|
@ -75,15 +75,11 @@ App.Presenters.PostEditPresenter = function(
|
||||
}
|
||||
|
||||
function postContentChanged(files) {
|
||||
postContentFileDropper.readAsDataURL(files[0], function(content) {
|
||||
postContent = content;
|
||||
});
|
||||
postContent = files[0];
|
||||
}
|
||||
|
||||
function postThumbnailChanged(files) {
|
||||
postThumbnailFileDropper.readAsDataURL(files[0], function(content) {
|
||||
postThumbnail = content;
|
||||
});
|
||||
postThumbnail = files[0];
|
||||
}
|
||||
|
||||
function getPrivileges() {
|
||||
@ -92,37 +88,36 @@ App.Presenters.PostEditPresenter = function(
|
||||
|
||||
function editPost() {
|
||||
var $form = $target.find('form');
|
||||
var formData = {};
|
||||
formData.seenEditTime = post.lastEditTime;
|
||||
formData.flags = {};
|
||||
var formData = new FormData();
|
||||
formData.append('seenEditTime', post.lastEditTime);
|
||||
|
||||
if (privileges.canChangeContent && postContent) {
|
||||
formData.content = postContent;
|
||||
formData.append('content', postContent);
|
||||
}
|
||||
|
||||
if (privileges.canChangeThumbnail && postThumbnail) {
|
||||
formData.thumbnail = postThumbnail;
|
||||
formData.append('thumbnail', postThumbnail);
|
||||
}
|
||||
|
||||
if (privileges.canChangeSource) {
|
||||
formData.source = $form.find('[name=source]').val();
|
||||
formData.append('source', $form.find('[name=source]').val());
|
||||
}
|
||||
|
||||
if (privileges.canChangeSafety) {
|
||||
formData.safety = $form.find('[name=safety]:checked').val();
|
||||
formData.append('safety', $form.find('[name=safety]:checked').val());
|
||||
}
|
||||
|
||||
if (privileges.canChangeTags) {
|
||||
formData.tags = tagInput.getTags().join(' ');
|
||||
formData.append('tags', tagInput.getTags().join(' '));
|
||||
}
|
||||
|
||||
if (privileges.canChangeRelations) {
|
||||
formData.relations = $form.find('[name=relations]').val();
|
||||
formData.append('relations', $form.find('[name=relations]').val());
|
||||
}
|
||||
|
||||
if (privileges.canChangeFlags) {
|
||||
if (post.contentType === 'video') {
|
||||
formData.flags.loop = $form.find('[name=loop]').is(':checked') ? 1 : 0;
|
||||
formData.append('loop', $form.find('[name=loop]').is(':checked') ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,7 +126,7 @@ App.Presenters.PostEditPresenter = function(
|
||||
return;
|
||||
}
|
||||
|
||||
promise.wait(api.put('/posts/' + post.id, formData))
|
||||
promise.wait(api.post('/posts/' + post.id, formData))
|
||||
.then(function(response) {
|
||||
tagList.refreshTags();
|
||||
if (typeof(updateCallback) !== 'undefined') {
|
||||
|
@ -29,6 +29,7 @@ App.Presenters.PostListPresenter = function(
|
||||
params.query = params.query || {};
|
||||
|
||||
privileges.canMassTag = auth.hasPrivilege(auth.privileges.massTag);
|
||||
privileges.canViewPosts = auth.hasPrivilege(auth.privileges.viewPosts);
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('post-list'),
|
||||
@ -165,6 +166,7 @@ App.Presenters.PostListPresenter = function(
|
||||
util: util,
|
||||
query: params.query,
|
||||
post: post,
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
$post.data('post', post);
|
||||
util.loadImagesNicely($post.find('img'));
|
||||
@ -217,7 +219,7 @@ App.Presenters.PostListPresenter = function(
|
||||
var formData = {};
|
||||
formData.seenEditTime = post.lastEditTime;
|
||||
formData.tags = tags.join(' ');
|
||||
promise.wait(api.put('/posts/' + post.id, formData))
|
||||
promise.wait(api.post('/posts/' + post.id, formData))
|
||||
.then(function(response) {
|
||||
post = response.json;
|
||||
$post.data('post', post);
|
||||
|
@ -14,7 +14,7 @@ App.Presenters.PostPresenter = function(
|
||||
postsAroundCalculator,
|
||||
postEditPresenter,
|
||||
postContentPresenter,
|
||||
postCommentListPresenter,
|
||||
commentListPresenter,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
|
||||
@ -70,7 +70,7 @@ App.Presenters.PostPresenter = function(
|
||||
presenterManager.initPresenters([
|
||||
[postContentPresenter, {post: post, $target: $el.find('#post-content-target')}],
|
||||
[postEditPresenter, {post: post, $target: $el.find('#post-edit-target'), updateCallback: postEdited}],
|
||||
[postCommentListPresenter, {post: post, $target: $el.find('#post-comments-target')}]],
|
||||
[commentListPresenter, {post: post, $target: $el.find('#post-comments-target')}]],
|
||||
function() { });
|
||||
|
||||
}).fail(function() {
|
||||
@ -164,6 +164,7 @@ App.Presenters.PostPresenter = function(
|
||||
postHistory: post.history,
|
||||
|
||||
formatRelativeTime: util.formatRelativeTime,
|
||||
formatAbsoluteTime: util.formatAbsoluteTime,
|
||||
formatFileSize: util.formatFileSize,
|
||||
|
||||
historyTemplate: templates.history,
|
||||
@ -333,7 +334,7 @@ App.DI.register('postPresenter', [
|
||||
'postsAroundCalculator',
|
||||
'postEditPresenter',
|
||||
'postContentPresenter',
|
||||
'postCommentListPresenter',
|
||||
'commentListPresenter',
|
||||
'topNavigationPresenter',
|
||||
'messagePresenter'],
|
||||
App.Presenters.PostPresenter);
|
||||
|
@ -256,10 +256,9 @@ App.Presenters.PostUploadPresenter = function(
|
||||
}
|
||||
|
||||
function addPostFromFile(file) {
|
||||
var post = _.extend({}, getDefaultPost(), {fileName: file.name});
|
||||
var post = _.extend({}, getDefaultPost(), {fileName: file.name, file: file});
|
||||
|
||||
fileDropper.readAsDataURL(file, function(content) {
|
||||
post.content = content;
|
||||
if (file.type.match('image.*')) {
|
||||
post.thumbnail = content;
|
||||
postThumbnailLoaded(post);
|
||||
@ -442,7 +441,6 @@ App.Presenters.PostUploadPresenter = function(
|
||||
function setPostsSource(posts, newSource) {
|
||||
_.each(posts, function(post) {
|
||||
var maxSourceLength = 200;
|
||||
console.log(newSource);
|
||||
if (newSource.length > maxSourceLength) {
|
||||
newSource = newSource.substring(0, maxSourceLength - 5) + '(...)';
|
||||
}
|
||||
@ -576,17 +574,17 @@ App.Presenters.PostUploadPresenter = function(
|
||||
var post = posts[0];
|
||||
var $row = post.$tableRow;
|
||||
|
||||
var formData = {};
|
||||
var formData = new FormData();
|
||||
if (post.url) {
|
||||
formData.url = post.url;
|
||||
formData.append('url', post.url);
|
||||
} else {
|
||||
formData.content = post.content;
|
||||
formData.contentFileName = post.fileName;
|
||||
formData.append('content', post.file);
|
||||
formData.append('contentFileName', post.fileName);
|
||||
}
|
||||
formData.source = post.source;
|
||||
formData.safety = post.safety;
|
||||
formData.anonymous = (post.anonymous | 0);
|
||||
formData.tags = post.tags.join(' ');
|
||||
formData.append('source', post.source || '');
|
||||
formData.append('safety', post.safety);
|
||||
formData.append('anonymous', (post.anonymous | 0));
|
||||
formData.append('tags', post.tags.join(' '));
|
||||
|
||||
if (post.tags.length === 0) {
|
||||
showUploadError('No tags set.');
|
||||
|
@ -10,8 +10,6 @@ App.Presenters.TagListPresenter = function(
|
||||
pagerPresenter,
|
||||
topNavigationPresenter) {
|
||||
|
||||
var KEY_RETURN = 13;
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var $searchInput;
|
||||
var templates = {};
|
||||
@ -78,8 +76,8 @@ App.Presenters.TagListPresenter = function(
|
||||
function render() {
|
||||
$el.html(templates.list());
|
||||
$searchInput = $el.find('input[name=query]');
|
||||
$searchInput.keydown(searchInputKeyPressed);
|
||||
$el.find('form').submit(searchFormSubmitted);
|
||||
App.Controls.AutoCompleteInput($searchInput);
|
||||
softRender();
|
||||
}
|
||||
|
||||
@ -88,13 +86,6 @@ App.Presenters.TagListPresenter = function(
|
||||
}
|
||||
|
||||
|
||||
function searchInputKeyPressed(e) {
|
||||
if (e.which !== KEY_RETURN) {
|
||||
return;
|
||||
}
|
||||
updateSearch();
|
||||
}
|
||||
|
||||
function searchFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
updateSearch();
|
||||
|
@ -38,6 +38,7 @@ App.Presenters.TagPresenter = function(
|
||||
privileges.canViewHistory = auth.hasPrivilege(auth.privileges.viewHistory);
|
||||
privileges.canDelete = auth.hasPrivilege(auth.privileges.deleteTags);
|
||||
privileges.canMerge = auth.hasPrivilege(auth.privileges.mergeTags);
|
||||
privileges.canViewPosts = auth.hasPrivilege(auth.privileges.viewPosts);
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('tag'),
|
||||
@ -87,6 +88,7 @@ App.Presenters.TagPresenter = function(
|
||||
siblings: siblings,
|
||||
tagCategories: JSON.parse(jQuery('head').attr('data-tag-categories')),
|
||||
formatRelativeTime: util.formatRelativeTime,
|
||||
formatAbsoluteTime: util.formatAbsoluteTime,
|
||||
historyTemplate: templates.history,
|
||||
}));
|
||||
$el.find('.post-list').hide();
|
||||
@ -126,6 +128,7 @@ App.Presenters.TagPresenter = function(
|
||||
promise.wait(api.put('/tags/' + tag.name, formData))
|
||||
.then(function(response) {
|
||||
router.navigateInplace('#/tag/' + response.json.name);
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
@ -138,6 +141,7 @@ App.Presenters.TagPresenter = function(
|
||||
promise.wait(api.delete('/tags/' + tag.name))
|
||||
.then(function(response) {
|
||||
router.navigate('#/tags');
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
@ -149,6 +153,7 @@ App.Presenters.TagPresenter = function(
|
||||
promise.wait(api.put('/tags/' + tag.name + '/merge', {targetTag: targetTag}))
|
||||
.then(function(response) {
|
||||
router.navigate('#/tags');
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
@ -162,6 +167,7 @@ App.Presenters.TagPresenter = function(
|
||||
util: util,
|
||||
post: post,
|
||||
query: {query: tag.name},
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
$target.append($post);
|
||||
});
|
||||
@ -180,4 +186,16 @@ App.Presenters.TagPresenter = function(
|
||||
|
||||
};
|
||||
|
||||
App.DI.register('tagPresenter', ['_', 'jQuery', 'util', 'promise', 'auth', 'api', 'tagList', 'router', 'keyboard', 'topNavigationPresenter', 'messagePresenter'], App.Presenters.TagPresenter);
|
||||
App.DI.register('tagPresenter', [
|
||||
'_',
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'auth',
|
||||
'api',
|
||||
'tagList',
|
||||
'router',
|
||||
'keyboard',
|
||||
'topNavigationPresenter',
|
||||
'messagePresenter'],
|
||||
App.Presenters.TagPresenter);
|
||||
|
@ -77,11 +77,7 @@ App.Presenters.UserAccountSettingsPresenter = function(
|
||||
}
|
||||
|
||||
function avatarContentChanged(files) {
|
||||
if (files.length === 1) {
|
||||
fileDropper.readAsDataURL(files[0], function(content) {
|
||||
avatarContent = content;
|
||||
});
|
||||
}
|
||||
avatarContent = files[0];
|
||||
}
|
||||
|
||||
function accountSettingsFormSubmitted(e) {
|
||||
@ -89,41 +85,45 @@ App.Presenters.UserAccountSettingsPresenter = function(
|
||||
var $el = jQuery(target);
|
||||
var $messages = jQuery(target).find('.messages');
|
||||
messagePresenter.hideMessages($messages);
|
||||
var formData = {};
|
||||
var formData = new FormData();
|
||||
|
||||
if (privileges.canChangeAvatarStyle) {
|
||||
formData.avatarStyle = $el.find('[name=avatar-style]:checked').val();
|
||||
formData.append('avatarStyle', $el.find('[name=avatar-style]:checked').val());
|
||||
if (avatarContent) {
|
||||
formData.avatarContent = avatarContent;
|
||||
formData.append('avatarContent', avatarContent);
|
||||
}
|
||||
}
|
||||
if (privileges.canChangeName) {
|
||||
formData.userName = $el.find('[name=userName]').val();
|
||||
formData.append('userName', $el.find('[name=userName]').val());
|
||||
}
|
||||
|
||||
if (privileges.canChangeEmailAddress) {
|
||||
formData.email = $el.find('[name=email]').val();
|
||||
formData.append('email', $el.find('[name=email]').val());
|
||||
}
|
||||
|
||||
if (privileges.canChangePassword) {
|
||||
formData.password = $el.find('[name=password]').val();
|
||||
formData.passwordConfirmation = $el.find('[name=passwordConfirmation]').val();
|
||||
var password = $el.find('[name=password]').val();
|
||||
var passwordConfirmation = $el.find('[name=passwordConfirmation]').val();
|
||||
|
||||
if (password) {
|
||||
if (password !== passwordConfirmation) {
|
||||
messagePresenter.showError($messages, 'Passwords must be the same.');
|
||||
return;
|
||||
}
|
||||
|
||||
formData.append('password', password);
|
||||
}
|
||||
}
|
||||
|
||||
if (privileges.canChangeAccessRank) {
|
||||
formData.accessRank = $el.find('[name=access-rank]:checked').val();
|
||||
formData.append('accessRank', $el.find('[name=access-rank]:checked').val());
|
||||
}
|
||||
|
||||
if (privileges.canBan) {
|
||||
formData.banned = $el.find('[name=ban]').is(':checked') ? 1 : 0;
|
||||
formData.append('banned', $el.find('[name=ban]').is(':checked') ? 1 : 0);
|
||||
}
|
||||
|
||||
if (!validateAccountSettingsFormData(formData)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!formData.password) {
|
||||
delete formData.password;
|
||||
delete formData.passwordConfirmation;
|
||||
}
|
||||
|
||||
promise.wait(api.put('/users/' + user.name, formData))
|
||||
promise.wait(api.post('/users/' + user.name, formData))
|
||||
.then(function(response) {
|
||||
editSuccess(response);
|
||||
}).fail(function(response) {
|
||||
@ -153,16 +153,6 @@ App.Presenters.UserAccountSettingsPresenter = function(
|
||||
messagePresenter.showError($messages, apiResponse.json && apiResponse.json.error || apiResponse);
|
||||
}
|
||||
|
||||
function validateAccountSettingsFormData(formData) {
|
||||
var $messages = jQuery(target).find('.messages');
|
||||
if (formData.password !== formData.passwordConfirmation) {
|
||||
messagePresenter.showError($messages, 'Passwords must be the same.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
|
@ -13,11 +13,14 @@ App.Presenters.UserListPresenter = function(
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var params;
|
||||
var privileges = {};
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('users');
|
||||
topNavigationPresenter.changeTitle('Users');
|
||||
|
||||
privileges.canViewUsers = auth.hasPrivilege(auth.privileges.viewUsers);
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('user-list'),
|
||||
util.promiseTemplate('user-list-item'))
|
||||
@ -60,7 +63,7 @@ App.Presenters.UserListPresenter = function(
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.list());
|
||||
$el.html(templates.list(privileges));
|
||||
}
|
||||
|
||||
function updateActiveOrder(activeOrder) {
|
||||
@ -71,10 +74,11 @@ App.Presenters.UserListPresenter = function(
|
||||
function renderUsers($page, users) {
|
||||
var $target = $page.find('.users');
|
||||
_.each(users, function(user) {
|
||||
var $item = jQuery('<li>' + templates.listItem({
|
||||
var $item = jQuery('<li>' + templates.listItem(_.extend({
|
||||
user: user,
|
||||
formatRelativeTime: util.formatRelativeTime,
|
||||
}) + '</li>');
|
||||
formatAbsoluteTime: util.formatAbsoluteTime,
|
||||
}, privileges)) + '</li>');
|
||||
$target.append($item);
|
||||
});
|
||||
_.map(_.map($target.find('img'), jQuery), util.loadImagesNicely);
|
||||
|
@ -75,6 +75,7 @@ App.Presenters.UserPresenter = function(
|
||||
user: user,
|
||||
isLoggedIn: auth.isLoggedIn(user.name),
|
||||
formatRelativeTime: util.formatRelativeTime,
|
||||
formatAbsoluteTime: util.formatAbsoluteTime,
|
||||
canChangeBrowsingSettings: userBrowsingSettingsPresenter.getPrivileges().canChangeBrowsingSettings,
|
||||
canChangeAccountSettings: _.any(userAccountSettingsPresenter.getPrivileges()),
|
||||
canDeleteAccount: userAccountRemovalPresenter.getPrivileges().canDeleteAccount}));
|
||||
|
@ -146,6 +146,11 @@ App.Util.Misc = function(_, jQuery, marked, promise) {
|
||||
return future ? 'in ' + text : text + ' ago';
|
||||
}
|
||||
|
||||
function formatAbsoluteTime(timeString) {
|
||||
var time = new Date(Date.parse(timeString));
|
||||
return time.toString();
|
||||
}
|
||||
|
||||
function formatUnits(number, base, suffixes, callback) {
|
||||
if (!number && number !== 0) {
|
||||
return NaN;
|
||||
@ -205,6 +210,8 @@ App.Util.Misc = function(_, jQuery, marked, promise) {
|
||||
text = text.replace(/\[search\]((?:[^\[]|\[(?!\/?search\]))+)\[\/search\]/ig, '<a href="#/posts/query=$1"><code>$1</code></a>');
|
||||
//spoilers
|
||||
text = text.replace(/\[spoiler\]((?:[^\[]|\[(?!\/?spoiler\]))+)\[\/spoiler\]/ig, '<span class="spoiler">$1</span>');
|
||||
//[small]
|
||||
text = text.replace(/\[small\]((?:[^\[]|\[(?!\/?small\]))+)\[\/small\]/ig, '<small>$1</small>');
|
||||
//strike-through
|
||||
text = text.replace(/(^|[^\\])(~~|~)([^~]+)\2/g, '$1<del>$3</del>');
|
||||
text = text.replace(/\\~/g, '~');
|
||||
@ -233,6 +240,7 @@ App.Util.Misc = function(_, jQuery, marked, promise) {
|
||||
return {
|
||||
promiseTemplate: promiseTemplate,
|
||||
formatRelativeTime: formatRelativeTime,
|
||||
formatAbsoluteTime: formatAbsoluteTime,
|
||||
formatFileSize: formatFileSize,
|
||||
formatMarkdown: formatMarkdown,
|
||||
enableExitConfirmation: enableExitConfirmation,
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div class="comment">
|
||||
<div class="avatar">
|
||||
<% if (comment.user.name) { %>
|
||||
<% if (comment.user.name && canViewUsers) { %>
|
||||
<a href="#/user/<%= comment.user.name %>">
|
||||
<% } %>
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
src="/data/thumbnails/40x40/avatars/<%= comment.user.name || '!' %>"
|
||||
alt="<%= comment.user.name || 'Anonymous user' %>"/>
|
||||
|
||||
<% if (comment.user.name) { %>
|
||||
<% if (comment.user.name && canViewUsers) { %>
|
||||
</a>
|
||||
<% } %>
|
||||
</div>
|
||||
@ -16,18 +16,18 @@
|
||||
<div class="body">
|
||||
<div class="header">
|
||||
<span class="nickname">
|
||||
<% if (comment.user.name) { %>
|
||||
<% if (comment.user.name && canViewUsers) { %>
|
||||
<a href="#/user/<%= comment.user.name %>">
|
||||
<% } %>
|
||||
|
||||
<%= comment.user.name || 'Anonymous user' %>
|
||||
|
||||
<% if (comment.user.name) { %>
|
||||
<% if (comment.user.name && canViewUsers) { %>
|
||||
</a>
|
||||
<% } %>
|
||||
</span>
|
||||
|
||||
<span class="date" title="<%= comment.creationTime %>">
|
||||
<span class="date" title="<%= formatAbsoluteTime(comment.creationTime) %>">
|
||||
<%= formatRelativeTime(comment.creationTime) %>
|
||||
</span>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div class="post-comment">
|
||||
<div class="post">
|
||||
<%= postTemplate({post: post, util: util}) %>
|
||||
<%= postTemplate({post: post, util: util, canViewPosts: canViewPosts}) %>
|
||||
</div>
|
||||
|
||||
<div class="post-comments-target">
|
||||
|
@ -5,13 +5,24 @@ var reprValue = function(value) {
|
||||
}
|
||||
return JSON.stringify(value);
|
||||
};
|
||||
|
||||
var showDifference = function(className, difference) {
|
||||
_.each(difference, function(value, key) {
|
||||
if (!Array.isArray(value)) {
|
||||
value = [value];
|
||||
}
|
||||
_.each(value, function(v) {
|
||||
%><li class="<%= className %> difference-<%= key %>"><%= key + ':' + reprValue(v) %></li><%
|
||||
});
|
||||
});
|
||||
};
|
||||
%>
|
||||
|
||||
<table class="history">
|
||||
<tbody>
|
||||
<% _.each(history, function( historyEntry) { %>
|
||||
<tr>
|
||||
<td class="time">
|
||||
<td class="time" title="<%= formatAbsoluteTime(historyEntry.time) %>">
|
||||
<%= formatRelativeTime(historyEntry.time) %>
|
||||
</td>
|
||||
|
||||
@ -59,17 +70,8 @@ var reprValue = function(value) {
|
||||
|
||||
<% if (historyEntry.dataDifference) { %>
|
||||
<ul><!--
|
||||
--><% _.each(historyEntry.dataDifference['+'], function (difference) { %><!--
|
||||
--><li class="addition difference-<%= difference[0] %>"><!--
|
||||
--><%= difference[0] + ':' + reprValue(difference[1]) %><!--
|
||||
--></li><!--
|
||||
--><% }) %><!--
|
||||
|
||||
--><% _.each(historyEntry.dataDifference['-'], function (difference) { %><!--
|
||||
--><li class="removal difference-<%= difference[0] %>"><!--
|
||||
--><%= difference[0] + ':' + reprValue(difference[1]) %><!--
|
||||
--></li><!--
|
||||
--><% }) %><!--
|
||||
--><% showDifference('addition', historyEntry.dataDifference['+']) %><!--
|
||||
--><% showDifference('removal', historyEntry.dataDifference['-']) %><!--
|
||||
--></ul>
|
||||
<% } %>
|
||||
<% } %>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div id="home">
|
||||
<h1><%= title %></h1>
|
||||
<p>
|
||||
<small>Serving <%= globals.postCount || 0 %> posts (<%= formatFileSize(globals.postSize || 0) %>)</small>
|
||||
<p class="subheader">
|
||||
Serving <%= globals.postCount || 0 %> posts (<%= formatFileSize(globals.postSize || 0) %>)
|
||||
</p>
|
||||
|
||||
<% if (post && post.id) { %>
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
<div class="post-footer">
|
||||
|
||||
<small class="left">
|
||||
<span class="left">
|
||||
<% var showLink = canViewPosts %>
|
||||
|
||||
<% if (showLink) { %>
|
||||
@ -26,9 +26,9 @@
|
||||
|
||||
uploaded
|
||||
<%= formatRelativeTime(post.uploadTime) %>
|
||||
</small>
|
||||
</span>
|
||||
|
||||
<small class="right">
|
||||
<span class="right">
|
||||
featured
|
||||
<%= formatRelativeTime(post.lastFeatureTime) %>
|
||||
by
|
||||
@ -48,7 +48,7 @@
|
||||
<% if (showLink) { %>
|
||||
</a>
|
||||
<% } %>
|
||||
</small>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,7 +1,12 @@
|
||||
<div class="post-small post-type-<%= post.contentType %> ">
|
||||
<a class="link"
|
||||
href="<%= util.appendComplexRouteParam('#/post/' + post.id, typeof(query) !== 'undefined' ? query : {}) %>"
|
||||
title="<%= _.map(post.tags, function(tag) { return '#' + tag.name; }).join(', ') %>">
|
||||
|
||||
<% if (canViewPosts) { %>
|
||||
<a class="link"
|
||||
href="<%= util.appendComplexRouteParam('#/post/' + post.id, typeof(query) !== 'undefined' ? query : {}) %>"
|
||||
title="<%= _.map(post.tags, function(tag) { return '#' + tag.name; }).join(', ') %>">
|
||||
<% } else { %>
|
||||
<span class="link">
|
||||
<% } %>
|
||||
|
||||
<img width="160" height="160" class="thumb" src="/data/thumbnails/160x160/posts/<%= post.name %>" alt="<%= post.idMarkdown %>"/>
|
||||
|
||||
@ -31,7 +36,12 @@
|
||||
</ul>
|
||||
</div>
|
||||
<% } %>
|
||||
</a>
|
||||
|
||||
<% if (canViewPosts) { %>
|
||||
</a>
|
||||
<% } else { %>
|
||||
</span>
|
||||
<% } %>
|
||||
|
||||
<div class="action">
|
||||
<button>Action</button>
|
||||
|
@ -10,7 +10,7 @@
|
||||
</div>
|
||||
|
||||
<div class="search">
|
||||
<a href="#/posts/query=<%= query.query %>;order=<%= query.order %>">
|
||||
<a class="enabled" href="#/posts/query=<%= query.query %>;order=<%= query.order %>">
|
||||
Current search: <%= query.query || '-' %>
|
||||
</a>
|
||||
</div>
|
||||
@ -27,13 +27,15 @@
|
||||
<div id="post-view-wrapper">
|
||||
<div id="sidebar">
|
||||
<ul class="essential">
|
||||
<li>
|
||||
<a class="download" href="<%= permaLink %>">
|
||||
<i class="fa fa-download"></i>
|
||||
<br/>
|
||||
<%= post.contentExtension + ', ' + formatFileSize(post.originalFileSize) %>
|
||||
</a>
|
||||
</li>
|
||||
<% if (post.contentType !== 'youtube') { %>
|
||||
<li>
|
||||
<a class="download" href="<%= permaLink %>">
|
||||
<i class="fa fa-download"></i>
|
||||
<br/>
|
||||
<%= post.contentExtension + ', ' + formatFileSize(post.originalFileSize) %>
|
||||
</a>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
<% if (isLoggedIn) { %>
|
||||
<li>
|
||||
@ -107,7 +109,9 @@
|
||||
|
||||
<br/>
|
||||
|
||||
<span class="date"><%= formatRelativeTime(post.uploadTime) %></span>
|
||||
<span class="date" title="<%= formatAbsoluteTime(post.uploadTime) %>">
|
||||
<%= formatRelativeTime(post.uploadTime) %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ul class="other-info">
|
||||
@ -136,7 +140,9 @@
|
||||
<% if (post.lastEditTime !== post.uploadTime) { %>
|
||||
<li>
|
||||
Edited:
|
||||
<%= formatRelativeTime(post.lastEditTime) %>
|
||||
<span title="<%= formatAbsoluteTime(post.lastEditTime) %>">
|
||||
<%= formatRelativeTime(post.lastEditTime) %>
|
||||
</span>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
@ -271,7 +277,8 @@
|
||||
<h1>History</h1>
|
||||
<%= historyTemplate({
|
||||
history: postHistory,
|
||||
formatRelativeTime: formatRelativeTime
|
||||
formatRelativeTime: formatRelativeTime,
|
||||
formatAbsoluteTime: formatAbsoluteTime,
|
||||
}) %>
|
||||
</div>
|
||||
<% } %>
|
||||
|
@ -103,7 +103,8 @@
|
||||
<h3>History</h3>
|
||||
<%= historyTemplate({
|
||||
history: tag.history,
|
||||
formatRelativeTime: formatRelativeTime
|
||||
formatRelativeTime: formatRelativeTime,
|
||||
formatAbsoluteTime: formatAbsoluteTime,
|
||||
}) %>
|
||||
</div>
|
||||
<% } %>
|
||||
|
@ -1,17 +1,28 @@
|
||||
<div class="user">
|
||||
<a href="#/user/<%= user.name %>">
|
||||
<img width="80" height="80" src="/data/thumbnails/80x80/avatars/<%= user.name %>" alt="<%= user.name %>"/>
|
||||
</a>
|
||||
<div class="avatar">
|
||||
<% if (canViewUsers) { %>
|
||||
<a href="#/user/<%= user.name %>">
|
||||
<% } %>
|
||||
<img width="80" height="80" src="/data/thumbnails/80x80/avatars/<%= user.name %>" alt="<%= user.name %>"/>
|
||||
<% if (canViewUsers) { %>
|
||||
</a>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="details">
|
||||
<h1>
|
||||
<a href="#/user/<%= user.name %>">
|
||||
<% if (canViewUsers) { %>
|
||||
<a href="#/user/<%= user.name %>">
|
||||
<%= user.name %>
|
||||
</a>
|
||||
<% } else { %>
|
||||
<%= user.name %>
|
||||
</a>
|
||||
<% } %>
|
||||
</h1>
|
||||
<div class="date-joined" title="<%= user.registrationTime %>">
|
||||
<div class="date-joined" title="<%= formatAbsoluteTime(user.registrationTime) %>">
|
||||
Joined: <%= formatRelativeTime(user.registrationTime) %>
|
||||
</div>
|
||||
<div class="date-seen">
|
||||
<div class="date-seen" title="<%= formatAbsoluteTime(user.lastLoginTime) %>">
|
||||
Last seen: <%= formatRelativeTime(user.lastLoginTime) %>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -51,12 +51,16 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td>Registered:</td>
|
||||
<td><%= formatRelativeTime(user.registrationTime) %></td>
|
||||
<td title="<%= formatAbsoluteTime(user.registrationTime) %>">
|
||||
<%= formatRelativeTime(user.registrationTime) %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Seen:</td>
|
||||
<td><%= formatRelativeTime(user.lastLoginTime) %></td>
|
||||
<td title="<%= formatAbsoluteTime(user.lastLoginTime) %>">
|
||||
<%= formatRelativeTime(user.lastLoginTime) %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<% if (user.accessRank) { %>
|
||||
|
@ -25,7 +25,7 @@ if ($testMode)
|
||||
|
||||
$databaseConnection = \Szurubooru\Injector::get(\Szurubooru\DatabaseConnection::class);
|
||||
$pdo = $databaseConnection->getPDO();
|
||||
$pdo->exec('DROP DATABASE szuru_test');
|
||||
$pdo->exec('DROP DATABASE IF EXISTS szuru_test');
|
||||
$pdo->exec('CREATE DATABASE szuru_test');
|
||||
$pdo->exec('USE szuru_test');
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
<?php
|
||||
namespace Szurubooru;
|
||||
|
||||
class ControllerRepository
|
||||
{
|
||||
private $controllers = [];
|
||||
|
||||
public function __construct(array $controllers)
|
||||
{
|
||||
$this->controllers = $controllers;
|
||||
}
|
||||
|
||||
public function getControllers()
|
||||
{
|
||||
return $this->controllers;
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
use Szurubooru\Router;
|
||||
|
||||
abstract class AbstractController
|
||||
{
|
||||
abstract function registerRoutes(Router $router);
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
use Szurubooru\Controllers\ViewProxies\CommentViewProxy;
|
||||
use Szurubooru\Controllers\ViewProxies\PostViewProxy;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Router;
|
||||
use Szurubooru\SearchServices\Filters\CommentFilter;
|
||||
use Szurubooru\SearchServices\Filters\PostFilter;
|
||||
use Szurubooru\SearchServices\Requirements\Requirement;
|
||||
use Szurubooru\SearchServices\Requirements\RequirementRangedValue;
|
||||
use Szurubooru\SearchServices\Requirements\RequirementSingleValue;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\CommentService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
|
||||
final class CommentController extends AbstractController
|
||||
{
|
||||
private $privilegeService;
|
||||
private $authService;
|
||||
private $postService;
|
||||
private $commentService;
|
||||
private $commentViewProxy;
|
||||
private $postViewProxy;
|
||||
private $inputReader;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
AuthService $authService,
|
||||
PostService $postService,
|
||||
CommentService $commentService,
|
||||
CommentViewProxy $commentViewProxy,
|
||||
PostViewProxy $postViewProxy,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->authService = $authService;
|
||||
$this->postService = $postService;
|
||||
$this->commentService = $commentService;
|
||||
$this->commentViewProxy = $commentViewProxy;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
$this->inputReader = $inputReader;
|
||||
}
|
||||
|
||||
public function registerRoutes(Router $router)
|
||||
{
|
||||
$router->get('/api/comments', [$this, 'getComments']);
|
||||
$router->get('/api/comments/:postNameOrId', [$this, 'getPostComments']);
|
||||
$router->post('/api/comments/:postNameOrId', [$this, 'addComment']);
|
||||
$router->put('/api/comments/:commentId', [$this, 'editComment']);
|
||||
$router->delete('/api/comments/:commentId', [$this, 'deleteComment']);
|
||||
}
|
||||
|
||||
public function getComments()
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::LIST_COMMENTS);
|
||||
|
||||
$filter = new PostFilter();
|
||||
$filter->setPageSize(10);
|
||||
$filter->setPageNumber($this->inputReader->page);
|
||||
$filter->setOrder([
|
||||
PostFilter::ORDER_LAST_COMMENT_TIME =>
|
||||
PostFilter::ORDER_DESC]);
|
||||
|
||||
$this->postService->decorateFilterFromBrowsingSettings($filter);
|
||||
|
||||
$requirement = new Requirement();
|
||||
$requirement->setValue(new RequirementRangedValue());
|
||||
$requirement->getValue()->setMinValue(1);
|
||||
$requirement->setType(PostFilter::REQUIREMENT_COMMENT_COUNT);
|
||||
$filter->addRequirement($requirement);
|
||||
|
||||
$result = $this->postService->getFiltered($filter);
|
||||
$posts = $result->getEntities();
|
||||
|
||||
$data = [];
|
||||
foreach ($posts as $post)
|
||||
{
|
||||
$data[] = [
|
||||
'post' => $this->postViewProxy->fromEntity($post),
|
||||
'comments' => $this->commentViewProxy->fromArray(
|
||||
array_reverse($this->commentService->getByPost($post)),
|
||||
$this->getCommentsFetchConfig()),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'data' => $data,
|
||||
'pageSize' => $result->getPageSize(),
|
||||
'totalRecords' => $result->getTotalRecords()];
|
||||
}
|
||||
|
||||
public function getPostComments($postNameOrId)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::LIST_COMMENTS);
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
|
||||
$filter = new CommentFilter();
|
||||
$filter->setOrder([
|
||||
CommentFilter::ORDER_ID =>
|
||||
CommentFilter::ORDER_ASC]);
|
||||
|
||||
$requirement = new Requirement();
|
||||
$requirement->setValue(new RequirementSingleValue($post->getId()));
|
||||
$requirement->setType(CommentFilter::REQUIREMENT_POST_ID);
|
||||
$filter->addRequirement($requirement);
|
||||
|
||||
$result = $this->commentService->getFiltered($filter);
|
||||
$entities = $this->commentViewProxy->fromArray($result->getEntities(), $this->getCommentsFetchConfig());
|
||||
return ['data' => $entities];
|
||||
}
|
||||
|
||||
public function addComment($postNameOrId)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::ADD_COMMENTS);
|
||||
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
$comment = $this->commentService->createComment($post, $this->inputReader->text);
|
||||
return $this->commentViewProxy->fromEntity($comment, $this->getCommentsFetchConfig());
|
||||
}
|
||||
|
||||
public function editComment($commentId)
|
||||
{
|
||||
$comment = $this->commentService->getById($commentId);
|
||||
|
||||
$this->privilegeService->assertPrivilege(
|
||||
($comment->getUser() && $this->privilegeService->isLoggedIn($comment->getUser()))
|
||||
? Privilege::EDIT_OWN_COMMENTS
|
||||
: Privilege::EDIT_ALL_COMMENTS);
|
||||
|
||||
$comment = $this->commentService->updateComment($comment, $this->inputReader->text);
|
||||
return $this->commentViewProxy->fromEntity($comment, $this->getCommentsFetchConfig());
|
||||
}
|
||||
|
||||
public function deleteComment($commentId)
|
||||
{
|
||||
$comment = $this->commentService->getById($commentId);
|
||||
|
||||
$this->privilegeService->assertPrivilege(
|
||||
$this->privilegeService->isLoggedIn($comment->getUser())
|
||||
? Privilege::DELETE_OWN_COMMENTS
|
||||
: Privilege::DELETE_ALL_COMMENTS);
|
||||
|
||||
return $this->commentService->deleteComment($comment);
|
||||
}
|
||||
|
||||
private function getCommentsFetchConfig()
|
||||
{
|
||||
return
|
||||
[
|
||||
CommentViewProxy::FETCH_OWN_SCORE => true,
|
||||
];
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
use Szurubooru\Controllers\ViewProxies\UserViewProxy;
|
||||
use Szurubooru\Router;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\FavoritesService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
|
||||
final class FavoritesController extends AbstractController
|
||||
{
|
||||
private $privilegeService;
|
||||
private $authService;
|
||||
private $postService;
|
||||
private $favoritesService;
|
||||
private $userViewProxy;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
AuthService $authService,
|
||||
PostService $postService,
|
||||
FavoritesService $favoritesService,
|
||||
UserViewProxy $userViewProxy)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->authService = $authService;
|
||||
$this->postService = $postService;
|
||||
$this->favoritesService = $favoritesService;
|
||||
$this->userViewProxy = $userViewProxy;
|
||||
}
|
||||
|
||||
public function registerRoutes(Router $router)
|
||||
{
|
||||
$router->get('/api/posts/:postNameOrId/favorites', [$this, 'getFavoriteUsers']);
|
||||
$router->post('/api/posts/:postNameOrId/favorites', [$this, 'addFavorite']);
|
||||
$router->delete('/api/posts/:postNameOrId/favorites', [$this, 'deleteFavorite']);
|
||||
}
|
||||
|
||||
public function getFavoriteUsers($postNameOrId)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
$users = $this->favoritesService->getFavoriteUsers($post);
|
||||
return ['data' => $this->userViewProxy->fromArray($users)];
|
||||
}
|
||||
|
||||
public function addFavorite($postNameOrId)
|
||||
{
|
||||
$this->privilegeService->assertLoggedIn();
|
||||
$user = $this->authService->getLoggedInUser();
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
$this->favoritesService->addFavorite($user, $post);
|
||||
return $this->getFavoriteUsers($postNameOrId);
|
||||
}
|
||||
|
||||
public function deleteFavorite($postNameOrId)
|
||||
{
|
||||
$this->privilegeService->assertLoggedIn();
|
||||
$user = $this->authService->getLoggedInUser();
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
$this->favoritesService->deleteFavorite($user, $post);
|
||||
return $this->getFavoriteUsers($postNameOrId);
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
use Szurubooru\Dao\GlobalParamDao;
|
||||
use Szurubooru\Router;
|
||||
|
||||
final class GlobalParamController extends AbstractController
|
||||
{
|
||||
private $globalParamDao;
|
||||
|
||||
public function __construct(GlobalParamDao $globalParamDao)
|
||||
{
|
||||
$this->globalParamDao = $globalParamDao;
|
||||
}
|
||||
|
||||
public function registerRoutes(Router $router)
|
||||
{
|
||||
$router->get('/api/globals', [$this, 'getGlobals']);
|
||||
}
|
||||
|
||||
public function getGlobals()
|
||||
{
|
||||
$globals = $this->globalParamDao->findAll();
|
||||
$return = [];
|
||||
foreach ($globals as $global)
|
||||
{
|
||||
$return[$global->getKey()] = $global->getValue();
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
use Szurubooru\Config;
|
||||
use Szurubooru\Controllers\ViewProxies\PostViewProxy;
|
||||
use Szurubooru\Controllers\ViewProxies\SnapshotViewProxy;
|
||||
use Szurubooru\Controllers\ViewProxies\UserViewProxy;
|
||||
use Szurubooru\Entities\Post;
|
||||
use Szurubooru\FormData\PostEditFormData;
|
||||
use Szurubooru\FormData\UploadFormData;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Router;
|
||||
use Szurubooru\SearchServices\Parsers\PostSearchParser;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\PostFeatureService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
|
||||
final class PostController extends AbstractController
|
||||
{
|
||||
private $config;
|
||||
private $authService;
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
private $postFeatureService;
|
||||
private $postSearchParser;
|
||||
private $inputReader;
|
||||
private $postViewProxy;
|
||||
private $snapshotViewProxy;
|
||||
|
||||
public function __construct(
|
||||
Config $config,
|
||||
AuthService $authService,
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService,
|
||||
PostFeatureService $postFeatureService,
|
||||
PostSearchParser $postSearchParser,
|
||||
InputReader $inputReader,
|
||||
UserViewProxy $userViewProxy,
|
||||
PostViewProxy $postViewProxy,
|
||||
SnapshotViewProxy $snapshotViewProxy)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->authService = $authService;
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
$this->postFeatureService = $postFeatureService;
|
||||
$this->postSearchParser = $postSearchParser;
|
||||
$this->inputReader = $inputReader;
|
||||
$this->userViewProxy = $userViewProxy;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
$this->snapshotViewProxy = $snapshotViewProxy;
|
||||
}
|
||||
|
||||
public function registerRoutes(Router $router)
|
||||
{
|
||||
$router->post('/api/posts', [$this, 'createPost']);
|
||||
$router->get('/api/posts', [$this, 'getFiltered']);
|
||||
$router->get('/api/posts/featured', [$this, 'getFeatured']);
|
||||
$router->get('/api/posts/:postNameOrId', [$this, 'getByNameOrId']);
|
||||
$router->get('/api/posts/:postNameOrId/history', [$this, 'getHistory']);
|
||||
$router->put('/api/posts/:postNameOrId', [$this, 'updatePost']);
|
||||
$router->delete('/api/posts/:postNameOrId', [$this, 'deletePost']);
|
||||
$router->post('/api/posts/:postNameOrId/feature', [$this, 'featurePost']);
|
||||
$router->put('/api/posts/:postNameOrId/feature', [$this, 'featurePost']);
|
||||
}
|
||||
|
||||
public function getFeatured()
|
||||
{
|
||||
$post = $this->postFeatureService->getFeaturedPost();
|
||||
$user = $this->postFeatureService->getFeaturedPostUser();
|
||||
return [
|
||||
'user' => $this->userViewProxy->fromEntity($user),
|
||||
'post' => $this->postViewProxy->fromEntity($post, $this->getFullFetchConfig()),
|
||||
];
|
||||
}
|
||||
|
||||
public function getByNameOrId($postNameOrId)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
return $this->postViewProxy->fromEntity($post, $this->getFullFetchConfig());
|
||||
}
|
||||
|
||||
public function getHistory($postNameOrId)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::VIEW_HISTORY);
|
||||
$post = $this->getByNameOrId($postNameOrId);
|
||||
return ['data' => $this->snapshotViewProxy->fromArray($this->postService->getHistory($post))];
|
||||
}
|
||||
|
||||
public function getFiltered()
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::LIST_POSTS);
|
||||
|
||||
$filter = $this->postSearchParser->createFilterFromInputReader($this->inputReader);
|
||||
$filter->setPageSize($this->config->posts->postsPerPage);
|
||||
$this->postService->decorateFilterFromBrowsingSettings($filter);
|
||||
|
||||
$result = $this->postService->getFiltered($filter);
|
||||
$entities = $this->postViewProxy->fromArray($result->getEntities(), $this->getLightFetchConfig());
|
||||
return [
|
||||
'data' => $entities,
|
||||
'pageSize' => $result->getPageSize(),
|
||||
'totalRecords' => $result->getTotalRecords()];
|
||||
}
|
||||
|
||||
public function createPost()
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::UPLOAD_POSTS);
|
||||
$formData = new UploadFormData($this->inputReader);
|
||||
|
||||
$this->privilegeService->assertPrivilege(Privilege::UPLOAD_POSTS);
|
||||
|
||||
if ($formData->anonymous)
|
||||
$this->privilegeService->assertPrivilege(Privilege::UPLOAD_POSTS_ANONYMOUSLY);
|
||||
|
||||
$post = $this->postService->createPost($formData);
|
||||
return $this->postViewProxy->fromEntity($post, $this->getFullFetchConfig());
|
||||
}
|
||||
|
||||
public function updatePost($postNameOrId)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
$formData = new PostEditFormData($this->inputReader);
|
||||
|
||||
if ($formData->content !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_POST_CONTENT);
|
||||
|
||||
if ($formData->thumbnail !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_POST_THUMBNAIL);
|
||||
|
||||
if ($formData->safety !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_POST_SAFETY);
|
||||
|
||||
if ($formData->source !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_POST_SOURCE);
|
||||
|
||||
if ($formData->tags !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_POST_TAGS);
|
||||
|
||||
$this->postService->updatePost($post, $formData);
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
return $this->postViewProxy->fromEntity($post, $this->getFullFetchConfig());
|
||||
}
|
||||
|
||||
public function deletePost($postNameOrId)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
$this->postService->deletePost($post);
|
||||
}
|
||||
|
||||
public function featurePost($postNameOrId)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
$this->postFeatureService->featurePost($post);
|
||||
}
|
||||
|
||||
private function getFullFetchConfig()
|
||||
{
|
||||
return
|
||||
[
|
||||
PostViewProxy::FETCH_RELATIONS => true,
|
||||
PostViewProxy::FETCH_TAGS => true,
|
||||
PostViewProxy::FETCH_USER => true,
|
||||
PostViewProxy::FETCH_HISTORY => true,
|
||||
PostViewProxy::FETCH_OWN_SCORE => true,
|
||||
PostViewProxy::FETCH_FAVORITES => true,
|
||||
PostViewProxy::FETCH_NOTES => true,
|
||||
];
|
||||
}
|
||||
|
||||
private function getLightFetchConfig()
|
||||
{
|
||||
return
|
||||
[
|
||||
PostViewProxy::FETCH_TAGS => true,
|
||||
];
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
use Szurubooru\Controllers\ViewProxies\PostNoteViewProxy;
|
||||
use Szurubooru\FormData\PostNoteFormData;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Router;
|
||||
use Szurubooru\Services\PostNotesService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
|
||||
final class PostNotesController extends AbstractController
|
||||
{
|
||||
private $inputReader;
|
||||
private $postService;
|
||||
private $postNotesService;
|
||||
private $privilegeService;
|
||||
private $postNoteViewProxy;
|
||||
|
||||
public function __construct(
|
||||
InputReader $inputReader,
|
||||
PostService $postService,
|
||||
PostNotesService $postNotesService,
|
||||
PrivilegeService $privilegeService,
|
||||
PostNoteViewProxy $postNoteViewProxy)
|
||||
{
|
||||
$this->inputReader = $inputReader;
|
||||
$this->postService = $postService;
|
||||
$this->postNotesService = $postNotesService;
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postNoteViewProxy = $postNoteViewProxy;
|
||||
}
|
||||
|
||||
public function registerRoutes(Router $router)
|
||||
{
|
||||
$router->get('/api/notes/:postNameOrId', [$this, 'getPostNotes']);
|
||||
$router->post('/api/notes/:postNameOrId', [$this, 'addPostNote']);
|
||||
$router->put('/api/notes/:postNoteId', [$this, 'editPostNote']);
|
||||
$router->delete('/api/notes/:postNoteId', [$this, 'deletePostNote']);
|
||||
}
|
||||
|
||||
public function getPostNotes($postNameOrId)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
$postNotes = $this->postNotesService->getByPost($post);
|
||||
return $this->postNoteViewProxy->fromArray($postNotes);
|
||||
}
|
||||
|
||||
public function addPostNote($postNameOrId)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
|
||||
$this->privilegeService->assertPrivilege(Privilege::ADD_POST_NOTES);
|
||||
|
||||
$formData = new PostNoteFormData($this->inputReader);
|
||||
$postNote = $this->postNotesService->createPostNote($post, $formData);
|
||||
return $this->postNoteViewProxy->fromEntity($postNote);
|
||||
}
|
||||
|
||||
public function editPostNote($postNoteId)
|
||||
{
|
||||
$postNote = $this->postNotesService->getById($postNoteId);
|
||||
|
||||
$this->privilegeService->assertPrivilege(Privilege::EDIT_POST_NOTES);
|
||||
|
||||
$formData = new PostNoteFormData($this->inputReader);
|
||||
$postNote = $this->postNotesService->updatePostNote($postNote, $formData);
|
||||
return $this->postNoteViewProxy->fromEntity($postNote);
|
||||
}
|
||||
|
||||
public function deletePostNote($postNoteId)
|
||||
{
|
||||
$postNote = $this->postNotesService->getById($postNoteId);
|
||||
$this->privilegeService->assertPrivilege(Privilege::DELETE_POST_NOTES);
|
||||
return $this->postNotesService->deletePostNote($postNote);
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
use Szurubooru\Entities\Entity;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Router;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\CommentService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\Services\ScoreService;
|
||||
|
||||
final class ScoreController extends AbstractController
|
||||
{
|
||||
private $privilegeService;
|
||||
private $authService;
|
||||
private $postService;
|
||||
private $commentService;
|
||||
private $scoreService;
|
||||
private $inputReader;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
AuthService $authService,
|
||||
PostService $postService,
|
||||
CommentService $commentService,
|
||||
ScoreService $scoreService,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->authService = $authService;
|
||||
$this->postService = $postService;
|
||||
$this->commentService = $commentService;
|
||||
$this->scoreService = $scoreService;
|
||||
$this->inputReader = $inputReader;
|
||||
}
|
||||
|
||||
public function registerRoutes(Router $router)
|
||||
{
|
||||
$router->get('/api/posts/:postNameOrId/score', [$this, 'getPostScore']);
|
||||
$router->post('/api/posts/:postNameOrId/score', [$this, 'setPostScore']);
|
||||
$router->get('/api/comments/:commentId/score', [$this, 'getCommentScore']);
|
||||
$router->post('/api/comments/:commentId/score', [$this, 'setCommentScore']);
|
||||
}
|
||||
|
||||
public function getPostScore($postNameOrId)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
return $this->getScore($post);
|
||||
}
|
||||
|
||||
public function setPostScore($postNameOrId)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
return $this->setScore($post);
|
||||
}
|
||||
|
||||
public function getCommentScore($commentId)
|
||||
{
|
||||
$comment = $this->commentService->getById($commentId);
|
||||
return $this->getScore($comment);
|
||||
}
|
||||
|
||||
public function setCommentScore($commentId)
|
||||
{
|
||||
$comment = $this->commentService->getById($commentId);
|
||||
return $this->setScore($comment);
|
||||
}
|
||||
|
||||
private function setScore(Entity $entity)
|
||||
{
|
||||
$this->privilegeService->assertLoggedIn();
|
||||
$score = intval($this->inputReader->score);
|
||||
$user = $this->authService->getLoggedInUser();
|
||||
$result = $this->scoreService->setUserScore($user, $entity, $score);
|
||||
return [
|
||||
'score' => $this->scoreService->getScoreValue($entity),
|
||||
'ownScore' => $result->getScore(),
|
||||
];
|
||||
}
|
||||
|
||||
private function getScore(Entity $entity)
|
||||
{
|
||||
$user = $this->authService->getLoggedInUser();
|
||||
return [
|
||||
'score' => $this->scoreService->getScoreValue($entity),
|
||||
'ownScore' => $this->scoreService->getUserScoreValue($user, $entity),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
use Szurubooru\Controllers\ViewProxies\TagViewProxy;
|
||||
use Szurubooru\FormData\TagEditFormData;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Router;
|
||||
use Szurubooru\SearchServices\Parsers\TagSearchParser;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\Services\TagService;
|
||||
|
||||
final class TagController extends AbstractController
|
||||
{
|
||||
private $privilegeService;
|
||||
private $tagService;
|
||||
private $tagViewProxy;
|
||||
private $tagSearchParser;
|
||||
private $inputReader;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
TagService $tagService,
|
||||
TagViewProxy $tagViewProxy,
|
||||
TagSearchParser $tagSearchParser,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->tagService = $tagService;
|
||||
$this->tagViewProxy = $tagViewProxy;
|
||||
$this->tagSearchParser = $tagSearchParser;
|
||||
$this->inputReader = $inputReader;
|
||||
}
|
||||
|
||||
public function registerRoutes(Router $router)
|
||||
{
|
||||
$router->get('/api/tags', [$this, 'getTags']);
|
||||
$router->get('/api/tags/:tagName', [$this, 'getTag']);
|
||||
$router->get('/api/tags/:tagName/siblings', [$this, 'getTagSiblings']);
|
||||
$router->put('/api/tags/:tagName', [$this, 'updateTag']);
|
||||
$router->put('/api/tags/:tagName/merge', [$this, 'mergeTag']);
|
||||
$router->delete('/api/tags/:tagName', [$this, 'deleteTag']);
|
||||
}
|
||||
|
||||
public function getTag($tagName)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::LIST_TAGS);
|
||||
|
||||
$tag = $this->tagService->getByName($tagName);
|
||||
return $this->tagViewProxy->fromEntity($tag, $this->getFullFetchConfig());
|
||||
}
|
||||
|
||||
public function getTags()
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::LIST_TAGS);
|
||||
|
||||
$filter = $this->tagSearchParser->createFilterFromInputReader($this->inputReader);
|
||||
$filter->setPageSize(50);
|
||||
|
||||
$result = $this->tagService->getFiltered($filter);
|
||||
$entities = $this->tagViewProxy->fromArray($result->getEntities(), $this->getFullFetchConfig());
|
||||
return [
|
||||
'data' => $entities,
|
||||
'pageSize' => $result->getPageSize(),
|
||||
'totalRecords' => $result->getTotalRecords()];
|
||||
}
|
||||
|
||||
public function getTagSiblings($tagName)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::LIST_TAGS);
|
||||
$tag = $this->tagService->getByName($tagName);
|
||||
$result = $this->tagService->getSiblings($tagName);
|
||||
$entities = $this->tagViewProxy->fromArray($result);
|
||||
return [
|
||||
'data' => $entities,
|
||||
];
|
||||
}
|
||||
|
||||
public function updateTag($tagName)
|
||||
{
|
||||
$tag = $this->tagService->getByName($tagName);
|
||||
$formData = new TagEditFormData($this->inputReader);
|
||||
|
||||
if ($formData->name !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_TAG_NAME);
|
||||
|
||||
if ($formData->category !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_TAG_CATEGORY);
|
||||
|
||||
if ($formData->banned !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::BAN_TAGS);
|
||||
|
||||
if ($formData->implications !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_TAG_IMPLICATIONS);
|
||||
|
||||
if ($formData->suggestions !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_TAG_SUGGESTIONS);
|
||||
|
||||
$tag = $this->tagService->updateTag($tag, $formData);
|
||||
return $this->tagViewProxy->fromEntity($tag, $this->getFullFetchConfig());
|
||||
}
|
||||
|
||||
public function deleteTag($tagName)
|
||||
{
|
||||
$tag = $this->tagService->getByName($tagName);
|
||||
$this->privilegeService->assertPrivilege(Privilege::DELETE_TAGS);
|
||||
return $this->tagService->deleteTag($tag);
|
||||
}
|
||||
|
||||
public function mergeTag($tagName)
|
||||
{
|
||||
$targetTagName = $this->inputReader->targetTag;
|
||||
$sourceTag = $this->tagService->getByName($tagName);
|
||||
$targetTag = $this->tagService->getByName($targetTagName);
|
||||
$this->privilegeService->assertPrivilege(Privilege::MERGE_TAGS);
|
||||
return $this->tagService->mergeTag($sourceTag, $targetTag);
|
||||
}
|
||||
|
||||
private function getFullFetchConfig()
|
||||
{
|
||||
return
|
||||
[
|
||||
TagViewProxy::FETCH_IMPLICATIONS => true,
|
||||
TagViewProxy::FETCH_SUGGESTIONS => true,
|
||||
TagViewProxy::FETCH_HISTORY => true,
|
||||
];
|
||||
}
|
||||
}
|
@ -1,176 +0,0 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
use Szurubooru\Config;
|
||||
use Szurubooru\Controllers\ViewProxies\UserViewProxy;
|
||||
use Szurubooru\FormData\RegistrationFormData;
|
||||
use Szurubooru\FormData\UserEditFormData;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Router;
|
||||
use Szurubooru\SearchServices\Parsers\UserSearchParser;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\Services\TokenService;
|
||||
use Szurubooru\Services\UserService;
|
||||
|
||||
final class UserController extends AbstractController
|
||||
{
|
||||
private $config;
|
||||
private $privilegeService;
|
||||
private $userService;
|
||||
private $tokenService;
|
||||
private $userSearchParser;
|
||||
private $inputReader;
|
||||
private $userViewProxy;
|
||||
|
||||
public function __construct(
|
||||
Config $config,
|
||||
PrivilegeService $privilegeService,
|
||||
UserService $userService,
|
||||
TokenService $tokenService,
|
||||
UserSearchParser $userSearchParser,
|
||||
InputReader $inputReader,
|
||||
UserViewProxy $userViewProxy)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->userService = $userService;
|
||||
$this->tokenService = $tokenService;
|
||||
$this->userSearchParser = $userSearchParser;
|
||||
$this->inputReader = $inputReader;
|
||||
$this->userViewProxy = $userViewProxy;
|
||||
}
|
||||
|
||||
public function registerRoutes(Router $router)
|
||||
{
|
||||
$router->post('/api/users', [$this, 'createUser']);
|
||||
$router->get('/api/users', [$this, 'getFiltered']);
|
||||
$router->get('/api/users/:userNameOrEmail', [$this, 'getByNameOrEmail']);
|
||||
$router->put('/api/users/:userNameOrEmail', [$this, 'updateUser']);
|
||||
$router->delete('/api/users/:userNameOrEmail', [$this, 'deleteUser']);
|
||||
$router->post('/api/password-reset/:userNameOrEmail', [$this, 'passwordReset']);
|
||||
$router->post('/api/finish-password-reset/:tokenName', [$this, 'finishPasswordReset']);
|
||||
$router->post('/api/activation/:userNameOrEmail', [$this, 'activation']);
|
||||
$router->post('/api/finish-activation/:tokenName', [$this, 'finishActivation']);
|
||||
}
|
||||
|
||||
public function getByNameOrEmail($userNameOrEmail)
|
||||
{
|
||||
if (!$this->privilegeService->isLoggedIn($userNameOrEmail))
|
||||
$this->privilegeService->assertPrivilege(Privilege::VIEW_USERS);
|
||||
$user = $this->userService->getByNameOrEmail($userNameOrEmail);
|
||||
return $this->userViewProxy->fromEntity($user);
|
||||
}
|
||||
|
||||
public function getFiltered()
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::LIST_USERS);
|
||||
|
||||
$filter = $this->userSearchParser->createFilterFromInputReader($this->inputReader);
|
||||
$filter->setPageSize($this->config->users->usersPerPage);
|
||||
$result = $this->userService->getFiltered($filter);
|
||||
$entities = $this->userViewProxy->fromArray($result->getEntities());
|
||||
return [
|
||||
'data' => $entities,
|
||||
'pageSize' => $result->getPageSize(),
|
||||
'totalRecords' => $result->getTotalRecords()];
|
||||
}
|
||||
|
||||
public function createUser()
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::REGISTER);
|
||||
$formData = new RegistrationFormData($this->inputReader);
|
||||
$user = $this->userService->createUser($formData);
|
||||
return $this->userViewProxy->fromEntity($user);
|
||||
}
|
||||
|
||||
public function updateUser($userNameOrEmail)
|
||||
{
|
||||
$user = $this->userService->getByNameOrEmail($userNameOrEmail);
|
||||
$formData = new UserEditFormData($this->inputReader);
|
||||
|
||||
if ($formData->avatarStyle !== null || $formData->avatarContent !== null)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(
|
||||
$this->privilegeService->isLoggedIn($userNameOrEmail)
|
||||
? Privilege::CHANGE_OWN_AVATAR_STYLE
|
||||
: Privilege::CHANGE_ALL_AVATAR_STYLES);
|
||||
}
|
||||
|
||||
if ($formData->userName !== null)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(
|
||||
$this->privilegeService->isLoggedIn($userNameOrEmail)
|
||||
? Privilege::CHANGE_OWN_NAME
|
||||
: Privilege::CHANGE_ALL_NAMES);
|
||||
}
|
||||
|
||||
if ($formData->password !== null)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(
|
||||
$this->privilegeService->isLoggedIn($userNameOrEmail)
|
||||
? Privilege::CHANGE_OWN_PASSWORD
|
||||
: Privilege::CHANGE_ALL_PASSWORDS);
|
||||
}
|
||||
|
||||
if ($formData->email !== null)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(
|
||||
$this->privilegeService->isLoggedIn($userNameOrEmail)
|
||||
? Privilege::CHANGE_OWN_EMAIL_ADDRESS
|
||||
: Privilege::CHANGE_ALL_EMAIL_ADDRESSES);
|
||||
}
|
||||
|
||||
if ($formData->accessRank)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_ACCESS_RANK);
|
||||
}
|
||||
|
||||
if ($formData->browsingSettings)
|
||||
{
|
||||
$this->privilegeService->assertLoggedIn($userNameOrEmail);
|
||||
}
|
||||
|
||||
if ($formData->banned !== null)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::BAN_USERS);
|
||||
}
|
||||
|
||||
$user = $this->userService->updateUser($user, $formData);
|
||||
return $this->userViewProxy->fromEntity($user);
|
||||
}
|
||||
|
||||
public function deleteUser($userNameOrEmail)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(
|
||||
$this->privilegeService->isLoggedIn($userNameOrEmail)
|
||||
? Privilege::DELETE_OWN_ACCOUNT
|
||||
: Privilege::DELETE_ACCOUNTS);
|
||||
|
||||
$user = $this->userService->getByNameOrEmail($userNameOrEmail);
|
||||
return $this->userService->deleteUser($user);
|
||||
}
|
||||
|
||||
public function passwordReset($userNameOrEmail)
|
||||
{
|
||||
$user = $this->userService->getByNameOrEmail($userNameOrEmail);
|
||||
return $this->userService->sendPasswordResetEmail($user);
|
||||
}
|
||||
|
||||
public function activation($userNameOrEmail)
|
||||
{
|
||||
$user = $this->userService->getByNameOrEmail($userNameOrEmail, true);
|
||||
return $this->userService->sendActivationEmail($user);
|
||||
}
|
||||
|
||||
public function finishPasswordReset($tokenName)
|
||||
{
|
||||
$token = $this->tokenService->getByName($tokenName);
|
||||
return ['newPassword' => $this->userService->finishPasswordReset($token)];
|
||||
}
|
||||
|
||||
public function finishActivation($tokenName)
|
||||
{
|
||||
$token = $this->tokenService->getByName($tokenName);
|
||||
$this->userService->finishActivation($token);
|
||||
}
|
||||
}
|
@ -3,12 +3,12 @@ namespace Szurubooru\Dao;
|
||||
use Szurubooru\Dao\EntityConverters\IEntityConverter;
|
||||
use Szurubooru\DatabaseConnection;
|
||||
use Szurubooru\Entities\Entity;
|
||||
use Szurubooru\SearchServices\Filters\IFilter;
|
||||
use Szurubooru\SearchServices\Requirements\Requirement;
|
||||
use Szurubooru\SearchServices\Requirements\RequirementCompositeValue;
|
||||
use Szurubooru\SearchServices\Requirements\RequirementRangedValue;
|
||||
use Szurubooru\SearchServices\Requirements\RequirementSingleValue;
|
||||
use Szurubooru\SearchServices\Result;
|
||||
use Szurubooru\Search\Filters\IFilter;
|
||||
use Szurubooru\Search\Requirements\Requirement;
|
||||
use Szurubooru\Search\Requirements\RequirementCompositeValue;
|
||||
use Szurubooru\Search\Requirements\RequirementRangedValue;
|
||||
use Szurubooru\Search\Requirements\RequirementSingleValue;
|
||||
use Szurubooru\Search\Result;
|
||||
|
||||
abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||
{
|
||||
@ -137,7 +137,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||
$query->execute();
|
||||
$lastUsedId = $this->pdo->query('SELECT @lastUsedId')->fetchColumn();
|
||||
|
||||
$entity->setId($lastUsedId);
|
||||
$entity->setId(intval($lastUsedId));
|
||||
$arrayEntity = $this->entityConverter->toArray($entity);
|
||||
$this->pdo->insertInto($this->tableName)->values($arrayEntity)->execute();
|
||||
return $entity;
|
||||
|
@ -42,6 +42,6 @@ abstract class AbstractEntityConverter implements IEntityConverter
|
||||
|
||||
protected function entityTimeToDbTime($time)
|
||||
{
|
||||
return $time;
|
||||
return $time === null ? null : date('Y-m-d H:i:s', strtotime($time));
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class CommentEntityConverter extends AbstractEntityConverter implements IEntityC
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Comment($array['id']);
|
||||
$entity = new Comment(intval($array['id']));
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setText($array['text']);
|
||||
|
@ -17,7 +17,7 @@ class FavoriteEntityConverter extends AbstractEntityConverter implements IEntity
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Favorite($array['id']);
|
||||
$entity = new Favorite(intval($array['id']));
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setTime($this->dbTimeToEntityTime($array['time']));
|
||||
|
@ -16,7 +16,7 @@ class GlobalParamEntityConverter extends AbstractEntityConverter implements IEnt
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new GlobalParam($array['id']);
|
||||
$entity = new GlobalParam(intval($array['id']));
|
||||
$entity->setKey($array['dataKey']);
|
||||
$entity->setValue($array['dataValue']);
|
||||
return $entity;
|
||||
|
@ -20,7 +20,7 @@ class PostNoteEntityConverter extends AbstractEntityConverter implements IEntity
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new PostNote($array['id']);
|
||||
$entity = new PostNote(intval($array['id']));
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setLeft(floatval($array['x']));
|
||||
$entity->setTop(floatval($array['y']));
|
||||
|
@ -19,7 +19,7 @@ class ScoreEntityConverter extends AbstractEntityConverter implements IEntityCon
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Score($array['id']);
|
||||
$entity = new Score(intval($array['id']));
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setCommentId($array['commentId']);
|
||||
|
@ -14,8 +14,8 @@ class SnapshotEntityConverter extends AbstractEntityConverter implements IEntity
|
||||
'primaryKey' => $entity->getPrimaryKey(),
|
||||
'userId' => $entity->getUserId(),
|
||||
'operation' => $entity->getOperation(),
|
||||
'data' => json_encode($entity->getData()),
|
||||
'dataDifference' => json_encode($entity->getDataDifference()),
|
||||
'data' => gzdeflate(json_encode($entity->getData())),
|
||||
'dataDifference' => gzdeflate(json_encode($entity->getDataDifference())),
|
||||
];
|
||||
}
|
||||
|
||||
@ -25,10 +25,10 @@ class SnapshotEntityConverter extends AbstractEntityConverter implements IEntity
|
||||
$entity->setTime($this->dbTimeToEntityTime($array['time']));
|
||||
$entity->setType(intval($array['type']));
|
||||
$entity->setPrimaryKey($array['primaryKey']);
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setUserId(intval($array['userId']));
|
||||
$entity->setOperation($array['operation']);
|
||||
$entity->setData(json_decode($array['data'], true));
|
||||
$entity->setDataDifference(json_decode($array['dataDifference'], true));
|
||||
$entity->setData(json_decode(gzinflate($array['data']), true));
|
||||
$entity->setDataDifference(json_decode(gzinflate($array['dataDifference']), true));
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
@ -11,14 +11,14 @@ class TagEntityConverter extends AbstractEntityConverter implements IEntityConve
|
||||
[
|
||||
'name' => $entity->getName(),
|
||||
'creationTime' => $this->entityTimeToDbTime($entity->getCreationTime()),
|
||||
'banned' => $entity->isBanned(),
|
||||
'banned' => intval($entity->isBanned()),
|
||||
'category' => $entity->getCategory(),
|
||||
];
|
||||
}
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Tag($array['id']);
|
||||
$entity = new Tag(intval($array['id']));
|
||||
$entity->setName($array['name']);
|
||||
$entity->setCreationTime($this->dbTimeToEntityTime($array['creationTime']));
|
||||
$entity->setMeta(Tag::META_USAGES, intval($array['usages']));
|
||||
|
@ -19,8 +19,8 @@ class UserEntityConverter extends AbstractEntityConverter implements IEntityConv
|
||||
'lastLoginTime' => $this->entityTimeToDbTime($entity->getLastLoginTime()),
|
||||
'avatarStyle' => $entity->getAvatarStyle(),
|
||||
'browsingSettings' => json_encode($entity->getBrowsingSettings()),
|
||||
'accountConfirmed' => $entity->isAccountConfirmed(),
|
||||
'banned' => $entity->isBanned(),
|
||||
'accountConfirmed' => intval($entity->isAccountConfirmed()),
|
||||
'banned' => intval($entity->isBanned()),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,8 @@ use Szurubooru\Dao\UserDao;
|
||||
use Szurubooru\DatabaseConnection;
|
||||
use Szurubooru\Entities\Entity;
|
||||
use Szurubooru\Entities\Post;
|
||||
use Szurubooru\SearchServices\Filters\PostFilter;
|
||||
use Szurubooru\SearchServices\Requirements\Requirement;
|
||||
use Szurubooru\Search\Filters\PostFilter;
|
||||
use Szurubooru\Search\Requirements\Requirement;
|
||||
use Szurubooru\Services\ThumbnailService;
|
||||
|
||||
class PostDao extends AbstractDao implements ICrudDao
|
||||
@ -44,7 +44,7 @@ class PostDao extends AbstractDao implements ICrudDao
|
||||
public function getTotalFileSize()
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName)->select('SUM(originalFileSize) AS __sum');
|
||||
return intval(iterator_to_array($query)[0]['__sum']);
|
||||
return iterator_to_array($query)[0]['__sum'];
|
||||
}
|
||||
|
||||
public function findByName($name)
|
||||
|
@ -22,13 +22,17 @@ class SnapshotDao extends AbstractDao
|
||||
$this->userDao = $userDao;
|
||||
}
|
||||
|
||||
public function findByTypeAndKey($type, $primaryKey)
|
||||
public function findEarlierSnapshots(Snapshot $snapshot)
|
||||
{
|
||||
$query = $this->pdo
|
||||
->from($this->tableName)
|
||||
->where('type', $type)
|
||||
->where('primaryKey', $primaryKey)
|
||||
->where('type', $snapshot->getType())
|
||||
->where('primaryKey', $snapshot->getPrimaryKey())
|
||||
->orderBy('time DESC');
|
||||
|
||||
if ($snapshot->getId())
|
||||
$query->where('id < ?', $snapshot->getId());
|
||||
|
||||
return $this->arrayToEntities(iterator_to_array($query));
|
||||
}
|
||||
|
||||
@ -44,7 +48,7 @@ class SnapshotDao extends AbstractDao
|
||||
|
||||
private function getUser(Snapshot $snapshot)
|
||||
{
|
||||
$userId = $snapshot->getUserId();
|
||||
$userId = $snapshot->getUserId();
|
||||
return $this->userDao->findById($userId);
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ use Szurubooru\Dao\EntityConverters\TagEntityConverter;
|
||||
use Szurubooru\DatabaseConnection;
|
||||
use Szurubooru\Entities\Entity;
|
||||
use Szurubooru\Entities\Tag;
|
||||
use Szurubooru\SearchServices\Filters\TagFilter;
|
||||
use Szurubooru\SearchServices\Requirements\Requirement;
|
||||
use Szurubooru\Search\Filters\TagFilter;
|
||||
use Szurubooru\Search\Requirements\Requirement;
|
||||
|
||||
class TagDao extends AbstractDao implements ICrudDao
|
||||
{
|
||||
|
@ -2,7 +2,6 @@
|
||||
namespace Szurubooru;
|
||||
use Szurubooru\Bootstrap;
|
||||
use Szurubooru\Config;
|
||||
use Szurubooru\ControllerRepository;
|
||||
use Szurubooru\DatabaseConnection;
|
||||
use Szurubooru\Helpers\HttpHelper;
|
||||
use Szurubooru\Router;
|
||||
@ -24,7 +23,7 @@ final class Dispatcher
|
||||
HttpHelper $httpHelper,
|
||||
AuthService $authService,
|
||||
TokenService $tokenService,
|
||||
ControllerRepository $controllerRepository)
|
||||
RouteRepository $routeRepository)
|
||||
{
|
||||
$this->router = $router;
|
||||
$this->config = $config;
|
||||
@ -36,8 +35,7 @@ final class Dispatcher
|
||||
//if script fails prematurely, mark it as fail from advance
|
||||
$this->httpHelper->setResponseCode(500);
|
||||
|
||||
foreach ($controllerRepository->getControllers() as $controller)
|
||||
$controller->registerRoutes($router);
|
||||
$routeRepository->injectRoutes($router);
|
||||
}
|
||||
|
||||
public function run($requestMethod, $requestUri)
|
||||
|
@ -20,8 +20,8 @@ class PostEditFormData implements IValidatable
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->content = $inputReader->decodeBase64($inputReader->content);
|
||||
$this->thumbnail = $inputReader->decodeBase64($inputReader->thumbnail);
|
||||
$this->content = $inputReader->readFile('content');
|
||||
$this->thumbnail = $inputReader->readFile('thumbnail');
|
||||
if ($inputReader->safety)
|
||||
$this->safety = EnumHelper::postSafetyFromString($inputReader->safety);
|
||||
if ($inputReader->source !== null)
|
||||
@ -31,7 +31,7 @@ class PostEditFormData implements IValidatable
|
||||
$this->relations = array_filter(preg_split('/[\s+]/', $inputReader->relations));
|
||||
$this->seenEditTime = $inputReader->seenEditTime;
|
||||
$this->flags = new \StdClass;
|
||||
$this->flags->loop = !empty($inputReader->flags['loop']);
|
||||
$this->flags->loop = !empty($inputReader->loop);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ class UploadFormData implements IValidatable
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->contentFileName = $inputReader->contentFileName;
|
||||
$this->content = $inputReader->decodeBase64($inputReader->content);
|
||||
$this->content = $inputReader->readFile('content');
|
||||
$this->url = $inputReader->url;
|
||||
$this->anonymous = $inputReader->anonymous;
|
||||
$this->safety = EnumHelper::postSafetyFromString($inputReader->safety);
|
||||
|
@ -27,7 +27,7 @@ class UserEditFormData implements IValidatable
|
||||
$this->accessRank = EnumHelper::accessRankFromString($inputReader->accessRank);
|
||||
if ($inputReader->avatarStyle !== null)
|
||||
$this->avatarStyle = EnumHelper::avatarStyleFromString($inputReader->avatarStyle);
|
||||
$this->avatarContent = $inputReader->decodeBase64($inputReader->avatarContent);
|
||||
$this->avatarContent = $inputReader->readFile('avatarContent');
|
||||
$this->browsingSettings = json_decode($inputReader->browsingSettings);
|
||||
if ($inputReader->banned !== null)
|
||||
$this->banned = boolval($inputReader->banned);
|
||||
|
@ -25,13 +25,11 @@ final class InputReader extends \ArrayObject
|
||||
return parent::offsetGet($index);
|
||||
}
|
||||
|
||||
public function decodeBase64($base64string)
|
||||
public function readFile($fileName)
|
||||
{
|
||||
if ($base64string === null)
|
||||
if (!isset($_FILES[$fileName]))
|
||||
return null;
|
||||
$commaPosition = strpos($base64string, ',');
|
||||
if ($commaPosition !== null)
|
||||
$base64string = substr($base64string, $commaPosition + 1);
|
||||
return base64_decode($base64string);
|
||||
|
||||
return file_get_contents($_FILES[$fileName]['tmp_name']);
|
||||
}
|
||||
}
|
||||
|
@ -1,51 +0,0 @@
|
||||
<?php
|
||||
namespace Szurubooru;
|
||||
|
||||
final class Route
|
||||
{
|
||||
public $query;
|
||||
public $route;
|
||||
|
||||
public function __construct($query, callable $route)
|
||||
{
|
||||
$this->query = $query;
|
||||
$this->route = $route;
|
||||
$this->regex = $this->getRegex();
|
||||
}
|
||||
|
||||
public function handle($query, &$output)
|
||||
{
|
||||
$query = trim($query, '/');
|
||||
if (!preg_match($this->regex, $query, $matches))
|
||||
return false;
|
||||
$routeArguments = $this->getRouteArguments($matches);
|
||||
$func = $this->route;
|
||||
$output = $func(...array_values($routeArguments));
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getRegex()
|
||||
{
|
||||
$quotedQuery = preg_quote(trim($this->query, '/'), '/');
|
||||
return '/^' . preg_replace('/\\\?\:([a-zA-Z_-]*)/', '(?P<\1>[^\/]+)', $quotedQuery) . '$/i';
|
||||
}
|
||||
|
||||
private function getRouteArguments($matches)
|
||||
{
|
||||
$reflectionFunction = is_array($this->route)
|
||||
? new \ReflectionMethod($this->route[0], $this->route[1])
|
||||
: new \ReflectionFunction($this->route);
|
||||
$arguments = [];
|
||||
foreach ($reflectionFunction->getParameters() as $reflectionParameter)
|
||||
{
|
||||
$key = $reflectionParameter->name;
|
||||
if (isset($matches[$key]))
|
||||
$arguments[$key] = $matches[$key];
|
||||
elseif ($reflectionParameter->isDefaultValueAvailable())
|
||||
$arguments[$key] = $reflectionParameter->getDefaultValue();
|
||||
else
|
||||
$arguments[$key] = null;
|
||||
}
|
||||
return $arguments;
|
||||
}
|
||||
}
|
29
src/RouteRepository.php
Normal file
29
src/RouteRepository.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Szurubooru;
|
||||
|
||||
class RouteRepository
|
||||
{
|
||||
private $routes = [];
|
||||
|
||||
public function __construct(array $routes)
|
||||
{
|
||||
$this->routes = $routes;
|
||||
}
|
||||
|
||||
public function getRoutes()
|
||||
{
|
||||
return $this->routes;
|
||||
}
|
||||
|
||||
public function injectRoutes(Router $router)
|
||||
{
|
||||
foreach ($this->routes as $route)
|
||||
{
|
||||
foreach ($route->getMethods() as $method)
|
||||
{
|
||||
$method = strtolower($method);
|
||||
$router->$method($route->getUrl(), [$route, 'work']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,29 +5,24 @@ class Router
|
||||
{
|
||||
private $routes;
|
||||
|
||||
public function get($query, callable $route)
|
||||
public function get($url, callable $function)
|
||||
{
|
||||
$this->route('GET', $query, $route);
|
||||
$this->inject('GET', $url, $function);
|
||||
}
|
||||
|
||||
public function put($query, callable $route)
|
||||
public function post($url, callable $function)
|
||||
{
|
||||
$this->route('PUT', $query, $route);
|
||||
$this->inject('POST', $url, $function);
|
||||
}
|
||||
|
||||
public function delete($query, callable $route)
|
||||
public function put($url, callable $function)
|
||||
{
|
||||
$this->route('DELETE', $query, $route);
|
||||
$this->inject('PUT', $url, $function);
|
||||
}
|
||||
|
||||
public function post($query, callable $route)
|
||||
public function delete($url, callable $function)
|
||||
{
|
||||
$this->route('POST', $query, $route);
|
||||
}
|
||||
|
||||
private function route($method, $query, callable $route)
|
||||
{
|
||||
$this->routes[$method][] = new Route($query, $route);
|
||||
$this->inject('DELETE', $url, $function);
|
||||
}
|
||||
|
||||
public function handle($method, $request)
|
||||
@ -35,14 +30,28 @@ class Router
|
||||
if (!isset($this->routes[$method]))
|
||||
throw new \DomainException('Unhandled request method: ' . $method);
|
||||
|
||||
foreach ($this->routes[$method] as $route)
|
||||
$request = trim($request, '/');
|
||||
foreach ($this->routes[$method] as $url => $callback)
|
||||
{
|
||||
if ($route->handle($request, $output))
|
||||
{
|
||||
return $output;
|
||||
}
|
||||
if (!preg_match(self::getRegex($url), $request, $matches))
|
||||
continue;
|
||||
|
||||
return $callback($matches);
|
||||
}
|
||||
|
||||
throw new \DomainException('Unhandled request address: ' . $request);
|
||||
}
|
||||
|
||||
private function inject($method, $url, callable $function)
|
||||
{
|
||||
if (!isset($this->routes[$method]))
|
||||
$this->routes[$method] = [];
|
||||
$this->routes[$method][$url] = $function;
|
||||
}
|
||||
|
||||
private static function getRegex($url)
|
||||
{
|
||||
$quotedQuery = preg_quote(trim($url, '/'), '/');
|
||||
return '/^' . preg_replace('/\\\?\:([a-zA-Z_-]*)/', '(?P<\1>[^\/]+)', $quotedQuery) . '$/i';
|
||||
}
|
||||
}
|
||||
|
11
src/Routes/AbstractRoute.php
Normal file
11
src/Routes/AbstractRoute.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes;
|
||||
|
||||
abstract class AbstractRoute
|
||||
{
|
||||
public abstract function getMethods();
|
||||
|
||||
public abstract function getUrl();
|
||||
|
||||
public abstract function work($args);
|
||||
}
|
15
src/Routes/Comments/AbstractCommentRoute.php
Normal file
15
src/Routes/Comments/AbstractCommentRoute.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Comments;
|
||||
use Szurubooru\Routes\AbstractRoute;
|
||||
use Szurubooru\ViewProxies\CommentViewProxy;
|
||||
|
||||
abstract class AbstractCommentRoute extends AbstractRoute
|
||||
{
|
||||
protected function getCommentsFetchConfig()
|
||||
{
|
||||
return
|
||||
[
|
||||
CommentViewProxy::FETCH_OWN_SCORE => true,
|
||||
];
|
||||
}
|
||||
}
|
54
src/Routes/Comments/AddComment.php
Normal file
54
src/Routes/Comments/AddComment.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Comments;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Services\CommentService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\CommentViewProxy;
|
||||
use Szurubooru\ViewProxies\PostViewProxy;
|
||||
|
||||
class AddComment extends AbstractCommentRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
private $commentService;
|
||||
private $commentViewProxy;
|
||||
private $postViewProxy;
|
||||
private $inputReader;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService,
|
||||
CommentService $commentService,
|
||||
CommentViewProxy $commentViewProxy,
|
||||
PostViewProxy $postViewProxy,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
$this->commentService = $commentService;
|
||||
$this->commentViewProxy = $commentViewProxy;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
$this->inputReader = $inputReader;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['POST'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/comments/:postNameOrId';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::ADD_COMMENTS);
|
||||
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
$comment = $this->commentService->createComment($post, $this->inputReader->text);
|
||||
return $this->commentViewProxy->fromEntity($comment, $this->getCommentsFetchConfig());
|
||||
}
|
||||
}
|
57
src/Routes/Comments/DeleteComment.php
Normal file
57
src/Routes/Comments/DeleteComment.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Comments;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Services\CommentService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\CommentViewProxy;
|
||||
use Szurubooru\ViewProxies\PostViewProxy;
|
||||
|
||||
class DeleteComment extends AbstractCommentRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
private $commentService;
|
||||
private $commentViewProxy;
|
||||
private $postViewProxy;
|
||||
private $inputReader;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService,
|
||||
CommentService $commentService,
|
||||
CommentViewProxy $commentViewProxy,
|
||||
PostViewProxy $postViewProxy,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
$this->commentService = $commentService;
|
||||
$this->commentViewProxy = $commentViewProxy;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
$this->inputReader = $inputReader;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['DELETE'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/comments/:commentId';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$comment = $this->commentService->getById($args['commentId']);
|
||||
|
||||
$this->privilegeService->assertPrivilege(
|
||||
$this->privilegeService->isLoggedIn($comment->getUser())
|
||||
? Privilege::DELETE_OWN_COMMENTS
|
||||
: Privilege::DELETE_ALL_COMMENTS);
|
||||
|
||||
return $this->commentService->deleteComment($comment);
|
||||
}
|
||||
}
|
58
src/Routes/Comments/EditComment.php
Normal file
58
src/Routes/Comments/EditComment.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Comments;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Services\CommentService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\CommentViewProxy;
|
||||
use Szurubooru\ViewProxies\PostViewProxy;
|
||||
|
||||
class EditComment extends AbstractCommentRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
private $commentService;
|
||||
private $commentViewProxy;
|
||||
private $postViewProxy;
|
||||
private $inputReader;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService,
|
||||
CommentService $commentService,
|
||||
CommentViewProxy $commentViewProxy,
|
||||
PostViewProxy $postViewProxy,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
$this->commentService = $commentService;
|
||||
$this->commentViewProxy = $commentViewProxy;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
$this->inputReader = $inputReader;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['PUT'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/comments/:commentId';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$comment = $this->commentService->getById($args['commentId']);
|
||||
|
||||
$this->privilegeService->assertPrivilege(
|
||||
($comment->getUser() && $this->privilegeService->isLoggedIn($comment->getUser()))
|
||||
? Privilege::EDIT_OWN_COMMENTS
|
||||
: Privilege::EDIT_ALL_COMMENTS);
|
||||
|
||||
$comment = $this->commentService->updateComment($comment, $this->inputReader->text);
|
||||
return $this->commentViewProxy->fromEntity($comment, $this->getCommentsFetchConfig());
|
||||
}
|
||||
}
|
87
src/Routes/Comments/GetComments.php
Normal file
87
src/Routes/Comments/GetComments.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Comments;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Search\Filters\PostFilter;
|
||||
use Szurubooru\Search\Requirements\Requirement;
|
||||
use Szurubooru\Search\Requirements\RequirementRangedValue;
|
||||
use Szurubooru\Services\CommentService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\CommentViewProxy;
|
||||
use Szurubooru\ViewProxies\PostViewProxy;
|
||||
|
||||
class GetComments extends AbstractCommentRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
private $commentService;
|
||||
private $commentViewProxy;
|
||||
private $postViewProxy;
|
||||
private $inputReader;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService,
|
||||
CommentService $commentService,
|
||||
CommentViewProxy $commentViewProxy,
|
||||
PostViewProxy $postViewProxy,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
$this->commentService = $commentService;
|
||||
$this->commentViewProxy = $commentViewProxy;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
$this->inputReader = $inputReader;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/comments';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::LIST_COMMENTS);
|
||||
|
||||
$filter = new PostFilter();
|
||||
$filter->setPageSize(10);
|
||||
$filter->setPageNumber($this->inputReader->page);
|
||||
$filter->setOrder([
|
||||
PostFilter::ORDER_LAST_COMMENT_TIME =>
|
||||
PostFilter::ORDER_DESC]);
|
||||
|
||||
$this->postService->decorateFilterFromBrowsingSettings($filter);
|
||||
|
||||
$requirement = new Requirement();
|
||||
$requirement->setValue(new RequirementRangedValue());
|
||||
$requirement->getValue()->setMinValue(1);
|
||||
$requirement->setType(PostFilter::REQUIREMENT_COMMENT_COUNT);
|
||||
$filter->addRequirement($requirement);
|
||||
|
||||
$result = $this->postService->getFiltered($filter);
|
||||
$posts = $result->getEntities();
|
||||
|
||||
$data = [];
|
||||
foreach ($posts as $post)
|
||||
{
|
||||
$data[] = [
|
||||
'post' => $this->postViewProxy->fromEntity($post),
|
||||
'comments' => $this->commentViewProxy->fromArray(
|
||||
array_reverse($this->commentService->getByPost($post)),
|
||||
$this->getCommentsFetchConfig()),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'data' => $data,
|
||||
'pageSize' => $result->getPageSize(),
|
||||
'totalRecords' => $result->getTotalRecords()];
|
||||
}
|
||||
}
|
68
src/Routes/Comments/GetPostComments.php
Normal file
68
src/Routes/Comments/GetPostComments.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Comments;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Search\Filters\CommentFilter;
|
||||
use Szurubooru\Search\Requirements\Requirement;
|
||||
use Szurubooru\Search\Requirements\RequirementSingleValue;
|
||||
use Szurubooru\Services\CommentService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\CommentViewProxy;
|
||||
use Szurubooru\ViewProxies\PostViewProxy;
|
||||
|
||||
class GetPostComments extends AbstractCommentRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
private $commentService;
|
||||
private $commentViewProxy;
|
||||
private $postViewProxy;
|
||||
private $inputReader;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService,
|
||||
CommentService $commentService,
|
||||
CommentViewProxy $commentViewProxy,
|
||||
PostViewProxy $postViewProxy,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
$this->commentService = $commentService;
|
||||
$this->commentViewProxy = $commentViewProxy;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
$this->inputReader = $inputReader;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/comments/:postNameOrId';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::LIST_COMMENTS);
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
|
||||
$filter = new CommentFilter();
|
||||
$filter->setOrder([
|
||||
CommentFilter::ORDER_ID =>
|
||||
CommentFilter::ORDER_ASC]);
|
||||
|
||||
$requirement = new Requirement();
|
||||
$requirement->setValue(new RequirementSingleValue($post->getId()));
|
||||
$requirement->setType(CommentFilter::REQUIREMENT_POST_ID);
|
||||
$filter->addRequirement($requirement);
|
||||
|
||||
$result = $this->commentService->getFiltered($filter);
|
||||
$entities = $this->commentViewProxy->fromArray($result->getEntities(), $this->getCommentsFetchConfig());
|
||||
return ['data' => $entities];
|
||||
}
|
||||
}
|
52
src/Routes/Favorites/AddToFavorites.php
Normal file
52
src/Routes/Favorites/AddToFavorites.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Favorites;
|
||||
use Szurubooru\Routes\AbstractRoute;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\FavoritesService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\UserViewProxy;
|
||||
|
||||
class AddToFavorites extends AbstractRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $authService;
|
||||
private $postService;
|
||||
private $favoritesService;
|
||||
private $userViewProxy;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
AuthService $authService,
|
||||
PostService $postService,
|
||||
FavoritesService $favoritesService,
|
||||
UserViewProxy $userViewProxy)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->authService = $authService;
|
||||
$this->postService = $postService;
|
||||
$this->favoritesService = $favoritesService;
|
||||
$this->userViewProxy = $userViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['POST', 'PUT'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts/:postNameOrId/favorites';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertLoggedIn();
|
||||
$user = $this->authService->getLoggedInUser();
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
$this->favoritesService->addFavorite($user, $post);
|
||||
|
||||
$users = $this->favoritesService->getFavoriteUsers($post);
|
||||
return ['data' => $this->userViewProxy->fromArray($users)];
|
||||
}
|
||||
}
|
48
src/Routes/Favorites/GetFavoriteUsers.php
Normal file
48
src/Routes/Favorites/GetFavoriteUsers.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Favorites;
|
||||
use Szurubooru\Routes\AbstractRoute;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\FavoritesService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\UserViewProxy;
|
||||
|
||||
class GetFavoriteUsers extends AbstractRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $authService;
|
||||
private $postService;
|
||||
private $favoritesService;
|
||||
private $userViewProxy;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
AuthService $authService,
|
||||
PostService $postService,
|
||||
FavoritesService $favoritesService,
|
||||
UserViewProxy $userViewProxy)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->authService = $authService;
|
||||
$this->postService = $postService;
|
||||
$this->favoritesService = $favoritesService;
|
||||
$this->userViewProxy = $userViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts/:postNameOrId/favorites';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
$users = $this->favoritesService->getFavoriteUsers($post);
|
||||
return ['data' => $this->userViewProxy->fromArray($users)];
|
||||
}
|
||||
}
|
52
src/Routes/Favorites/RemoveFromFavorites.php
Normal file
52
src/Routes/Favorites/RemoveFromFavorites.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Favorites;
|
||||
use Szurubooru\Routes\AbstractRoute;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\FavoritesService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\UserViewProxy;
|
||||
|
||||
class RemoveFromFavorites extends AbstractRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $authService;
|
||||
private $postService;
|
||||
private $favoritesService;
|
||||
private $userViewProxy;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
AuthService $authService,
|
||||
PostService $postService,
|
||||
FavoritesService $favoritesService,
|
||||
UserViewProxy $userViewProxy)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->authService = $authService;
|
||||
$this->postService = $postService;
|
||||
$this->favoritesService = $favoritesService;
|
||||
$this->userViewProxy = $userViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['DELETE'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts/:postNameOrId/favorites';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertLoggedIn();
|
||||
$user = $this->authService->getLoggedInUser();
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
$this->favoritesService->deleteFavorite($user, $post);
|
||||
|
||||
$users = $this->favoritesService->getFavoriteUsers($post);
|
||||
return ['data' => $this->userViewProxy->fromArray($users)];
|
||||
}
|
||||
}
|
34
src/Routes/GetGlobals.php
Normal file
34
src/Routes/GetGlobals.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes;
|
||||
use Szurubooru\Dao\GlobalParamDao;
|
||||
|
||||
class GetGlobals extends AbstractRoute
|
||||
{
|
||||
private $globalParamDao;
|
||||
|
||||
public function __construct(GlobalParamDao $globalParamDao)
|
||||
{
|
||||
$this->globalParamDao = $globalParamDao;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/globals';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$globals = $this->globalParamDao->findAll();
|
||||
$result = [];
|
||||
foreach ($globals as $global)
|
||||
{
|
||||
$result[$global->getKey()] = $global->getValue();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
use Szurubooru\Controllers\ViewProxies\SnapshotViewProxy;
|
||||
namespace Szurubooru\Routes;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Router;
|
||||
use Szurubooru\SearchServices\Parsers\SnapshotSearchParser;
|
||||
use Szurubooru\Routes\AbstractRoute;
|
||||
use Szurubooru\Search\Parsers\SnapshotSearchParser;
|
||||
use Szurubooru\Services\HistoryService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\SnapshotViewProxy;
|
||||
|
||||
final class HistoryController extends AbstractController
|
||||
class GetHistory extends AbstractRoute
|
||||
{
|
||||
private $historyService;
|
||||
private $privilegeService;
|
||||
@ -30,12 +30,17 @@ final class HistoryController extends AbstractController
|
||||
$this->snapshotViewProxy = $snapshotViewProxy;
|
||||
}
|
||||
|
||||
public function registerRoutes(Router $router)
|
||||
public function getMethods()
|
||||
{
|
||||
$router->get('/api/history', [$this, 'getFiltered']);
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getFiltered()
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/history';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::VIEW_HISTORY);
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
use Szurubooru\Controllers\ViewProxies\TokenViewProxy;
|
||||
use Szurubooru\Controllers\ViewProxies\UserViewProxy;
|
||||
namespace Szurubooru\Routes;
|
||||
use Szurubooru\FormData\LoginFormData;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Router;
|
||||
@ -9,8 +7,10 @@ use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\Services\TokenService;
|
||||
use Szurubooru\Services\UserService;
|
||||
use Szurubooru\ViewProxies\TokenViewProxy;
|
||||
use Szurubooru\ViewProxies\UserViewProxy;
|
||||
|
||||
final class AuthController extends AbstractController
|
||||
class Login extends AbstractRoute
|
||||
{
|
||||
private $authService;
|
||||
private $userService;
|
||||
@ -38,13 +38,17 @@ final class AuthController extends AbstractController
|
||||
$this->tokenViewProxy = $tokenViewProxy;
|
||||
}
|
||||
|
||||
public function registerRoutes(Router $router)
|
||||
public function getMethods()
|
||||
{
|
||||
$router->post('/api/login', [$this, 'login']);
|
||||
$router->put('/api/login', [$this, 'login']);
|
||||
return ['POST', 'PUT'];
|
||||
}
|
||||
|
||||
public function login()
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/login';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
if (isset($this->inputReader->userNameOrEmail) && isset($this->inputReader->password))
|
||||
{
|
29
src/Routes/Posts/AbstractPostRoute.php
Normal file
29
src/Routes/Posts/AbstractPostRoute.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts;
|
||||
use Szurubooru\Routes\AbstractRoute;
|
||||
use Szurubooru\ViewProxies\PostViewProxy;
|
||||
|
||||
abstract class AbstractPostRoute extends AbstractRoute
|
||||
{
|
||||
protected function getFullFetchConfig()
|
||||
{
|
||||
return
|
||||
[
|
||||
PostViewProxy::FETCH_RELATIONS => true,
|
||||
PostViewProxy::FETCH_TAGS => true,
|
||||
PostViewProxy::FETCH_USER => true,
|
||||
PostViewProxy::FETCH_HISTORY => true,
|
||||
PostViewProxy::FETCH_OWN_SCORE => true,
|
||||
PostViewProxy::FETCH_FAVORITES => true,
|
||||
PostViewProxy::FETCH_NOTES => true,
|
||||
];
|
||||
}
|
||||
|
||||
protected function getLightFetchConfig()
|
||||
{
|
||||
return
|
||||
[
|
||||
PostViewProxy::FETCH_TAGS => true,
|
||||
];
|
||||
}
|
||||
}
|
52
src/Routes/Posts/CreatePost.php
Normal file
52
src/Routes/Posts/CreatePost.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts;
|
||||
use Szurubooru\FormData\UploadFormData;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\PostViewProxy;
|
||||
|
||||
class CreatePost extends AbstractPostRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
private $inputReader;
|
||||
private $postViewProxy;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService,
|
||||
InputReader $inputReader,
|
||||
PostViewProxy $postViewProxy)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
$this->inputReader = $inputReader;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['POST'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::UPLOAD_POSTS);
|
||||
$formData = new UploadFormData($this->inputReader);
|
||||
|
||||
$this->privilegeService->assertPrivilege(Privilege::UPLOAD_POSTS);
|
||||
|
||||
if ($formData->anonymous)
|
||||
$this->privilegeService->assertPrivilege(Privilege::UPLOAD_POSTS_ANONYMOUSLY);
|
||||
|
||||
$post = $this->postService->createPost($formData);
|
||||
return $this->postViewProxy->fromEntity($post, $this->getFullFetchConfig());
|
||||
}
|
||||
}
|
37
src/Routes/Posts/DeletePost.php
Normal file
37
src/Routes/Posts/DeletePost.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
|
||||
class DeletePost extends AbstractPostRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['DELETE'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts/:postNameOrId';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::DELETE_POSTS);
|
||||
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
$this->postService->deletePost($post);
|
||||
}
|
||||
}
|
41
src/Routes/Posts/FeaturePost.php
Normal file
41
src/Routes/Posts/FeaturePost.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Services\PostFeatureService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
|
||||
class FeaturePost extends AbstractPostRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
private $postFeatureService;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService,
|
||||
PostFeatureService $postFeatureService)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
$this->postFeatureService = $postFeatureService;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['POST', 'PUT'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts/:postNameOrId/feature';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::FEATURE_POSTS);
|
||||
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
$this->postFeatureService->featurePost($post);
|
||||
}
|
||||
}
|
42
src/Routes/Posts/GetFeaturedPost.php
Normal file
42
src/Routes/Posts/GetFeaturedPost.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts;
|
||||
use Szurubooru\Entities\Post;
|
||||
use Szurubooru\Services\PostFeatureService;
|
||||
use Szurubooru\ViewProxies\PostViewProxy;
|
||||
use Szurubooru\ViewProxies\UserViewProxy;
|
||||
|
||||
class GetFeaturedPost extends AbstractPostRoute
|
||||
{
|
||||
private $postFeatureService;
|
||||
private $postViewProxy;
|
||||
|
||||
public function __construct(
|
||||
PostFeatureService $postFeatureService,
|
||||
UserViewProxy $userViewProxy,
|
||||
PostViewProxy $postViewProxy)
|
||||
{
|
||||
$this->postFeatureService = $postFeatureService;
|
||||
$this->userViewProxy = $userViewProxy;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts/featured';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$post = $this->postFeatureService->getFeaturedPost();
|
||||
$user = $this->postFeatureService->getFeaturedPostUser();
|
||||
return [
|
||||
'user' => $this->userViewProxy->fromEntity($user),
|
||||
'post' => $this->postViewProxy->fromEntity($post, $this->getFullFetchConfig()),
|
||||
];
|
||||
}
|
||||
}
|
41
src/Routes/Posts/GetPost.php
Normal file
41
src/Routes/Posts/GetPost.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\PostViewProxy;
|
||||
|
||||
class GetPost extends AbstractPostRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
private $postViewProxy;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService,
|
||||
PostViewProxy $postViewProxy)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts/:postNameOrId';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::VIEW_POSTS);
|
||||
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
return $this->postViewProxy->fromEntity($post, $this->getFullFetchConfig());
|
||||
}
|
||||
}
|
56
src/Routes/Posts/GetPostContent.php
Normal file
56
src/Routes/Posts/GetPostContent.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts;
|
||||
use Szurubooru\Config;
|
||||
use Szurubooru\Dao\PublicFileDao;
|
||||
use Szurubooru\Entities\Post;
|
||||
use Szurubooru\Helpers\MimeHelper;
|
||||
use Szurubooru\Services\NetworkingService;
|
||||
use Szurubooru\Services\PostService;
|
||||
|
||||
class GetPostContent extends AbstractPostRoute
|
||||
{
|
||||
private $config;
|
||||
private $fileDao;
|
||||
private $postService;
|
||||
private $networkingService;
|
||||
|
||||
public function __construct(
|
||||
Config $config,
|
||||
PublicFileDao $fileDao,
|
||||
PostService $postService,
|
||||
NetworkingService $networkingService)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->fileDao = $fileDao;
|
||||
$this->postService = $postService;
|
||||
$this->networkingService = $networkingService;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts/:postName/content';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$post = $this->postService->getByName($args['postName']);
|
||||
|
||||
$customFileName = sprintf('%s_%s.%s',
|
||||
$this->config->basic->serviceName,
|
||||
$post->getName(),
|
||||
strtolower(MimeHelper::getExtension($post->getContentMimeType())));
|
||||
|
||||
if ($post->getContentType() === Post::POST_TYPE_YOUTUBE)
|
||||
{
|
||||
$this->networkingService->nonCachedRedirect($post->getOriginalFileName());
|
||||
return;
|
||||
}
|
||||
|
||||
$this->networkingService->serveFile($this->fileDao->getFullPath($post->getContentPath()), $customFileName);
|
||||
}
|
||||
}
|
@ -1,14 +1,13 @@
|
||||
<?php
|
||||
namespace Szurubooru\Controllers;
|
||||
namespace Szurubooru\Routes\Posts;
|
||||
use Szurubooru\Config;
|
||||
use Szurubooru\Dao\PublicFileDao;
|
||||
use Szurubooru\Helpers\MimeHelper;
|
||||
use Szurubooru\Router;
|
||||
use Szurubooru\Entities\Post;
|
||||
use Szurubooru\Services\NetworkingService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PostThumbnailService;
|
||||
|
||||
final class PostContentController extends AbstractController
|
||||
class GetPostThumbnail extends AbstractPostRoute
|
||||
{
|
||||
private $config;
|
||||
private $fileDao;
|
||||
@ -30,27 +29,20 @@ final class PostContentController extends AbstractController
|
||||
$this->postThumbnailService = $postThumbnailService;
|
||||
}
|
||||
|
||||
public function registerRoutes(Router $router)
|
||||
public function getMethods()
|
||||
{
|
||||
$router->get('/api/posts/:postName/content', [$this, 'getPostContent']);
|
||||
$router->get('/api/posts/:postName/thumbnail/:size', [$this, 'getPostThumbnail']);
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getPostContent($postName)
|
||||
public function getUrl()
|
||||
{
|
||||
$post = $this->postService->getByName($postName);
|
||||
|
||||
$customFileName = sprintf('%s_%s.%s',
|
||||
$this->config->basic->serviceName,
|
||||
$post->getName(),
|
||||
strtolower(MimeHelper::getExtension($post->getContentMimeType())));
|
||||
|
||||
$this->networkingService->serveFile($this->fileDao->getFullPath($post->getContentPath()), $customFileName);
|
||||
return '/api/posts/:postName/thumbnail/:size';
|
||||
}
|
||||
|
||||
public function getPostThumbnail($postName, $size)
|
||||
public function work($args)
|
||||
{
|
||||
$post = $this->postService->getByName($postName);
|
||||
$size = $args['size'];
|
||||
$post = $this->postService->getByName($args['postName']);
|
||||
$thumbnailName = $this->postThumbnailService->generateIfNeeded($post, $size, $size);
|
||||
$this->networkingService->serveFile($this->fileDao->getFullPath($thumbnailName));
|
||||
}
|
61
src/Routes/Posts/GetPosts.php
Normal file
61
src/Routes/Posts/GetPosts.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts;
|
||||
use Szurubooru\Config;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Search\Parsers\PostSearchParser;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\PostViewProxy;
|
||||
|
||||
class GetPosts extends AbstractPostRoute
|
||||
{
|
||||
private $config;
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
private $postSearchParser;
|
||||
private $inputReader;
|
||||
private $postViewProxy;
|
||||
|
||||
public function __construct(
|
||||
Config $config,
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService,
|
||||
PostSearchParser $postSearchParser,
|
||||
InputReader $inputReader,
|
||||
PostViewProxy $postViewProxy)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
$this->postSearchParser = $postSearchParser;
|
||||
$this->inputReader = $inputReader;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::LIST_POSTS);
|
||||
|
||||
$filter = $this->postSearchParser->createFilterFromInputReader($this->inputReader);
|
||||
$filter->setPageSize($this->config->posts->postsPerPage);
|
||||
$this->postService->decorateFilterFromBrowsingSettings($filter);
|
||||
|
||||
$result = $this->postService->getFiltered($filter);
|
||||
$entities = $this->postViewProxy->fromArray($result->getEntities(), $this->getLightFetchConfig());
|
||||
return [
|
||||
'data' => $entities,
|
||||
'pageSize' => $result->getPageSize(),
|
||||
'totalRecords' => $result->getTotalRecords()];
|
||||
}
|
||||
}
|
54
src/Routes/Posts/Notes/AddPostNote.php
Normal file
54
src/Routes/Posts/Notes/AddPostNote.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts\Notes;
|
||||
use Szurubooru\FormData\PostNoteFormData;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Routes\Posts\AbstractPostRoute;
|
||||
use Szurubooru\Services\PostNotesService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\PostNoteViewProxy;
|
||||
|
||||
class AddPostNote extends AbstractPostRoute
|
||||
{
|
||||
private $inputReader;
|
||||
private $postService;
|
||||
private $postNotesService;
|
||||
private $privilegeService;
|
||||
private $postNoteViewProxy;
|
||||
|
||||
public function __construct(
|
||||
InputReader $inputReader,
|
||||
PostService $postService,
|
||||
PostNotesService $postNotesService,
|
||||
PrivilegeService $privilegeService,
|
||||
PostNoteViewProxy $postNoteViewProxy)
|
||||
{
|
||||
$this->inputReader = $inputReader;
|
||||
$this->postService = $postService;
|
||||
$this->postNotesService = $postNotesService;
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postNoteViewProxy = $postNoteViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['POST'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/notes/:postNameOrId';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
|
||||
$this->privilegeService->assertPrivilege(Privilege::ADD_POST_NOTES);
|
||||
|
||||
$formData = new PostNoteFormData($this->inputReader);
|
||||
$postNote = $this->postNotesService->createPostNote($post, $formData);
|
||||
return $this->postNoteViewProxy->fromEntity($postNote);
|
||||
}
|
||||
}
|
37
src/Routes/Posts/Notes/DeletePostNote.php
Normal file
37
src/Routes/Posts/Notes/DeletePostNote.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts\Notes;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Routes\Posts\AbstractPostRoute;
|
||||
use Szurubooru\Services\PostNotesService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
|
||||
class DeletePostNote extends AbstractPostRoute
|
||||
{
|
||||
private $postNotesService;
|
||||
private $privilegeService;
|
||||
|
||||
public function __construct(
|
||||
PostNotesService $postNotesService,
|
||||
PrivilegeService $privilegeService)
|
||||
{
|
||||
$this->postNotesService = $postNotesService;
|
||||
$this->privilegeService = $privilegeService;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['DELETE'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/notes/:postNoteId';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$postNote = $this->postNotesService->getById($args['postNoteId']);
|
||||
$this->privilegeService->assertPrivilege(Privilege::DELETE_POST_NOTES);
|
||||
return $this->postNotesService->deletePostNote($postNote);
|
||||
}
|
||||
}
|
49
src/Routes/Posts/Notes/GetPostNotes.php
Normal file
49
src/Routes/Posts/Notes/GetPostNotes.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts\Notes;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Routes\Posts\AbstractPostRoute;
|
||||
use Szurubooru\Services\PostNotesService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\PostNoteViewProxy;
|
||||
|
||||
class GetPostNotes extends AbstractPostRoute
|
||||
{
|
||||
private $inputReader;
|
||||
private $postService;
|
||||
private $postNotesService;
|
||||
private $privilegeService;
|
||||
private $postNoteViewProxy;
|
||||
|
||||
public function __construct(
|
||||
InputReader $inputReader,
|
||||
PostService $postService,
|
||||
PostNotesService $postNotesService,
|
||||
PrivilegeService $privilegeService,
|
||||
PostNoteViewProxy $postNoteViewProxy)
|
||||
{
|
||||
$this->inputReader = $inputReader;
|
||||
$this->postService = $postService;
|
||||
$this->postNotesService = $postNotesService;
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postNoteViewProxy = $postNoteViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/notes/:postNameOrId';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
$postNotes = $this->postNotesService->getByPost($post);
|
||||
return $this->postNoteViewProxy->fromArray($postNotes);
|
||||
}
|
||||
}
|
50
src/Routes/Posts/Notes/UpdatePostNote.php
Normal file
50
src/Routes/Posts/Notes/UpdatePostNote.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts\Notes;
|
||||
use Szurubooru\FormData\PostNoteFormData;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Routes\Posts\AbstractPostRoute;
|
||||
use Szurubooru\Services\PostNotesService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\PostNoteViewProxy;
|
||||
|
||||
class UpdatePostNote extends AbstractPostRoute
|
||||
{
|
||||
private $inputReader;
|
||||
private $postNotesService;
|
||||
private $privilegeService;
|
||||
private $postNoteViewProxy;
|
||||
|
||||
public function __construct(
|
||||
InputReader $inputReader,
|
||||
PostNotesService $postNotesService,
|
||||
PrivilegeService $privilegeService,
|
||||
PostNoteViewProxy $postNoteViewProxy)
|
||||
{
|
||||
$this->inputReader = $inputReader;
|
||||
$this->postNotesService = $postNotesService;
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postNoteViewProxy = $postNoteViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['PUT'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/notes/:postNoteId';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$postNote = $this->postNotesService->getById($args['postNoteId']);
|
||||
|
||||
$this->privilegeService->assertPrivilege(Privilege::EDIT_POST_NOTES);
|
||||
|
||||
$formData = new PostNoteFormData($this->inputReader);
|
||||
$postNote = $this->postNotesService->updatePostNote($postNote, $formData);
|
||||
return $this->postNoteViewProxy->fromEntity($postNote);
|
||||
}
|
||||
}
|
64
src/Routes/Posts/UpdatePost.php
Normal file
64
src/Routes/Posts/UpdatePost.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Posts;
|
||||
use Szurubooru\FormData\PostEditFormData;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\ViewProxies\PostViewProxy;
|
||||
|
||||
class UpdatePost extends AbstractPostRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $postService;
|
||||
private $inputReader;
|
||||
private $postViewProxy;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
PostService $postService,
|
||||
InputReader $inputReader,
|
||||
PostViewProxy $postViewProxy)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->postService = $postService;
|
||||
$this->inputReader = $inputReader;
|
||||
$this->postViewProxy = $postViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['POST'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts/:postNameOrId';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$postNameOrId = $args['postNameOrId'];
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
$formData = new PostEditFormData($this->inputReader);
|
||||
|
||||
if ($formData->content !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_POST_CONTENT);
|
||||
|
||||
if ($formData->thumbnail !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_POST_THUMBNAIL);
|
||||
|
||||
if ($formData->safety !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_POST_SAFETY);
|
||||
|
||||
if ($formData->source !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_POST_SOURCE);
|
||||
|
||||
if ($formData->tags !== null)
|
||||
$this->privilegeService->assertPrivilege(Privilege::CHANGE_POST_TAGS);
|
||||
|
||||
$this->postService->updatePost($post, $formData);
|
||||
$post = $this->postService->getByNameOrId($postNameOrId);
|
||||
return $this->postViewProxy->fromEntity($post, $this->getFullFetchConfig());
|
||||
}
|
||||
}
|
48
src/Routes/Scores/AbstractScoreRoute.php
Normal file
48
src/Routes/Scores/AbstractScoreRoute.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Scores;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Entities\Entity;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\Services\ScoreService;
|
||||
use Szurubooru\Routes\AbstractRoute;
|
||||
|
||||
abstract class AbstractScoreRoute extends AbstractRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $scoreService;
|
||||
private $authService;
|
||||
|
||||
public function __construct(
|
||||
AuthService $authService,
|
||||
InputReader $inputReader,
|
||||
PrivilegeService $privilegeService,
|
||||
ScoreService $scoreService)
|
||||
{
|
||||
$this->authService = $authService;
|
||||
$this->inputReader = $inputReader;
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->scoreService = $scoreService;
|
||||
}
|
||||
|
||||
protected function getScore(Entity $entity)
|
||||
{
|
||||
$user = $this->authService->getLoggedInUser();
|
||||
return [
|
||||
'score' => $this->scoreService->getScoreValue($entity),
|
||||
'ownScore' => $this->scoreService->getUserScoreValue($user, $entity),
|
||||
];
|
||||
}
|
||||
|
||||
protected function setScore(Entity $entity)
|
||||
{
|
||||
$this->privilegeService->assertLoggedIn();
|
||||
$score = intval($this->inputReader->score);
|
||||
$user = $this->authService->getLoggedInUser();
|
||||
$result = $this->scoreService->setUserScore($user, $entity, $score);
|
||||
return [
|
||||
'score' => $this->scoreService->getScoreValue($entity),
|
||||
'ownScore' => $result->getScore(),
|
||||
];
|
||||
}
|
||||
}
|
45
src/Routes/Scores/GetCommentScore.php
Normal file
45
src/Routes/Scores/GetCommentScore.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Scores;
|
||||
use Szurubooru\Entities\Entity;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\CommentService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\Services\ScoreService;
|
||||
|
||||
class GetCommentScore extends AbstractScoreRoute
|
||||
{
|
||||
private $commentService;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
AuthService $authService,
|
||||
CommentService $commentService,
|
||||
ScoreService $scoreService,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
parent::__construct(
|
||||
$authService,
|
||||
$inputReader,
|
||||
$privilegeService,
|
||||
$scoreService);
|
||||
|
||||
$this->commentService = $commentService;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/comments/:commentId/score';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$comment = $this->commentService->getById($args['commentId']);
|
||||
return $this->getScore($comment);
|
||||
}
|
||||
}
|
45
src/Routes/Scores/GetPostScore.php
Normal file
45
src/Routes/Scores/GetPostScore.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Scores;
|
||||
use Szurubooru\Entities\Entity;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\Services\ScoreService;
|
||||
|
||||
class GetPostScore extends AbstractScoreRoute
|
||||
{
|
||||
private $postService;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
AuthService $authService,
|
||||
PostService $postService,
|
||||
ScoreService $scoreService,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
parent::__construct(
|
||||
$authService,
|
||||
$inputReader,
|
||||
$privilegeService,
|
||||
$scoreService);
|
||||
|
||||
$this->postService = $postService;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts/:postNameOrId/score';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
return $this->getScore($post);
|
||||
}
|
||||
}
|
45
src/Routes/Scores/SetCommentScore.php
Normal file
45
src/Routes/Scores/SetCommentScore.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Scores;
|
||||
use Szurubooru\Entities\Entity;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\CommentService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\Services\ScoreService;
|
||||
|
||||
class SetCommentScore extends AbstractScoreRoute
|
||||
{
|
||||
private $commentService;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
AuthService $authService,
|
||||
CommentService $commentService,
|
||||
ScoreService $scoreService,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
parent::__construct(
|
||||
$authService,
|
||||
$inputReader,
|
||||
$privilegeService,
|
||||
$scoreService);
|
||||
|
||||
$this->commentService = $commentService;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['POST', 'PUT'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/comments/:commentId/score';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$comment = $this->commentService->getById($args['commentId']);
|
||||
return $this->setScore($comment);
|
||||
}
|
||||
}
|
45
src/Routes/Scores/SetPostScore.php
Normal file
45
src/Routes/Scores/SetPostScore.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Scores;
|
||||
use Szurubooru\Entities\Entity;
|
||||
use Szurubooru\Helpers\InputReader;
|
||||
use Szurubooru\Services\AuthService;
|
||||
use Szurubooru\Services\PostService;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\Services\ScoreService;
|
||||
|
||||
class SetPostScore extends AbstractScoreRoute
|
||||
{
|
||||
private $postService;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
AuthService $authService,
|
||||
PostService $postService,
|
||||
ScoreService $scoreService,
|
||||
InputReader $inputReader)
|
||||
{
|
||||
parent::__construct(
|
||||
$authService,
|
||||
$inputReader,
|
||||
$privilegeService,
|
||||
$scoreService);
|
||||
|
||||
$this->postService = $postService;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['POST', 'PUT'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/posts/:postNameOrId/score';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$post = $this->postService->getByNameOrId($args['postNameOrId']);
|
||||
return $this->setScore($post);
|
||||
}
|
||||
}
|
17
src/Routes/Tags/AbstractTagRoute.php
Normal file
17
src/Routes/Tags/AbstractTagRoute.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Tags;
|
||||
use Szurubooru\Routes\AbstractRoute;
|
||||
use Szurubooru\ViewProxies\TagViewProxy;
|
||||
|
||||
abstract class AbstractTagRoute extends AbstractRoute
|
||||
{
|
||||
protected function getFullFetchConfig()
|
||||
{
|
||||
return
|
||||
[
|
||||
TagViewProxy::FETCH_IMPLICATIONS => true,
|
||||
TagViewProxy::FETCH_SUGGESTIONS => true,
|
||||
TagViewProxy::FETCH_HISTORY => true,
|
||||
];
|
||||
}
|
||||
}
|
36
src/Routes/Tags/DeleteTag.php
Normal file
36
src/Routes/Tags/DeleteTag.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Tags;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\Services\TagService;
|
||||
|
||||
class DeleteTag extends AbstractTagRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $tagService;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
TagService $tagService)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->tagService = $tagService;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['DELETE'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/tags/:tagName';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$tag = $this->tagService->getByName($args['tagName']);
|
||||
$this->privilegeService->assertPrivilege(Privilege::DELETE_TAGS);
|
||||
return $this->tagService->deleteTag($tag);
|
||||
}
|
||||
}
|
41
src/Routes/Tags/GetTag.php
Normal file
41
src/Routes/Tags/GetTag.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
namespace Szurubooru\Routes\Tags;
|
||||
use Szurubooru\Privilege;
|
||||
use Szurubooru\Services\PrivilegeService;
|
||||
use Szurubooru\Services\TagService;
|
||||
use Szurubooru\ViewProxies\TagViewProxy;
|
||||
|
||||
class GetTag extends AbstractTagRoute
|
||||
{
|
||||
private $privilegeService;
|
||||
private $tagService;
|
||||
private $tagViewProxy;
|
||||
|
||||
public function __construct(
|
||||
PrivilegeService $privilegeService,
|
||||
TagService $tagService,
|
||||
TagViewProxy $tagViewProxy)
|
||||
{
|
||||
$this->privilegeService = $privilegeService;
|
||||
$this->tagService = $tagService;
|
||||
$this->tagViewProxy = $tagViewProxy;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return ['GET'];
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return '/api/tags/:tagName';
|
||||
}
|
||||
|
||||
public function work($args)
|
||||
{
|
||||
$this->privilegeService->assertPrivilege(Privilege::LIST_TAGS);
|
||||
|
||||
$tag = $this->tagService->getByName($args['tagName']);
|
||||
return $this->tagViewProxy->fromEntity($tag, $this->getFullFetchConfig());
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user