PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/api/libs/Publish.php

https://gitlab.com/x33n/respond
PHP | 1561 lines | 867 code | 447 blank | 247 comment | 174 complexity | 8163643868ad503ff6cc9fdc06d68521 MD5 | raw file
  1. <?php
  2. class Publish
  3. {
  4. // publishes the entire site
  5. public static function PublishSite($siteId){
  6. // repbulish Content
  7. Publish::PublishContent($siteId);
  8. // repbulish engine
  9. Publish::PublishEngine($siteId);
  10. }
  11. // publishes the content for the site (Pages, Current Theme CSS, Menu JSON, Sitemap, RSS)
  12. public static function PublishContent($siteId){
  13. $site = Site::GetBySiteId($siteId);
  14. // inject site settings
  15. Publish::InjectSiteSettings($site);
  16. // publish all pages
  17. Publish::PublishAllPages($site);
  18. // publish menu JSON
  19. Publish::PublishMenuJSON($site);
  20. // publish CSS
  21. Publish::PublishAllCSS($site);
  22. // publish sitemap
  23. Publish::PublishSiteMap($site);
  24. // publish RSS
  25. Publish::PublishRssForPageTypes($site);
  26. }
  27. // publishes the engine for the site (JS libs, CSS libs, Plugins, Locales, Htaccess)
  28. public static function PublishEngine($siteId){
  29. $site = Site::GetBySiteId($siteId);
  30. // publish common JS (libs)
  31. Publish::PublishCommonJS($site);
  32. // publish common css (libs)
  33. Publish::PublishCommonCSS($site);
  34. // publish plugins
  35. Publish::PublishPlugins($site);
  36. // publish locales
  37. Publish::PublishLocales($site);
  38. // setup htaccess
  39. Publish::SetupHtaccess($site);
  40. // update version
  41. Site::EditVersion($site['SiteId'], VERSION);
  42. }
  43. // publishes locales for the site
  44. public static function PublishLocales($site){
  45. // copy templates/respond
  46. $locales_src = APP_LOCATION.'/site/locales';
  47. $locales_dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/locales';
  48. // create libs directory if it does not exist
  49. if(!file_exists($locales_dest)){
  50. mkdir($locales_dest, 0755, true);
  51. Utilities::CopyDirectory($locales_src, $locales_dest);
  52. }
  53. }
  54. // creates .htaccess to deny access to a specific directory
  55. public static function CreateDeny($dir){
  56. // create dir if needed
  57. if(!file_exists($dir)){
  58. mkdir($dir, 0755, true);
  59. }
  60. // create .htaccess to deny access
  61. $deny = $dir.'.htaccess';
  62. file_put_contents($deny, 'Deny from all'); // save to file
  63. }
  64. // creates .htaccess for html5 sites
  65. public static function SetupHtaccess($site){
  66. $htaccess = SITES_LOCATION.'/'.$site['FriendlyId'].'/.htaccess';
  67. if($site['UrlMode'] == 'html5'){
  68. $contents = 'Options -Indexes'.PHP_EOL.
  69. 'RewriteEngine On'.PHP_EOL.
  70. 'RewriteCond %{REQUEST_FILENAME} !-f'.PHP_EOL.
  71. 'RewriteCond %{REQUEST_FILENAME} !-d'.PHP_EOL.
  72. 'RewriteCond %{REQUEST_URI} !.*\.(cssĀ¦js|html|png)'.PHP_EOL.
  73. 'RewriteRule (.*) index.html [L]';
  74. file_put_contents($htaccess, $contents); // save to file
  75. }
  76. else if($site['UrlMode'] == 'static'){
  77. $contents = 'Options -Indexes'.PHP_EOL.
  78. '<IfModule mod_rewrite.c>'.PHP_EOL.
  79. 'RewriteEngine On'.PHP_EOL.
  80. 'RewriteCond %{REQUEST_FILENAME} !-f'.PHP_EOL.
  81. 'RewriteRule ^([^\.]+)$ $1.html [NC,L]'.PHP_EOL.
  82. 'ErrorDocument 404 /page/error'.PHP_EOL.
  83. '</IfModule>'.PHP_EOL.
  84. '<IfModule mod_expires.c>'.PHP_EOL.
  85. 'ExpiresActive On '.PHP_EOL.
  86. 'ExpiresDefault "access plus 1 month"'.PHP_EOL.
  87. 'ExpiresByType image/x-icon "access plus 1 year"'.PHP_EOL.
  88. 'ExpiresByType image/gif "access plus 1 month"'.PHP_EOL.
  89. 'ExpiresByType image/png "access plus 1 month"'.PHP_EOL.
  90. 'ExpiresByType image/jpg "access plus 1 month"'.PHP_EOL.
  91. 'ExpiresByType image/jpeg "access plus 1 month"'.PHP_EOL.
  92. 'ExpiresByType text/css "access 1 month"'.PHP_EOL.
  93. 'ExpiresByType application/javascript "access plus 1 year"'.PHP_EOL.
  94. '</IfModule>';
  95. file_put_contents($htaccess, $contents); // save to file
  96. }
  97. }
  98. // publishes default content for a theme
  99. public static function PublishDefaultContent($site, $theme, $userId){
  100. // read the defaults file
  101. $default_json_file = APP_LOCATION.THEMES_FOLDER.'/'.$theme.'/default.json';
  102. // set $siteId
  103. $siteId = $site['SiteId'];
  104. // check to make sure the defaults.json exists
  105. if(file_exists($default_json_file)){
  106. // get json from the file
  107. $json_text = file_get_contents($default_json_file);
  108. // decode json
  109. $json = json_decode($json_text, true);
  110. // pagetypes
  111. $pagetypes = array();
  112. // menu counts
  113. $primaryMenuCount = 0;
  114. $footerMenuCount = 0;
  115. // clear default types
  116. MenuItem::RemoveForType('primary', $siteId);
  117. MenuItem::RemoveForType('footer', $siteId);
  118. // walk through defaults array
  119. foreach($json as &$value){
  120. // get values from array
  121. $url = $value['url'];
  122. $source = $value['source'];
  123. $name = $value['name'];
  124. $description = $value['description'];
  125. $layout = $value['layout'];
  126. $stylesheet = $value['stylesheet'];
  127. $primaryMenu = $value['primaryMenu'];
  128. $footerMenu = $value['footerMenu'];
  129. $includeOnly = 0;
  130. // set includeOnly (if specified in default)
  131. if(isset($value['includeOnly'])){
  132. if($value['includeOnly'] == true){
  133. $includeOnly = 1;
  134. }
  135. }
  136. // initialize PT
  137. $pageType = NULL;
  138. if(strpos($url, '/') !== false){ // the url has a pagetype
  139. $arr = explode('/', $url);
  140. // get friendly ids from $url
  141. $pageTypeFriendlyId = $arr[0];
  142. $pageFriendlyId = $arr[1];
  143. $pageTypeId = -1;
  144. $pageType = PageType::GetByFriendlyId($pageTypeFriendlyId, $siteId);
  145. // create a new pagetype
  146. if($pageType == NULL){
  147. $pageType = PageType::Add($pageTypeFriendlyId, $layout, $stylesheet, 0, $siteId, $userId);
  148. }
  149. // get newly minted page type
  150. $pageTypeId = $pageType['PageTypeId'];
  151. }
  152. else{ // root, no pagetype
  153. $pageFriendlyId = $url;
  154. $pageTypeId = -1;
  155. }
  156. // determine if page is unique
  157. $isUnique = Page::IsFriendlyIdUnique($pageFriendlyId, $pageTypeId, $site['SiteId']);
  158. // initialize page
  159. $page = NULL;
  160. // if page has not been created, create a page
  161. if($isUnique == true){
  162. // create a page
  163. $page = Page::Add($pageFriendlyId, $name, $description,
  164. $layout, $stylesheet, $pageTypeId, $site['SiteId'], $userId);
  165. }
  166. else{
  167. // get the page
  168. $page = Page::GetByFriendlyId($pageFriendlyId, $pageTypeId, $site['SiteId']);
  169. }
  170. // quick check
  171. if($page != NULL){
  172. // set the page to active
  173. Page::SetIsActive($page['PageId'], 1);
  174. // set include only
  175. Page::SetIncludeOnly($page['PageId'], $includeOnly);
  176. // build the content file
  177. $filename = APP_LOCATION.THEMES_FOLDER.'/'.$theme.'/'.$source;
  178. $content = '';
  179. // get the content for the page
  180. if(file_exists($filename)){
  181. $content = file_get_contents($filename);
  182. // fix images
  183. $content = str_replace('{{site-dir}}', $site['Domain'], $content);
  184. }
  185. // edit the page content
  186. Page::EditContent($page['PageId'], $content, $userId);
  187. // build the primary menu
  188. if($primaryMenu == true){
  189. MenuItem::Add($name, '', 'primary', $url, $page['PageId'],
  190. $primaryMenuCount, $site['SiteId'], $userId);
  191. $primaryMenuCount++;
  192. }
  193. // build the footer menu
  194. if($footerMenu == true){
  195. MenuItem::Add($name, '', 'footer', $url, $page['PageId'],
  196. $footerMenuCount, $site['SiteId'], $userId);
  197. $footerMenuCount++;
  198. }
  199. }
  200. }
  201. }
  202. }
  203. // publishes a theme
  204. public static function PublishTheme($site, $theme){
  205. $theme_dir = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/';
  206. // create theme directory
  207. if(!file_exists($theme_dir)){
  208. mkdir($theme_dir, 0755, true);
  209. }
  210. // create directory for theme
  211. $theme_dir .= $theme .'/';
  212. if(!file_exists($theme_dir)){
  213. mkdir($theme_dir, 0755, true);
  214. }
  215. // create directory for layouts
  216. $layouts_dir = $theme_dir.'layouts/';
  217. if(!file_exists($layouts_dir)){
  218. mkdir($layouts_dir, 0755, true);
  219. }
  220. // create directory for styles
  221. $styles_dir = $theme_dir.'styles/';
  222. if(!file_exists($styles_dir)){
  223. mkdir($styles_dir, 0755, true);
  224. }
  225. // create directory for resources
  226. $res_dir = $theme_dir.'resources/';
  227. if(!file_exists($res_dir)){
  228. mkdir($res_dir, 0755, true);
  229. }
  230. // copy layouts
  231. $layouts_src = APP_LOCATION.'/'.THEMES_FOLDER.'/'.$theme.'/layouts/';
  232. if(file_exists($layouts_src)){
  233. $layouts_dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/'.$theme.'/layouts/';
  234. Utilities::CopyDirectory($layouts_src, $layouts_dest);
  235. }
  236. // copy the index from the layouts
  237. $index_src = $theme_dir.'/layouts/index.html';
  238. $index_dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/index.html';
  239. if(file_exists($index_src)){
  240. copy($index_src, $index_dest);
  241. }
  242. // copy styles
  243. $styles_src = APP_LOCATION.THEMES_FOLDER.'/'.$theme.'/styles/';
  244. if(file_exists($styles_src)){
  245. $styles_dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/'.$theme.'/styles/';
  246. Utilities::CopyDirectory($styles_src, $styles_dest);
  247. }
  248. // copy the configure.json file
  249. $configure_src = APP_LOCATION.THEMES_FOLDER.'/'.$theme.'/configure.json';
  250. $configure_dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/'.$theme.'/configure.json';
  251. if(file_exists($configure_src)){
  252. copy($configure_src, $configure_dest);
  253. }
  254. // copy files
  255. if(FILES_ON_S3 == true){ // copy files to S3
  256. $files_src = APP_LOCATION.THEMES_FOLDER.'/'.$theme.'/files';
  257. // deploy directory to S3
  258. S3::DeployDirectory($site, $files_src, 'files/');
  259. }
  260. else{ // copy files locally
  261. $files_src = APP_LOCATION.THEMES_FOLDER.'/'.$theme.'/files/';
  262. if(file_exists($files_src)){
  263. $files_dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/files/';
  264. Utilities::CopyDirectory($files_src, $files_dest);
  265. }
  266. }
  267. // copy resources
  268. $res_src = APP_LOCATION.THEMES_FOLDER.'/'.$theme.'/resources/';
  269. if(file_exists($res_src)){
  270. $res_dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/'.$theme.'/resources/';
  271. Utilities::CopyDirectory($res_src, $res_dest);
  272. }
  273. }
  274. // publishes common js
  275. public static function PublishCommonJS($site, $env = 'local'){
  276. $src = APP_LOCATION.'/site/js';
  277. $dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/js';
  278. // create dir if it doesn't exist
  279. if(!file_exists($dest)){
  280. mkdir($dest, 0755, true);
  281. }
  282. // copies a directory
  283. Utilities::CopyDirectory($src, $dest);
  284. // inject site information
  285. Publish::InjectSiteSettings($site);
  286. }
  287. // injects site information into the respond.site.js file
  288. public static function InjectSiteSettings($site, $env = 'local'){
  289. // set logoUrl
  290. $logoUrl = '';
  291. if($site['LogoUrl'] != ''){
  292. $logoUrl = 'files/'.$site['LogoUrl'];
  293. }
  294. // set altLogoUrl
  295. $altLogoUrl = '';
  296. if($site['AltLogoUrl'] != '' && $site['AltLogoUrl'] != NULL){
  297. $altLogoUrl = 'files/'.$site['AltLogoUrl'];
  298. }
  299. // set payPalLogoUrl
  300. $payPalLogoUrl = '';
  301. if($site['PayPalLogoUrl'] != '' && $site['PayPalLogoUrl'] != NULL){
  302. $payPalLogoUrl = 'files/'.$site['PayPalLogoUrl'];
  303. }
  304. // set imagesURL
  305. if($env == 'local'){ // if it is locally deployed
  306. $imagesURL = $site['Domain'].'/';
  307. // if files are stored on S3
  308. if(FILES_ON_S3 == true){
  309. $bucket = $site['Bucket'];
  310. $imagesURL = str_replace('{{bucket}}', $bucket, S3_URL).'/';
  311. $imagesURL = str_replace('{{site}}', $site['FriendlyId'], $imagesURL);
  312. }
  313. }
  314. else{ // if the deployment is on S3
  315. $imagesURL = '/';
  316. }
  317. // set iconUrl
  318. $iconUrl = '';
  319. if($site['IconUrl'] != ''){
  320. $iconUrl = $imagesURL.'files/'.$site['IconUrl'];
  321. }
  322. // set display
  323. $showCart = false;
  324. $showSettings = false;
  325. $showLanguages = false;
  326. $showLogin = false;
  327. $showSearch = false;
  328. if($site['ShowCart'] == 1){
  329. $showCart = true;
  330. }
  331. if($site['ShowSettings'] == 1){
  332. $showSettings = true;
  333. }
  334. if($site['ShowLanguages'] == 1){
  335. $showLanguages = true;
  336. }
  337. if($site['ShowLogin'] == 1){
  338. $showLogin = true;
  339. }
  340. if($site['ShowSearch'] == 1){
  341. $showSearch = true;
  342. }
  343. // create settings
  344. $settings = array(
  345. 'SiteId' => $site['SiteId'],
  346. 'Domain' => $site['Domain'],
  347. 'API' => API_URL,
  348. 'Name' => $site['Name'],
  349. 'ImagesUrl' => $imagesURL,
  350. 'UrlMode' => $site['UrlMode'],
  351. 'LogoUrl' => $logoUrl,
  352. 'AltLogoUrl' => $altLogoUrl,
  353. 'PayPalLogoUrl' => $payPalLogoUrl,
  354. 'IconUrl' => $iconUrl,
  355. 'IconBg' => $site['IconBg'],
  356. 'Theme' => $site['Theme'],
  357. 'PrimaryEmail' => $site['PrimaryEmail'],
  358. 'Language' => $site['Language'],
  359. 'Direction' => $site['Direction'],
  360. 'ShowCart' => $showCart,
  361. 'ShowSettings' => $showSettings,
  362. 'ShowLanguages' => $showLanguages,
  363. 'ShowLogin' => $showLogin,
  364. 'ShowSearch' => $showSearch,
  365. 'Currency' => $site['Currency'],
  366. 'WeightUnit' => $site['WeightUnit'],
  367. 'ShippingCalculation' => $site['ShippingCalculation'],
  368. 'ShippingRate' => $site['ShippingRate'],
  369. 'ShippingTiers' => $site['ShippingTiers'],
  370. 'TaxRate' => $site['TaxRate'],
  371. 'PayPalId' => $site['PayPalId'],
  372. 'PayPalUseSandbox' => $site['PayPalUseSandbox'],
  373. 'FormPublicId' => $site['FormPublicId']
  374. );
  375. // settings
  376. $str_settings = json_encode($settings);
  377. // get site file
  378. $file = SITES_LOCATION.'/'.$site['FriendlyId'].'/js/respond.site.js';
  379. echo 'pre-check, file='.$file;
  380. if(file_exists($file)){
  381. // get contents
  382. $content = file_get_contents($file);
  383. $start = 'settings: {';
  384. $end = '}';
  385. // remove { }
  386. $new = str_replace('{', '', $str_settings);
  387. $new = str_replace('}', '', $new);
  388. // replace
  389. $content = preg_replace('#('.preg_quote($start).')(.*?)('.preg_quote($end).')#si', '$1'.$new.'$3', $content);
  390. // add settings
  391. //$content = str_replace('settings: {},', 'settings: '.$str_settings.',', $content);
  392. // publish updates
  393. file_put_contents($file, $content);
  394. }
  395. }
  396. // publishes plugins for the site
  397. public static function PublishPlugins($site){
  398. // copy polyfills
  399. $components_src = APP_LOCATION.'/site/components/lib/webcomponentsjs';
  400. $components_dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/components/lib/webcomponentsjs';
  401. // create polyfills directory if it does not exist
  402. if(!file_exists($components_dest)){
  403. mkdir($components_dest, 0755, true);
  404. }
  405. // copy polyfills directory
  406. if(file_exists($components_dest)){
  407. Utilities::CopyDirectory($components_src, $components_dest);
  408. }
  409. // copy build
  410. $build_src = APP_LOCATION.'/site/components/respond-build.html';
  411. $build_dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/components/respond-build.html';
  412. if(file_exists($build_src)){
  413. $content = file_get_contents($build_src);
  414. file_put_contents($build_dest, $content);
  415. }
  416. // open plugins direcotry
  417. if($handle = opendir(APP_LOCATION.'plugins')){
  418. $blacklist = array('.', '..');
  419. // walk through directories
  420. while (false !== ($file = readdir($handle))) {
  421. if (!in_array($file, $blacklist)) {
  422. $dir = $file;
  423. // source resources directory
  424. $src_dir = APP_LOCATION.'plugins/'.$dir.'/component';
  425. // add templates
  426. if(file_exists($src_dir)){
  427. // destination templates directory
  428. $dest_dir = SITES_LOCATION.'/'.$site['FriendlyId'].'/components';
  429. // create destination directory
  430. if(!file_exists($dest_dir)){
  431. mkdir($dest_dir, 0755, true);
  432. }
  433. // copies the directory
  434. Utilities::CopyDirectory($src_dir, $dest_dir);
  435. }
  436. }
  437. }
  438. closedir($handle);
  439. }
  440. }
  441. // publishes common css
  442. public static function PublishCommonCSS($site){
  443. $src = APP_LOCATION.'/site/css';
  444. $dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/css';
  445. // create dir if it doesn't exist
  446. if(!file_exists($dest)){
  447. mkdir($dest, 0755, true);
  448. }
  449. // copies a directory
  450. Utilities::CopyDirectory($src, $dest);
  451. }
  452. // publishes all the pages in the site
  453. public static function PublishAllPages($site){
  454. // Get all pages
  455. $list = Page::GetPagesForSite($site['SiteId']);
  456. foreach ($list as $row){
  457. Publish::PublishPage($row['PageId'], false, false);
  458. }
  459. }
  460. // publish menu
  461. public static function PublishMenuJSON($site){
  462. $types = MenuType::GetMenuTypes($site['SiteId']);
  463. // create types for primary, footer
  464. $primary = array(
  465. 'MenuTypeId' => -1,
  466. 'FriendlyId' => 'primary'
  467. );
  468. $footer = array(
  469. 'MenuTypeId' => -1,
  470. 'FriendlyId' => 'footer'
  471. );
  472. // push default types
  473. array_push($types, $primary);
  474. array_push($types, $footer);
  475. // walk through types
  476. foreach($types as $type){
  477. // get items for type
  478. $list = MenuItem::GetMenuItemsForType($site['SiteId'], $type['FriendlyId']);
  479. // encode to json
  480. $encoded = json_encode($list);
  481. $dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/data/';
  482. Utilities::SaveContent($dest, 'menu-'.$type['FriendlyId'].'.json', $encoded);
  483. }
  484. }
  485. // publish rss for all page types
  486. public static function PublishRssForPageTypes($site){
  487. $list = PageType::GetPageTypes($site['SiteId']);
  488. foreach ($list as $row){
  489. Publish::PublishRssForPageType($site, $row['PageTypeId']);
  490. }
  491. }
  492. // publish rss for pages
  493. public static function PublishRssForPageType($site, $pageTypeId){
  494. $dest = SITES_LOCATION.'/'.$site['FriendlyId'];
  495. $pageType = PageType::GetByPageTypeId($pageTypeId);
  496. // generate rss
  497. $rss = Utilities::GenerateRSS($site, $pageType);
  498. Utilities::SaveContent($dest.'/data/', strtolower($pageType['FriendlyId']).'.xml', $rss);
  499. }
  500. // publish sitemap
  501. public static function PublishSiteMap($site){
  502. $dest = SITES_LOCATION.'/'.$site['FriendlyId'];
  503. // generate default site map
  504. $content = Utilities::GenerateSiteMap($site);
  505. Utilities::SaveContent($dest.'/', 'sitemap.xml', $content);
  506. }
  507. // gets errors for teh less files
  508. public static function GetLESSErrors($site, $name){
  509. // get references to file
  510. $lessDir = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/'.$site['Theme'].'/styles/';
  511. $cssDir = SITES_LOCATION.'/'.$site['FriendlyId'].'/css/';
  512. // get reference to config file
  513. $configFile = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/'.$site['Theme'].'/configure.json';
  514. $lessFile = $lessDir.$name.'.less';
  515. $cssFile = $cssDir.$name.'.css';
  516. // create css directory (if needed)
  517. if(!file_exists($cssDir)){
  518. mkdir($cssDir, 0755, true);
  519. }
  520. if(file_exists($lessFile)){
  521. $content = file_get_contents($lessFile);
  522. $less = new lessc;
  523. try{
  524. $css = $content;
  525. // set configurations
  526. $css = Publish::SetConfigurations($configFile, $css);
  527. // compile less to css
  528. $css = $less->compile($css);
  529. return NULL;
  530. }
  531. catch(exception $e){
  532. return $e->getMessage();
  533. }
  534. }
  535. else{
  536. return NULL;
  537. }
  538. }
  539. // publishes a specific css file
  540. public static function PublishCSS($site, $name){
  541. // get references to file
  542. $lessDir = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/'.$site['Theme'].'/styles/';
  543. $cssDir = SITES_LOCATION.'/'.$site['FriendlyId'].'/css/';
  544. // get reference to config file
  545. $configFile = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/'.$site['Theme'].'/configure.json';
  546. $lessFile = $lessDir.$name.'.less';
  547. $cssFile = $cssDir.$name.'.css';
  548. // create css directory (if needed)
  549. if(!file_exists($cssDir)){
  550. mkdir($cssDir, 0755, true);
  551. }
  552. if(file_exists($lessFile)){
  553. $content = file_get_contents($lessFile);
  554. $less = new lessc;
  555. try{
  556. $css = $content;
  557. // set configurations
  558. $css = Publish::SetConfigurations($configFile, $css);
  559. // compile less to css
  560. $css = $less->compile($css);
  561. // compress css, #ref: http://manas.tungare.name/software/css-compression-in-php/
  562. // remove comments
  563. $css = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css);
  564. // Remove space after colons
  565. $css = str_replace(': ', ':', $css);
  566. // Remove whitespace
  567. $css = str_replace(array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $css);
  568. // put css into file
  569. file_put_contents($cssFile, $css);
  570. return $css;
  571. }
  572. catch(exception $e){
  573. return NULL;
  574. }
  575. }
  576. else{
  577. return NULL;
  578. }
  579. }
  580. // publish configurations
  581. public static function SetConfigurations($configFile, $css){
  582. if(file_exists($configFile)){
  583. // get jsontxt
  584. $json = file_get_contents($configFile);
  585. // decode json file
  586. $configs = json_decode($json, true);
  587. // walk through configs
  588. foreach($configs as $config){
  589. $controls = $config['controls'];
  590. // walk through controls
  591. foreach($controls as $control){
  592. $replace = $control['replace'];
  593. $selected = $control['selected'];
  594. $prefix = '';
  595. $postfix = '';
  596. // set prefix (deprecated)
  597. if(isset($control['prefix'])){
  598. $prefix = $control['prefix'];
  599. $selected = $prefix.$selected;
  600. }
  601. // set postfix
  602. if(isset($control['postfix'])){
  603. $postfix = $control['postfix'];
  604. $selected = $selected.$postfix;
  605. }
  606. // set format
  607. if(isset($control['cssFormat'])){
  608. $cssFormat = $control['cssFormat'];
  609. $selected = str_replace('%1', $selected, $cssFormat);
  610. }
  611. // replace config with selection
  612. $css = str_replace($replace, $selected, $css);
  613. }
  614. }
  615. }
  616. return $css;
  617. }
  618. // publishes all css
  619. public static function PublishAllCSS($site){
  620. $lessDir = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/'.$site['Theme'].'/styles/';
  621. //get all image files with a .less ext
  622. $files = glob($lessDir . "*.less");
  623. // combined css
  624. $combined_css = '';
  625. //print each file name
  626. foreach($files as $file){
  627. $f_arr = explode("/",$file);
  628. $count = count($f_arr);
  629. $filename = $f_arr[$count-1];
  630. $name = str_replace('.less', '', $filename);
  631. if(strpos($name, 'respond.min') === FALSE){
  632. $combined_css .= Publish::PublishCSS($site, $name);
  633. }
  634. }
  635. // publish combined css
  636. $css_file = SITES_LOCATION.'/'.$site['FriendlyId'].'/css/respond.min.css';
  637. // put combined css
  638. file_put_contents($css_file, $combined_css);
  639. }
  640. // publishes a page
  641. // live -> /site/{{site.FriendlyId}}/templates/page/{{pageType.FriendlyId}}.{{page.FriendlyId}}.html
  642. // preview -> /site/{{site.FriendlyId}}/templates/preview/{{pageType.FriendlyId}}.{{page.FriendlyId}}.html
  643. public static function PublishPage($pageId, $preview = false, $remove_draft = false){
  644. $page = Page::GetByPageId($pageId);
  645. if($page!=null){
  646. $site = Site::GetBySiteId($page['SiteId']); // test for now
  647. Publish::PublishTemplate($page, $site, $preview, $remove_draft);
  648. // do not publish a static page for include only pages
  649. if($page['IncludeOnly'] == 0){
  650. Publish::PublishStaticPage($page, $site, $preview, $remove_draft);
  651. }
  652. }
  653. }
  654. // publishes a template for the page
  655. public static function PublishTemplate($page, $site, $preview = false, $remove_draft = false){
  656. $dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/templates/';
  657. $imageurl = $dest.'files/';
  658. $siteurl = $site['Domain'].'/';
  659. $friendlyId = $page['FriendlyId'];
  660. $url = '';
  661. $file = '';
  662. // set full destination
  663. if($preview==true){
  664. $dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/templates/preview/';
  665. }
  666. else{
  667. $dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/templates/page/';
  668. }
  669. // create directory if it does not exist
  670. if(!file_exists($dest)){
  671. mkdir($dest, 0755, true);
  672. }
  673. // set friendlyId
  674. $file = $page['FriendlyId'].'.html';
  675. // initialize PT
  676. $pageType = NULL;
  677. // create a nice path to store the file
  678. if($page['PageTypeId'] != -1){
  679. $pageType = PageType::GetByPageTypeId($page['PageTypeId']);
  680. // prepend the friendlyId to the fullname
  681. if($pageType!=null){
  682. $file = strtolower($pageType['FriendlyId']).'.'.$file;
  683. }
  684. else{
  685. $file = 'uncategorized.'.$file;
  686. }
  687. }
  688. // generate default
  689. $html = '';
  690. if($preview == true){
  691. $html = $page['Draft'];
  692. }
  693. else{
  694. $html = $page['Content'];
  695. }
  696. // remove any drafts associated with the page
  697. if($remove_draft==true){
  698. // remove a draft from the page
  699. Page::RemoveDraft($page['PageId']);
  700. }
  701. // save the content to the published file
  702. Utilities::SaveContent($dest, $file, $html);
  703. return $dest.$file;
  704. }
  705. // publishes a static version of the page
  706. public static function PublishStaticPage($page, $site, $preview = false, $remove_draft = false){
  707. $dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/';
  708. $imageurl = $dest.'files/';
  709. $siteurl = $site['Domain'].'/';
  710. $friendlyId = $page['FriendlyId'];
  711. $url = '';
  712. $file = '';
  713. // created ctrl
  714. $ctrl = ucfirst($page['FriendlyId']);
  715. $ctrl = str_replace('-', '', $ctrl);
  716. // set base
  717. $base = '';
  718. // create a static location for the page
  719. if($page['PageTypeId'] == -1){
  720. $url = $page['FriendlyId'].'.html';
  721. $dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/';
  722. }
  723. else{
  724. $pageType = PageType::GetByPageTypeId($page['PageTypeId']);
  725. $dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/uncategorized/';
  726. if($pageType!=null){
  727. $dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/'.$pageType['FriendlyId'].'/';
  728. // created ctrl
  729. $ctrl = ucfirst($pageType['FriendlyId']).$ctrl;
  730. $ctrl = str_replace('-', '', $ctrl);
  731. }
  732. // set $base to the root of the director
  733. $base = '../';
  734. }
  735. // create directory if it does not exist
  736. if(!file_exists($dest)){
  737. mkdir($dest, 0755, true);
  738. }
  739. // generate default
  740. $html = '';
  741. $content = '';
  742. // get index and layout (file_get_contents)
  743. $index = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/'.$site['Theme'].'/layouts/index.html';
  744. $layout = SITES_LOCATION.'/'.$site['FriendlyId'].'/themes/'.$site['Theme'].'/layouts/'.$page['Layout'].'.html';
  745. // get index html
  746. if(file_exists($index)){
  747. $html = file_get_contents($index);
  748. }
  749. // get layout html
  750. if(file_exists($layout)){
  751. $layout_html = file_get_contents($layout);
  752. // set class
  753. $cssClass = $page['Stylesheet'];
  754. // set show-cart, show-settings, show-languages, show-login
  755. if($site['ShowCart'] == 1){
  756. $cssClass .= ' show-cart';
  757. }
  758. if($site['ShowSettings'] == 1){
  759. $cssClass .= ' show-settings';
  760. }
  761. if($site['ShowLanguages'] == 1){
  762. $cssClass .= ' show-languages';
  763. }
  764. if($site['ShowLogin'] == 1){
  765. $cssClass .= ' show-login';
  766. }
  767. $html = str_replace('<body ui-view></body>', '<body page="'.$page['PageId'].'" class="'.$cssClass.'">'.$layout_html.'</body>', $html);
  768. $html = str_replace('<body></body>', '<body page="'.$page['PageId'].'" class="'.$cssClass.'">'.$layout_html.'</body>', $html);
  769. }
  770. // get draft/content
  771. if($preview == true){
  772. $file = $page['FriendlyId'].'.preview.html';
  773. $content = $page['Draft'];
  774. }
  775. else{
  776. $file = $page['FriendlyId'].'.html';
  777. $content = $page['Content'];
  778. }
  779. // replace respond-content for layout with content
  780. $html = str_replace('<respond-content id="main-content" url="{{page.Url}}"></respond-content>', $content, $html);
  781. // remove any drafts associated with the page
  782. if($remove_draft==true){
  783. // remove a draft from the page
  784. Page::RemoveDraft($page['PageId']);
  785. }
  786. // replace mustaches syntax {{page.Description}} {{site.Name}}
  787. $html = str_replace('{{page.Name}}', $page['Name'], $html);
  788. $html = str_replace('{{page.Description}}', $page['Description'], $html);
  789. $html = str_replace('{{page.Keywords}}', $page['Keywords'], $html);
  790. $html = str_replace('{{page.Callout}}', $page['Callout'], $html);
  791. $html = str_replace('{{site.Name}}', $site['Name'], $html);
  792. $html = str_replace('{{site.Language}}', $site['Language'], $html);
  793. $html = str_replace('{{site.Direction}}', $site['Direction'], $html);
  794. $html = str_replace('{{site.IconBg}}', $site['IconBg'], $html);
  795. $html = str_replace('{{page.FullStylesheetUrl}}', 'css/'.$page['Stylesheet'].'.css', $html);
  796. // meta data
  797. $photo = '';
  798. $firstName = '';
  799. $lastName = '';
  800. $lastModifiedDate = $page['LastModifiedDate'];
  801. // replace last modified
  802. if($page['LastModifiedBy'] != NULL){
  803. // get user
  804. $user = User::GetByUserId($page['LastModifiedBy']);
  805. // set user infomration
  806. if($user != NULL){
  807. $photo = $user['PhotoUrl'];
  808. $firstName = $user['FirstName'];
  809. $lastName = $user['LastName'];
  810. }
  811. }
  812. // set page information
  813. $html = str_replace('{{page.PhotoUrl}}', $photo, $html);
  814. $html = str_replace('{{page.FirstName}}', $firstName, $html);
  815. $html = str_replace('{{page.LastName}}', $lastName, $html);
  816. $html = str_replace('{{page.LastModifiedDate}}', $lastModifiedDate, $html);
  817. // add a timestamp
  818. $html = str_replace('{{timestamp}}', time(), $html);
  819. // set imaages URL
  820. $imagesURL = $site['Domain'].'/';
  821. // if files are stored on S3
  822. if(FILES_ON_S3 == true){
  823. $bucket = $site['Bucket'];
  824. $imagesURL = str_replace('{{bucket}}', $bucket, S3_URL).'/';
  825. $imagesURL = str_replace('{{site}}', $site['FriendlyId'], $imagesURL);
  826. }
  827. // set iconURL
  828. $iconURL = '';
  829. if($site['IconUrl'] != ''){
  830. $iconURL = $imagesURL.'files/'.$site['IconUrl'];
  831. }
  832. // replace
  833. $html = str_replace('ng-src', 'src', $html);
  834. $html = str_replace('{{site.ImagesUrl}}', $imagesURL, $html);
  835. $html = str_replace('{{site.ImagesURL}}', $imagesURL, $html);
  836. $html = str_replace('{{site.IconUrl}}', $iconURL, $html);
  837. // set fullLogo
  838. $html = str_replace('{{fullLogoUrl}}', $imagesURL.'files/'.$site['LogoUrl'], $html);
  839. // set altLogo (defaults to full logo if not available)
  840. if($site['AltLogoUrl'] != '' && $site['AltLogoUrl'] != NULL){
  841. $html = str_replace('{{fullAltLogoUrl}}', $imagesURL.'files/'.$site['AltLogoUrl'], $html);
  842. }
  843. else{
  844. $html = str_replace('{{fullAltLogoUrl}}', $imagesURL.'files/'.$site['LogoUrl'], $html);
  845. }
  846. // update base
  847. $html = str_replace('<base href="/">', '<base href="'.$base.'">', $html);
  848. // parse the html for menus
  849. $html = str_get_html($html, true, true, DEFAULT_TARGET_CHARSET, false, DEFAULT_BR_TEXT);
  850. // build out the menus where render is set to publish
  851. foreach($html->find('respond-menu[render=publish]') as $el){
  852. // get the type
  853. if($el->type){
  854. $type = $el->type;
  855. // init menu
  856. $menu = '<ul';
  857. // set class if applicable
  858. if(isset($el->class)){
  859. $menu .= ' class="'.$el->class.'">';
  860. }
  861. else{
  862. $menu .= '>';
  863. }
  864. // get items for type
  865. $menuItems = MenuItem::GetMenuItemsForType($site['SiteId'], $type);
  866. $i = 0;
  867. $parent_flag = false;
  868. $new_parent = true;
  869. // walk through items
  870. foreach($menuItems as $menuItem){
  871. $url = $menuItem['Url'];
  872. $name = $menuItem['Name'];
  873. $css = '';
  874. $cssClass = '';
  875. $active = '';
  876. if($page['PageId']==$menuItem['PageId']){
  877. $css = 'active';
  878. }
  879. $css .= ' '.$menuItem['CssClass'];
  880. if(trim($css)!=''){
  881. $cssClass = ' class="'.$css.'"';
  882. }
  883. // check for new parent
  884. if(isset($menuItems[$i+1])){
  885. if($menuItems[$i+1]['IsNested'] == 1 && $new_parent==true){
  886. $parent_flag = true;
  887. }
  888. }
  889. $menu_root = '/';
  890. // check for external links
  891. if(strpos($url,'http') !== false) {
  892. $menu_root = '';
  893. }
  894. if($new_parent == true && $parent_flag == true){
  895. $menu .= '<li class="dropdown">';
  896. $menu .= '<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">'.$menuItem['Name'].' <span class="caret"></span></a>';
  897. $menu .= '<ul class="dropdown-menu">';
  898. $new_parent = false;
  899. }
  900. else{
  901. $menu .= '<li'.$cssClass.'>';
  902. $menu .= '<a href="'.$url.'">'.$menuItem['Name'].'</a>';
  903. $menu .= '</li>';
  904. }
  905. // end parent
  906. if(isset($menuItems[$i+1])){
  907. if($menuItems[$i+1]['IsNested'] == 0 && $parent_flag==true){
  908. $menu .= '</ul></li>'; // end parent if next item is not nested
  909. $parent_flag = false;
  910. $new_parent = true;
  911. }
  912. }
  913. else{
  914. if($parent_flag == true){
  915. $menu .= '</ul></li>'; // end parent if next menu item is null
  916. $parent_flag = false;
  917. $new_parent = true;
  918. }
  919. }
  920. $i = $i+1;
  921. }
  922. $menu .= '</ul>';
  923. $el->outertext = $menu;
  924. }
  925. /* isset */
  926. }
  927. /* foreach */
  928. // replace content where render is set to publish
  929. foreach($html->find('respond-content[render=publish]') as $el){
  930. // get the url
  931. if(isset($el->url)){
  932. $url = $el->url;
  933. // replace the / with a period
  934. $url = str_replace('/', '.', $url);
  935. $url .= '.html';
  936. $content_html = '';
  937. // get the content from the site
  938. $content_dest = SITES_LOCATION.'/'.$site['FriendlyId'].'/templates/page/'.$url;
  939. if(file_exists($content_dest)){
  940. $content_html = file_get_contents($content_dest);
  941. }
  942. // update images url
  943. $content_html = str_replace('{{site.ImagesUrl}}', $imagesURL, $content_html);
  944. $content_html = str_replace('{{site.ImagesURL}}', $imagesURL, $content_html);
  945. // set outer text
  946. if($content_html != ''){
  947. $el->outertext = $content_html;
  948. }
  949. }
  950. }
  951. /* foreach */
  952. // replace background color
  953. foreach($html->find('[backgroundcolor]') as $el){
  954. // set existing style
  955. $style = '';
  956. if(isset($el->style)){
  957. $style = $el->style.' ';
  958. }
  959. // if it is nested, break
  960. if(isset($el->{'data-nested'})){
  961. if($el->{'data-nested'} != 'nested'){
  962. $el->style = $style.'background-color: '.$el->backgroundcolor.';';
  963. }
  964. }
  965. else{
  966. $el->style = $style.'background-color: '.$el->backgroundcolor.';';
  967. }
  968. }
  969. /* foreach */
  970. // replace background image
  971. foreach($html->find('[backgroundimage]') as $el){
  972. // set existing style
  973. $style = '';
  974. if(isset($el->style)){
  975. $style = $el->style.' ';
  976. }
  977. $backgroundimage = $el->backgroundimage;
  978. $backgroundstyle = 'cover';
  979. // add site url for files that start with files
  980. if(substr( $backgroundimage, 0, 5 ) === "files"){
  981. $backgroundimage = $imagesURL.$el->backgroundimage;
  982. }
  983. // set background style
  984. if(isset($el->backgroundstyle)){
  985. $backgroundstyle = $el->backgroundstyle;
  986. }
  987. // if it is nested, break
  988. if(isset($el->{'data-nested'})){
  989. if($el->{'data-nested'} != 'nested'){
  990. if($backgroundstyle == 'parallax'){
  991. $el->{'data-parallax'} = 'scroll';
  992. $el->{'data-image-src'} = $backgroundimage;
  993. }
  994. else if($backgroundstyle == 'repeat'){
  995. $el->style = $style.'background-image: url('.$backgroundimage.'); background-repeat: repeat;';
  996. }
  997. else{
  998. $el->style = $style.'background-image: url('.$backgroundimage.'); background-size: cover; background-position: center center;';
  999. }
  1000. }
  1001. }
  1002. else{
  1003. if($backgroundstyle == 'parallax'){
  1004. $el->{'data-parallax'} = 'scroll';
  1005. $el->{'data-image-src'} = $backgroundimage;
  1006. }
  1007. else if($backgroundstyle == 'repeat'){
  1008. $el->style = $style.'background-image: url('.$backgroundimage.'); background-repeat: repeat;';
  1009. }
  1010. else{
  1011. $el->style = $style.'background-image: url('.$backgroundimage.'); background-size: cover; background-position: center center;';
  1012. }
  1013. }
  1014. }
  1015. /* foreach */
  1016. // replace textcolor
  1017. foreach($html->find('[textcolor]') as $el){
  1018. // if it is nested, break
  1019. if(isset($el->style)){
  1020. $el->style = $el->style.' color: '.$el->textcolor.';';
  1021. }
  1022. else{
  1023. $el->style = 'color: '.$el->textcolor.';';
  1024. }
  1025. }
  1026. /* foreach */
  1027. // replace paddingtop
  1028. foreach($html->find('[paddingtop]') as $el){
  1029. // if it is nested, break
  1030. if(isset($el->style)){
  1031. $el->style = $el->style.' padding-top: '.$el->paddingtop.'px;';
  1032. }
  1033. else{
  1034. $el->style = 'padding-top: '.$el->paddingtop.'px;';
  1035. }
  1036. }
  1037. /* foreach */
  1038. // replace paddingright
  1039. foreach($html->find('[paddingright]') as $el){
  1040. // if it is nested, break
  1041. if(isset($el->style)){
  1042. $el->style = $el->style.' padding-right: '.$el->paddingright.'px;';
  1043. }
  1044. else{
  1045. $el->style = 'padding-right: '.$el->paddingright.'px;';
  1046. }
  1047. }
  1048. /* foreach */
  1049. // replace paddingbottom
  1050. foreach($html->find('[paddingbottom]') as $el){
  1051. // if it is nested, break
  1052. if(isset($el->style)){
  1053. $el->style = $el->style.' padding-bottom: '.$el->paddingbottom.'px;';
  1054. }
  1055. else{
  1056. $el->style = 'padding-bottom: '.$el->paddingbottom.'px;';
  1057. }
  1058. }
  1059. /* foreach */
  1060. // replace paddingleft
  1061. foreach($html->find('[paddingleft]') as $el){
  1062. // if it is nested, break
  1063. if(isset($el->style)){
  1064. $el->style = $el->style.' padding-left: '.$el->paddingleft.'px;';
  1065. }
  1066. else{
  1067. $el->style = 'padding-left: '.$el->paddingleft.'px;';
  1068. }
  1069. }
  1070. /* foreach */
  1071. // replace textshadowcolor
  1072. foreach($html->find('[textshadowcolor]') as $el){
  1073. $color = $el->textshadowcolor;
  1074. $horizontal = '1px';
  1075. $vertical = '1px';
  1076. $blur = '1px';
  1077. if(isset($el->textshadowhorizontal)){
  1078. $horizontal = $el->textshadowhorizontal;
  1079. }
  1080. if(isset($el->textshadowvertical)){
  1081. $vertical = $el->textshadowblur;
  1082. }
  1083. if(isset($el->textshadowvertical)){
  1084. $blur = $el->textshadowblur;
  1085. }
  1086. // build shadow
  1087. $textshadow = $horizontal.' '.$vertical.' '.$blur.' '.$color.';';
  1088. // if it is nested, break
  1089. if(isset($el->style)){
  1090. $el->style = $el->style.' text-shadow: '.$textshadow;
  1091. }
  1092. else{
  1093. $el->style = 'text-shadow: '.$textshadow;
  1094. }
  1095. }
  1096. /* foreach */
  1097. // replace textsize
  1098. foreach($html->find('[textsize]') as $el){
  1099. $textsize = $el->textsize;
  1100. $el->innertext = '<span style="font-size:'.$textsize.'">'.$el->innertext.'</span>';
  1101. }
  1102. /* foreach */
  1103. // save the content to the published file
  1104. Utilities::SaveContent($dest, $file, $html);
  1105. return $dest.$file;
  1106. }
  1107. // removes a draft of the page
  1108. public static function RemoveDraft($pageId){
  1109. // remove a draft from the page
  1110. Page::RemoveDraft($page['PageId']);
  1111. return false;
  1112. }
  1113. }
  1114. ?>