public function execute(){ // If it exists and is good, nothing else needs to be done, (other than flush the session data) // This is hit if the user has to manually copy in the configuration.xml data. if(file_exists(ROOT_PDIR . '/config/configuration.xml')){ unset($_SESSION['configs']); $this->setAsPassed(); reload(); } // Load in the configuration example, merge in the SESSION data, and apply them or display the code. $xml = new \XMLLoader(); $xml->setRootName('configuration'); $xml->loadFromFile(ROOT_PDIR . 'config/configuration.example.xml'); $elements = $xml->getElements('return|define'); foreach($elements as $el){ $name = $el->getAttribute('name'); $children = $el->childNodes; foreach($children as $c){ if($c->nodeName == 'value'){ // This one requires a random string. if($name == 'SECRET_ENCRYPTION_PASSPHRASE' && isset($_SESSION['configs'][$name]) && $_SESSION['configs'][$name] == 'RANDOM'){ $value = \Core\random_hex(96); $c->nodeValue = $value; } elseif($name == 'SERVER_ID' && isset($_SESSION['configs'][$name]) && $_SESSION['configs'][$name] == 'RANDOM'){ // The server ID is a 32-digit random string. $value = \Core\random_hex(32); $c->nodeValue = $value; } // An override is provided, use that and overwrite the xml. elseif(isset($_SESSION['configs'][$name])){ $value = $_SESSION['configs'][$name]; $c->nodeValue = $value; } } } } // Try to save this back down. $fdata = $xml->asPrettyXML(); if(is_writable(ROOT_PDIR . '/config')){ // Just automatically copy it over, (with the necessary tranformations). file_put_contents(ROOT_PDIR . 'config/configuration.xml', $fdata); unset($_SESSION['configs']); $this->setAsPassed(); reload(); // :) } else{ // Display the instructions to the user. $this->getTemplate()->assign('contents', $fdata); } }
/** * Get all screenshots in this metafile * * @return array */ public function getScreenshots() { $s = $this->_xmlloader->getElements('//screenshots/screenshot'); if (!$s) { return []; } else { $f = \Core\Filestore\Factory::File($this->getBaseDir() . $s->getAttribute('file')); return ['file' => $f, 'title' => $s->getAttribute('title') ? $s->getAttribute('title') : $this->getName()]; } }
/** * Function to get any changed templates in this component. * A changed file is any file whose md5 doesn't match what's in the component.xml metafile. * * @return array */ public function getChangedAssets(){ $changes = array(); foreach($this->_xmlloader->getElements('/assets/file') as $file){ // <file filename="CHANGELOG" md5="e55e5457abe2f0a3a8edcb6a927c92e3"/> /** @var $md5 string */ $md5 = $file->getAttribute('md5'); /** @var $filename string */ $filename = $file->getAttribute('filename'); /** @var $object \Core\Filestore\Backends\FileLocal */ $object = \Core\Filestore\Factory::File($this->getBaseDir() . $filename); if($object->getHash() != $md5){ $changes[] = $filename; } } return $changes; }
public function execute(){ // If there's already a configuration file present... just skip to the next. if(file_exists(ROOT_PDIR . '/config/configuration.xml')){ $this->setAsPassed(); reload(); } // This will contain the temporary configuration values for the installer. if(!isset($_SESSION['configs'])) $_SESSION['configs'] = []; $xml = new \XMLLoader(); $xml->setRootName('configuration'); $xml->loadFromFile(ROOT_PDIR . 'config/configuration.example.xml'); $formelements = []; // Since we're pulling from the ant version, set some nice defaults for the user. $valuedefaults = [ '@{db.server}@' => 'localhost', '@{db.port}@' => '3306', '@{db.type}@' => 'mysqli', '@{db.name}@' => '', '@{db.user}@' => '', '@{db.pass}@' => '', '@{devmode}@' => 'false', '/tmp/coreplus-web/' => '/tmp/' . $_SERVER['HTTP_HOST'] . '-web/', '/tmp/coreplus-cli/' => '/tmp/' . $_SERVER['HTTP_HOST'] . '-cli/', 'RANDOM' => \Core\random_hex(96), ]; $elements = $xml->getElements('return|define'); foreach($elements as $el){ $node = $el->nodeName; $name = $el->getAttribute('name'); $type = $el->getAttribute('type'); $formtype = $el->getAttribute('formtype'); $advanced = $el->getAttribute('advanced'); $children = $el->childNodes; $value = null; $valuenode = null; $description = null; $options = []; // Defaults if($advanced === null || $advanced === '') $advanced = "1"; foreach($children as $c){ switch($c->nodeName){ case 'value': $value = trim($c->nodeValue); $valuenode = $c; break; case 'description': $description = trim($c->nodeValue); break; case 'option': $options[] = trim($c->nodeValue); break; case '#text': break; case '#comment': break; default: trigger_error('Unknown sub-node for ' . $node . ' ' . $name . ': ' . $c->nodeName); } } // Since we're pulling from the ant version, set some nice defaults for the user. if(isset($valuedefaults[$value])){ $value = $valuedefaults[$value]; } // Save the value? if($_SERVER['REQUEST_METHOD'] == 'POST'){ if($type == 'boolean' && $formtype == 'checkbox'){ $value = isset($_POST[$name]) ? 'true' : 'false'; } else{ $value = isset($_POST[$name]) ? $_POST[$name] : ''; } $_SESSION['configs'][$name] = $value; } elseif(isset($_SESSION['configs'][$name])){ $value = $_SESSION['configs'][$name]; } //$value = $el->getElement('value')->nodeValue; // Throw this element onto the array for the template to render out. $formelements[] = [ 'name' => $name, // Make the title more appealing than machine names... 'title' => ucwords(strtolower(str_replace('_', ' ', $name))), // Remap "formtype" to "type", since this will be used in a form afterall! 'type' => $formtype, 'value' => $value, 'description' => $description, 'options' => $options, 'advanced' => $advanced, ]; } // If it's a POST... try the settings and if valid, proceed. $message = null; $instructions = null; if($_SERVER['REQUEST_METHOD'] == 'POST'){ if($message === null){ $connectionresults = $this->testDatabaseConnection(); if($connectionresults['status'] != 'passed'){ //var_dump($connectionresults); die(); $message = $connectionresults['message']; $instructions = $connectionresults['instructions']; } } if($message === null){ // Test the assets too! $results = $this->testDirectoryWritable('assets/'); if($results['status'] != 'passed'){ //var_dump($connectionresults); die(); $message = $results['message']; $instructions = $results['instructions']; } } if($message === null){ // Test the assets too! $results = $this->testDirectoryWritable('public/'); if($results['status'] != 'passed'){ //var_dump($connectionresults); die(); $message = $results['message']; $instructions = $results['instructions']; } } if($message === null){ // Still null after all the tests have ran? // w00t! $this->setAsPassed(); reload(); } } $this->getTemplate()->assign('message', $message); $this->getTemplate()->assign('instructions', $instructions); $this->getTemplate()->assign('formelements', $formelements); //var_dump($formelements);// die(); }
/** * Helper utility to import a given remote blog. * * @param bool $verbose Set to true to enable real-time verbose output of the operation. * @return array * * @throws Exception */ public function importFeed($verbose = false) { $blogid = $this->get('id'); if (!$this->exists()) { throw new Exception('Unable to import a blog that does not exist!'); } // Make sure this is a remote blog. if ($this->get('type') != 'remote') { throw new Exception('Cannot import a blog that is not remote!'); } $file = \Core\Filestore\Factory::File($this->get('remote_url')); if (!$file->exists()) { throw new Exception($this->get('remote_url') . ' does not appear to exist'); } $defaults = ['parenturl' => $this->get('baseurl'), 'site' => $this->get('site'), 'component' => 'blog']; $changes = ['added' => 0, 'updated' => 0, 'skipped' => 0, 'deleted' => 0]; $changelog = ''; // I need a list of current articles in this feed. This is because remote deletions won't be coming in on the feed. $map = array(); $articles = BlogArticleModel::FindRaw(['blogid = ' . $blogid]); foreach ($articles as $a) { $map[$a['guid']] = $a['id']; } // I can't trust that remote files list what they actually are because many frameworks, // (WP in specific), do not correctly use content-types :/ $contents = $file->getContents(); // Which feed type is this? $header = substr($contents, 0, 400); // All the standardized records $records = array(); if (strpos($header, '<rss ') !== false) { if ($verbose) { echo 'Found an RSS feed with the URL of ' . $file->getURL() . '!<br/>' . "\n"; ob_flush(); flush(); } $xml = new XMLLoader(); $xml->setRootName('rss'); $xml->loadFromString($contents); foreach ($xml->getElements('channel/item') as $item) { $dat = ['guid' => '', 'link' => '', 'thumbnail' => '', 'published' => '', 'updated' => '', 'description' => '']; foreach ($item->childNodes as $child) { if ($child->nodeName == '#text') { continue; } switch ($child->nodeName) { case 'media:thumbnail': $dat['thumbnail'] = $child->getAttribute('url'); break; case 'pubDate': $dat['published'] = $child->nodeValue; break; default: $dat[$child->nodeName] = $child->nodeValue; } } $records[] = $dat; } } elseif (strpos($header, 'http://www.w3.org/2005/Atom') !== false) { if ($verbose) { echo 'Found an ATOM feed with the URL of ' . $file->getURL() . '!<br/>' . "\n"; ob_flush(); flush(); } $xml = new XMLLoader(); $xml->setRootName('feed'); $xml->loadFromString($contents); foreach ($xml->getRootDOM()->childNodes as $item) { if ($item->nodeName != 'entry') { continue; } $dat = ['guid' => '', 'link' => '', 'thumbnail' => '', 'published' => '', 'updated' => '', 'description' => '']; $imgheight = 0; foreach ($item->childNodes as $child) { if ($child->nodeName == '#text') { continue; } switch ($child->nodeName) { case 'id': $dat['guid'] = $child->nodeValue; break; case 'link': if ($child->getAttribute('rel') == 'alternate' && $child->getAttribute('type') == 'text/html') { if ($child->nodeValue) { $dat['link'] = $child->nodeValue; } else { $dat['link'] = $child->getAttribute('href'); } } break; case 'im:image': if ($child->getAttribute('height') > $imgheight) { $dat['thumbnail'] = $child->nodeValue; $imgheight = $child->getAttribute('height'); } break; case 'updated': $dat['updated'] = strtotime($child->nodeValue); break; case 'summary': if ($dat['description'] != '') { $dat['description'] = $child->nodeValue; } break; case 'content': $dat['description'] = $child->nodeValue; break; default: $dat[$child->nodeName] = $child->nodeValue; } } if (!$dat['published'] && $dat['updated']) { // make sure that there's a published date. $dat['published'] = $dat['updated']; } $records[] = $dat; } } else { throw new Exception('Invalid remote file found, please ensure it is either an RSS or Atom feed!'); } // Now that they're standardized... foreach ($records as $dat) { /** @var PageModel $page */ $page = PageModel::Construct($dat['link']); $published = $dat['published'] == '' || is_numeric($dat['published']) ? $dat['published'] : strtotime($dat['published']); $updated = $dat['updated'] != '' ? is_numeric($dat['updated']) ? $dat['updated'] : strtotime($dat['updated']) : $published; $pagedat = ['published' => $published, 'title' => $dat['title'], 'body' => $dat['description'], 'updated' => $updated]; $newpagedat = array_merge($defaults, ['selectable' => '0']); $page->setFromArray($pagedat); if (!$page->exists()) { // Add the "new" dat only if the page doesn't exist before. $page->setFromArray($newpagedat); } if ($dat['thumbnail']) { $remote = \Core\Filestore\Factory::File($dat['thumbnail']); $new = $remote->copyTo('public/blog/'); $page->setMeta('image', $new->getFilename(false)); } $page->setMeta('guid', $dat['guid']); $thischange = $page->exists() ? 'updated' : 'added'; if ($page->changed()) { $page->save(); $changes[$thischange]++; $changelog .= $thischange . ' ' . $dat['title'] . "<br/>\n"; if ($verbose) { echo $thischange . ' ' . $dat['title'] . "<br/>\n"; ob_flush(); flush(); } } else { $changes['skipped']++; if ($verbose) { echo 'No changes to ' . $dat['title'] . "<br/>\n"; ob_flush(); flush(); } } } return ['status' => 1, 'message' => 'Import feed successfully!', 'added' => $changes['added'], 'updated' => $changes['updated'], 'deleted' => $changes['deleted'], 'skipped' => $changes['skipped'], 'changelog' => $changelog]; }