1<?php 2 3use dokuwiki\Extension\ActionPlugin; 4use dokuwiki\Extension\EventHandler; 5use dokuwiki\Extension\Event; 6use dokuwiki\Form\Form; 7use dokuwiki\plugin\structpublish\meta\Constants; 8use dokuwiki\plugin\structpublish\meta\Revision; 9 10/** 11 * Action component responsible for the publish banner 12 * attached to struct data of a page 13 */ 14class action_plugin_structpublish_banner extends ActionPlugin 15{ 16 /** @var \helper_plugin_structpublish_db */ 17 protected $dbHelper; 18 19 /** @var bool */ 20 protected $compactView; 21 22 /** @inheritDoc */ 23 public function register(EventHandler $controller) 24 { 25 $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, 'renderBanner'); 26 } 27 28 /** 29 * Add banner to pages under structpublish control 30 */ 31 public function renderBanner(Event $event) 32 { 33 global $ID; 34 global $INFO; 35 global $REV; 36 37 if ($event->data !== 'show') { 38 return; 39 } 40 41 $this->dbHelper = plugin_load('helper', 'structpublish_db'); 42 43 if (!$this->dbHelper->isPublishable()) { 44 return; 45 } 46 47 $this->compactView = (bool)$this->getConf('compact_view'); 48 49 // get the possible revisions needed in the banner 50 $newestRevision = new Revision($ID, $INFO['currentrev']); 51 if ($REV) { 52 $shownRevision = new Revision($ID, $REV); 53 } else { 54 $shownRevision = $newestRevision; 55 } 56 $latestpubRevision = $newestRevision->getLatestPublishedRevision(); 57 $prevpubRevision = $shownRevision->getLatestPublishedRevision($REV ?: $INFO['currentrev']); 58 59 $compactClass = $this->compactView ? ' compact' : ''; 60 $banner = '<div class="plugin-structpublish-banner ' . $shownRevision->getStatus() . $compactClass . '">'; 61 62 // status of the shown revision 63 $banner .= '<span class="icon">' . 64 inlineSVG(__DIR__ . '/../ico/' . $shownRevision->getStatus() . '.svg') . 65 '</span>'; 66 $banner .= $this->getBannerText('status_' . $shownRevision->getStatus(), $shownRevision); 67 68 // link to previous or newest published version 69 if ($latestpubRevision !== null && $shownRevision->getRev() < $latestpubRevision->getRev()) { 70 $banner .= $this->getBannerText('latest_publish', $latestpubRevision, $shownRevision->getRev()); 71 } else { 72 $banner .= $this->getBannerText('previous_publish', $prevpubRevision, $shownRevision->getRev()); 73 } 74 75 // link to newest draft, if exists, is not shown already and user has a role 76 if ( 77 $newestRevision->getRev() != $shownRevision->getRev() && 78 $newestRevision->getStatus() != Constants::STATUS_PUBLISHED && 79 $this->dbHelper->checkAccess($ID) 80 ) { 81 $banner .= $this->getBannerText('latest_draft', $newestRevision, $shownRevision->getRev()); 82 } 83 84 // action buttons 85 if ($shownRevision->getRev() == $newestRevision->getRev()) { 86 $banner .= $this->actionButtons( 87 $shownRevision->getStatus(), 88 $latestpubRevision ? $this->increaseVersion($latestpubRevision->getVersion()) : '1' 89 ); 90 } 91 92 $banner .= '</div>'; 93 echo $banner; 94 } 95 96 /** 97 * Fills place holder texts with data from the given Revision 98 * 99 * @param string $name 100 * @param Revision $rev 101 * @return string 102 */ 103 protected function getBannerText($name, $rev, $diff = '') 104 { 105 if ($rev === null) { 106 return ''; 107 } 108 109 $replace = [ 110 '{user}' => userlink($rev->getUser()), 111 '{revision}' => $this->makeLink($rev->getId(), $rev->getRev(), dformat($rev->getRev())), 112 '{datetime}' => $this->makeLink($rev->getId(), $rev->getRev(), dformat($rev->getTimestamp())), 113 '{version}' => hsc($rev->getVersion()), 114 ]; 115 116 $text = $this->getLang($this->compactView ? "compact_banner_$name" : "banner_$name"); 117 118 $text = strtr($text, $replace); 119 120 // add link to diff view 121 if ($diff && $diff !== $rev->getRev()) { 122 $link = wl($rev->getId(), ['do' => 'diff', 'rev2[0]' => $rev->getRev(), 'rev2[1]' => $diff]); 123 $icon = inlineSVG(__DIR__ . '/../ico/diff.svg'); 124 $text .= ' <a href="' . $link . '" title="' . $this->getLang('diff') . '">' . $icon . '</a>'; 125 } 126 127 $tag = $this->compactView ? 'span' : 'p'; 128 129 return "<$tag class='$name'>$text</$tag>"; 130 } 131 132 /** 133 * Create a HTML link to a specific revision 134 * 135 * @param string $id page id 136 * @param int $rev revision to link to 137 * @param int $text the link text to use 138 * @return string 139 */ 140 protected function makeLink($id, $rev, $text) 141 { 142 $url = wl($id, ['rev' => $rev]); 143 return '<a href="' . $url . '">' . hsc($text) . '</a>'; 144 } 145 146 /** 147 * Create the form for approval and publishing 148 * 149 * @param string $status current status 150 * @param string $newVersion suggested new Version 151 * @return string 152 */ 153 protected function actionButtons($status, $newVersion) 154 { 155 global $ID; 156 if ($status === Constants::STATUS_PUBLISHED) { 157 return ''; 158 } 159 160 $form = new Form(); 161 162 if ( 163 $status !== Constants::STATUS_APPROVED && 164 $this->dbHelper->checkAccess($ID, [Constants::ACTION_APPROVE]) 165 ) { 166 $form->addButton( 167 'structpublish[' . Constants::ACTION_APPROVE . ']', 168 $this->getLang('action_' . Constants::ACTION_APPROVE) 169 )->attr('type', 'submit'); 170 } 171 172 if ($this->dbHelper->checkAccess($ID, [Constants::ACTION_PUBLISH])) { 173 $form->addTextInput('version', $this->getLang('newversion'))->val($newVersion); 174 $form->addButton( 175 'structpublish[' . Constants::ACTION_PUBLISH . ']', 176 $this->getLang('action_' . Constants::ACTION_PUBLISH) 177 )->attr('type', 'submit'); 178 } 179 180 return $form->toHTML(); 181 } 182 183 /** 184 * Tries to increase a given version 185 * 186 * @param string $version 187 * @return string 188 */ 189 protected function increaseVersion($version) 190 { 191 $parts = explode('.', $version); 192 $last = array_pop($parts); 193 194 if (is_numeric($last)) { 195 $last++; 196 } 197 $parts[] = $last; 198 199 return implode('.', $parts); 200 } 201} 202