From bf9684bcc7bd75b3f7fdb046fa31df49d9ff65e4 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Tue, 5 Jan 2021 20:52:15 +0100 Subject: [PATCH 01/10] first go a refactoring the media manager For now this only adds code. This takes care of encapsulating media file information and has some UI classes to display those files in the fullscreen media manager and the popup. The code is untested and not integrated to run, yet. Next step is to replace the parts in the media manager to call this new code (and fix any bugs). I tried not to change much HTML yet. This can be done later. For now the goal is to just make it run again. --- inc/Media/MediaFile.php | 170 +++++++++++++++++++++++++++++++++++ inc/Ui/Media/Display.php | 79 ++++++++++++++++ inc/Ui/Media/DisplayRow.php | 92 +++++++++++++++++++ inc/Ui/Media/DisplayTile.php | 52 +++++++++++ 4 files changed, 393 insertions(+) create mode 100644 inc/Media/MediaFile.php create mode 100644 inc/Ui/Media/Display.php create mode 100644 inc/Ui/Media/DisplayRow.php create mode 100644 inc/Ui/Media/DisplayTile.php diff --git a/inc/Media/MediaFile.php b/inc/Media/MediaFile.php new file mode 100644 index 000000000..a9a876167 --- /dev/null +++ b/inc/Media/MediaFile.php @@ -0,0 +1,170 @@ +id = $id; //FIXME should it be cleaned? + $this->path = mediaFN($id); + + list($this->mime, $this->ext, $this->downloadable) = mimetype($this->path, false); + } + + /** + * Factory to create a new MediaFile from a Media Path + * + * @param string $path The path of a file, relative to the media base dir + * @return MediaFile + */ + static public function fromRelativePath($path) + { + if ($path[0] === '/' || $path[1] === ':') { + throw new \RuntimeException('Only paths relative to the media directory may be used'); + } + + return new MediaFile(pathID($path, true)); + } + + /** @return string */ + public function getId() + { + return $this->id; + } + + /** @return string */ + public function getPath() + { + return $this->path; + } + + /** + * The ID without namespace, used for display purposes + * + * @return string + */ + public function getDisplayName() + { + return noNS($this->id); + } + + /** @return string */ + public function getMime() + { + if (!$this->mime) return 'application/octet-stream'; + return $this->mime; + } + + /** @return string */ + public function getExtension() + { + return (string)$this->ext; + } + + /** + * Similar to the extesion but does some clean up + * + * @return string + */ + public function getIcoClass() + { + $ext = $this->getExtension(); + if ($ext === '') $ext = 'file'; + return preg_replace('/[^_\-a-z0-9]+/i', '_', $ext); + } + + /** + * Should this file be downloaded instead being displayed inline? + * + * @return bool + */ + public function isDownloadable() + { + return $this->downloadable; + } + + /** @return int */ + public function getFileSize() + { + return filesize($this->path); + } + + /** @return int */ + public function getLastModified() + { + return filemtime($this->path); + } + + /** @return bool */ + public function isWritable() + { + return is_writable($this->path); + } + + /** @return bool */ + public function isImage() + { + return (substr($this->mime, 0, 6) === 'image/'); + } + + /** + * initializes width and height for images when requested + */ + protected function initSizes() + { + $this->width = 0; + $this->height = 0; + if (!$this->isImage()) return; + $info = getimagesize($this->path); + if ($info === false) return; + list($this->width, $this->height) = $info; + } + + /** + * Returns the width if this is a supported image, 0 otherwise + * + * @return int + */ + public function getWidth() + { + if ($this->width === null) $this->initSizes(); + return $this->width; + } + + /** + * Returns the height if this is a supported image, 0 otherwise + * + * @return int + */ + public function getHeight() + { + if ($this->height === null) $this->initSizes(); + return $this->height; + } + + /** @return \JpegMeta */ + public function getMeta() + { + if($this->meta === null) $this->meta = new \JpegMeta($this->path); + return $this->meta; + } +} diff --git a/inc/Ui/Media/Display.php b/inc/Ui/Media/Display.php new file mode 100644 index 000000000..ba23cfc81 --- /dev/null +++ b/inc/Ui/Media/Display.php @@ -0,0 +1,79 @@ +mediaFile = $mediaFile; + } + + /** + * Get the HTML to display a preview image if possible, otherwise show an icon + * + * @param int $w bounding box width to resize pixel based images to + * @param int $h bounding box height to resize pixel based images to + * @return string + */ + public function getPreviewHtml($w, $h) + { + if ($this->mediaFile->isImage()) { + $src = ml($this->mediaFile, ['w' => $w, 'h' => $h]); + } else { + $src = $this->getIconUrl(); + } + + return '' . hsc($this->mediaFile->getDisplayName()) . ''; + } + + /** + * Return the URL to the icon for this file + * + * @return string + */ + public function getIconUrl() + { + $link = 'lib/images/fileicons/svg/' . $this->mediaFile->getIcoClass() . '.svg'; + if (!file_exists(DOKU_INC . $link)) $link = 'lib/images/fileicons/svg/file.svg'; + return DOKU_BASE . $link; + } + + /** @return string */ + protected function formatDate() + { + return dformat($this->mediaFile->getLastModified()); + } + + /** + * Output the image dimension if any + * + * @param string $empty what to show when no dimensions are available + * @return string + */ + protected function formatDimensions($empty = ' ') + { + $w = $this->mediaFile->getWidth(); + $h = $this->mediaFile->getHeight(); + if ($w && $h) { + return $w . '×' . $h; + } else { + return $empty; + } + } + + /** @return string */ + protected function formatFileSize() + { + return filesize_h($this->mediaFile->getFileSize()); + } +} diff --git a/inc/Ui/Media/DisplayRow.php b/inc/Ui/Media/DisplayRow.php new file mode 100644 index 000000000..84a99f476 --- /dev/null +++ b/inc/Ui/Media/DisplayRow.php @@ -0,0 +1,92 @@ + maybe for search? + + $id = $this->mediaFile->getId(); + $class = 'select mediafile mf_' . $this->mediaFile->getIcoClass(); + $info = trim($this->formatDimensions('') . ' ' . $this->formatDate() . ' ' . $this->formatFileSize()); + + echo '
'; + echo '' . + $this->mediaFile->getDisplayName() . + ' '; + echo '(' . $info . ')' . NL; + + // view button + $link = ml($id, '', true); + echo ' '; + + // mediamanager button + $link = wl('', array('do' => 'media', 'image' => $id, 'ns' => getNS($id))); + echo ' '; + + // delete button FIXME + if ($item['writable'] && $auth >= AUTH_DELETE) { + $link = DOKU_BASE . 'lib/exe/mediamanager.php?delete=' . rawurlencode($id) . + '&sectok=' . getSecurityToken(); + echo ' ' . + '' . $lang['btn_delete'] . ''; + } + + echo '
'; + echo $lang['mediausage'] . ' {{:' . $id . '}}'; + echo '
'; + if ($item['isimg']) media_printimgdetail($item); + echo '
' . NL; + echo '
' . NL; + + } + + public function showDetails() + { + $id = $this->mediaFile->getId(); + + echo '
'; + echo ''; + + // read EXIF/IPTC data + $t = $this->mediaFile->getMeta()->getField(array('IPTC.Headline', 'xmp.dc:title')); + $d = $this->mediaFile->getMeta()->getField(array( + 'IPTC.Caption', + 'EXIF.UserComment', + 'EXIF.TIFFImageDescription', + 'EXIF.TIFFUserComment', + )); + if (PhpString::strlen($d) > 250) $d = PhpString::substr($d, 0, 250) . '...'; + $k = $this->mediaFile->getMeta()->getField(array('IPTC.Keywords', 'IPTC.Category', 'xmp.dc:subject')); + + // print EXIF/IPTC data + if ($t || $d || $k) { + echo '

'; + if ($t) echo '' . hsc($t) . '
'; + if ($d) echo hsc($d) . '
'; + if ($t) echo '' . hsc($k) . ''; + echo '

'; + } + echo '
'; + } + +} diff --git a/inc/Ui/Media/DisplayTile.php b/inc/Ui/Media/DisplayTile.php new file mode 100644 index 000000000..7fc1c93cf --- /dev/null +++ b/inc/Ui/Media/DisplayTile.php @@ -0,0 +1,52 @@ +mmUrl = media_managerURL([ + 'image' => $this->mediaFile->getId(), + 'ns' => getNS($this->mediaFile->getId()), + 'tab_details' => 'view', + ]); + } + + /** + * Display the tile + */ + public function show() + { + echo '
'; + echo '
'; + echo ''; + echo $this->getPreviewHtml(90, 90); + echo ''; + echo '
'; + + echo '
'; + echo '' . + $this->mediaFile->getDisplayName() . + ''; + echo '
'; + + echo '
' . $this->formatDimensions() . '
'; + echo '
' . $this->formatDate() . '
'; + echo '
' . $this->formatFileSize() . '
'; + + echo '
'; + } +} From 8f7d0e1180e5f499a5af3acc8664032d141a7f17 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Tue, 5 Jan 2021 20:54:58 +0100 Subject: [PATCH 02/10] SVG based file icons To be used in the new code. Courtesy of https://fileicons.org/ --- lib/images/fileicons/svg/7z.svg | 1 + lib/images/fileicons/svg/asm.svg | 1 + lib/images/fileicons/svg/bash.svg | 1 + lib/images/fileicons/svg/bz2.svg | 1 + lib/images/fileicons/svg/c.svg | 1 + lib/images/fileicons/svg/conf.svg | 1 + lib/images/fileicons/svg/cpp.svg | 1 + lib/images/fileicons/svg/cs.svg | 1 + lib/images/fileicons/svg/csh.svg | 1 + lib/images/fileicons/svg/css.svg | 1 + lib/images/fileicons/svg/csv.svg | 1 + lib/images/fileicons/svg/deb.svg | 1 + lib/images/fileicons/svg/doc.svg | 1 + lib/images/fileicons/svg/docx.svg | 1 + lib/images/fileicons/svg/file.svg | 1 + lib/images/fileicons/svg/gif.svg | 1 + lib/images/fileicons/svg/gz.svg | 1 + lib/images/fileicons/svg/h.svg | 1 + lib/images/fileicons/svg/htm.svg | 1 + lib/images/fileicons/svg/html.svg | 1 + lib/images/fileicons/svg/ico.svg | 1 + lib/images/fileicons/svg/java.svg | 1 + lib/images/fileicons/svg/jpeg.svg | 1 + lib/images/fileicons/svg/jpg.svg | 1 + lib/images/fileicons/svg/js.svg | 1 + lib/images/fileicons/svg/json.svg | 1 + lib/images/fileicons/svg/lua.svg | 1 + lib/images/fileicons/svg/mp3.svg | 1 + lib/images/fileicons/svg/mp4.svg | 1 + lib/images/fileicons/svg/ods.svg | 1 + lib/images/fileicons/svg/odt.svg | 1 + lib/images/fileicons/svg/ogg.svg | 1 + lib/images/fileicons/svg/ogv.svg | 1 + lib/images/fileicons/svg/pdf.svg | 1 + lib/images/fileicons/svg/php.svg | 1 + lib/images/fileicons/svg/pl.svg | 1 + lib/images/fileicons/svg/png.svg | 1 + lib/images/fileicons/svg/ppt.svg | 1 + lib/images/fileicons/svg/pptx.svg | 1 + lib/images/fileicons/svg/ps.svg | 1 + lib/images/fileicons/svg/py.svg | 1 + lib/images/fileicons/svg/rar.svg | 1 + lib/images/fileicons/svg/rb.svg | 1 + lib/images/fileicons/svg/rpm.svg | 1 + lib/images/fileicons/svg/rtf.svg | 1 + lib/images/fileicons/svg/sh.svg | 1 + lib/images/fileicons/svg/sql.svg | 1 + lib/images/fileicons/svg/svg.svg | 1 + lib/images/fileicons/svg/swf.svg | 1 + lib/images/fileicons/svg/tar.svg | 1 + lib/images/fileicons/svg/tgz.svg | 1 + lib/images/fileicons/svg/txt.svg | 1 + lib/images/fileicons/svg/wav.svg | 1 + lib/images/fileicons/svg/webm.svg | 1 + lib/images/fileicons/svg/xls.svg | 1 + lib/images/fileicons/svg/xlsx.svg | 1 + lib/images/fileicons/svg/xml.svg | 1 + lib/images/fileicons/svg/zip.svg | 1 + 58 files changed, 58 insertions(+) create mode 100644 lib/images/fileicons/svg/7z.svg create mode 100644 lib/images/fileicons/svg/asm.svg create mode 100644 lib/images/fileicons/svg/bash.svg create mode 100644 lib/images/fileicons/svg/bz2.svg create mode 100644 lib/images/fileicons/svg/c.svg create mode 100644 lib/images/fileicons/svg/conf.svg create mode 100644 lib/images/fileicons/svg/cpp.svg create mode 100644 lib/images/fileicons/svg/cs.svg create mode 100644 lib/images/fileicons/svg/csh.svg create mode 100644 lib/images/fileicons/svg/css.svg create mode 100644 lib/images/fileicons/svg/csv.svg create mode 100644 lib/images/fileicons/svg/deb.svg create mode 100644 lib/images/fileicons/svg/doc.svg create mode 100644 lib/images/fileicons/svg/docx.svg create mode 100644 lib/images/fileicons/svg/file.svg create mode 100644 lib/images/fileicons/svg/gif.svg create mode 100644 lib/images/fileicons/svg/gz.svg create mode 100644 lib/images/fileicons/svg/h.svg create mode 100644 lib/images/fileicons/svg/htm.svg create mode 100644 lib/images/fileicons/svg/html.svg create mode 100644 lib/images/fileicons/svg/ico.svg create mode 100644 lib/images/fileicons/svg/java.svg create mode 100644 lib/images/fileicons/svg/jpeg.svg create mode 100644 lib/images/fileicons/svg/jpg.svg create mode 100644 lib/images/fileicons/svg/js.svg create mode 100644 lib/images/fileicons/svg/json.svg create mode 100644 lib/images/fileicons/svg/lua.svg create mode 100644 lib/images/fileicons/svg/mp3.svg create mode 100644 lib/images/fileicons/svg/mp4.svg create mode 100644 lib/images/fileicons/svg/ods.svg create mode 100644 lib/images/fileicons/svg/odt.svg create mode 100644 lib/images/fileicons/svg/ogg.svg create mode 100644 lib/images/fileicons/svg/ogv.svg create mode 100644 lib/images/fileicons/svg/pdf.svg create mode 100644 lib/images/fileicons/svg/php.svg create mode 100644 lib/images/fileicons/svg/pl.svg create mode 100644 lib/images/fileicons/svg/png.svg create mode 100644 lib/images/fileicons/svg/ppt.svg create mode 100644 lib/images/fileicons/svg/pptx.svg create mode 100644 lib/images/fileicons/svg/ps.svg create mode 100644 lib/images/fileicons/svg/py.svg create mode 100644 lib/images/fileicons/svg/rar.svg create mode 100644 lib/images/fileicons/svg/rb.svg create mode 100644 lib/images/fileicons/svg/rpm.svg create mode 100644 lib/images/fileicons/svg/rtf.svg create mode 100644 lib/images/fileicons/svg/sh.svg create mode 100644 lib/images/fileicons/svg/sql.svg create mode 100644 lib/images/fileicons/svg/svg.svg create mode 100644 lib/images/fileicons/svg/swf.svg create mode 100644 lib/images/fileicons/svg/tar.svg create mode 100644 lib/images/fileicons/svg/tgz.svg create mode 100644 lib/images/fileicons/svg/txt.svg create mode 100644 lib/images/fileicons/svg/wav.svg create mode 100644 lib/images/fileicons/svg/webm.svg create mode 100644 lib/images/fileicons/svg/xls.svg create mode 100644 lib/images/fileicons/svg/xlsx.svg create mode 100644 lib/images/fileicons/svg/xml.svg create mode 100644 lib/images/fileicons/svg/zip.svg diff --git a/lib/images/fileicons/svg/7z.svg b/lib/images/fileicons/svg/7z.svg new file mode 100644 index 000000000..44e435e43 --- /dev/null +++ b/lib/images/fileicons/svg/7z.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/asm.svg b/lib/images/fileicons/svg/asm.svg new file mode 100644 index 000000000..748386696 --- /dev/null +++ b/lib/images/fileicons/svg/asm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/bash.svg b/lib/images/fileicons/svg/bash.svg new file mode 100644 index 000000000..8406f792f --- /dev/null +++ b/lib/images/fileicons/svg/bash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/bz2.svg b/lib/images/fileicons/svg/bz2.svg new file mode 100644 index 000000000..44e435e43 --- /dev/null +++ b/lib/images/fileicons/svg/bz2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/c.svg b/lib/images/fileicons/svg/c.svg new file mode 100644 index 000000000..d014cb253 --- /dev/null +++ b/lib/images/fileicons/svg/c.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/conf.svg b/lib/images/fileicons/svg/conf.svg new file mode 100644 index 000000000..1a9cae0db --- /dev/null +++ b/lib/images/fileicons/svg/conf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/cpp.svg b/lib/images/fileicons/svg/cpp.svg new file mode 100644 index 000000000..178f532a0 --- /dev/null +++ b/lib/images/fileicons/svg/cpp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/cs.svg b/lib/images/fileicons/svg/cs.svg new file mode 100644 index 000000000..c6853d00c --- /dev/null +++ b/lib/images/fileicons/svg/cs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/csh.svg b/lib/images/fileicons/svg/csh.svg new file mode 100644 index 000000000..8406f792f --- /dev/null +++ b/lib/images/fileicons/svg/csh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/css.svg b/lib/images/fileicons/svg/css.svg new file mode 100644 index 000000000..f359b94cc --- /dev/null +++ b/lib/images/fileicons/svg/css.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/csv.svg b/lib/images/fileicons/svg/csv.svg new file mode 100644 index 000000000..318ba0573 --- /dev/null +++ b/lib/images/fileicons/svg/csv.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/deb.svg b/lib/images/fileicons/svg/deb.svg new file mode 100644 index 000000000..2cdb6d758 --- /dev/null +++ b/lib/images/fileicons/svg/deb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/doc.svg b/lib/images/fileicons/svg/doc.svg new file mode 100644 index 000000000..ac084a0dc --- /dev/null +++ b/lib/images/fileicons/svg/doc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/docx.svg b/lib/images/fileicons/svg/docx.svg new file mode 100644 index 000000000..ac084a0dc --- /dev/null +++ b/lib/images/fileicons/svg/docx.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/file.svg b/lib/images/fileicons/svg/file.svg new file mode 100644 index 000000000..2537cbec9 --- /dev/null +++ b/lib/images/fileicons/svg/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/gif.svg b/lib/images/fileicons/svg/gif.svg new file mode 100644 index 000000000..8d4cac8c0 --- /dev/null +++ b/lib/images/fileicons/svg/gif.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/gz.svg b/lib/images/fileicons/svg/gz.svg new file mode 100644 index 000000000..44e435e43 --- /dev/null +++ b/lib/images/fileicons/svg/gz.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/h.svg b/lib/images/fileicons/svg/h.svg new file mode 100644 index 000000000..b80f32f2c --- /dev/null +++ b/lib/images/fileicons/svg/h.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/htm.svg b/lib/images/fileicons/svg/htm.svg new file mode 100644 index 000000000..1e37bd48a --- /dev/null +++ b/lib/images/fileicons/svg/htm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/html.svg b/lib/images/fileicons/svg/html.svg new file mode 100644 index 000000000..1e37bd48a --- /dev/null +++ b/lib/images/fileicons/svg/html.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/ico.svg b/lib/images/fileicons/svg/ico.svg new file mode 100644 index 000000000..da894c465 --- /dev/null +++ b/lib/images/fileicons/svg/ico.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/java.svg b/lib/images/fileicons/svg/java.svg new file mode 100644 index 000000000..2a095856b --- /dev/null +++ b/lib/images/fileicons/svg/java.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/jpeg.svg b/lib/images/fileicons/svg/jpeg.svg new file mode 100644 index 000000000..8d4cac8c0 --- /dev/null +++ b/lib/images/fileicons/svg/jpeg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/jpg.svg b/lib/images/fileicons/svg/jpg.svg new file mode 100644 index 000000000..8d4cac8c0 --- /dev/null +++ b/lib/images/fileicons/svg/jpg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/js.svg b/lib/images/fileicons/svg/js.svg new file mode 100644 index 000000000..c97554772 --- /dev/null +++ b/lib/images/fileicons/svg/js.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/json.svg b/lib/images/fileicons/svg/json.svg new file mode 100644 index 000000000..fde9988be --- /dev/null +++ b/lib/images/fileicons/svg/json.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/lua.svg b/lib/images/fileicons/svg/lua.svg new file mode 100644 index 000000000..8c2a373c3 --- /dev/null +++ b/lib/images/fileicons/svg/lua.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/mp3.svg b/lib/images/fileicons/svg/mp3.svg new file mode 100644 index 000000000..7d5a0a818 --- /dev/null +++ b/lib/images/fileicons/svg/mp3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/mp4.svg b/lib/images/fileicons/svg/mp4.svg new file mode 100644 index 000000000..f2a277268 --- /dev/null +++ b/lib/images/fileicons/svg/mp4.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/ods.svg b/lib/images/fileicons/svg/ods.svg new file mode 100644 index 000000000..e36187083 --- /dev/null +++ b/lib/images/fileicons/svg/ods.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/odt.svg b/lib/images/fileicons/svg/odt.svg new file mode 100644 index 000000000..f30088bf5 --- /dev/null +++ b/lib/images/fileicons/svg/odt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/ogg.svg b/lib/images/fileicons/svg/ogg.svg new file mode 100644 index 000000000..7d5a0a818 --- /dev/null +++ b/lib/images/fileicons/svg/ogg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/ogv.svg b/lib/images/fileicons/svg/ogv.svg new file mode 100644 index 000000000..f2a277268 --- /dev/null +++ b/lib/images/fileicons/svg/ogv.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/pdf.svg b/lib/images/fileicons/svg/pdf.svg new file mode 100644 index 000000000..e6472df17 --- /dev/null +++ b/lib/images/fileicons/svg/pdf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/php.svg b/lib/images/fileicons/svg/php.svg new file mode 100644 index 000000000..096500ab5 --- /dev/null +++ b/lib/images/fileicons/svg/php.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/pl.svg b/lib/images/fileicons/svg/pl.svg new file mode 100644 index 000000000..9abc83799 --- /dev/null +++ b/lib/images/fileicons/svg/pl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/png.svg b/lib/images/fileicons/svg/png.svg new file mode 100644 index 000000000..8d4cac8c0 --- /dev/null +++ b/lib/images/fileicons/svg/png.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/ppt.svg b/lib/images/fileicons/svg/ppt.svg new file mode 100644 index 000000000..edcc771bb --- /dev/null +++ b/lib/images/fileicons/svg/ppt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/pptx.svg b/lib/images/fileicons/svg/pptx.svg new file mode 100644 index 000000000..edcc771bb --- /dev/null +++ b/lib/images/fileicons/svg/pptx.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/ps.svg b/lib/images/fileicons/svg/ps.svg new file mode 100644 index 000000000..9cb18357c --- /dev/null +++ b/lib/images/fileicons/svg/ps.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/py.svg b/lib/images/fileicons/svg/py.svg new file mode 100644 index 000000000..4c268d42c --- /dev/null +++ b/lib/images/fileicons/svg/py.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/rar.svg b/lib/images/fileicons/svg/rar.svg new file mode 100644 index 000000000..44e435e43 --- /dev/null +++ b/lib/images/fileicons/svg/rar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/rb.svg b/lib/images/fileicons/svg/rb.svg new file mode 100644 index 000000000..28b037b78 --- /dev/null +++ b/lib/images/fileicons/svg/rb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/rpm.svg b/lib/images/fileicons/svg/rpm.svg new file mode 100644 index 000000000..2cdb6d758 --- /dev/null +++ b/lib/images/fileicons/svg/rpm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/rtf.svg b/lib/images/fileicons/svg/rtf.svg new file mode 100644 index 000000000..629562858 --- /dev/null +++ b/lib/images/fileicons/svg/rtf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/sh.svg b/lib/images/fileicons/svg/sh.svg new file mode 100644 index 000000000..8406f792f --- /dev/null +++ b/lib/images/fileicons/svg/sh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/sql.svg b/lib/images/fileicons/svg/sql.svg new file mode 100644 index 000000000..b2c3e21de --- /dev/null +++ b/lib/images/fileicons/svg/sql.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/svg.svg b/lib/images/fileicons/svg/svg.svg new file mode 100644 index 000000000..9cb18357c --- /dev/null +++ b/lib/images/fileicons/svg/svg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/swf.svg b/lib/images/fileicons/svg/swf.svg new file mode 100644 index 000000000..4642c115b --- /dev/null +++ b/lib/images/fileicons/svg/swf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/tar.svg b/lib/images/fileicons/svg/tar.svg new file mode 100644 index 000000000..2cdb6d758 --- /dev/null +++ b/lib/images/fileicons/svg/tar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/tgz.svg b/lib/images/fileicons/svg/tgz.svg new file mode 100644 index 000000000..44e435e43 --- /dev/null +++ b/lib/images/fileicons/svg/tgz.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/txt.svg b/lib/images/fileicons/svg/txt.svg new file mode 100644 index 000000000..629562858 --- /dev/null +++ b/lib/images/fileicons/svg/txt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/wav.svg b/lib/images/fileicons/svg/wav.svg new file mode 100644 index 000000000..7d5a0a818 --- /dev/null +++ b/lib/images/fileicons/svg/wav.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/webm.svg b/lib/images/fileicons/svg/webm.svg new file mode 100644 index 000000000..f2a277268 --- /dev/null +++ b/lib/images/fileicons/svg/webm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/xls.svg b/lib/images/fileicons/svg/xls.svg new file mode 100644 index 000000000..ddf80382f --- /dev/null +++ b/lib/images/fileicons/svg/xls.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/xlsx.svg b/lib/images/fileicons/svg/xlsx.svg new file mode 100644 index 000000000..ddf80382f --- /dev/null +++ b/lib/images/fileicons/svg/xlsx.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/xml.svg b/lib/images/fileicons/svg/xml.svg new file mode 100644 index 000000000..6af9a7866 --- /dev/null +++ b/lib/images/fileicons/svg/xml.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/images/fileicons/svg/zip.svg b/lib/images/fileicons/svg/zip.svg new file mode 100644 index 000000000..44e435e43 --- /dev/null +++ b/lib/images/fileicons/svg/zip.svg @@ -0,0 +1 @@ + \ No newline at end of file From 4f33babf5709281d9b8753c9620d1257ced36f67 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Tue, 5 Jan 2021 21:37:38 +0100 Subject: [PATCH 03/10] make use of the new media file classes This just crudely replaces the calls to the old functions with usage of the new classes. This however already works and makes (manual) testing of these classes easier. Next steps: remove the old media_printfile and media_printfile_thumbs methods and fix/drop/replace the tests depending on them. search_media might be obsolete, too already. For search results the display classes need to show full namespaces. This needs to be fixed again. No idea about the jump mechanism, yet. --- inc/Media/MediaFile.php | 28 +++++++++----------- inc/Ui/Media/Display.php | 2 +- inc/Ui/Media/DisplayRow.php | 9 ++++--- inc/media.php | 29 ++++++++++++++++----- inc/search.php | 52 +++++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 26 deletions(-) diff --git a/inc/Media/MediaFile.php b/inc/Media/MediaFile.php index a9a876167..e618fe879 100644 --- a/inc/Media/MediaFile.php +++ b/inc/Media/MediaFile.php @@ -27,22 +27,7 @@ class MediaFile $this->id = $id; //FIXME should it be cleaned? $this->path = mediaFN($id); - list($this->mime, $this->ext, $this->downloadable) = mimetype($this->path, false); - } - - /** - * Factory to create a new MediaFile from a Media Path - * - * @param string $path The path of a file, relative to the media base dir - * @return MediaFile - */ - static public function fromRelativePath($path) - { - if ($path[0] === '/' || $path[1] === ':') { - throw new \RuntimeException('Only paths relative to the media directory may be used'); - } - - return new MediaFile(pathID($path, true)); + list($this->ext, $this->mime, $this->downloadable) = mimetype($this->path, false); } /** @return string */ @@ -161,6 +146,17 @@ class MediaFile return $this->height; } + /** + * Returns the permissions the current user has on the file + * + * @todo doing this for each file within a namespace is a waste, we need to cache this somehow + * @return int + */ + public function userPermission() + { + return auth_quickaclcheck(getNS($this->id).':*'); + } + /** @return \JpegMeta */ public function getMeta() { diff --git a/inc/Ui/Media/Display.php b/inc/Ui/Media/Display.php index ba23cfc81..a7428054b 100644 --- a/inc/Ui/Media/Display.php +++ b/inc/Ui/Media/Display.php @@ -28,7 +28,7 @@ class Display public function getPreviewHtml($w, $h) { if ($this->mediaFile->isImage()) { - $src = ml($this->mediaFile, ['w' => $w, 'h' => $h]); + $src = ml($this->mediaFile->getId(), ['w' => $w, 'h' => $h]); } else { $src = $this->getIconUrl(); } diff --git a/inc/Ui/Media/DisplayRow.php b/inc/Ui/Media/DisplayRow.php index 84a99f476..f74510251 100644 --- a/inc/Ui/Media/DisplayRow.php +++ b/inc/Ui/Media/DisplayRow.php @@ -39,7 +39,7 @@ class DisplayRow extends DisplayTile 'alt="' . $lang['btn_media'] . '" title="' . $lang['btn_media'] . '" class="btn" />'; // delete button FIXME - if ($item['writable'] && $auth >= AUTH_DELETE) { + if ($this->mediaFile->isWritable() && $this->mediaFile->userPermission() >= AUTH_DELETE) { $link = DOKU_BASE . 'lib/exe/mediamanager.php?delete=' . rawurlencode($id) . '&sectok=' . getSecurityToken(); echo ' ' . @@ -50,13 +50,16 @@ class DisplayRow extends DisplayTile echo '
'; echo $lang['mediausage'] . ' {{:' . $id . '}}'; echo '
'; - if ($item['isimg']) media_printimgdetail($item); + if ($this->mediaFile->getWidth()) $this->showDetails(); echo '
' . NL; echo '' . NL; } - public function showDetails() + /** + * Show Thumbnail and EXIF data + */ + protected function showDetails() { $id = $this->mediaFile->getId(); diff --git a/inc/media.php b/inc/media.php index b5e295c0d..ecd745e2e 100644 --- a/inc/media.php +++ b/inc/media.php @@ -699,7 +699,7 @@ function media_filelist($ns,$auth=null,$jump='',$fullscreenview=false,$sort=fals $dir = utf8_encodeFN(str_replace(':','/',$ns)); $data = array(); - search($data,$conf['mediadir'],'search_media', + search($data,$conf['mediadir'],'search_mediafiles', array('showmsg'=>true,'depth'=>1),$dir,1,$sort); if(!count($data)){ @@ -710,9 +710,15 @@ function media_filelist($ns,$auth=null,$jump='',$fullscreenview=false,$sort=fals } foreach($data as $item){ if (!$fullscreenview) { - media_printfile($item,$auth,$jump); + //FIXME old call: media_printfile($item,$auth,$jump); + $display = new \dokuwiki\Ui\Media\DisplayRow($item); + $display->show(); } else { - media_printfile_thumbs($item,$auth,$jump); + //FIXME old call: media_printfile_thumbs($item,$auth,$jump); + echo '
  • '; + $display = new \dokuwiki\Ui\Media\DisplayTile($item); + $display->show(); + echo '
  • '; } } if ($fullscreenview) echo ''.NL; @@ -1536,7 +1542,7 @@ function media_searchlist($query,$ns,$auth=null,$fullscreen=false,$sort='natural $pattern = '/'.$quoted.'/i'; search($evdata['data'], $conf['mediadir'], - 'search_media', + 'search_mediafiles', array('showmsg'=>false,'pattern'=>$pattern), $dir, 1, @@ -1558,8 +1564,19 @@ function media_searchlist($query,$ns,$auth=null,$fullscreen=false,$sort='natural echo '
      '; } foreach($evdata['data'] as $item){ - if (!$fullscreen) media_printfile($item,$item['perm'],'',true); - else media_printfile_thumbs($item,$item['perm'],false,true); + if (!$fullscreen) { + // FIXME old call: media_printfile($item,$item['perm'],'',true); + // FIXME we actually want the namespace here -> needs fixing + $display = new \dokuwiki\Ui\Media\DisplayRow($item); + $display->show(); + } else { + // FIXME old call: media_printfile_thumbs($item,$item['perm'],false,true); + // FIXME we actually want the namespace here -> needs fixing + $display = new \dokuwiki\Ui\Media\DisplayTile($item); + echo '
    • '; + $display->show(); + echo '
    • '; + } } if ($fullscreen) echo '
    '.NL; } diff --git a/inc/search.php b/inc/search.php index 98be6cbf8..47892d01c 100644 --- a/inc/search.php +++ b/inc/search.php @@ -232,6 +232,58 @@ function search_media(&$data,$base,$file,$type,$lvl,$opts){ return false; } +/** + * List all mediafiles in a namespace + * $opts['depth'] recursion level, 0 for all + * $opts['showmsg'] shows message if invalid media id is used + * $opts['skipacl'] skip acl checking + * $opts['pattern'] check given pattern + * $opts['hash'] add hashes to result list + * + * @todo This is a temporary copy of search_media returning a list of MediaFile intances + * + * @param array $data + * @param string $base + * @param string $file + * @param string $type + * @param integer $lvl + * @param array $opts + * + * @return bool + */ +function search_mediafiles(&$data,$base,$file,$type,$lvl,$opts){ + + //we do nothing with directories + if($type == 'd') { + if(empty($opts['depth'])) return true; // recurse forever + $depth = substr_count($file,'/'); + if($depth >= $opts['depth']) return false; // depth reached + return true; + } + + $id = pathID($file,true); + if($id != cleanID($id)){ + if($opts['showmsg']) + msg(hsc($id).' is not a valid file name for DokuWiki - skipped',-1); + return false; // skip non-valid files + } + + //check ACL for namespace (we have no ACL for mediafiles) + $info['perm'] = auth_quickaclcheck(getNS($id).':*'); + if(empty($opts['skipacl']) && $info['perm'] < AUTH_READ){ + return false; + } + + //check pattern filter + if(!empty($opts['pattern']) && !@preg_match($opts['pattern'], $id)){ + return false; + } + + $data[] = new \dokuwiki\Media\MediaFile($id); + return false; +} + + /** * This function just lists documents (for RSS namespace export) * From 17409362b5692ff27ff29702912adcf1e33741fe Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 6 Jan 2021 20:00:54 +0100 Subject: [PATCH 04/10] simplified the media_searchlist tests --- _test/tests/inc/media_searchlist.test.php | 233 ++++------------------ 1 file changed, 42 insertions(+), 191 deletions(-) diff --git a/_test/tests/inc/media_searchlist.test.php b/_test/tests/inc/media_searchlist.test.php index b881ccc95..705c51421 100644 --- a/_test/tests/inc/media_searchlist.test.php +++ b/_test/tests/inc/media_searchlist.test.php @@ -1,6 +1,7 @@ upload_ns.':'.$name; + protected function save($name, $copy) + { + $media_id = $this->upload_ns . ':' . $name; media_save(array('name' => $copy), $media_id, true, AUTH_UPLOAD, 'copy'); } @@ -23,7 +25,10 @@ class media_searchlist_test extends DokuWikiTest { * * @throws Exception */ - function setUp() { + public function setUp() + { + parent::setUp(); + //create some files to search $png = mediaFN('wiki:kind_zu_katze.png'); $ogv = mediaFN('wiki:kind_zu_katze.ogv'); @@ -44,54 +49,6 @@ class media_searchlist_test extends DokuWikiTest { } - /* - * Reset media_printfile static variable $twibble to stat state - */ - protected function reset_media_printfile() { - $reflect = new ReflectionFunction('media_printfile'); - $static = $reflect->getStaticVariables(); - if ($static['twibble'] == -1) { - ob_start(); - @media_printfile(array(), 0, ''); - ob_end_clean(); - } - } - - /** - * Build search result header as in media_searchlist() with $fullscreen = false - * - * @param $query search query - * @param $ns namespece where we search - * - * @return string - */ - protected function media_searchlist_header($query, $ns) { - global $lang; - - $header = '

    '.sprintf($lang['searchmedia_in'],hsc($ns).':*').'

    '.NL; - ob_start(); - media_searchform($ns,$query); - $header .= ob_get_contents(); - ob_end_clean(); - - return $header; - } - - /** - * Wrap around media_printfile: return the result. - * - * @param $item - * @return string - */ - protected function media_printfile($item) { - ob_start(); - media_printfile($item,$item['perm'],'',true); - $out = ob_get_contents(); - ob_end_clean(); - - return $out; - } - /** * Wrap around media_searchlist: return the result * Reset media_printfile static variables afterwards @@ -100,159 +57,53 @@ class media_searchlist_test extends DokuWikiTest { * @param $ns * @return string */ - protected function media_searchlist($query, $ns) { + protected function media_searchlist($query, $ns) + { ob_start(); media_searchlist($query, $ns); $out = ob_get_contents(); ob_end_clean(); - - //reset media_printfile static variables - $this->reset_media_printfile(); - return $out; } /** - * - * @param array[string] $rel_ids media ids relative to $this->upload_ns - * @return array $items as required by media_printfile + * @return array[] + * @see testSearch */ - protected function create_media_items($rel_ids) { - $items = array(); - foreach ($rel_ids as $rel_id){ - $file = mediaFN($this->upload_ns . ':' . $rel_id); - $info = array(); - $info['id'] = $this->upload_ns . ':' . $rel_id; - $info['perm'] = auth_quickaclcheck(getNS($info['id']).':*'); - $info['file'] = \dokuwiki\Utf8\PhpString::basename($file); - $info['size'] = filesize($file); - $info['mtime'] = filemtime($file); - $info['writable'] = is_writable($file); - if(preg_match("/\.(jpe?g|gif|png)$/",$file)){ - $info['isimg'] = true; - $info['meta'] = new JpegMeta($file); - }else{ - $info['isimg'] = false; - } - $info['hash'] = md5(io_readFile(mediaFN($info['id']),false)); - - $items[] = $info; - } - return $items; + public function provideSearch() + { + return [ + ['a.png', ['a:a.png', 'b:a.png', 'a.png', 'aa.png']], // no globbing + ['a*.png', ['a:a.png', 'b:a.png', 'a.png', 'aa.png', 'ab.png']], // globbing asterisk + ['*.ogv', ['a.ogv', 'aa.ogv', 'ab.ogv']], // globbing find by ext + ['a?.png', ['aa.png', 'ab.png']], // globbing question mark + ['a?.*', ['aa.ogv', 'aa.png', 'ab.ogv', 'ab.png']], // globbing question mark and asterisk + ['?.png', ['a:a.png', 'b:a.png', 'a.png']], // globbing question mark on the beginning + ['??.png', ['aa.png', 'ab.png']], // globbing two question marks on the beginning + ['??.*', ['aa.ogv', 'aa.png', 'ab.ogv', 'ab.png']], // globbing two letter file names + ['0', ['0.webm']], // zero search + ]; } /** - * Output result as in 'media_searchlist' but use an arbitrary media IDs list instead of actual searching - * Reset media_printfile static variables afterwards - * - * @param array[string] $rel_ids media ids relative to $this->upload_ns - * @param string $query actual seqrch query (used for filling search filed input) - * @param string $ns - * @return string + * @dataProvider provideSearch + * @param string $query The query to use + * @param string[] $expected The expected media IDs in the result HTML + * @throws Exception */ - protected function media_searchlist_except($rel_ids, $query, $ns) { - //build a search result header - $expect = $this->media_searchlist_header($query, $ns); + public function testSearch($query, $expected) + { + $result = $this->media_searchlist($query, $this->upload_ns); + $pq = phpQuery::newDocument($result); - //get the items list - $items = $this->create_media_items($rel_ids); - foreach ($items as $item) { - $expect .= $this->media_printfile($item); + $elements = $pq->find('a.mediafile'); + $actual = []; + foreach ($elements as $element) { + $actual[] = $element->textContent; } - //reset media_printfile static variables - $this->reset_media_printfile(); - - return $expect; + $this->assertEquals(count($expected), count($elements)); + $this->assertEquals($expected, $actual); } - public function test_noglobbing(){ - $query = 'a.png'; - $ns = $this->upload_ns; - - $result = $this->media_searchlist($query, $ns); - $expect = $this->media_searchlist_except(array('a:a.png', 'b:a.png', 'a.png', 'aa.png'), $query, $ns); - - $this->assertEquals($expect, $result); - } - - public function test_globbing_asterisk(){ - $query = 'a*.png'; - $ns = $this->upload_ns; - - $result = $this->media_searchlist($query, $ns); - $expect = $this->media_searchlist_except(array('a:a.png', 'b:a.png', 'a.png', 'aa.png', 'ab.png'), $query, $ns); - - $this->assertEquals($expect, $result); - } - - public function test_globbing_find_by_ext(){ - $query = '*.ogv'; - $ns = $this->upload_ns; - - $result = $this->media_searchlist($query, $ns); - $expect = $this->media_searchlist_except(array('a.ogv', 'aa.ogv', 'ab.ogv'), $query, $ns); - - $this->assertEquals($expect, $result); - } - - public function test_globbing_question_mark(){ - $query = 'a?.png'; - $ns = $this->upload_ns; - - $result = $this->media_searchlist($query, $ns); - $expect = $this->media_searchlist_except(array('aa.png', 'ab.png'), $query, $ns); - - $this->assertEquals($expect, $result); - } - - public function test_globbing_question_mark_and_asterisk(){ - $query = 'a?.*'; - $ns = $this->upload_ns; - - $result = $this->media_searchlist($query, $ns); - $expect = $this->media_searchlist_except(array('aa.ogv', 'aa.png', 'ab.ogv', 'ab.png'), $query, $ns); - - $this->assertEquals($expect, $result); - } - - public function test_globbing_question_mark_on_the_begining(){ - $query = '?.png'; - $ns = $this->upload_ns; - - $result = $this->media_searchlist($query, $ns); - $expect = $this->media_searchlist_except(array('a:a.png', 'b:a.png', 'a.png'), $query, $ns); - - $this->assertEquals($expect, $result); - } - - public function test_globbing_two_question_marks_on_the_begining(){ - $query = '??.png'; - $ns = $this->upload_ns; - - $result = $this->media_searchlist($query, $ns); - $expect = $this->media_searchlist_except(array('aa.png', 'ab.png'), $query, $ns); - - $this->assertEquals($expect, $result); - } - - public function test_globbing_two_letter_file_names(){ - $query = '??.*'; - $ns = $this->upload_ns; - - $result = $this->media_searchlist($query, $ns); - $expect = $this->media_searchlist_except(array('aa.ogv', 'aa.png', 'ab.ogv', 'ab.png'), $query, $ns); - - $this->assertEquals($expect, $result); - } - - public function test_zero_search(){ - $query = '0'; - $ns = $this->upload_ns; - - $result = $this->media_searchlist($query, $ns); - $expect = $this->media_searchlist_except(array('0.webm'), $query, $ns); - - $this->assertEquals($expect, $result); - } } From 79b008230541e34a988cd3273ba7267a1eef6d28 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 6 Jan 2021 20:19:36 +0100 Subject: [PATCH 05/10] reenable the option to display a relative namespace for media files This is used when searching for media files --- inc/Ui/Media/Display.php | 29 ++++++++++++++++++++++++++++- inc/Ui/Media/DisplayRow.php | 4 ++-- inc/Ui/Media/DisplayTile.php | 2 +- inc/media.php | 4 ++-- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/inc/Ui/Media/Display.php b/inc/Ui/Media/Display.php index a7428054b..81ec20aca 100644 --- a/inc/Ui/Media/Display.php +++ b/inc/Ui/Media/Display.php @@ -6,9 +6,12 @@ use dokuwiki\Media\MediaFile; class Display { - + /** @var MediaFile */ protected $mediaFile; + /** @var string should IDs be shown relative to this namespace? Used in search results */ + protected $relativeDisplay = null; + /** * Display constructor. * @param MediaFile $mediaFile @@ -48,6 +51,16 @@ class Display return DOKU_BASE . $link; } + /** + * Show IDs relative to this namespace + * + * @param string|null $ns Use null to disable + */ + public function relativeDisplay($ns) + { + $this->relativeDisplay = $ns; + } + /** @return string */ protected function formatDate() { @@ -76,4 +89,18 @@ class Display { return filesize_h($this->mediaFile->getFileSize()); } + + /** @return string */ + protected function formatDisplayName() + { + if ($this->relativeDisplay !== null) { + $id = $this->mediaFile->getId(); + if (substr($id, 0, strlen($this->relativeDisplay)) == $this->relativeDisplay) { + $id = substr($id, strlen($this->relativeDisplay)); + } + return ltrim($id, ':'); + } else { + return $this->mediaFile->getDisplayName(); + } + } } diff --git a/inc/Ui/Media/DisplayRow.php b/inc/Ui/Media/DisplayRow.php index f74510251..e45a8004b 100644 --- a/inc/Ui/Media/DisplayRow.php +++ b/inc/Ui/Media/DisplayRow.php @@ -24,7 +24,7 @@ class DisplayRow extends DisplayTile echo '
    '; echo '' . - $this->mediaFile->getDisplayName() . + $this->formatDisplayName() . ' '; echo '(' . $info . ')' . NL; @@ -38,7 +38,7 @@ class DisplayRow extends DisplayTile echo ' '; - // delete button FIXME + // delete button if ($this->mediaFile->isWritable() && $this->mediaFile->userPermission() >= AUTH_DELETE) { $link = DOKU_BASE . 'lib/exe/mediamanager.php?delete=' . rawurlencode($id) . '&sectok=' . getSecurityToken(); diff --git a/inc/Ui/Media/DisplayTile.php b/inc/Ui/Media/DisplayTile.php index 7fc1c93cf..ba4dbfc77 100644 --- a/inc/Ui/Media/DisplayTile.php +++ b/inc/Ui/Media/DisplayTile.php @@ -39,7 +39,7 @@ class DisplayTile extends Display echo '
    '; echo '' . - $this->mediaFile->getDisplayName() . + $this->formatDisplayName() . ''; echo '
    '; diff --git a/inc/media.php b/inc/media.php index ecd745e2e..84b69f784 100644 --- a/inc/media.php +++ b/inc/media.php @@ -1566,13 +1566,13 @@ function media_searchlist($query,$ns,$auth=null,$fullscreen=false,$sort='natural foreach($evdata['data'] as $item){ if (!$fullscreen) { // FIXME old call: media_printfile($item,$item['perm'],'',true); - // FIXME we actually want the namespace here -> needs fixing $display = new \dokuwiki\Ui\Media\DisplayRow($item); + $display->relativeDisplay($ns); $display->show(); } else { // FIXME old call: media_printfile_thumbs($item,$item['perm'],false,true); - // FIXME we actually want the namespace here -> needs fixing $display = new \dokuwiki\Ui\Media\DisplayTile($item); + $display->relativeDisplay($ns); echo '
  • '; $display->show(); echo '
  • '; From 9a1a86fb4c4dc988a0ae52a94b833ea5663fc319 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 6 Jan 2021 20:32:49 +0100 Subject: [PATCH 06/10] fix entity definition --- inc/Ui/Media/Display.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/Ui/Media/Display.php b/inc/Ui/Media/Display.php index 81ec20aca..440737b22 100644 --- a/inc/Ui/Media/Display.php +++ b/inc/Ui/Media/Display.php @@ -73,7 +73,7 @@ class Display * @param string $empty what to show when no dimensions are available * @return string */ - protected function formatDimensions($empty = ' ') + protected function formatDimensions($empty = ' ') { $w = $this->mediaFile->getWidth(); $h = $this->mediaFile->getHeight(); From 0a47efcd61763bd60dacfea1b0c7e806833e2a31 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 6 Jan 2021 21:55:52 +0100 Subject: [PATCH 07/10] fix use of $rev parameter --- inc/Media/MediaFile.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/Media/MediaFile.php b/inc/Media/MediaFile.php index e618fe879..bebacc8d4 100644 --- a/inc/Media/MediaFile.php +++ b/inc/Media/MediaFile.php @@ -25,7 +25,7 @@ class MediaFile public function __construct($id, $rev = '') { $this->id = $id; //FIXME should it be cleaned? - $this->path = mediaFN($id); + $this->path = mediaFN($id, $rev); list($this->ext, $this->mime, $this->downloadable) = mimetype($this->path, false); } From 9453716dc4e120c7e2ebc01fba4d27c53f881e0c Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 6 Jan 2021 22:11:42 +0100 Subject: [PATCH 08/10] readded $jump mechanism, removed unused functions --- inc/Ui/Media/Display.php | 13 +++ inc/Ui/Media/DisplayRow.php | 6 +- inc/Ui/Media/DisplayTile.php | 4 +- inc/media.php | 203 +---------------------------------- 4 files changed, 20 insertions(+), 206 deletions(-) diff --git a/inc/Ui/Media/Display.php b/inc/Ui/Media/Display.php index 440737b22..fd46fa6b2 100644 --- a/inc/Ui/Media/Display.php +++ b/inc/Ui/Media/Display.php @@ -12,6 +12,9 @@ class Display /** @var string should IDs be shown relative to this namespace? Used in search results */ protected $relativeDisplay = null; + /** @var bool scroll to this file on display? */ + protected $scrollIntoView = false; + /** * Display constructor. * @param MediaFile $mediaFile @@ -61,6 +64,16 @@ class Display $this->relativeDisplay = $ns; } + /** + * Scroll to this file on display? + * + * @param bool $set + */ + public function scrollIntoView($set = true) + { + $this->scrollIntoView = $set; + } + /** @return string */ protected function formatDate() { diff --git a/inc/Ui/Media/DisplayRow.php b/inc/Ui/Media/DisplayRow.php index e45a8004b..47feed088 100644 --- a/inc/Ui/Media/DisplayRow.php +++ b/inc/Ui/Media/DisplayRow.php @@ -13,16 +13,14 @@ class DisplayRow extends DisplayTile public function show() { global $lang; - - // FIXME support for jumping to file? // FIXME Zebra classes have been dropped and need to be readded via CSS - // FIXME use of $display_namespace unclear, dropped for now -> maybe for search? $id = $this->mediaFile->getId(); $class = 'select mediafile mf_' . $this->mediaFile->getIcoClass(); $info = trim($this->formatDimensions('') . ' ' . $this->formatDate() . ' ' . $this->formatFileSize()); + $jump = $this->scrollIntoView ? 'id="scroll__here"' : ''; - echo '
    '; + echo '
    '; echo '' . $this->formatDisplayName() . ' '; diff --git a/inc/Ui/Media/DisplayTile.php b/inc/Ui/Media/DisplayTile.php index ba4dbfc77..f20ed1407 100644 --- a/inc/Ui/Media/DisplayTile.php +++ b/inc/Ui/Media/DisplayTile.php @@ -30,7 +30,9 @@ class DisplayTile extends Display */ public function show() { - echo '
    '; + $jump = $this->scrollIntoView ? 'id="scroll__here"' : ''; + + echo '
    '; echo '
    '; echo ''; echo $this->getPreviewHtml(90, 90); diff --git a/inc/media.php b/inc/media.php index 84b69f784..92e685b99 100644 --- a/inc/media.php +++ b/inc/media.php @@ -712,11 +712,13 @@ function media_filelist($ns,$auth=null,$jump='',$fullscreenview=false,$sort=fals if (!$fullscreenview) { //FIXME old call: media_printfile($item,$auth,$jump); $display = new \dokuwiki\Ui\Media\DisplayRow($item); + $display->scrollIntoView($jump == $item->getID()); $display->show(); } else { //FIXME old call: media_printfile_thumbs($item,$auth,$jump); echo '
  • '; $display = new \dokuwiki\Ui\Media\DisplayTile($item); + $display->scrollIntoView($jump == $item->getID()); $display->show(); echo '
  • '; } @@ -1582,86 +1584,6 @@ function media_searchlist($query,$ns,$auth=null,$fullscreen=false,$sort='natural } } -/** - * Formats and prints one file in the list - * - * @param array $item - * @param int $auth permission level - * @param string $jump item id - * @param bool $display_namespace - */ -function media_printfile($item,$auth,$jump,$display_namespace=false){ - global $lang; - - // Prepare zebra coloring - // I always wanted to use this variable name :-D - static $twibble = 1; - $twibble *= -1; - $zebra = ($twibble == -1) ? 'odd' : 'even'; - - // Automatically jump to recent action - if($jump == $item['id']) { - $jump = ' id="scroll__here" '; - }else{ - $jump = ''; - } - - // Prepare fileicons - list($ext) = mimetype($item['file'],false); - $class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext); - $class = 'select mediafile mf_'.$class; - - // Prepare filename - $file = utf8_decodeFN($item['file']); - - // Prepare info - $info = ''; - if($item['isimg']){ - $info .= (int) $item['meta']->getField('File.Width'); - $info .= '×'; - $info .= (int) $item['meta']->getField('File.Height'); - $info .= ' '; - } - $info .= ''.dformat($item['mtime']).''; - $info .= ' '; - $info .= filesize_h($item['size']); - - // output - echo '
    '.NL; - if (!$display_namespace) { - echo ''.hsc($file).' '; - } else { - echo ''.hsc($item['id']).'
    '; - } - echo '('.$info.')'.NL; - - // view button - $link = ml($item['id'],'',true); - echo ' '; - - // mediamanager button - $link = wl('',array('do'=>'media','image'=>$item['id'],'ns'=>getNS($item['id']))); - echo ' '; - - // delete button - if($item['writable'] && $auth >= AUTH_DELETE){ - $link = DOKU_BASE.'lib/exe/mediamanager.php?delete='.rawurlencode($item['id']). - '&sectok='.getSecurityToken(); - echo ' '. - ''.$lang['btn_delete'].''; - } - - echo '
    '; - echo $lang['mediausage'].' {{:'.$item['id'].'}}'; - echo '
    '; - if($item['isimg']) media_printimgdetail($item); - echo '
    '.NL; - echo '
    '.NL; -} - /** * Display a media icon * @@ -1681,127 +1603,6 @@ function media_printicon($filename, $size=''){ return ''.$filename.''; } -/** - * Formats and prints one file in the list in the thumbnails view - * - * @author Kate Arzamastseva - * - * @param array $item - * @param int $auth permission level - * @param bool|string $jump item id - * @param bool $display_namespace - */ -function media_printfile_thumbs($item,$auth,$jump=false,$display_namespace=false){ - - // Prepare filename - $file = utf8_decodeFN($item['file']); - - // output - echo '
  • '.NL; - - echo '
    '; - if($item['isimg']) { - media_printimgdetail($item, true); - - } else { - echo ''; - echo media_printicon($item['id'], '32x32'); - echo ''; - } - echo '
    '.NL; - if (!$display_namespace) { - $name = hsc($file); - } else { - $name = hsc($item['id']); - } - echo '
    '.$name.'
    '.NL; - - if($item['isimg']){ - $size = ''; - $size .= (int) $item['meta']->getField('File.Width'); - $size .= '×'; - $size .= (int) $item['meta']->getField('File.Height'); - echo '
    '.$size.'
    '.NL; - } else { - echo '
     
    '.NL; - } - $date = dformat($item['mtime']); - echo '
    '.$date.'
    '.NL; - $filesize = filesize_h($item['size']); - echo '
    '.$filesize.'
    '.NL; - echo '
  • '.NL; -} - -/** - * Prints a thumbnail and metainfo - * - * @param array $item - * @param bool $fullscreen - */ -function media_printimgdetail($item, $fullscreen=false){ - // prepare thumbnail - $size = $fullscreen ? 90 : 120; - - $w = (int) $item['meta']->getField('File.Width'); - $h = (int) $item['meta']->getField('File.Height'); - if($w>$size || $h>$size){ - if (!$fullscreen) { - $ratio = $item['meta']->getResizeRatio($size); - } else { - $ratio = $item['meta']->getResizeRatio($size,$size); - } - $w = floor($w * $ratio); - $h = floor($h * $ratio); - } - $src = ml($item['id'],array('w'=>$w,'h'=>$h,'t'=>$item['mtime'])); - $p = array(); - if (!$fullscreen) { - // In fullscreen mediamanager view, image resizing is done via CSS. - $p['width'] = $w; - $p['height'] = $h; - } - $p['alt'] = $item['id']; - $att = buildAttributes($p); - - // output - if ($fullscreen) { - echo ''; - echo ''; - echo ''; - } - - if ($fullscreen) return; - - echo '
    '; - echo '
    '; - echo ''; - echo ''; - echo ''; - echo '
    '; - - // read EXIF/IPTC data - $t = $item['meta']->getField(array('IPTC.Headline','xmp.dc:title')); - $d = $item['meta']->getField(array('IPTC.Caption','EXIF.UserComment', - 'EXIF.TIFFImageDescription', - 'EXIF.TIFFUserComment')); - if(\dokuwiki\Utf8\PhpString::strlen($d) > 250) $d = \dokuwiki\Utf8\PhpString::substr($d,0,250).'...'; - $k = $item['meta']->getField(array('IPTC.Keywords','IPTC.Category','xmp.dc:subject')); - - // print EXIF/IPTC data - if($t || $d || $k ){ - echo '

    '; - if($t) echo ''.hsc($t).'
    '; - if($d) echo hsc($d).'
    '; - if($t) echo ''.hsc($k).''; - echo '

    '; - } - echo '
    '; -} - /** * Build link based on the current, adding/rewriting parameters * From 24115d4272bd0e03b95139e41c743d8cdb058328 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Thu, 7 Jan 2021 11:17:25 +0100 Subject: [PATCH 09/10] use SVG icons for media file links The dokuwiki template should probably be adjusted a bit. Old png files are not yet removed as they may be used elsewhere still. --- lib/exe/css.php | 20 ++++++++------------ lib/images/fileicons/svg/README | 1 + lib/images/fileicons/svg/index.php | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 lib/images/fileicons/svg/README create mode 100644 lib/images/fileicons/svg/index.php diff --git a/lib/exe/css.php b/lib/exe/css.php index 2ea2c0963..9ca1bac48 100644 --- a/lib/exe/css.php +++ b/lib/exe/css.php @@ -357,30 +357,26 @@ function css_filetypes(){ // default style echo '.mediafile {'; - echo ' background: transparent url('.DOKU_BASE.'lib/images/fileicons/file.png) 0px 1px no-repeat;'; - echo ' padding-left: 18px;'; - echo ' padding-bottom: 1px;'; + echo ' background: transparent url('.DOKU_BASE.'lib/images/fileicons/svg/file.svg) 0px 1px no-repeat;'; + echo ' background-size: 1.2em;'; + echo ' padding-left: 1.5em;'; echo '}'; // additional styles when icon available // scan directory for all icons $exts = array(); - if($dh = opendir(DOKU_INC.'lib/images/fileicons')){ + if($dh = opendir(DOKU_INC.'lib/images/fileicons/svg')){ while(false !== ($file = readdir($dh))){ - if(preg_match('/([_\-a-z0-9]+(?:\.[_\-a-z0-9]+)*?)\.(png|gif)/i',$file,$match)){ - $ext = strtolower($match[1]); - $type = '.'.strtolower($match[2]); - if($ext!='file' && (!isset($exts[$ext]) || $type=='.png')){ - $exts[$ext] = $type; - } + if(preg_match('/(.*?)\.svg$/i',$file, $match)){ + $exts[] = strtolower($match[1]); } } closedir($dh); } - foreach($exts as $ext=>$type){ + foreach($exts as $ext){ $class = preg_replace('/[^_\-a-z0-9]+/','_',$ext); echo ".mf_$class {"; - echo ' background-image: url('.DOKU_BASE.'lib/images/fileicons/'.$ext.$type.')'; + echo ' background-image: url('.DOKU_BASE.'lib/images/fileicons/svg/'.$ext.'.svg)'; echo '}'; } } diff --git a/lib/images/fileicons/svg/README b/lib/images/fileicons/svg/README new file mode 100644 index 000000000..4e7770bed --- /dev/null +++ b/lib/images/fileicons/svg/README @@ -0,0 +1 @@ +Icons come from https://fileicons.org/ diff --git a/lib/images/fileicons/svg/index.php b/lib/images/fileicons/svg/index.php new file mode 100644 index 000000000..66c4835af --- /dev/null +++ b/lib/images/fileicons/svg/index.php @@ -0,0 +1,22 @@ + + + + Filetype icons + + + + + + + '; +} +?> + + From 0603f506f0268170ae59481c161bf882d14307f9 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 13 Jan 2021 19:23:43 +0100 Subject: [PATCH 10/10] rename namespace Media to File This is a bit more generic and allows us to have additional File abstractions in here later. --- inc/{Media => File}/MediaFile.php | 2 +- inc/Ui/Media/Display.php | 2 +- inc/Ui/Media/DisplayTile.php | 2 +- inc/search.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename inc/{Media => File}/MediaFile.php (99%) diff --git a/inc/Media/MediaFile.php b/inc/File/MediaFile.php similarity index 99% rename from inc/Media/MediaFile.php rename to inc/File/MediaFile.php index bebacc8d4..4c27cc65c 100644 --- a/inc/Media/MediaFile.php +++ b/inc/File/MediaFile.php @@ -1,6 +1,6 @@