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