File modules/cms/generator/link/PublicLink.class.php

Last commit: Tue Feb 14 00:23:13 2023 +0100	Jan Dankert	New filters: Robots (for robots.txt) and Sitemap.
1 <?php 2 3 namespace cms\generator\link; 4 5 use cms\base\Configuration; 6 use cms\generator\PageContext; 7 use cms\model\BaseObject; 8 use cms\model\File; 9 use cms\model\Folder; 10 use cms\model\Language; 11 use cms\model\Link; 12 use cms\model\Page; 13 use cms\model\Project; 14 use cms\model\Template; 15 use cms\model\TemplateModel; 16 use cms\model\Url; 17 use cms\generator\target\Dav; 18 use cms\generator\target\Fax; 19 use cms\generator\target\Ftp; 20 use cms\generator\target\Ftps; 21 use cms\generator\target\Local; 22 use cms\generator\target\NoBaseTarget; 23 use cms\generator\target\Scp; 24 use cms\generator\target\SFtp; 25 use cms\generator\target\BaseTarget; 26 use util\exception\PublisherException; 27 use util\FileUtils; 28 use logger\Logger; 29 use util\exception\UIException; 30 use util\Session; 31 32 33 34 /** 35 * Linkformatter for public links. 36 * 37 * @author Jan Dankert 38 */ 39 40 class PublicLink implements LinkFormat 41 { 42 const SCHEMA_ABSOLUTE = 1; 43 const SCHEMA_RELATIVE = 2; 44 45 const MAX_RECURSIVE_COUNT = 10; 46 47 /** 48 * @var PageContext 49 */ 50 private $pageContext; 51 52 /** 53 * PublicLink constructor. 54 * @param $pageContext PageContext 55 */ 56 public function __construct($pageContext) 57 { 58 $this->pageContext = $pageContext; 59 } 60 61 62 /** 63 * Creates a link from an object to another object. 64 * 65 * @param $from \cms\model\BaseObject 66 * @param $to \cms\model\BaseObject 67 * 68 * @return string the url 69 */ 70 public function linkToObject( BaseObject $from, BaseObject $to ) { 71 72 $publishConfig = Configuration::subset('publish'); 73 74 $from->load(); 75 $fromProject = $from->getProject()->load(); 76 77 $schema = $fromProject->linkAbsolute?self::SCHEMA_ABSOLUTE:self::SCHEMA_RELATIVE; 78 79 $counter = 0; 80 while( $to->typeid == BaseObject::TYPEID_LINK ) 81 { 82 if ( $counter++ > self::MAX_RECURSIVE_COUNT) 83 throw new \LogicException("Too much redirects while following a link. Stopped at #".$to->objectid ); 84 85 $link = new Link( $to->objectid ); 86 $link->load(); 87 88 $to = new BaseObject( $link->linkedObjectId ); 89 $to->objectLoad(); 90 } 91 92 switch( $to->typeid ) { 93 case BaseObject::TYPEID_FILE: 94 case BaseObject::TYPEID_IMAGE: 95 case BaseObject::TYPEID_TEXT: 96 case BaseObject::TYPEID_SCRIPT: 97 98 $f = new File($to->objectid); 99 100 $f->load(); 101 $filename = $f->filename(); 102 103 if ( $fromProject->publishFileExtension && ! $fromProject->content_negotiation ) 104 // Add file extension 105 $filename .= '.'.$f->extension; 106 107 break; 108 109 case BaseObject::TYPEID_PAGE: 110 111 if ($fromProject->cut_index && $to->filename == $publishConfig->get('default','index')) { 112 $filename = ''; // Link auf Index-Datei, der Dateiname bleibt leer. 113 } else { 114 115 $page = new Page($to->objectid); 116 $page->load(); 117 118 $template = new Template( $page->templateid ); 119 $template->load(); 120 121 if ( ! $template->publish ) { 122 // fixme: target page is not publishable - what to do here? 123 return ''; 124 } 125 126 $parentFolder = new Folder($page->parentid); 127 $parentFolder->load(); 128 129 $format = $publishConfig->get('format','{filename}{language_sep}{language}{type_sep}{type}'); 130 $format = str_replace('{filename}', $page->filename(), $format); 131 132 $allLanguages = $fromProject->getLanguageIds(); 133 $allModels = $fromProject->getModelIds(); 134 135 $withLanguage = 136 !$fromProject->content_negotiation && 137 $fromProject->publishPageExtension && 138 (count($allLanguages) > 1 || $publishConfig->get('filename_language','auto') == 'always'); 139 140 $withModel = 141 ! $fromProject->content_negotiation && 142 $fromProject->publishPageExtension && 143 (count($allModels) > 1 || $publishConfig->get('filename_type','always') == 'always'); 144 145 $languagePart = ''; 146 $typePart = ''; 147 148 if ($withLanguage ) { 149 $l = new Language($this->pageContext->languageId); 150 $l->load(); 151 $languagePart = $l->isoCode; 152 } 153 154 if ( $withModel ) { 155 $templateModel = new TemplateModel( $page->templateid, $this->pageContext->modelId ); 156 $templateModel->load(); 157 158 $typePart = $templateModel->extension; 159 } 160 161 $languageSep = $languagePart? $publishConfig->get('language_sep','.') :''; 162 $typeSep = $typePart ? $publishConfig->get('type_sep' ,'.') :''; 163 164 $format = str_replace('{language}' ,$languagePart ,$format ); 165 $format = str_replace('{language_sep}',$languageSep ,$format ); 166 $format = str_replace('{type}' ,$typePart ,$format ); 167 $format = str_replace('{type_sep}' ,$typeSep ,$format ); 168 169 $filename = $format; 170 } 171 172 break; 173 174 case BaseObject::TYPEID_URL: 175 $url = new Url( $to->objectid ); 176 $url->load(); 177 return $url->url; 178 179 case BaseObject::TYPEID_FOLDER: 180 // of course it is not possible to link a folder 181 // this is a fallback if anywhere a folder is accidentally linked 182 $filename = ''; 183 break; 184 185 default: 186 throw new \LogicException("Could not build a link to the unknown Type ".$to->typeid.':'.$to->getType() ); 187 } 188 189 190 if ( $from->projectid != $to->projectid ) 191 { 192 // BaseTarget object is in another project. 193 // we have to use absolute URLs. 194 $schema = self::SCHEMA_ABSOLUTE; 195 196 // BaseTarget is in another Project. So we have to create an absolute URL. 197 $targetProject = Project::create( $to->projectid )->load(); 198 $host = $targetProject->url; 199 200 if ( ! strpos($host,'//' ) === FALSE ) { 201 // No protocol in hostname. So we have to prepend the URL with '//'. 202 $host = '//'.$host; 203 } 204 } 205 else { 206 $host = ''; 207 } 208 209 210 211 212 if ( $schema == self::SCHEMA_RELATIVE ) 213 { 214 $folder = new Folder( $from->getParentFolderId() ); 215 $folder->load(); 216 $fromPathFolders = $folder->parentObjectFileNames(false,true); 217 218 $folder = new Folder($to->getParentFolderId() ); 219 220 $toPathFolders = $folder->parentObjectFileNames(false, true); 221 222 // Shorten the relative URL 223 // if the actual page is /path/folder1/page1 224 // and the target page is /path/folder2/page2 225 // we shorten the link from ../../path/folder2/page2 226 // to ../folder2/page2 227 foreach( $fromPathFolders as $folderId => $folderFileName ) { 228 if ( count($toPathFolders) >= 1 && array_keys($toPathFolders)[0] == $folderId ) { 229 unset( $fromPathFolders[$folderId] ); 230 unset( $toPathFolders [$folderId] ); 231 }else { 232 break; 233 } 234 235 } 236 237 if ( $fromPathFolders ) 238 $path = str_repeat( '../',count($fromPathFolders) ); 239 else 240 $path = './'; // Just to clarify- this could be blank too. 241 242 if ( $toPathFolders ) 243 $path .= implode('/',$toPathFolders).'/'; 244 } 245 else { 246 // Absolute Pfadangaben 247 $folder = new Folder( $to->getParentFolderId() ); 248 $toPathFolders = $folder->parentObjectFileNames(false, true); 249 250 $path = '/'; 251 252 if ( $toPathFolders ) 253 $path .= implode('/',$toPathFolders).'/'; 254 } 255 256 257 $uri = $host . $path . $filename; 258 259 if( !$uri ) 260 $uri = '.'; 261 262 return $uri; 263 } 264 265 }
Download modules/cms/generator/link/PublicLink.class.php
History Tue, 14 Feb 2023 00:23:13 +0100 Jan Dankert New filters: Robots (for robots.txt) and Sitemap. Sat, 2 Jul 2022 01:20:38 +0200 Jan Dankert Fix: Fallback, if a folder is linked. Sat, 2 Jul 2022 00:14:56 +0200 Jan Dankert Fix: do not use page extensions in link (if configured in the project) Fri, 18 Mar 2022 22:38:42 +0100 dankert Refactoring: Extracted the TemplateGenerator out of the PageGenerator. Sat, 27 Feb 2021 02:40:09 +0100 Jan Dankert Fix: Use the sourceObjectId from the pageContext for links. Sun, 1 Nov 2020 00:36:50 +0100 Jan Dankert Refactoring: Only using the configuration object. Sat, 26 Sep 2020 04:26:55 +0200 Jan Dankert Refactoring: read configuration values with a class. Wed, 23 Sep 2020 01:04:05 +0200 Jan Dankert Cleanup of deprecated methods and deprecated class attributes. Mon, 21 Sep 2020 22:48:59 +0200 Jan Dankert Complexe refactoring: Moving all generation logic from the model (Value,Page,File) to generators classes.