Add simple acl for media
authorMatthias Schmidt <gravatronics@live.com>
Thu, 14 Jul 2016 18:00:18 +0000 (20:00 +0200)
committerMatthias Schmidt <gravatronics@live.com>
Thu, 14 Jul 2016 18:00:24 +0000 (20:00 +0200)
24 files changed:
com.woltlab.wcf/objectType.xml
com.woltlab.wcf/templates/__box.tpl
com.woltlab.wcf/templates/aclSimple.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/languageChooser.tpl
com.woltlab.wcf/templates/mediaEditor.tpl
com.woltlab.wcf/templates/mediaJavaScript.tpl
wcfsetup/install/files/acp/templates/aclSimple.tpl
wcfsetup/install/files/acp/templates/languageChooser.tpl
wcfsetup/install/files/acp/templates/mediaAdd.tpl
wcfsetup/install/files/acp/templates/mediaEditor.tpl
wcfsetup/install/files/acp/templates/mediaJavaScript.tpl
wcfsetup/install/files/js/WoltLab/WCF/Media/Editor.js
wcfsetup/install/files/js/WoltLab/WCF/Ui/Acl/Simple.js
wcfsetup/install/files/lib/acp/form/MediaEditForm.class.php
wcfsetup/install/files/lib/data/article/content/ViewableArticleContent.class.php
wcfsetup/install/files/lib/data/box/Box.class.php
wcfsetup/install/files/lib/data/media/Media.class.php
wcfsetup/install/files/lib/data/media/MediaAction.class.php
wcfsetup/install/files/lib/data/media/ViewableMedia.class.php
wcfsetup/install/files/lib/page/MediaPage.class.php
wcfsetup/install/files/lib/system/box/AbstractBoxController.class.php
wcfsetup/install/files/lib/system/box/IBoxController.class.php
wcfsetup/install/files/style/ui/media.scss
wcfsetup/install/lang/en.xml

index 92f027c6b6b35e5675d0fb99250a2bc68ac44cec..6c726a2bd12c27ba25bdb582bd83d4c5a656eb49 100644 (file)
                </type>
                <!-- /box controllers -->
                
-               <!-- pages -->
+               <!-- simple acl -->
                <type>
                        <name>com.woltlab.wcf.page</name>
                        <definitionname>com.woltlab.wcf.acl.simple</definitionname>
                        <name>com.woltlab.wcf.box</name>
                        <definitionname>com.woltlab.wcf.acl.simple</definitionname>
                </type>
-               <!-- /pages -->
+               <type>
+                       <name>com.woltlab.wcf.media</name>
+                       <definitionname>com.woltlab.wcf.acl.simple</definitionname>
+               </type>
+               <!-- /simple acl -->
                
                <!-- article list box condition -->
                <type>
index d6a72d066d71cc0c782947fb97a56458a26a9035..81d06a6d1b6b4395f629a5f0da7e33dec7e6a8dd 100644 (file)
@@ -1,5 +1,5 @@
-<{if $box->showHeader}section{else}div{/if} class="box{if $box->hasImage()} boxWithImage{/if}{if $box->cssClassName} {$box->cssClassName}{/if}" data-box-identifier="{@$box->identifier}">
-       {if $box->hasImage()}
+<{if $box->showHeader}section{else}div{/if} class="box{if $box->getImage()} boxWithImage{/if}{if $box->cssClassName} {$box->cssClassName}{/if}" data-box-identifier="{@$box->identifier}">
+       {if $box->getImage()}
                <div class="boxImage">
                        {if $box->hasLink()}
                                <a href="{$box->getLink()}">{@$box->getImage()}</a>
diff --git a/com.woltlab.wcf/templates/aclSimple.tpl b/com.woltlab.wcf/templates/aclSimple.tpl
new file mode 100644 (file)
index 0000000..3fa5a97
--- /dev/null
@@ -0,0 +1,59 @@
+{if !$__aclSimplePrefix|isset}{assign var='__aclSimplePrefix' value=''}{/if}
+
+<div class="section">
+       <dl>
+               <dt><label for="{@$__aclSimplePrefix}aclAllowAll">{lang}wcf.acl.allowAll{/lang}</label></dt>
+               <dd>
+                       <ol class="flexibleButtonGroup">
+                               <li>
+                                       <input type="radio" id="{@$__aclSimplePrefix}aclAllowAll" name="aclValues[allowAll]" value="1"{if $aclValues[allowAll]} checked{/if}>
+                                       <label for="{@$__aclSimplePrefix}aclAllowAll" class="green"><span class="icon icon16 fa-check"></span> {lang}wcf.acp.option.type.boolean.yes{/lang}</label>
+                               </li>
+                               <li>
+                                       <input type="radio" id="{@$__aclSimplePrefix}aclAllowAll_no" name="aclValues[allowAll]" value="0"{if !$aclValues[allowAll]} checked{/if}>
+                                       <label for="{@$__aclSimplePrefix}aclAllowAll_no" class="red"><span class="icon icon16 fa-times"></span> {lang}wcf.acp.option.type.boolean.no{/lang}</label>
+                               </li>
+                       </ol>
+               </dd>
+       </dl>
+</div>
+
+<section class="section" id="{@$__aclSimplePrefix}aclInputContainer"{if $aclValues[allowAll]} style="display: none;"{/if}>
+       <h2 class="sectionTitle">{lang}wcf.acl.access{/lang}</h2>
+       <dl>
+               <dt><label for="{@$__aclSimplePrefix}aclSearchInput">{lang}wcf.acl.access.grant{/lang}</label></dt>
+               <dd>
+                       <input type="text" id="{@$__aclSimplePrefix}aclSearchInput" class="long" placeholder="{lang}wcf.acl.search.description{/lang}">
+               </dd>
+       </dl>
+
+       <dl id="{@$__aclSimplePrefix}aclListContainer"{if $aclValues[allowAll]} style="display: none;"{/if}>
+               <dt>{lang}wcf.acl.access.granted{/lang}</dt>
+               <dd>
+                       <ul id="{@$__aclSimplePrefix}aclAccessList" class="aclList containerList">
+                               {foreach from=$aclValues[group] item=aclGroup}
+                                       <li>
+                                               <span class="icon icon16 fa-users"></span>
+                                               <span class="aclLabel">{$aclGroup}</span>
+                                               <span class="icon icon16 fa-times pointer jsTooltip" title="{lang}wcf.global.button.delete{/lang}"></span>
+                                               <input type="hidden" name="aclValues[group][]" value="{@$aclGroup->groupID}">
+                                       </li>
+                               {/foreach}
+                               {foreach from=$aclValues[user] item=aclUser}
+                                       <li>
+                                               <span class="icon icon16 fa-user"></span>
+                                               <span class="aclLabel">{$aclUser}</span>
+                                               <span class="icon icon16 fa-times pointer jsTooltip" title="{lang}wcf.global.button.delete{/lang}"></span>
+                                               <input type="hidden" name="aclValues[user][]" value="{@$aclUser->userID}">
+                                       </li>
+                               {/foreach}
+                       </ul>
+               </dd>
+       </dl>
+</section>
+
+<script data-relocate="true">
+       require(['WoltLab/WCF/Ui/Acl/Simple'], function(UiAclSimple) {
+               new UiAclSimple('{@$__aclSimplePrefix}');
+       });
+</script>
index b3fb0a854d6ec2f19492380656382ea3bac4099c..d537396a518a82c3642cc503521e9691ba2b735f 100644 (file)
@@ -1,9 +1,10 @@
+{if !$__languageChooserPrefix|isset}{assign var='__languageChooserPrefix' value=''}{/if}
 {if !$label|isset}{assign var='label' value='wcf.user.language'}{/if}
 
 {if $languages|count}
        <dl{if $errorField|isset && $errorField == 'languageID'} class="formError"{/if}>
                <dt>{lang}{$label}{/lang}</dt>
-               <dd id="languageIDContainer">
+               <dd id="{@$__languageChooserPrefix}languageIDContainer">
                        <noscript>
                                <select name="languageID" id="languageID">
                                        {foreach from=$languages item=__language}
@@ -25,7 +26,7 @@
                                {/implode}
                        };
                        
-                       LanguageChooser.init('languageIDContainer', 'languageID', {$languageID}, languages)
+                       LanguageChooser.init('{@$__languageChooserPrefix}languageIDContainer', 'languageID', {$languageID}, languages)
                });
        </script>
 {/if}
index 2e9b93993215aa21bccb2cba04439132ffd35b88..ef718a76d85f42a352c9d883adf317e1aa7f67ed 100644 (file)
@@ -1,65 +1,77 @@
-<div id="mediaThumbnail"></div>
+{if $media->isImage}
+       <div class="mediaThumbnail">
+               {@$media->getThumbnailTag('small')}
+       </div>
+{/if}
 
 <div class="box48">
-       <span id="mediaFileIcon" class="icon icon48 fa-file-o"></span>
-       
+       {if $media->isImage}
+               <span class="icon icon48 fa-file-image-o"></span>
+       {else}
+               {@$media->getElementTag(48)}
+       {/if}
+
        <dl class="plain dataList">
                <dt>{lang}wcf.media.filename{/lang}</dt>
-               <dd id="mediaFilename"></dd>
-               
+               <dd id="mediaFilename">{$media->filename}</dd>
+
                <dt>{lang}wcf.media.filesize{/lang}</dt>
-               <dd id="mediaFilesize"></dd>
-               
-               <dt>{lang}wcf.media.imageDimensions{/lang}</dt>
-               <dd id="mediaImageDimensions"></dd>
-               
+               <dd id="mediaFilesize">{@$media->filesize|filesize}</dd>
+
+               {if $media->isImage}
+                       <dt>{lang}wcf.media.imageDimensions{/lang}</dt>
+                       <dd id="mediaImageDimensions">{lang}wcf.media.imageDimensions.value{/lang}</dd>
+               {/if}
+
                <dt>{lang}wcf.media.uploader{/lang}</dt>
-               <dd id="mediaUploader"></dd>
+               <dd id="mediaUploader">{@$media->getUserProfile()->getAnchorTag()}</dd>
        </dl>
 </div>
 
 <section class="section">
        <h2 class="sectionTitle">{lang}wcf.global.form.data{/lang}</h2>
-       
+
        <dl>
                <dt></dt>
                <dd>
                        <label>
-                               <input type="checkbox" id="isMultilingual" name="isMultilingual" value="1">
+                               <input type="checkbox" name="isMultilingual" value="1"{if $media->isMultilingual} checked{/if}>
                                <span>{lang}wcf.media.isMultilingual{/lang}</span>
                        </label>
                </dd>
        </dl>
-       
+
        {include file='languageChooser' label='wcf.media.languageID'}
-       
+
        <dl>
-               <dt><label for="title">{lang}wcf.global.title{/lang}</label></dt>
+               <dt><label for="title_{@$media->mediaID}">{lang}wcf.global.title{/lang}</label></dt>
                <dd>
-                       <input type="text" id="title" name="title" class="long">
+                       <input type="text" id="title_{@$media->mediaID}" name="title" class="long" value="TODO">
                </dd>
        </dl>
-       {include file='multipleLanguageInputJavascript' elementIdentifier='title' forceSelection=true}
-       
+       {include file='multipleLanguageInputJavascript' elementIdentifier='title'|concat:'_':$media->mediaID forceSelection=true}
+
        <dl>
-               <dt><label for="caption">{lang}wcf.media.caption{/lang}</label></dt>
+               <dt><label for="caption_{@$media->mediaID}">{lang}wcf.media.caption{/lang}</label></dt>
                <dd>
-                       <textarea id="caption" name="caption" cols="40" rows="3"></textarea>
+                       <textarea id="caption_{@$media->mediaID}" name="caption" cols="40" rows="3">TODO</textarea>
                </dd>
        </dl>
-       {include file='multipleLanguageInputJavascript' elementIdentifier='caption' forceSelection=true}
-       
+       {include file='multipleLanguageInputJavascript' elementIdentifier='caption'|concat:'_':$media->mediaID forceSelection=true}
+
        <dl>
-               <dt><label for="altText">{lang}wcf.media.altText{/lang}</label></dt>
+               <dt><label for="altText_{@$media->mediaID}">{lang}wcf.media.altText{/lang}</label></dt>
                <dd>
-                       <input type="text" id="altText" name="altText" class="long">
+                       <input type="text" id="altText_{@$media->mediaID}" name="altText" class="long" value="TODO">
                </dd>
        </dl>
-       {include file='multipleLanguageInputJavascript' elementIdentifier='altText' forceSelection=true}
-       
+       {include file='multipleLanguageInputJavascript' elementIdentifier='altText'|concat:'_':$media->mediaID forceSelection=true}
+
        {event name='dataFields'}
 </section>
 
+{include file='aclSimple'}
+
 <div class="formSubmit">
        <button data-type="submit" class="buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
 </div>
index ccac490856bf68cea5eb6b0ee02742aaf90ee473..76d9aae80de49c658da8e97325c5daa9aeda57c8 100644 (file)
@@ -11,7 +11,6 @@
                        'wcf.media.insert.imageSize.original': '{lang}wcf.media.insert.imageSize.original{/lang}',
                        'wcf.media.manager': '{lang}wcf.media.manager{/lang}',
                        'wcf.media.edit': '{lang}wcf.media.edit{/lang}',
-                       'wcf.media.imageDimensions.value': '{lang __literal=true}wcf.media.imageDimensions.value{/lang}',
                        'wcf.media.button.insert': '{lang}wcf.media.button.insert{/lang}',
                        'wcf.media.search.filetype': '{lang}wcf.media.search.filetype{/lang}',
                        'wcf.media.search.noResults': '{lang}wcf.media.search.noResults{/lang}'
index 35a2d2b89759fac852311e7d0a02a9304297ab4d..0ddd8d3a2c465b0ebca59ad2671f0251f96c879f 100644 (file)
@@ -1,34 +1,36 @@
+{if !$__aclSimplePrefix|isset}{assign var='__aclSimplePrefix' value=''}{/if}
+
 <div class="section">
        <dl>
-               <dt><label for="aclAllowAll">{lang}wcf.acl.allowAll{/lang}</label></dt>
+               <dt><label for="{@$__aclSimplePrefix}aclAllowAll">{lang}wcf.acl.allowAll{/lang}</label></dt>
                <dd>
                        <ol class="flexibleButtonGroup">
                                <li>
-                                       <input type="radio" id="aclAllowAll" name="aclValues[allowAll]" value="1"{if $aclValues[allowAll]} checked{/if}>
-                                       <label for="aclAllowAll" class="green"><span class="icon icon16 fa-check"></span> {lang}wcf.acp.option.type.boolean.yes{/lang}</label>
+                                       <input type="radio" id="{@$__aclSimplePrefix}aclAllowAll" name="aclValues[allowAll]" value="1"{if $aclValues[allowAll]} checked{/if}>
+                                       <label for="{@$__aclSimplePrefix}aclAllowAll" class="green"><span class="icon icon16 fa-check"></span> {lang}wcf.acp.option.type.boolean.yes{/lang}</label>
                                </li>
                                <li>
-                                       <input type="radio" id="aclAllowAll_no" name="aclValues[allowAll]" value="0"{if !$aclValues[allowAll]} checked{/if}>
-                                       <label for="aclAllowAll_no" class="red"><span class="icon icon16 fa-times"></span> {lang}wcf.acp.option.type.boolean.no{/lang}</label>
+                                       <input type="radio" id="{@$__aclSimplePrefix}aclAllowAll_no" name="aclValues[allowAll]" value="0"{if !$aclValues[allowAll]} checked{/if}>
+                                       <label for="{@$__aclSimplePrefix}aclAllowAll_no" class="red"><span class="icon icon16 fa-times"></span> {lang}wcf.acp.option.type.boolean.no{/lang}</label>
                                </li>
                        </ol>
                </dd>
        </dl>
 </div>
 
-<section class="section" id="aclInputContainer"{if $aclValues[allowAll]} style="display: none;"{/if}>
+<section class="section" id="{@$__aclSimplePrefix}aclInputContainer"{if $aclValues[allowAll]} style="display: none;"{/if}>
        <h2 class="sectionTitle">{lang}wcf.acl.access{/lang}</h2>
        <dl>
-               <dt><label for="aclSearchInput">{lang}wcf.acl.access.grant{/lang}</label></dt>
+               <dt><label for="{@$__aclSimplePrefix}aclSearchInput">{lang}wcf.acl.access.grant{/lang}</label></dt>
                <dd>
-                       <input type="text" id="aclSearchInput" class="long" placeholder="{lang}wcf.acl.search.description{/lang}">
+                       <input type="text" id="{@$__aclSimplePrefix}aclSearchInput" class="long" placeholder="{lang}wcf.acl.search.description{/lang}">
                </dd>
        </dl>
        
-       <dl id="aclListContainer"{if $aclValues[allowAll]} style="display: none;"{/if}>
+       <dl id="{@$__aclSimplePrefix}aclListContainer"{if $aclValues[allowAll]} style="display: none;"{/if}>
                <dt>{lang}wcf.acl.access.granted{/lang}</dt>
                <dd>
-                       <ul id="aclAccessList" class="aclList containerList">
+                       <ul id="{@$__aclSimplePrefix}aclAccessList" class="aclList containerList">
                                {foreach from=$aclValues[group] item=aclGroup}
                                        <li>
                                                <span class="icon icon16 fa-users"></span>
@@ -52,6 +54,6 @@
 
 <script data-relocate="true">
        require(['WoltLab/WCF/Ui/Acl/Simple'], function(UiAclSimple) {
-               new UiAclSimple();
+               new UiAclSimple('{@$__aclSimplePrefix}');
        });
 </script>
index b3fb0a854d6ec2f19492380656382ea3bac4099c..d537396a518a82c3642cc503521e9691ba2b735f 100644 (file)
@@ -1,9 +1,10 @@
+{if !$__languageChooserPrefix|isset}{assign var='__languageChooserPrefix' value=''}{/if}
 {if !$label|isset}{assign var='label' value='wcf.user.language'}{/if}
 
 {if $languages|count}
        <dl{if $errorField|isset && $errorField == 'languageID'} class="formError"{/if}>
                <dt>{lang}{$label}{/lang}</dt>
-               <dd id="languageIDContainer">
+               <dd id="{@$__languageChooserPrefix}languageIDContainer">
                        <noscript>
                                <select name="languageID" id="languageID">
                                        {foreach from=$languages item=__language}
@@ -25,7 +26,7 @@
                                {/implode}
                        };
                        
-                       LanguageChooser.init('languageIDContainer', 'languageID', {$languageID}, languages)
+                       LanguageChooser.init('{@$__languageChooserPrefix}languageIDContainer', 'languageID', {$languageID}, languages)
                });
        </script>
 {/if}
index d2c9ebf96ffb47ec4f6e433412415d8cd4cf3770..d8c51c2db4d8281f3fa22da75b37db893dadebf5 100644 (file)
                        {event name='dataFields'}
                </section>
                
+               {include file='aclSimple'}
+               
                {event name='sections'}
                
                <div class="formSubmit">
index 2e9b93993215aa21bccb2cba04439132ffd35b88..69e982028f3355b2c09d8c13fc9d7ddc6b49e499 100644 (file)
@@ -1,20 +1,30 @@
-<div id="mediaThumbnail"></div>
+{if $media->isImage}
+       <div class="mediaThumbnail">
+               {@$media->getThumbnailTag('small')}
+       </div>
+{/if}
 
 <div class="box48">
-       <span id="mediaFileIcon" class="icon icon48 fa-file-o"></span>
+       {if $media->isImage}
+               <span class="icon icon48 fa-file-image-o"></span>
+       {else}
+               {@$media->getElementTag(48)}
+       {/if}
        
        <dl class="plain dataList">
                <dt>{lang}wcf.media.filename{/lang}</dt>
-               <dd id="mediaFilename"></dd>
+               <dd id="mediaFilename">{$media->filename}</dd>
                
                <dt>{lang}wcf.media.filesize{/lang}</dt>
-               <dd id="mediaFilesize"></dd>
+               <dd id="mediaFilesize">{@$media->filesize|filesize}</dd>
                
-               <dt>{lang}wcf.media.imageDimensions{/lang}</dt>
-               <dd id="mediaImageDimensions"></dd>
+               {if $media->isImage}
+                       <dt>{lang}wcf.media.imageDimensions{/lang}</dt>
+                       <dd id="mediaImageDimensions">{lang}wcf.media.imageDimensions.value{/lang}</dd>
+               {/if}
                
                <dt>{lang}wcf.media.uploader{/lang}</dt>
-               <dd id="mediaUploader"></dd>
+               <dd id="mediaUploader">{@$media->getUserProfile()->getAnchorTag()}</dd>
        </dl>
 </div>
 
@@ -25,7 +35,7 @@
                <dt></dt>
                <dd>
                        <label>
-                               <input type="checkbox" id="isMultilingual" name="isMultilingual" value="1">
+                               <input type="checkbox" name="isMultilingual" value="1"{if $media->isMultilingual} checked{/if}>
                                <span>{lang}wcf.media.isMultilingual{/lang}</span>
                        </label>
                </dd>
        {include file='languageChooser' label='wcf.media.languageID'}
        
        <dl>
-               <dt><label for="title">{lang}wcf.global.title{/lang}</label></dt>
+               <dt><label for="title_{@$media->mediaID}">{lang}wcf.global.title{/lang}</label></dt>
                <dd>
-                       <input type="text" id="title" name="title" class="long">
+                       <input type="text" id="title_{@$media->mediaID}" name="title" class="long" value="TODO">
                </dd>
        </dl>
-       {include file='multipleLanguageInputJavascript' elementIdentifier='title' forceSelection=true}
+       {include file='multipleLanguageInputJavascript' elementIdentifier='title'|concat:'_':$media->mediaID forceSelection=true}
        
        <dl>
-               <dt><label for="caption">{lang}wcf.media.caption{/lang}</label></dt>
+               <dt><label for="caption_{@$media->mediaID}">{lang}wcf.media.caption{/lang}</label></dt>
                <dd>
-                       <textarea id="caption" name="caption" cols="40" rows="3"></textarea>
+                       <textarea id="caption_{@$media->mediaID}" name="caption" cols="40" rows="3">TODO</textarea>
                </dd>
        </dl>
-       {include file='multipleLanguageInputJavascript' elementIdentifier='caption' forceSelection=true}
+       {include file='multipleLanguageInputJavascript' elementIdentifier='caption'|concat:'_':$media->mediaID forceSelection=true}
        
        <dl>
-               <dt><label for="altText">{lang}wcf.media.altText{/lang}</label></dt>
+               <dt><label for="altText_{@$media->mediaID}">{lang}wcf.media.altText{/lang}</label></dt>
                <dd>
-                       <input type="text" id="altText" name="altText" class="long">
+                       <input type="text" id="altText_{@$media->mediaID}" name="altText" class="long" value="TODO">
                </dd>
        </dl>
-       {include file='multipleLanguageInputJavascript' elementIdentifier='altText' forceSelection=true}
+       {include file='multipleLanguageInputJavascript' elementIdentifier='altText'|concat:'_':$media->mediaID forceSelection=true}
        
        {event name='dataFields'}
 </section>
 
+{include file='aclSimple'}
+
 <div class="formSubmit">
        <button data-type="submit" class="buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
 </div>
index ccac490856bf68cea5eb6b0ee02742aaf90ee473..76d9aae80de49c658da8e97325c5daa9aeda57c8 100644 (file)
@@ -11,7 +11,6 @@
                        'wcf.media.insert.imageSize.original': '{lang}wcf.media.insert.imageSize.original{/lang}',
                        'wcf.media.manager': '{lang}wcf.media.manager{/lang}',
                        'wcf.media.edit': '{lang}wcf.media.edit{/lang}',
-                       'wcf.media.imageDimensions.value': '{lang __literal=true}wcf.media.imageDimensions.value{/lang}',
                        'wcf.media.button.insert': '{lang}wcf.media.button.insert{/lang}',
                        'wcf.media.search.filetype': '{lang}wcf.media.search.filetype{/lang}',
                        'wcf.media.search.noResults': '{lang}wcf.media.search.noResults{/lang}'
index 7bae2439e7427e8b3cb149d307053d3018b3b414..04335cceaaa4a245594226f74145705ad4a09fe1 100644 (file)
@@ -37,7 +37,7 @@ define(
                this._callbackObject = callbackObject;
                this._media = null;
                
-               this._elements = {};
+               this._dialogs = new Dictionary();
        };
        MediaEditor.prototype = {
                /**
@@ -64,13 +64,13 @@ define(
                        
                        this._callbackObject._editorSuccess(this._media);
                        
-                       UiDialog.close('mediaEditor');
+                       UiDialog.close('mediaEditor_' + this._media.mediaID);
                        
                        this._media = null;
                },
                
                /**
-                * Is called if the editor is manually closed by the user.
+                * Is called if an editor is manually closed by the user.
                 */
                _close: function() {
                        this._media = null;
@@ -78,55 +78,6 @@ define(
                        this._callbackObject._editorClose();
                },
                
-               /**
-                * Returns the data for Ui/Dialog to setup the editor dialog.
-                * 
-                * @return      {object}        data to setup the editor dialog
-                */
-               _dialogSetup: function() {
-                       return {
-                               id: 'mediaEditor',
-                               options: {
-                                       backdropCloseOnClick: false,
-                                       onClose: this._close.bind(this),
-                                       title: Language.get('wcf.media.edit')
-                               },
-                               source: {
-                                       after: (function(content, data) {
-                                               var editor = UiDialog.getDialog('mediaEditor').content;
-                                               
-                                               // data elements
-                                               this._elements.thumbnail = elById('mediaThumbnail');
-                                               this._elements.filename = elById('mediaFilename');
-                                               this._elements.filesize = elById('mediaFilesize');
-                                               this._elements.imageDimensions = elById('mediaImageDimensions');
-                                               this._elements.fileIcon = elById('mediaFileIcon');
-                                               this._elements.uploader = elById('mediaUploader');
-                                               
-                                               // input elements
-                                               this._elements.altText = elById('altText');
-                                               this._elements.caption = elById('caption');
-                                               this._elements.isMultilingual = elById('isMultilingual');
-                                               this._elements.isMultilingual.addEventListener('change', this._updateLanguageFields.bind(this));
-                                               this._elements.title = elById('title');
-                                               this._elements.languageIdContainer = elById('languageIDContainer');
-                                               
-                                               var keyPress = this._keyPress.bind(this);
-                                               this._elements.altText.addEventListener('keypress', keyPress);
-                                               this._elements.title.addEventListener('keypress', keyPress);
-                                               
-                                               setTimeout(this._setData.bind(this), 100);
-                                               
-                                               elBySel('button[data-type="submit"]', editor).addEventListener(WCF_CLICK_EVENT, this._saveData.bind(this));
-                                       }).bind(this),
-                                       data: {
-                                               actionName: 'getEditorDialog',
-                                               className: 'wcf\\data\\media\\MediaAction'
-                                       }
-                               }
-                       };
-               },
-               
                /**
                 * Handles the `[ENTER]` key to submit the form.
                 * 
@@ -145,54 +96,76 @@ define(
                 * Saves the data of the currently edited media.
                 */
                _saveData: function() {
+                       var content = UiDialog.getDialog('mediaEditor_' + this._media.mediaID).content;
+                       
+                       var altText = elBySel('input[name=altText]', content);
+                       var caption = elBySel('textarea[name=caption]', content);
+                       var title = elBySel('input[name=title]', content);
+                       
                        var hasError = false;
-                       var altTextError = DomTraverse.childByClass(this._elements.altText.parentNode.parentNode, 'innerError');
-                       var captionError = DomTraverse.childByClass(this._elements.caption.parentNode.parentNode, 'innerError');
-                       var titleError = DomTraverse.childByClass(this._elements.title.parentNode.parentNode, 'innerError');
+                       var altTextError = DomTraverse.childByClass(altText.parentNode.parentNode, 'innerError');
+                       var captionError = DomTraverse.childByClass(caption.parentNode.parentNode, 'innerError');
+                       var titleError = DomTraverse.childByClass(title.parentNode.parentNode, 'innerError');
                        
-                       this._media.isMultilingual = ~~this._elements.isMultilingual.checked;
+                       this._media.isMultilingual = ~~elBySel('input[name=isMultilingual]', content).checked;
                        this._media.languageID = this._media.isMultilingual ? null : LanguageChooser.getLanguageId('languageID');
                        
                        this._media.altText = {};
                        this._media.caption = {};
                        this._media.title = {};
                        if (this._media.isMultilingual) {
-                               if (!LanguageInput.validate('altText', true)) {
+                               if (!LanguageInput.validate('altText_' + this._media.mediaID, true)) {
                                        hasError = true;
                                        if (!altTextError) {
                                                var error = elCreate('small');
                                                error.className = 'innerError';
                                                error.textContent = Language.get('wcf.global.form.error.multilingual');
-                                               this._elements.altText.parentNode.parentNode.appendChild(error);
+                                               altText.parentNode.parentNode.appendChild(error);
                                        }
                                }
-                               if (!LanguageInput.validate('caption', true)) {
+                               if (!LanguageInput.validate('caption_' + this._media.mediaID, true)) {
                                        hasError = true;
                                        if (!captionError) {
                                                var error = elCreate('small');
                                                error.className = 'innerError';
                                                error.textContent = Language.get('wcf.global.form.error.multilingual');
-                                               this._elements.caption.parentNode.parentNode.appendChild(error);
+                                               caption.parentNode.parentNode.appendChild(error);
                                        }
                                }
-                               if (!LanguageInput.validate('title', true)) {
+                               if (!LanguageInput.validate('title_' + this._media.mediaID, true)) {
                                        hasError = true;
                                        if (!titleError) {
                                                var error = elCreate('small');
                                                error.className = 'innerError';
                                                error.textContent = Language.get('wcf.global.form.error.multilingual');
-                                               this._elements.title.parentNode.parentNode.appendChild(error);
+                                               thistitle.parentNode.parentNode.appendChild(error);
                                        }
                                }
                                
-                               this._media.altText = LanguageInput.getValues('altText').toObject();
-                               this._media.caption = LanguageInput.getValues('caption').toObject();
-                               this._media.title = LanguageInput.getValues('title').toObject();
+                               this._media.altText = LanguageInput.getValues('altText_' + this._media.mediaID).toObject();
+                               this._media.caption = LanguageInput.getValues('caption_' + this._media.mediaID).toObject();
+                               this._media.title = LanguageInput.getValues('title_' + this._media.mediaID).toObject();
                        }
                        else {
-                               this._media.altText[this._media.languageID] = this._elements.altText.value;
-                               this._media.caption[this._media.languageID] = this._elements.caption.value;
-                               this._media.title[this._media.languageID] = this._elements.title.value;
+                               this._media.altText[this._media.languageID] = altText.value;
+                               this._media.caption[this._media.languageID] = caption.value;
+                               this._media.title[this._media.languageID] = title.value;
+                       }
+                       
+                       var aclValues = {
+                               allowAll: ~~elById('mediaEditor_' + this._media.mediaID + '_aclAllowAll').checked,
+                               group: [],
+                               user: [],
+                       };
+                       
+                       var aclGroups = elBySelAll('input[name="aclValues[group][]"]', content);
+                       for (var i = 0, length = aclGroups.length; i < length; i++) {
+                               aclValues.group.push(~~aclGroups[i].value);
+                       }
+                       
+                       var aclUsers = elBySelAll('input[name="aclValues[user][]"]', content);
+                       for (var i = 0, length = aclUsers.length; i < length; i++) {
+                               aclValues.user.push(~~aclUsers[i].value);
                        }
                        
                        if (!hasError) {
@@ -204,6 +177,7 @@ define(
                                        actionName: 'update',
                                        objectIDs: [ this._media.mediaID ],
                                        parameters: {
+                                               aclValues: aclValues,
                                                altText: this._media.altText,
                                                caption: this._media.caption,
                                                data: {
@@ -216,92 +190,28 @@ define(
                        }
                },
                
-               /**
-                * Inserts the data of the currently edited media into the dialog.
-                */
-               _setData: function() {
-                       this._elements.thumbnail.innerHTML = '';
-                       
-                       this._elements.filename.textContent = this._media.filename;
-                       this._elements.filesize.textContent = this._media.formattedFilesize;
-                       
-                       this._elements.uploader.innerHTML = '';
-                       if (this._media.userLink) {
-                               var a = elCreate('a');
-                               a.className = 'userLink';
-                               elAttr(a, 'href', this._media.userLink);
-                               elData(a, 'user-id', this._media.userID);
-                               a.textContent = this._media.username;
-                               
-                               this._elements.uploader.appendChild(a);
-                       }
-                       else {
-                               this._elements.uploader.textContent = this._media.username;
-                       }
-                       
-                       if (this._media.isImage) {
-                               if (this._media.smallThumbnailLink) {
-                                       var img = elCreate('img');
-                                       elAttr(img, 'src', this._media.smallThumbnailLink);
-                                       elAttr(img, 'alt', '');
-                                       
-                                       this._elements.thumbnail.appendChild(img);
-                               }
-                               
-                               this._elements.imageDimensions.textContent = Language.get('wcf.media.imageDimensions.value', {
-                                       height: this._media.height,
-                                       width: this._media.width
-                               });
-                               elShow(this._elements.imageDimensions);
-                               elShow(this._elements.imageDimensions.previousElementSibling);
-                               
-                               this._elements.fileIcon.className = 'icon icon48 fa-file-image-o';
-                       }
-                       else {
-                               elHide(this._elements.imageDimensions);
-                               elHide(this._elements.imageDimensions.previousElementSibling);
-                               
-                               this._elements.fileIcon.className = 'icon icon48 ' + FileUtil.getIconClassByMimeType(this._media.fileType);
-                       }
-                       
-                       this._elements.isMultilingual.checked = this._media.isMultilingual;
-                       
-                       LanguageChooser.setLanguageId('languageID', this._media.languageID || LANGUAGE_ID);
-                       
-                       if (this._media.isMultilingual) {
-                               LanguageInput.setValues('altText', Dictionary.fromObject(this._media.altText || { }));
-                               LanguageInput.setValues('caption', Dictionary.fromObject(this._media.caption || { }));
-                               LanguageInput.setValues('title', Dictionary.fromObject(this._media.title || { }));
-                       }
-                       else {
-                               this._elements.altText.value = this._media.altText ? this._media.altText[this._media.languageID] : '';
-                               this._elements.caption.value = this._media.caption ? this._media.caption[this._media.languageID] : '';
-                               this._elements.title.value = this._media.title ? this._media.title[this._media.languageID] : '';
-                       }
-                       
-                       this._updateLanguageFields();
-                       
-                       DomChangeListener.trigger();
-               },
-               
                /**
                 * Updates language-related input fields depending on whether multilingualism
                 * is enabled.
                 */
-               _updateLanguageFields: function() {
-                       if (this._elements.isMultilingual.checked) {
-                               LanguageInput.enable('title');
-                               LanguageInput.enable('caption');
-                               LanguageInput.enable('altText');
+               _updateLanguageFields: function(event, element) {
+                       if (event) element = event.currentTarget;
+                       
+                       var languageChooserContainer = elById('mediaEditor_' + this._media.mediaID + '_languageIDContainer').parentNode;
+                       
+                       if (element.checked) {
+                               LanguageInput.enable('title_' + this._media.mediaID);
+                               LanguageInput.enable('caption_' + this._media.mediaID);
+                               LanguageInput.enable('altText_' + this._media.mediaID);
                                
-                               elHide(this._elements.languageIdContainer.parentNode);
+                               elHide(languageChooserContainer);
                        }
                        else {
-                               LanguageInput.disable('title');
-                               LanguageInput.disable('caption');
-                               LanguageInput.disable('altText');
+                               LanguageInput.disable('title_' + this._media.mediaID);
+                               LanguageInput.disable('caption_' + this._media.mediaID);
+                               LanguageInput.disable('altText_' + this._media.mediaID);
                                
-                               elShow(this._elements.languageIdContainer.parentNode);
+                               elShow(languageChooserContainer);
                        }
                },
                
@@ -317,10 +227,57 @@ define(
                        
                        this._media = media;
                        
-                       if (UiDialog.getDialog('mediaEditor') !== undefined) {
-                               this._setData();
+                       if (!this._dialogs.has('mediaEditor_' + media.mediaID)) {
+                               this._dialogs.set('mediaEditor_' + media.mediaID, {
+                                       _dialogSetup: function() {
+                                               return {
+                                                       id: 'mediaEditor_' + media.mediaID,
+                                                       options: {
+                                                               backdropCloseOnClick: false,
+                                                               onClose: this._close.bind(this),
+                                                               title: Language.get('wcf.media.edit')
+                                                       },
+                                                       source: {
+                                                               after: (function(content, data) {
+                                                                       setTimeout(function() {
+                                                                               LanguageChooser.setLanguageId('languageID', this._media.languageID || LANGUAGE_ID);
+                                                                               
+                                                                               if (this._media.isMultilingual) {
+                                                                                       LanguageInput.setValues('altText_' + this._media.mediaID, Dictionary.fromObject(this._media.altText || { }));
+                                                                                       LanguageInput.setValues('caption_' + this._media.mediaID, Dictionary.fromObject(this._media.caption || { }));
+                                                                                       LanguageInput.setValues('title_' + this._media.mediaID, Dictionary.fromObject(this._media.title || { }));
+                                                                               }
+                                                                               
+                                                                               var isMultilingual = elBySel('input[name=isMultilingual]', content);
+                                                                               isMultilingual.addEventListener('change', this._updateLanguageFields.bind(this));
+                                                                               
+                                                                               this._updateLanguageFields(null, isMultilingual);
+                                                                               
+                                                                               var keyPress = this._keyPress.bind(this);
+                                                                               elBySel('input[name=altText]', content).addEventListener('keypress', keyPress);
+                                                                               elBySel('input[name=title]', content).addEventListener('keypress', keyPress);
+                                                                               
+                                                                               elBySel('button[data-type=submit]', content).addEventListener(WCF_CLICK_EVENT, this._saveData.bind(this));
+                                                                               
+                                                                               // remove focus from input elements and scroll dialog to top
+                                                                               document.activeElement.blur();
+                                                                               elById('mediaEditor_' + this._media.mediaID).parentNode.scrollTop = 0;
+                                                                               
+                                                                               DomChangeListener.trigger();
+                                                                       }.bind(this), 100);
+                                                               }).bind(this),
+                                                               data: {
+                                                                       actionName: 'getEditorDialog',
+                                                                       className: 'wcf\\data\\media\\MediaAction',
+                                                                       objectIDs: [media.mediaID]
+                                                               }
+                                                       }
+                                               };
+                                       }.bind(this),
+                               });
                        }
-                       UiDialog.open(this);
+                       
+                       UiDialog.open(this._dialogs.get('mediaEditor_' + media.mediaID));
                }
        };
        
index 6dd00ada85af6890818d11a5806d5734c8ed9952..a7bf8e042986114648ffb79958757401e0091509 100644 (file)
@@ -1,31 +1,33 @@
 define(['Language', 'Dom/ChangeListener', 'WoltLab/WCF/Ui/User/Search/Input'], function(Language, DomChangeListener, UiUserSearchInput) {
        "use strict";
        
-       function UiAclSimple() { this.init(); }
+       function UiAclSimple(prefix) { this.init(prefix); }
        UiAclSimple.prototype = {
-               init: function() {
+               init: function(prefix) {
+                       this._prefix = prefix || '';
+                       
                        this._build();
                },
                
                _build: function () {
-                       var container = elById('aclInputContainer');
+                       var container = elById(this._prefix + 'aclInputContainer');
                        
-                       elById('aclAllowAll').addEventListener('change', (function() {
+                       elById(this._prefix + 'aclAllowAll').addEventListener('change', (function() {
                                elHide(container);
                        }));
-                       elById('aclAllowAll_no').addEventListener('change', (function() {
+                       elById(this._prefix + 'aclAllowAll_no').addEventListener('change', (function() {
                                elShow(container);
                        }));
                        
-                       new UiUserSearchInput(elById('aclSearchInput'), {
+                       new UiUserSearchInput(elById(this._prefix + 'aclSearchInput'), {
                                callbackSelect: this._select.bind(this),
                                includeUserGroups: true,
                                preventSubmit: true
                        });
                        
-                       this._aclListContainer = elById('aclListContainer');
+                       this._aclListContainer = elById(this._prefix + 'aclListContainer');
                        
-                       this._list = elById('aclAccessList');
+                       this._list = elById(this._prefix + 'aclAccessList');
                        this._list.addEventListener(WCF_CLICK_EVENT, this._removeItem.bind(this));
                        
                        DomChangeListener.trigger();
index 0cdaf3d53e05fa7999dde7a03bf094a923bfa74e..97f37545b8dcfc426bab39d9a3a2f5d85396c0a0 100644 (file)
@@ -3,6 +3,7 @@ namespace wcf\acp\form;
 use wcf\data\media\MediaAction;
 use wcf\data\media\ViewableMedia;
 use wcf\form\AbstractForm;
+use wcf\system\acl\simple\SimpleAclHandler;
 use wcf\system\exception\IllegalLinkException;
 use wcf\system\exception\UserInputException;
 use wcf\system\language\I18nHandler;
@@ -20,6 +21,12 @@ use wcf\util\ArrayUtil;
  * @since      3.0
  */
 class MediaEditForm extends AbstractForm {
+       /**
+        * acl values
+        * @var array
+        */
+       public $aclValues = [];
+       
        /**
         * @inheritDoc
         */
@@ -63,6 +70,7 @@ class MediaEditForm extends AbstractForm {
                I18nHandler::getInstance()->assignVariables();
                
                WCF::getTPL()->assign([
+                       'aclValues' => SimpleAclHandler::getInstance()->getOutputValues($this->aclValues),
                        'action' => 'edit',
                        'isMultilingual' => $this->isMultilingual,
                        'languages' => LanguageFactory::getInstance()->getLanguages(),
@@ -96,6 +104,8 @@ class MediaEditForm extends AbstractForm {
                                if (!empty($contentData['caption'])) I18nHandler::getInstance()->setValues('caption', $contentData['caption']);
                                if (!empty($contentData['title'])) I18nHandler::getInstance()->setValues('title', $contentData['title']);
                        }
+                       
+                       $this->aclValues = SimpleAclHandler::getInstance()->getValues('com.woltlab.wcf.media', $this->media->mediaID);
                }
                
                if (!$this->languageID) {
@@ -114,6 +124,8 @@ class MediaEditForm extends AbstractForm {
                        if (isset($_POST['languageID'])) $this->languageID = intval($_POST['languageID']);
                }
                I18nHandler::getInstance()->readValues();
+               
+               if (isset($_POST['aclValues']) && is_array($_POST['aclValues'])) $this->aclValues = $_POST['aclValues'];
        }
        
        /**
@@ -151,6 +163,9 @@ class MediaEditForm extends AbstractForm {
                ]));
                $this->objectAction->executeAction();
                
+               // save acl
+               SimpleAclHandler::getInstance()->setValues('com.woltlab.wcf.media', $this->media->mediaID, $this->aclValues);
+               
                $this->saved();
                
                WCF::getTPL()->assign('success', true);
index 78da2ee575f7b02eb94823947c1decdfd76063df..abab56b4ba5fca5b315eb2d8c40a0539ad58d543 100644 (file)
@@ -12,7 +12,7 @@ use wcf\data\DatabaseObjectDecorator;
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    WoltLabSuite\Core\Data\Article\Content
  * @since      3.0
- *
+ * 
  * @method     ArticleContent  getDecoratedObject()
  * @mixin      ArticleContent
  */
@@ -34,25 +34,10 @@ class ViewableArticleContent extends DatabaseObjectDecorator {
         */
        protected $article;
        
-       /**
-        * Gets a specific article content decorated as viewable article content.
-        *
-        * @param       integer         $articleContentID
-        * @return      ViewableArticleContent
-        */
-       public static function getArticleContent($articleContentID) {
-               $list = new ViewableArticleContentList();
-               $list->setObjectIDs([$articleContentID]);
-               $list->readObjects();
-               $objects = $list->getObjects();
-               if (isset($objects[$articleContentID])) return $objects[$articleContentID];
-               return null;
-       }
-       
        /**
         * Returns article object.
-        *
-        * @return ViewableArticle
+        * 
+        * @return      ViewableArticle
         */
        public function getArticle() {
                if ($this->article === null) {
@@ -64,27 +49,29 @@ class ViewableArticleContent extends DatabaseObjectDecorator {
        
        /**
         * Sets the article objects.
-        *
-        * @param ViewableArticle $article
+        * 
+        * @param       ViewableArticle         $article
         */
        public function setArticle(ViewableArticle $article) {
                $this->article = $article;
        }
        
        /**
-        * Returns the article's image.
-        *
-        * @return ViewableMedia
+        * Returns the article's image if the active user can access it or `null`.
+        * 
+        * @return      ViewableMedia|null
         */
        public function getImage() {
                if ($this->image === null) {
                        if ($this->imageID) {
                                $this->image = ViewableMedia::getMedia($this->imageID);
-                               
-                               $this->image->setLinkParameters(['articleID' => $this->articleID]);
                        }
                }
                
+               if ($this->image === null || !$this->image->isAccessible()) {
+                       return null;
+               }
+               
                return $this->image;
        }
        
@@ -95,6 +82,19 @@ class ViewableArticleContent extends DatabaseObjectDecorator {
         */
        public function setImage(ViewableMedia $image) {
                $this->image = $image;
-               $this->image->setLinkParameters(['articleID' => $this->articleID]);
+       }
+       
+       /**
+        * Returns a specific article content decorated as viewable article content.
+        * 
+        * @param       integer         $articleContentID
+        * @return      ViewableArticleContent
+        */
+       public static function getArticleContent($articleContentID) {
+               $list = new ViewableArticleContentList();
+               $list->setObjectIDs([$articleContentID]);
+               $list->readObjects();
+               
+               return $list->search($articleContentID);
        }
 }
index f6511043f55e8e4813ff55da28570600003af32b..35bd9c01569d66efb4f9661100576c4cb5647335 100644 (file)
@@ -28,7 +28,7 @@ use wcf\system\WCF;
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    WoltLabSuite\Core\Data\Box
  * @since      3.0
- *
+ * 
  * @property-read      integer         $boxID
  * @property-read      integer|null    $objectTypeID           id of the box controller object type
  * @property-read      string          $identifier
@@ -107,6 +107,17 @@ class Box extends DatabaseObject {
         */
        public $boxContents;
        
+       /**
+        * @var IMenuPageHandler
+        */
+       protected $linkPageHandler;
+       
+       /**
+        * page object
+        * @var Page
+        */
+       protected $linkPage;
+       
        /**
         * @inheritDoc
         */
@@ -133,17 +144,6 @@ class Box extends DatabaseObject {
                }
        }
        
-       /**
-        * @var IMenuPageHandler
-        */
-       protected $linkPageHandler;
-       
-       /**
-        * page object
-        * @var Page
-        */
-       protected $linkPage;
-       
        /**
         * Returns true if the active user can delete this box.
         * 
@@ -323,56 +323,37 @@ class Box extends DatabaseObject {
         * @return      ViewableMedia
         */
        public function getImage() {
-               if ($this->boxType == 'system') {
-                       return $this->getController()->getImage();
-               }
-               else if ($this->boxType == 'menu') {
+               if ($this->boxType === 'menu') {
                        return null;
                }
                
-               if ($this->image !== null) {
-                       return $this->image;
-               }
-               
-               $this->getBoxContents();
-               if ($this->isMultilingual) {
-                       if (isset($this->boxContents[WCF::getLanguage()->languageID]) && $this->boxContents[WCF::getLanguage()->languageID]->imageID) {
-                               $this->image = ViewableMedia::getMedia($this->boxContents[WCF::getLanguage()->languageID]->imageID);
+               if ($this->image === null) {
+                       if ($this->boxType === 'system') {
+                               $this->image = $this->getController()->getImage();
+                       }
+                       else {
+                               $this->getBoxContents();
+                               if ($this->isMultilingual) {
+                                       if (isset($this->boxContents[WCF::getLanguage()->languageID]) && $this->boxContents[WCF::getLanguage()->languageID]->imageID) {
+                                               $this->image = ViewableMedia::getMedia($this->boxContents[WCF::getLanguage()->languageID]->imageID);
+                                       }
+                               }
+                               else if (isset($this->boxContents[0]) && $this->boxContents[0]->imageID) {
+                                       $this->image = ViewableMedia::getMedia($this->boxContents[0]->imageID);
+                               }
                        }
-               }
-               else if (isset($this->boxContents[0]) && $this->boxContents[0]->imageID) {
-                       $this->image = ViewableMedia::getMedia($this->boxContents[0]->imageID);
-               }
-               
-               $this->image->setLinkParameters(['boxID' => $this->boxID]);
-               
-               return $this->image;
-       }
-       
-       /**
-        * Returns true if this box has an image.
-        * 
-        * @return      boolean
-        */
-       public function hasImage() {
-               if ($this->boxType == 'system') {
-                       return $this->getController()->hasImage();
-               }
-               else if ($this->boxType == 'menu') {
-                       return false;
                }
                
-               $this->getBoxContents();
-               if ($this->isMultilingual) {
-                       return (isset($this->boxContents[WCF::getLanguage()->languageID]) && $this->boxContents[WCF::getLanguage()->languageID]->imageID);
+               if ($this->image === null || !$this->image->isAccessible()) {
+                       return null;
                }
                
-               return (isset($this->boxContents[0]) && $this->boxContents[0]->imageID);
+               return $this->image;
        }
        
        /**
         * Returns the URL of this box.
-        *
+        * 
         * @return      string
         */
        public function getLink() {
index 18caa5934b1ff9911012920c7e989404d845aaa9..57037182a25b9a6154494edc094968ee08352a04 100644 (file)
@@ -3,6 +3,7 @@ namespace wcf\data\media;
 use wcf\data\DatabaseObject;
 use wcf\data\ILinkableObject;
 use wcf\data\IThumbnailFile;
+use wcf\system\acl\simple\SimpleAclResolver;
 use wcf\system\request\IRouteController;
 use wcf\system\request\LinkHandler;
 use wcf\system\WCF;
@@ -53,12 +54,6 @@ class Media extends DatabaseObject implements ILinkableObject, IRouteController,
         */
        protected $i18nData;
        
-       /**
-        * parameters used to build the link to the media file
-        * @var array
-        */
-       protected $linkParameters = [];
-       
        /**
         * @inheritDoc
         */
@@ -100,18 +95,7 @@ class Media extends DatabaseObject implements ILinkableObject, IRouteController,
         * @inheritDoc
         */
        public function getLink() {
-               return LinkHandler::getInstance()->getLink('Media', array_merge($this->linkParameters, [
-                       'object' => $this
-               ]));
-       }
-       
-       /**
-        * Sets additional parameters used to build the link to the media file.
-        * 
-        * @param       array           $parameters
-        */
-       public function setLinkParameters(array $parameters) {
-               $this->linkParameters = $parameters;
+               return LinkHandler::getInstance()->getLink('Media', ['object' => $this]);
        }
        
        /**
@@ -133,10 +117,10 @@ class Media extends DatabaseObject implements ILinkableObject, IRouteController,
                        return $this->getLink();
                }
                
-               return LinkHandler::getInstance()->getLink('Media', array_merge($this->linkParameters, [
+               return LinkHandler::getInstance()->getLink('Media', [
                        'object' => $this,
                        'thumbnail' => $size
-               ]));
+               ]);
        }
        
        /**
@@ -224,6 +208,15 @@ class Media extends DatabaseObject implements ILinkableObject, IRouteController,
                return $this->i18nData;
        }
        
+       /**
+        * Returns true if the media file can be accessed by the active user.
+        * 
+        * @return      boolean
+        */
+       public function isAccessible() {
+               return WCF::getSession()->getPermission('admin.content.cms.canManageMedia') || SimpleAclResolver::getInstance()->canAccess('com.woltlab.wcf.media', $this->mediaID);
+       }
+       
        /**
         * Returns the storage path of the media files.
         * 
index 475c12530d235194cdf50c12aec8f560c9b14468..0c40ecabcc5d817c7d9f97b0d45ac5bb38188bf6 100644 (file)
@@ -3,6 +3,7 @@ namespace wcf\data\media;
 use wcf\data\AbstractDatabaseObjectAction;
 use wcf\data\ISearchAction;
 use wcf\data\IUploadAction;
+use wcf\system\acl\simple\SimpleAclHandler;
 use wcf\system\clipboard\ClipboardHandler;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
 use wcf\system\exception\PermissionDeniedException;
@@ -238,6 +239,8 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
         */
        public function validateGetEditorDialog() {
                WCF::getSession()->checkPermissions(['admin.content.cms.canManageMedia']);
+               
+               $this->getSingleObject();
        }
        
        /**
@@ -246,15 +249,21 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
         * @return      string[]
         */
        public function getEditorDialog() {
-               I18nHandler::getInstance()->register('title');
-               I18nHandler::getInstance()->register('caption');
-               I18nHandler::getInstance()->register('altText');
+               $media = new ViewableMedia($this->getSingleObject()->getDecoratedObject());
+               
+               I18nHandler::getInstance()->register('title_' . $media->mediaID);
+               I18nHandler::getInstance()->register('caption_' . $media->mediaID);
+               I18nHandler::getInstance()->register('altText_' . $media->mediaID);
                I18nHandler::getInstance()->assignVariables();
                
                return [
                        'template' => WCF::getTPL()->fetch('mediaEditor', 'wcf', [
+                               '__aclSimplePrefix' => 'mediaEditor_' . $media->mediaID . '_',
+                               'aclValues' => SimpleAclHandler::getInstance()->getValues('com.woltlab.wcf.media', $media->mediaID),
+                               '__languageChooserPrefix' => 'mediaEditor_' . $media->mediaID . '_',
                                'languageID' => WCF::getUser()->languageID,
-                               'languages' => LanguageFactory::getInstance()->getLanguages()
+                               'languages' => LanguageFactory::getInstance()->getLanguages(),
+                               'media' => $media
                        ])
                ];
        }
@@ -362,6 +371,10 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
                                        ]);
                                }
                        }
+                       
+                       if (!empty($this->parameters['aclValues'])) {
+                               SimpleAclHandler::getInstance()->setValues('com.woltlab.wcf.media', $media->mediaID, $this->parameters['aclValues']);
+                       }
                }
        }
        
index f30148903188e2232cc877d84e655fd6a6a7004e..2568f41e58615ce504ec498e61c3f8e70ce31450 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 namespace wcf\data\media;
+use wcf\data\user\UserProfile;
 use wcf\data\DatabaseObjectDecorator;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
 use wcf\util\FileUtil;
 use wcf\util\StringUtil;
 
@@ -20,6 +22,12 @@ use wcf\util\StringUtil;
  * @property-read      string|null     $altText
  */
 class ViewableMedia extends DatabaseObjectDecorator {
+       /**
+        * user profile of the user who uploaded the media file
+        * @var UserProfile
+        */
+       protected $userProfile;
+       
        /**
         * @inheritDoc
         */
@@ -70,6 +78,24 @@ class ViewableMedia extends DatabaseObjectDecorator {
                return '<img src="'.StringUtil::encodeHTML($this->getThumbnailLink($size)).'" alt="'.StringUtil::encodeHTML($this->altText).'" '.($this->title ? 'title="'.StringUtil::encodeHTML($this->title).'" ' : '').'style="width: ' . $this->getThumbnailWidth($size) . 'px; height: ' . $this->getThumbnailHeight($size) . 'px;">';
        }
        
+       /**
+        * Returns the user profile of the user who uploaded the media file.
+        * 
+        * @return      UserProfile
+        */
+       public function getUserProfile() {
+               if ($this->userProfile === null) {
+                       if ($this->userID) {
+                               $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->userID);
+                       }
+                       else {
+                               $this->userProfile = UserProfile::getGuestUserProfile($this->username);
+                       }
+               }
+               
+               return $this->userProfile;
+       }
+       
        /**
         * Returns the viewable media file with the given id.
         * 
index 514573882cb1eb2d2e4612aabc5510f547fb304e..ddf24739b2c562b7deafdc7a7473e6bf1307b857 100644 (file)
@@ -23,30 +23,6 @@ use wcf\util\StringUtil;
  * @since      3.0
  */
 class MediaPage extends AbstractPage {
-       /**
-        * article which uses the media file as the main article image
-        * @var Article|null
-        */
-       public $article;
-       
-       /**
-        * id of the article which uses the media file as the main article image
-        * @var integer
-        */
-       public $articleID = 0;
-       
-       /**
-        * box which uses the media file as box image
-        * @var Box
-        */
-       public $box;
-       
-       /**
-        * id of the box which uses the media file as box image
-        * @var integer
-        */
-       public $boxID = 0;
-       
        /**
         * etag for the media file
         * @var string
@@ -65,24 +41,6 @@ class MediaPage extends AbstractPage {
         */
        public $media;
        
-       /**
-        * message in which the media is embedded
-        * @var IMessage
-        */
-       public $message;
-       
-       /**
-        * id of the message in which the media is embedded
-        * @var integer
-        */
-       public $messageID = 0;
-       
-       /**
-        * name of the object type of the message in which the media is embedded
-        * @var string
-        */
-       public $messageObjectType = '';
-       
        /**
         * id of the requested media file
         * @var integer
@@ -113,46 +71,6 @@ class MediaPage extends AbstractPage {
                'image/pjpeg'
        ];
        
-       /**
-        * @inheritDoc
-        */
-       public function checkPermissions() {
-               parent::checkPermissions();
-               
-               if (!WCF::getSession()->getPermission('admin.content.cms.canManageMedia')) {
-                       if ($this->articleID) {
-                               $this->article = new Article($this->articleID);
-                               
-                               if (!$this->article->articleID || !$this->article->canRead()) {
-                                       throw new PermissionDeniedException();
-                               }
-                       }
-                       else if ($this->boxID) {
-                               $this->box = BoxHandler::getInstance()->getBox($this->boxID);
-                               
-                               if ($this->box === null || !$this->box->isAccessible()) {
-                                       throw new PermissionDeniedException();
-                               }
-                       }
-                       else if ($this->messageID) {
-                               MessageEmbeddedObjectManager::getInstance()->loadObjects($this->messageObjectType, [$this->messageID]);
-                               $this->message = MessageEmbeddedObjectManager::getInstance()->getObject($this->messageObjectType, $this->messageID);
-                               if ($this->message === null || !($this->message instanceof IMessage) || !$this->message->isVisible()) {
-                                       throw new PermissionDeniedException();
-                               }
-                       }
-                       else {
-                               $parameters = ['canAccess' => false];
-                               
-                               EventHandler::getInstance()->fireAction($this, 'checkMediaAccess', $parameters);
-                               
-                               if (empty($parameters['canAccess'])) {
-                                       throw new PermissionDeniedException();
-                               }
-                       }
-               }
-       }
-       
        /**
         * @inheritDoc
         */
@@ -201,6 +119,9 @@ class MediaPage extends AbstractPage {
                if (!$this->media->mediaID) {
                        throw new IllegalLinkException();
                }
+               if (!$this->media->isAccessible()) {
+                       throw new PermissionDeniedException();
+               }
                
                if (isset($_REQUEST['thumbnail'])) $this->thumbnail = StringUtil::trim($_REQUEST['thumbnail']);
                if ($this->thumbnail && !isset(Media::getThumbnailSizes()[$this->thumbnail])) {
@@ -210,18 +131,6 @@ class MediaPage extends AbstractPage {
                if ($this->thumbnail && !$this->media->{$this->thumbnail.'ThumbnailType'}) {
                        $this->thumbnail = '';
                }
-               
-               // read context parameters
-               if (isset($_REQUEST['articleID'])) {
-                       $this->articleID = intval($_REQUEST['articleID']);
-               }
-               else if (isset($_REQUEST['boxID'])) {
-                       $this->boxID = intval($_REQUEST['boxID']);
-               }
-               else if (isset($_REQUEST['messageObjectType']) && isset($_REQUEST['messageID'])) {
-                       $this->messageObjectType = StringUtil::trim($_REQUEST['messageObjectType']);
-                       $this->messageID = intval($_REQUEST['messageID']);
-               }
        }
        
        /**
index 8b8a9671efefc472a7b2e00e510424abed18cb72..73742704eb3198c4552a6033401d72ed3a8efcee 100644 (file)
@@ -69,13 +69,6 @@ abstract class AbstractBoxController implements IBoxController {
                return null;
        }
        
-       /**
-        * @inheritDoc
-        */
-       public function hasImage() {
-               return false;
-       }
-       
        /**
         * @inheritDoc
         */
index fc06a71f1d8886e8787200e5c28c23180adedaeb..f279bd020ca601d854b4f5993fa5e22eadc11e28 100644 (file)
@@ -4,7 +4,7 @@ use wcf\data\box\Box;
 
 /**
  * Default interface for box controllers.
- *
+ * 
  * @author     Marcel Werk
  * @copyright  2001-2016 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
@@ -28,18 +28,13 @@ interface IBoxController {
        
        /**
         * Returns the image of this box.
+        * 
+        * Note: The box itself checks if the active user can access the returned media file.
         *
         * @return      \wcf\data\media\ViewableMedia
         */
        public function getImage();
        
-       /**
-        * Returns true if this box has an image.
-        *
-        * @return      boolean
-        */
-       public function hasImage();
-       
        /**
         * Returns the title link of this box.
         *
index a2a7abda8c7b1d2e82fb9fe7e8f6c9f2786ae739..55b8e5db3cd9ab8121f92a24446558dca8e05ea3 100644 (file)
        }
 }
 
-#mediaEditor {
-       #mediaThumbnail {
+[id^=mediaEditor] {
+       .mediaThumbnail {
                text-align: center;
+               margin-bottom: 20px;
                
                + .box48 > dl {
                        font-size: $wcfFontSizeSmall;
index 8161f6a8b67faab43192b977d0eb53593accd50d..aeb409af4ccebd162737ae22b94890e1414b4519 100644 (file)
@@ -2478,7 +2478,7 @@ Errors are:
                <item name="wcf.media.filename"><![CDATA[Filename]]></item>
                <item name="wcf.media.filesize"><![CDATA[Filesize]]></item>
                <item name="wcf.media.imageDimensions"><![CDATA[Dimensions]]></item>
-               <item name="wcf.media.imageDimensions.value"><![CDATA[{#$width}×{#$height}]]></item>
+               <item name="wcf.media.imageDimensions.value"><![CDATA[{#$media->width}×{#$media->height}]]></item>
                <item name="wcf.media.insert"><![CDATA[Insert File]]></item>
                <item name="wcf.media.insert.imageSize"><![CDATA[Image Size]]></item>
                <item name="wcf.media.insert.imageSize.large"><![CDATA[Large Thumbnail]]></item>