<import>
<smiley name=":)">
<title>smile</title>
- <path>images/smilies/smile_emojione.png</path>
+ <path>images/smilies/emojione/263a.png</path>
+ <path2x>images/smilies/emojione/263a@2x.png</path2x>
<aliases><![CDATA[:-)
(:]]></aliases>
</smiley>
<smiley name=":(">
<title>sad</title>
- <path>images/smilies/sad_emojione.png</path>
+ <path>images/smilies/emojione/2639.png</path>
+ <path2x>images/smilies/emojione/2639@2x.png</path2x>
<aliases><![CDATA[:-(
):]]></aliases>
</smiley>
<smiley name=";)">
<title>wink</title>
- <path>images/smilies/wink_emojione.png</path>
+ <path>images/smilies/emojione/1f609.png</path>
+ <path2x>images/smilies/emojione/1f609@2x.png</path2x>
<aliases><![CDATA[;-)
(;]]></aliases>
</smiley>
<smiley name=":P">
<title>tongue</title>
- <path>images/smilies/tongue_emojione.png</path>
+ <path>images/smilies/emojione/1f61b.png</path>
+ <path2x>images/smilies/emojione/1f61b@2x.png</path2x>
<aliases><![CDATA[:-P]]></aliases>
</smiley>
<smiley name="^^">
<title>grin</title>
- <path>images/smilies/grin_emojione.png</path>
+ <path>images/smilies/emojione/1f600.png</path>
+ <path2x>images/smilies/emojione/1f600@2x.png</path2x>
<aliases><![CDATA[^.^
^_^
^-^]]></aliases>
</smiley>
<smiley name=":D">
<title>biggrin</title>
- <path>images/smilies/biggrin_emojione.png</path>
+ <path>images/smilies/emojione/1f601.png</path>
+ <path2x>images/smilies/emojione/1f601@2x.png</path2x>
<aliases><![CDATA[:-D]]></aliases>
</smiley>
<smiley name=";(">
<title>crying</title>
- <path>images/smilies/crying_emojione.png</path>
+ <path>images/smilies/emojione/1f62d.png</path>
+ <path2x>images/smilies/emojione/1f62d@2x.png</path2x>
<aliases><![CDATA[;-(
:'(
;_;]]></aliases>
</smiley>
<smiley name="X(">
<title>angry</title>
- <path>images/smilies/angry_emojione.png</path>
+ <path>images/smilies/emojione/1f620.png</path>
+ <path2x>images/smilies/emojione/1f620@2x.png</path2x>
<aliases><![CDATA[>.<
>_<]]></aliases>
</smiley>
<smiley name=":*">
<title>kiss</title>
- <path>images/smilies/kiss_emojione.png</path>
+ <path>images/smilies/emojione/1f618.png</path>
+ <path2x>images/smilies/emojione/1f618@2x.png</path2x>
<aliases><![CDATA[:-*
*:]]></aliases>
</smiley>
<smiley name=":|">
<title>mellow</title>
- <path>images/smilies/mellow_emojione.png</path>
+ <path>images/smilies/emojione/1f610.png</path>
+ <path2x>images/smilies/emojione/1f610@2x.png</path2x>
</smiley>
<smiley name="8o">
<title>w00t</title>
- <path>images/smilies/w00t_emojione.png</path>
+ <path>images/smilies/emojione/1f62f.png</path>
+ <path2x>images/smilies/emojione/1f62f@2x.png</path2x>
</smiley>
<smiley name="=O">
<title>scared</title>
- <path>images/smilies/scared_emojione.png</path>
+ <path>images/smilies/emojione/1f631.png</path>
+ <path2x>images/smilies/emojione/1f631@2x.png</path2x>
</smiley>
<smiley name="<X">
<title>sick</title>
- <path>images/smilies/sick_emojione.png</path>
+ <path>images/smilies/emojione/1f922.png</path>
+ <path2x>images/smilies/emojione/1f922@2x.png</path2x>
</smiley>
<smiley name="||">
<title>tired</title>
- <path>images/smilies/tired_emojione.png</path>
+ <path>images/smilies/emojione/1f62b.png</path>
+ <path2x>images/smilies/emojione/1f62b@2x.png</path2x>
</smiley>
<smiley name=":/">
<title>unsure</title>
- <path>images/smilies/unsure_emojione.png</path>
+ <path>images/smilies/emojione/1f914.png</path>
+ <path2x>images/smilies/emojione/1f914@2x.png</path2x>
</smiley>
<smiley name=":S">
<title>wacko</title>
- <path>images/smilies/wacko_emojione.png</path>
+ <path>images/smilies/emojione/1f635.png</path>
+ <path2x>images/smilies/emojione/1f635@2x.png</path2x>
</smiley>
<smiley name="X/">
<title>pinch</title>
- <path>images/smilies/pinch_emojione.png</path>
+ <path>images/smilies/emojione/1f612.png</path>
+ <path2x>images/smilies/emojione/1f612@2x.png</path2x>
</smiley>
<smiley name="8)">
<title>cool</title>
- <path>images/smilies/cool_emojione.png</path>
+ <path>images/smilies/emojione/1f60e.png</path>
+ <path2x>images/smilies/emojione/1f60e@2x.png</path2x>
</smiley>
<smiley name="?(">
<title>confused</title>
- <path>images/smilies/confused_emojione.png</path>
+ <path>images/smilies/emojione/1f614.png</path>
+ <path2x>images/smilies/emojione/1f614@2x.png</path2x>
</smiley>
<smiley name=":huh:">
<title>Huh</title>
- <path>images/smilies/huh_emojione.png</path>
+ <path>images/smilies/emojione/1f62e.png</path>
+ <path2x>images/smilies/emojione/1f62e@2x.png</path2x>
</smiley>
<smiley name=":rolleyes:">
<title>rolleyes</title>
- <path>images/smilies/rolleyes_emojione.png</path>
+ <path>images/smilies/emojione/1f644.png</path>
+ <path2x>images/smilies/emojione/1f644@2x.png</path2x>
</smiley>
<smiley name=":love:">
<title>love</title>
- <path>images/smilies/love_emojione.png</path>
+ <path>images/smilies/emojione/1f60d.png</path>
+ <path2x>images/smilies/emojione/1f60d@2x.png</path2x>
</smiley>
<smiley name="8|">
<title>blink</title>
- <path>images/smilies/blink_emojione.png</path>
+ <path>images/smilies/emojione/1f615.png</path>
+ <path2x>images/smilies/emojione/1f615@2x.png</path2x>
<aliases><![CDATA[o.O]]></aliases>
</smiley>
<smiley name=":cursing:">
<title>cursing</title>
- <path>images/smilies/cursing_emojione.png</path>
+ <path>images/smilies/emojione/1f621.png</path>
+ <path2x>images/smilies/emojione/1f621@2x.png</path2x>
</smiley>
<smiley name=":thumbdown:">
<title>thumbdown</title>
- <path>images/smilies/thumbdown_emojione.png</path>
+ <path>images/smilies/emojione/1f44e.png</path>
+ <path2x>images/smilies/emojione/1f44e@2x.png</path2x>
</smiley>
<smiley name=":thumbup:">
<title>thumbup</title>
- <path>images/smilies/thumbup_emojione.png</path>
+ <path>images/smilies/emojione/1f44d.png</path>
+ <path2x>images/smilies/emojione/1f44d@2x.png</path2x>
<aliases><![CDATA[:thumbsup:]]></aliases>
</smiley>
<smiley name=":sleeping:">
<title>sleeping</title>
- <path>images/smilies/sleeping_emojione.png</path>
+ <path>images/smilies/emojione/1f634.png</path>
+ <path2x>images/smilies/emojione/1f634@2x.png</path2x>
</smiley>
<smiley name=":whistling:">
<title>whistling</title>
- <path>images/smilies/whistling_emojione.png</path>
+ <path>images/smilies/emojione/1f61e.png</path>
+ <path2x>images/smilies/emojione/1f61e@2x.png</path2x>
</smiley>
<smiley name=":evil:">
<title>evil</title>
- <path>images/smilies/evil_emojione.png</path>
+ <path>images/smilies/emojione/1f608.png</path>
+ <path2x>images/smilies/emojione/1f608@2x.png</path2x>
</smiley>
<smiley name=":saint:">
<title>saint</title>
- <path>images/smilies/saint_emojione.png</path>
+ <path>images/smilies/emojione/1f607.png</path>
+ <path2x>images/smilies/emojione/1f607@2x.png</path2x>
</smiley>
<smiley name="<3">
<title>heart</title>
- <path>images/smilies/heart_emojione.png</path>
+ <path>images/smilies/emojione/2764.png</path>
+ <path2x>images/smilies/emojione/2764@2x.png</path2x>
</smiley>
<smiley name=":!:">
<title>attention</title>
- <path>images/smilies/attention_emojione.png</path>
+ <path>images/smilies/emojione/2757.png</path>
+ <path2x>images/smilies/emojione/2757@2x.png</path2x>
</smiley>
<smiley name=":?:">
<title>question</title>
- <path>images/smilies/question_emojione.png</path>
+ <path>images/smilies/emojione/2753.png</path>
+ <path2x>images/smilies/emojione/2753@2x.png</path2x>
</smiley>
</import>
</data>
<ul class="inlineList smileyList">
{foreach from=$smilies item=smiley}
- <li><a title="{lang}{$smiley->smileyTitle}{/lang}" class="jsTooltip jsSmiley" data-smiley-code="{$smiley->smileyCode}" data-smiley-path="{$smiley->getURL()}"><img src="{$smiley->getURL()}" alt="{$smiley->smileyCode}"></a></li>
+ <li><a title="{lang}{$smiley->smileyTitle}{/lang}" class="jsTooltip jsSmiley">{@$smiley->getHtml()}</a></li>
{/foreach}
</ul>
\ No newline at end of file
<section class="section">
<h2 class="sectionTitle">{lang}wcf.acp.smiley.smileyFile{/lang}</h2>
- <dl{if $errorField == 'fileUpload'} class="formError"{/if}>
- <dt><label for="fileUpload">{lang}wcf.acp.smiley.fileUpload{/lang}</label></dt>
- <dd>
- {if $uploadedFilename}
- <img src="{@$__wcf->getPath()}images/smilies/{$uploadedFilename}" alt="">
- <input type="hidden" name="uploadedFilename" value="{$uploadedFilename}">
- {/if}
- <input type="file" id="fileUpload" name="fileUpload" value="">
-
- {if $errorField == 'fileUpload'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {else}
- {lang}wcf.acp.smiley.fileUpload.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- <small>{lang}wcf.acp.smiley.fileUpload.description{/lang}</small>
- </dd>
- </dl>
-
- <dl{if $errorField == 'smileyPath'} class="formError"{/if}>
- <dt><label for="smileyPath">{lang}wcf.acp.smiley.smileyPath{/lang}</label></dt>
- <dd>
- <input type="text" id="smileyPath" name="smileyPath" value="{$smileyPath}" class="long">
-
- {if $errorField == 'smileyPath'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {else}
- {lang}wcf.acp.smiley.smileyPath.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- <small>{lang}wcf.acp.smiley.smileyPath.description{/lang}</small>
- </dd>
- </dl>
+ <div class="row rowColGap formGrid">
+ <dl class="col-xs-12 col-md-6{if $errorField == 'fileUpload'} formError{/if}">
+ <dt><label for="fileUpload">{lang}wcf.acp.smiley.fileUpload{/lang}</label></dt>
+ <dd>
+ {if $uploadedFilename}
+ <input type="hidden" name="uploadedFilename" value="{$uploadedFilename}">
+ {/if}
+ <input type="file" id="fileUpload" name="fileUpload" value="">
+
+ {if $errorField == 'fileUpload'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {else}
+ {lang}wcf.acp.smiley.fileUpload.error.{@$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ <small>{lang}wcf.acp.smiley.fileUpload.description{/lang}</small>
+ </dd>
+ </dl>
+
+ <dl class="col-xs-12 col-md-6{if $errorField == 'smileyPath'} formError{/if}">
+ <dt><label for="smileyPath">{lang}wcf.acp.smiley.smileyPath{/lang}</label></dt>
+ <dd>
+ <input type="text" id="smileyPath" name="smileyPath" value="{$smileyPath}" class="long">
+
+ {if $errorField == 'smileyPath'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {else}
+ {lang}wcf.acp.smiley.smileyPath.error.{@$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ <small>{lang}wcf.acp.smiley.smileyPath.description{/lang}</small>
+ </dd>
+ </dl>
+ </div>
{event name='smileyFileFields'}
</section>
+ <section class="section">
+ <header class="sectionHeader">
+ <h2 class="sectionTitle">{lang}wcf.acp.smiley.smileyFile2x{/lang}</h2>
+ <p class="sectionDescription">{lang}wcf.acp.smiley.smileyFile2x.description{/lang}</p>
+ </header>
+
+ <div class="row rowColGap formGrid">
+ <dl class="col-xs-12 col-md-6{if $errorField == 'fileUpload2x'} formError{/if}">
+ <dt><label for="fileUpload2x">{lang}wcf.acp.smiley.fileUpload{/lang}</label></dt>
+ <dd>
+ {if $uploadedFilename2x}
+ <input type="hidden" name="uploadedFilename2x" value="{$uploadedFilename2x}">
+ {/if}
+ <input type="file" id="fileUpload2x" name="fileUpload2x" value="">
+
+ {if $errorField == 'fileUpload2x'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {else}
+ {lang}wcf.acp.smiley.fileUpload.error.{@$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ <small>{lang}wcf.acp.smiley.fileUpload.description{/lang}</small>
+ </dd>
+ </dl>
+
+ <dl class="col-xs-12 col-md-6{if $errorField == 'smileyPath2x'} formError{/if}">
+ <dt><label for="smileyPath2x">{lang}wcf.acp.smiley.smileyPath{/lang}</label></dt>
+ <dd>
+ <input type="text" id="smileyPath2x" name="smileyPath2x" value="{$smileyPath2x}" class="long">
+
+ {if $errorField == 'smileyPath2x'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {else}
+ {lang}wcf.acp.smiley.smileyPath.error.{@$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ <small>{lang}wcf.acp.smiley.smileyPath.description{/lang}</small>
+ </dd>
+ </dl>
+ </div>
+
+ {event name='smileyFile2xFields'}
+ </section>
+
{event name='sections'}
<div class="formSubmit">
{foreach from=$objects item=smiley}
<li class="sortableNode sortableNoNesting smileyRow" data-object-id="{@$smiley->smileyID}">
<span class="sortableNodeLabel">
- <a href="{link controller='SmileyEdit' id=$smiley->smileyID}{/link}"><img src="{$smiley->getURL()}" alt="" class="smiley"> {lang}{$smiley->smileyTitle}{/lang}</a> <span class="badge">{$smiley->smileyCode}</span>{foreach from=$smiley->getAliases() item='alias'} <span class="badge" style="margin-left: 5px">{$alias}</span>{/foreach}
+ <a href="{link controller='SmileyEdit' id=$smiley->smileyID}{/link}">{@$smiley->getHtml()} {lang}{$smiley->smileyTitle}{/lang}</a> <span class="badge">{$smiley->smileyCode}</span>{foreach from=$smiley->getAliases() item='alias'} <span class="badge" style="margin-left: 5px">{$alias}</span>{/foreach}
<span class="statusDisplay sortableButtonContainer">
<a href="{link controller='SmileyEdit' id=$smiley->smileyID}{/link}"><span title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip icon icon16 fa-pencil"></a>
_insert: function(data) {
this.buffer.set();
- this.insert.html('<img src="' + data.path + '" class="smiley" alt="' + data.code + '">');
+ this.insert.html(data.img.cloneNode().outerHTML);
}
}
};
require(['EventHandler'], (function(EventHandler) {
EventHandler.fire('com.woltlab.wcf.redactor2', 'insertSmiley_' + this._editorId, {
- code: elData(event.currentTarget, 'smiley-code'),
- path: elData(event.currentTarget, 'smiley-path')
+ img: event.currentTarget.children[0]
});
}).bind(this));
}
public $smileyCode = '';
/**
- * showorder value
+ * show order value
* @var integer
*/
public $showOrder = 0;
*/
public $smileyPath = '';
+ /**
+ * path to the smiley file (2x)
+ * @var string
+ */
+ public $smileyPath2x = '';
+
/**
* node tree with available smiley categories
* @var CategoryNodeTree
/**
* data of the uploaded smiley file
- * @var array()
+ * @var array
*/
public $fileUpload = [];
+ /**
+ * data of the uploaded smiley file (2x)
+ * @var array
+ */
+ public $fileUpload2x = [];
+
/**
* temporary name of the uploaded smiley file
* @var string
*/
public $uploadedFilename = '';
+ /**
+ * temporary name of the uploaded smiley file (2x)
+ * @var string
+ */
+ public $uploadedFilename2x = '';
+
/**
* @inheritDoc
*/
'smileyCode' => $this->smileyCode,
'aliases' => $this->aliases,
'smileyPath' => $this->smileyPath,
+ 'smileyPath2x' => $this->smileyPath2x,
'categoryNodeList' => $this->categoryNodeTree->getIterator(),
- 'uploadedFilename' => $this->uploadedFilename
+ 'uploadedFilename' => $this->uploadedFilename,
+ 'uploadedFilename2x' => $this->uploadedFilename2x
]);
}
if (isset($_POST['smileyPath'])) $this->smileyPath = FileUtil::removeLeadingSlash(StringUtil::trim($_POST['smileyPath']));
if (isset($_POST['uploadedFilename'])) $this->uploadedFilename = StringUtil::trim($_POST['uploadedFilename']);
if (isset($_FILES['fileUpload'])) $this->fileUpload = $_FILES['fileUpload'];
+ if (isset($_POST['smileyPath2x'])) $this->smileyPath2x = FileUtil::removeLeadingSlash(StringUtil::trim($_POST['smileyPath2x']));
+ if (isset($_POST['uploadedFilename2x'])) $this->uploadedFilename2x = StringUtil::trim($_POST['uploadedFilename2x']);
+ if (isset($_FILES['fileUpload2x'])) $this->fileUpload2x = $_FILES['fileUpload2x'];
}
/**
'smileyCode' => $this->smileyCode,
'aliases' => $this->aliases,
'smileyPath' => $this->smileyPath,
+ 'smileyPath2x' => $this->smileyPath2x,
'showOrder' => $this->showOrder,
'categoryID' => $this->categoryID ?: null,
'packageID' => 1
]),
- 'fileLocation' => $this->uploadedFilename ? WCF_DIR.'images/smilies/'.$this->uploadedFilename : ''
+ 'fileLocation' => $this->uploadedFilename ? WCF_DIR.'images/smilies/'.$this->uploadedFilename : '',
+ 'fileLocation2x' => $this->uploadedFilename2x ? WCF_DIR.'images/smilies/'.$this->uploadedFilename2x : ''
]);
$this->objectAction->executeAction();
$returnValues = $this->objectAction->getReturnValues();
$this->smileyCode = '';
$this->categoryID = 0;
$this->showOrder = 0;
- $this->smileyPath = '';
+ $this->smileyPath = $this->smileyPath2x = '';
$this->aliases = '';
- $this->uploadedFilename = '';
+ $this->uploadedFilename = $this->uploadedFilename2x = '';
I18nHandler::getInstance()->reset();
}
}
+ if ($this->uploadedFilename2x) {
+ if (!file_exists(WCF_DIR.'images/smilies/'.$this->uploadedFilename2x)) {
+ $this->uploadedFilename2x = '';
+ throw new UserInputException('fileUpload2x', 'uploadFailed');
+ }
+ }
+ else if (!empty($this->fileUpload2x['name'])) {
+ if (!getimagesize($this->fileUpload2x['tmp_name'])) {
+ $this->uploadedFilename2x = '';
+ throw new UserInputException('fileUpload2x', 'noImage');
+ }
+
+ do {
+ $this->uploadedFilename2x = StringUtil::getRandomID().'.'.mb_strtolower(mb_substr($this->fileUpload2x['name'], mb_strrpos($this->fileUpload2x['name'], '.') + 1));
+ }
+ while (file_exists(WCF_DIR.'images/smilies/'.$this->uploadedFilename2x));
+
+ if (!@move_uploaded_file($this->fileUpload2x['tmp_name'], WCF_DIR.'images/smilies/'.$this->uploadedFilename2x)) {
+ $this->uploadedFilename2x = '';
+ throw new UserInputException('fileUpload2x', 'uploadFailed');
+ }
+ }
+ else if ($this->smileyPath2x && !is_file(WCF_DIR.$this->smileyPath2x)) {
+ throw new UserInputException('smileyPath2x', 'notFound');
+ }
+
// validate title
if (!I18nHandler::getInstance()->validateValue('smileyTitle')) {
if (I18nHandler::getInstance()->isPlainValue('smileyTitle')) {
'smileyCode' => $this->smileyCode,
'aliases' => $this->aliases,
'smileyPath' => $this->smileyPath,
+ 'smileyPath2x' => $this->smileyPath2x,
'showOrder' => $this->showOrder,
'categoryID' => $this->categoryID ?: null
]),
- 'fileLocation' => $this->uploadedFilename ? WCF_DIR.'images/smilies/'.$this->uploadedFilename : ''
+ 'fileLocation' => $this->uploadedFilename ? WCF_DIR.'images/smilies/'.$this->uploadedFilename : '',
+ 'fileLocation2x' => $this->uploadedFilename2x ? WCF_DIR.'images/smilies/'.$this->uploadedFilename2x : ''
]);
$this->objectAction->executeAction();
$this->smileyCode = $this->smiley->smileyCode;
$this->aliases = $this->smiley->aliases;
$this->smileyPath = $this->smiley->smileyPath;
+ $this->smileyPath2x = $this->smiley->smileyPath2x;
$this->showOrder = $this->smiley->showOrder;
$this->categoryID = $this->smiley->categoryID;
}
* @property-read integer $smileyID unique id of the smiley
* @property-read integer $packageID id of the package which delivers the smiley
* @property-read integer|null $categoryID id of the category the smiley belongs to or `null` if it belongs to the default category
- * @property-read string $smileyPath path to the smiley file relative to wcf's defsult path
+ * @property-read string $smileyPath path to the smiley file relative to wcf's default path
+ * @property-read string $smileyPath2x path to the smiley file relative to wcf's default path (2x version)
* @property-read string $smileyTitle title of the smiley
* @property-read string $smileyCode code used for displaying the smiley
* @property-read string $aliases alternative codes used for displaying the smiley
* @property-read integer $showOrder position of the smiley in relation to the other smileys in the same category
*/
class Smiley extends DatabaseObject {
+ protected $height;
+
+ public $smileyCodes;
+
/**
* Returns the url to this smiley.
*
return WCF::getPath().$this->smileyPath;
}
+ public function getURL2x() {
+ return ($this->smileyPath2x) ? WCF::getPath().$this->smileyPath2x : '';
+ }
+
/**
* Returns all aliases for this smiley.
*
return explode("\n", StringUtil::unifyNewlines($this->aliases));
}
+
+ public function getHeight() {
+ if ($this->height === null) {
+ $this->height = 0;
+
+ $file = WCF_DIR . $this->smileyPath;
+ if (file_exists($file) && preg_match('~\.(gif|jpe?g|png)$~', $file)) {
+ $data = getimagesize($file);
+ if ($data !== false) {
+ // index '1' contains the height of the image
+ $this->height = $data[1];
+ }
+ }
+ }
+
+ return $this->height;
+ }
+
+ public function getHtml() {
+ $srcset = ($this->smileyPath2x) ? ' srcset="' . StringUtil::encodeHTML($this->getURL2x()) . ' 2x"' : '';
+ $style = ($this->getHeight()) ? ' style="height: ' . $this->getHeight() . 'px"' : '';
+
+ return '<img src="' . StringUtil::encodeHTML($this->getURL()) . '" alt="' . StringUtil::encodeHTML($this->smileyCode) . '" class="smiley"' . $srcset . $style . '>';
+ }
}
/** @var Smiley $smiley */
$smiley = parent::create();
+ $data = [];
if (!empty($this->parameters['fileLocation'])) {
$smileyFilename = 'smiley'.$smiley->smileyID.'.'.mb_strtolower(mb_substr($this->parameters['fileLocation'], mb_strrpos($this->parameters['fileLocation'], '.') + 1));
@rename($this->parameters['fileLocation'], WCF_DIR.'images/smilies/'.$smileyFilename);
+ $data['smileyPath'] = 'images/smilies/'.$smileyFilename;
+
+
+ }
+ if (!empty($this->parameters['fileLocation2x'])) {
+ $smileyFilename2x = 'smiley'.$smiley->smileyID.'@2x.'.mb_strtolower(mb_substr($this->parameters['fileLocation2x'], mb_strrpos($this->parameters['fileLocation2x'], '.') + 1));
+ @rename($this->parameters['fileLocation2x'], WCF_DIR.'images/smilies/'.$smileyFilename2x);
+
+ $data['smileyPath2x'] = 'images/smilies/'.$smileyFilename2x;
+ }
+
+ if (!empty($data)) {
$smileyEditor = new SmileyEditor($smiley);
- $smileyEditor->update([
- 'smileyPath' => 'images/smilies/'.$smileyFilename
- ]);
+ $smileyEditor->update($data);
$smiley = new Smiley($smiley->smileyID);
}
$this->readObjects();
}
- if (count($this->objects) == 1 && !empty($this->parameters['fileLocation'])) {
- $smiley = reset($this->objects);
- $smileyFilename = 'smiley'.$smiley->smileyID.'.'.mb_strtolower(mb_substr($this->parameters['fileLocation'], mb_strrpos($this->parameters['fileLocation'], '.') + 1));
- @rename($this->parameters['fileLocation'], WCF_DIR.'images/smilies/'.$smileyFilename);
-
- $this->parameters['data']['smileyPath'] = 'images/smilies/'.$smileyFilename;
+ if (count($this->objects) == 1) {
+ if (!empty($this->parameters['fileLocation'])) {
+ $smiley = reset($this->objects);
+ $smileyFilename = 'smiley' . $smiley->smileyID . '.' . mb_strtolower(mb_substr($this->parameters['fileLocation'], mb_strrpos($this->parameters['fileLocation'], '.') + 1));
+ @rename($this->parameters['fileLocation'], WCF_DIR . 'images/smilies/' . $smileyFilename);
+
+ $this->parameters['data']['smileyPath'] = 'images/smilies/' . $smileyFilename;
+ }
+ if (!empty($this->parameters['fileLocation2x'])) {
+ $smiley = reset($this->objects);
+ $smileyFilename2x = 'smiley' . $smiley->smileyID . '@2x.' . mb_strtolower(mb_substr($this->parameters['fileLocation2x'], mb_strrpos($this->parameters['fileLocation2x'], '.') + 1));
+ @rename($this->parameters['fileLocation2x'], WCF_DIR . 'images/smilies/' . $smileyFilename2x);
+
+ $this->parameters['data']['smileyPath2x'] = 'images/smilies/' . $smileyFilename2x;
+ }
}
parent::update();
*/
protected $cachedSmilies = [];
+ protected $cachedSmileyByCode = [];
+
/**
* cached smiley categories
* @var SmileyCategory[]
protected function init() {
// get smiley cache
$this->cachedSmilies = SmileyCacheBuilder::getInstance()->getData([], 'smilies');
+ $this->cachedSmileyByCode = SmileyCacheBuilder::getInstance()->getData([], 'codes');
$smileyCategories = CategoryHandler::getInstance()->getCategories('com.woltlab.wcf.bbcode.smiley');
$this->cachedCategories[null] = new SmileyCategory(new Category(null, [
return $this->cachedSmilies;
}
+ public function getSmileyByCode($code) {
+ if (isset($this->cachedSmileyByCode[$code])) {
+ return $this->cachedSmileyByCode[$code];
+ }
+
+ return null;
+ }
+
/**
* Returns all smiley categories.
*
/** @var Smiley $smiley */
foreach ($categorySmilies as $smiley) {
foreach ($smiley->smileyCodes as $smileyCode) {
- $this->smilies[$smileyCode] = '<img src="'.$smiley->getURL().'" alt="'.StringUtil::encodeHTML($smiley->smileyCode).'">';
+ $this->smilies[$smileyCode] = $smiley->getHtml();
}
}
}
* @inheritDoc
*/
protected function rebuild(array $parameters) {
- $data = ['smilies' => []];
+ $data = ['codes' => [], 'smilies' => []];
// get smilies
$sql = "SELECT *
$object->smileyCodes = $object->getAliases();
$object->smileyCodes[] = $object->smileyCode;
+ // this call will cause the image height to be added to the cache
+ $object->getHeight();
+
$data['smilies'][$object->categoryID][$object->smileyID] = $object;
+
+ foreach ($object->smileyCodes as $smileyCode) {
+ $data['codes'][$smileyCode] = $object;
+ }
}
return $data;
// add data-attachment-id="" for <img>
$definition->addAttribute('img', 'data-attachment-id', 'Number');
+ $definition->addAttribute('img', 'srcset', 'Text');
$parameters = [
'config' => $config,
<?php
namespace wcf\system\html\input\node;
+use wcf\data\smiley\Smiley;
+use wcf\data\smiley\SmileyCache;
use wcf\system\bbcode\BBCodeHandler;
use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\util\DOMUtil;
/** @var \DOMElement $element */
foreach ($elements as $element) {
$class = $element->getAttribute('class');
- if (!preg_match('~\bwoltlabAttachment\b~', $class)) {
- continue;
+ if (preg_match('~\bwoltlabAttachment\b~', $class)) {
+ $this->handleAttachment($element, $class);
}
-
- $attachmentID = intval($element->getAttribute('data-attachment-id'));
- if (!$attachmentID) {
- continue;
- }
-
- $float = 'none';
- $thumbnail = false;
-
- if (strpos($element->getAttribute('src'), 'thumbnail=1') !== false) {
- $thumbnail = true;
- }
-
- if (preg_match('~\bmessageFloatObject(?P<float>Left|Right)\b~', $class, $matches)) {
- $float = ($matches['float'] === 'Left') ? 'left' : 'right';
+ else if (preg_match('~\bsmiley\b~', $class)) {
+ $this->handleSmiley($element);
}
+ }
+ }
+
+ protected function handleAttachment(\DOMElement $element, $class) {
+ $attachmentID = intval($element->getAttribute('data-attachment-id'));
+ if (!$attachmentID) {
+ return;
+ }
+
+ $float = 'none';
+ $thumbnail = false;
+
+ if (strpos($element->getAttribute('src'), 'thumbnail=1') !== false) {
+ $thumbnail = true;
+ }
+
+ if (preg_match('~\bmessageFloatObject(?P<float>Left|Right)\b~', $class, $matches)) {
+ $float = ($matches['float'] === 'Left') ? 'left' : 'right';
+ }
+
+ $attributes = [
+ $attachmentID,
+ $float,
+ $thumbnail
+ ];
+
+ $newElement = $element->ownerDocument->createElement('woltlab-metacode');
+ $newElement->setAttribute('data-name', 'attach');
+ $newElement->setAttribute('data-attributes', base64_encode(JSON::encode($attributes)));
+ DOMUtil::replaceElement($element, $newElement, false);
+ }
+
+ protected function handleSmiley(\DOMElement $element) {
+ $code = $element->getAttribute('alt');
+
+ /** @var Smiley $smiley */
+ $smiley = SmileyCache::getInstance()->getSmileyByCode($code);
+ if ($smiley === null) {
+ $element->parentNode->insertBefore($element->ownerDocument->createTextNode($code), $element);
+ $element->parentNode->removeChild($element);
+ }
+ else {
+ // enforce database values for src, srcset and style
+ $element->setAttribute('src', $smiley->getURL());
- $attributes = [
- $attachmentID,
- $float,
- $thumbnail
- ];
+ if ($smiley->getHeight()) $element->setAttribute('style', 'height: ' . $smiley->getHeight() . 'px');
+ else $element->removeAttribute('style');
- $newElement = $element->ownerDocument->createElement('woltlab-metacode');
- $newElement->setAttribute('data-name', 'attach');
- $newElement->setAttribute('data-attributes', base64_encode(JSON::encode($attributes)));
- DOMUtil::replaceElement($element, $newElement, false);
+ if ($smiley->smileyPath2x) $element->setAttribute('srcset', $smiley->getURL2x() . ' 2x');
+ else $element->removeAttribute('srcset');
}
}
}
<?php
namespace wcf\system\html\output\node;
+use wcf\data\smiley\Smiley;
+use wcf\data\smiley\SmileyCache;
use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\system\request\LinkHandler;
use wcf\util\exception\CryptoException;
* @inheritDoc
*/
public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
- if (!MODULE_IMAGE_PROXY) {
- return;
- }
-
/** @var \DOMElement $element */
foreach ($elements as $element) {
- $src = $element->getAttribute('src');
- if ($src) {
- $element->setAttribute('src', $this->getProxyLink($src));
+ $class = $element->getAttribute('class');
+ if (preg_match('~\bsmiley\b~', $class)) {
+ $code = $element->getAttribute('alt');
+
+ /** @var Smiley $smiley */
+ $smiley = SmileyCache::getInstance()->getSmileyByCode($code);
+ if ($smiley === null) {
+ // output as raw code instead
+ $element->parentNode->insertBefore($element->ownerDocument->createTextNode($code), $element);
+ $element->parentNode->removeChild($element);
+ }
+ else {
+ // enforce database values for src, srcset and style
+ $element->setAttribute('src', $smiley->getURL());
+
+ if ($smiley->getHeight()) $element->setAttribute('style', 'height: ' . $smiley->getHeight() . 'px');
+ else $element->removeAttribute('style');
+
+ if ($smiley->smileyPath2x) $element->setAttribute('srcset', $smiley->getURL2x() . ' 2x');
+ else $element->removeAttribute('srcset');
+ }
+ }
+ else if (MODULE_IMAGE_PROXY) {
+ $src = $element->getAttribute('src');
+ if ($src) {
+ $element->setAttribute('src', $this->getProxyLink($src));
+ }
}
}
}
'smileyCode' => $data['attributes']['name'],
'smileyTitle' => $data['elements']['title'],
'smileyPath' => $data['elements']['path'],
+ 'smileyPath2x' => isset($data['elements']['path2x']) ? $data['elements']['path2x'] : '',
'aliases' => isset($data['elements']['aliases']) ? $data['elements']['aliases'] : '',
'showOrder' => $showOrder
];
<item name="wcf.acp.smiley.smileyPath.description"><![CDATA[Der Smiley-Pfad wird relativ zu „{$__wcf->getPath()}“ interpretiert.]]></item>
<item name="wcf.acp.smiley.smileyPath.error.notFound"><![CDATA[Es wurde keine Datei unter dem angegebenen Pfad gefunden]]></item>
<item name="wcf.acp.smiley.smileyFile"><![CDATA[Smiley-Datei]]></item>
+ <item name="wcf.acp.smiley.smileyFile2x"><![CDATA[Smiley-Datei (HD)]]></item>
+ <item name="wcf.acp.smiley.smileyFile2x.description"><![CDATA[Optionale Grafik die auf hochauflösenden Bildschirmen (z.B. Apple Retina-Display oder 4K/UHD-Monitore) verwendet wird, diese muss doppelt so groß sein wie die normale Grafik.]]></item>
<item name="wcf.acp.smiley.fileUpload"><![CDATA[Smiley hochladen]]></item>
<item name="wcf.acp.smiley.fileUpload.description"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Lade{else}Laden Sie{/if} hier die Bilddatei des Smileys hoch.]]></item>
<item name="wcf.acp.smiley.fileUpload.error.noImage"><![CDATA[Bei der hochgeladenen Datei handelt es sich um keine Bilddatei.]]></item>
<item name="wcf.acp.smiley.smileyPath.description"><![CDATA[Smiley path is relative to “{$__wcf->getPath()}”.]]></item>
<item name="wcf.acp.smiley.smileyPath.error.notFound"><![CDATA[Unable to find a file on given path.]]></item>
<item name="wcf.acp.smiley.smileyFile"><![CDATA[Smiley File]]></item>
+ <item name="wcf.acp.smiley.smileyFile2x"><![CDATA[Smiley File (HD)]]></item>
+ <item name="wcf.acp.smiley.smileyFile2x.description"><![CDATA[Optional image used for display on high resolution displays such as Apple Retina or 4K/UHD-displays. Image must be double times the dimensions of the normal image to work.]]></item>
<item name="wcf.acp.smiley.fileUpload"><![CDATA[Upload Smiley]]></item>
<item name="wcf.acp.smiley.fileUpload.description"><![CDATA[Upload the image file for the smiley.]]></item>
<item name="wcf.acp.smiley.fileUpload.error.noImage"><![CDATA[The uploaded file is not an image file.]]></item>
packageID INT(10) NOT NULL,
categoryID INT(10),
smileyPath VARCHAR(255) NOT NULL DEFAULT '',
+ smileyPath2x VARCHAR(255) NOT NULL DEFAULT '',
smileyTitle VARCHAR(255) NOT NULL DEFAULT '',
smileyCode VARCHAR(191) NOT NULL DEFAULT '',
aliases TEXT NOT NULL,