public function getSettingsHtml() { $pluginSettings = craft()->plugins->getPlugin('placid')->getSettings(); // Get placid requests and send them to the widget settings $requests = craft()->placid_requests->findAllRequests(); $requestsArray = array('' => 'No request selected'); foreach ($requests as $request) { $requestsArray[$request->handle] = $request->name; } $templatesPath = craft()->path->getSiteTemplatesPath() . $pluginSettings->widgetTemplatesPath; $templates = IOHelper::getFolderContents($templatesPath, TRUE); $templatesArray = array('' => Craft::t('No template selected')); if (!$templates) { $templatesArray = array('' => 'Cannot find templates'); Craft::log('Cannot find templates in path "' . $templatesPath . '"', LogLevel::Error); } else { // Turn array into ArrayObject $templates = new \ArrayObject($templates); // Iterate over template list // * Remove full path // * Remove folders from list for ($list = $templates->getIterator(); $list->valid(); $list->next()) { $filename = $list->current(); $filename = str_replace($templatesPath, '', $filename); $filenameIncludingSubfolder = $filename; $isTemplate = preg_match("/(.html|.twig)\$/u", $filename); if ($isTemplate) { $templatesArray[$filenameIncludingSubfolder] = $filename; } } } return craft()->templates->render('placid/_widgets/request/settings', array('requests' => $requestsArray, 'templates' => $templatesArray, 'settings' => $this->getSettings())); }
public function getInputHtml($name, $value) { // Get site templates path $templatesPath = $siteTemplatesPath = craft()->path->getSiteTemplatesPath(); // Check if the templates path is overriden by configuration // TODO: Normalize path $limitToSubfolder = craft()->config->get('templateselectSubfolder'); if ($limitToSubfolder) { $templatesPath = $templatesPath . rtrim($limitToSubfolder, '/') . '/'; } // Check if folder exists, or give error if (!IOHelper::folderExists($templatesPath)) { throw new \InvalidArgumentException('(Template Select) Folder doesn\'t exist: ' . $templatesPath); } // Get folder contents $templates = IOHelper::getFolderContents($templatesPath, TRUE); // Add placeholder for when there is no template selected $filteredTemplates = array('' => Craft::t('No template selected')); // Turn array into ArrayObject $templates = new \ArrayObject($templates); // Iterate over template list // * Remove full path // * Remove folders from list for ($list = $templates->getIterator(); $list->valid(); $list->next()) { $filename = $list->current(); $filename = str_replace($templatesPath, '', $filename); $filenameIncludingSubfolder = $limitToSubfolder ? $limitToSubfolder . $filename : $filename; $isTemplate = preg_match("/(.html|.twig)\$/u", $filename); if ($isTemplate) { $filteredTemplates[$filenameIncludingSubfolder] = $filename; } } // Render field return craft()->templates->render('_includes/forms/select', array('name' => $name, 'value' => $value, 'options' => $filteredTemplates)); }
/** * Finds installable records from the models folder. * * @return array */ public function findInstallableRecords() { $records = array(); $recordsFolder = craft()->path->getAppPath() . 'records/'; $recordFiles = IOHelper::getFolderContents($recordsFolder, false, ".*Record\\.php\$"); foreach ($recordFiles as $file) { if (IOHelper::fileExists($file)) { $fileName = IOHelper::getFileName($file, false); $class = __NAMESPACE__ . '\\' . $fileName; // Ignore abstract classes and interfaces $ref = new \ReflectionClass($class); if ($ref->isAbstract() || $ref->isInterface()) { Craft::log("Skipping record {$file} because it’s abstract or an interface.", LogLevel::Warning); continue; } $obj = new $class('install'); if (method_exists($obj, 'createTable')) { $records[] = $obj; } else { Craft::log("Skipping record {$file} because it doesn’t have a createTable() method.", LogLevel::Warning); } } else { Craft::log("Skipping record {$file} because it doesn’t exist.", LogLevel::Warning); } } return $records; }
/** * Returns the path to the logo, or false if a logo hasn't been uploaded. * * @access private * @return string */ private function _getLogoPath() { if (!isset($this->_logoPath)) { $files = IOHelper::getFolderContents(craft()->path->getStoragePath() . 'logo/', false); if (!empty($files)) { $this->_logoPath = $files[0]; } else { $this->_logoPath = false; } } return $this->_logoPath; }
/** * Returns the field's settings HTML. * * @return string|null */ public function getSettingsHtml() { $configOptions = array('' => Craft::t('Default')); $configPath = craft()->path->getConfigPath() . 'redactor/'; if (IOHelper::folderExists($configPath)) { $configFiles = IOHelper::getFolderContents($configPath, false, '\\.json$'); if (is_array($configFiles)) { foreach ($configFiles as $file) { $configOptions[IOHelper::getFileName($file)] = IOHelper::getFileName($file, false); } } } return craft()->templates->render('_components/fieldtypes/RichText/settings', array('settings' => $this->getSettings(), 'configOptions' => $configOptions)); }
/** * @inheritDoc ISavableComponentType::getSettingsHtml() * * @return string|null */ public function getSettingsHtml() { $configOptions = array('' => Craft::t('Default')); $configPath = craft()->path->getConfigPath() . 'redactor/'; if (IOHelper::folderExists($configPath)) { $configFiles = IOHelper::getFolderContents($configPath, false, '\\.json$'); if (is_array($configFiles)) { foreach ($configFiles as $file) { $configOptions[IOHelper::getFileName($file)] = IOHelper::getFileName($file, false); } } } $columns = array('text' => Craft::t('Text (stores about 64K)'), 'mediumtext' => Craft::t('MediumText (stores about 4GB)')); return craft()->templates->render('_components/fieldtypes/RichText/settings', array('settings' => $this->getSettings(), 'configOptions' => $configOptions, 'columns' => $columns, 'existing' => !empty($this->model->id))); }
/** * @return array * * @throws Exception */ public final function fetchLogFiles($logPath) { $logFileNames = []; $logFolderContents = IOHelper::getFolderContents($logPath); if ($logFolderContents === false) { throw new Exception('Could not get log folder contents'); } else { foreach ($logFolderContents as $index => $filePath) { if ($this->shouldFileBeIncluded($filePath)) { $logFileNames[] = IOHelper::getFileName($filePath); } } } return $logFileNames; }
/** * Returns an array of locales that Craft is translated into. The list of locales is based on whatever files exist * in craft/app/translations/. * * @return array An array of {@link LocaleModel} objects. */ public function getAppLocales() { if (!$this->_appLocales) { $this->_appLocales = array(new LocaleModel('en_us')); $path = craft()->path->getCpTranslationsPath(); $folders = IOHelper::getFolderContents($path, false, ".*\\.php"); if (is_array($folders) && count($folders) > 0) { foreach ($folders as $dir) { $localeId = IOHelper::getFileName($dir, false); if ($localeId != 'en_us') { $this->_appLocales[] = new LocaleModel($localeId); } } } } return $this->_appLocales; }
public function getTemplateFiles() { $folderEmpty = true; if (IOHelper::isFolderEmpty(craft()->path->getPluginsPath() . 'formbuilder2/templates/email/layouts')) { throw new HttpException(404, Craft::t('Looks like you don\'t have any templates in your email/layouts folder.')); } else { $folderEmpty = false; } $fileList = IOHelper::getFolderContents(craft()->path->getPluginsPath() . 'formbuilder2/templates/email/layouts'); $files = []; $filesModel = []; if (!$folderEmpty) { foreach ($fileList as $key => $file) { $files[$key] = ['fileName' => IOHelper::getFileName($file, false), 'fileOriginalName' => IOHelper::getFileName($file), 'fileNameCleaned' => IOHelper::cleanFilename(IOHelper::getFileName($file, false)), 'fileExtension' => IOHelper::getExtension($file), 'filePath' => $file, 'fileContents' => IOHelper::getFileContents($file)]; $filesModel[] = FormBuilder2_FileModel::populateModel($files[$key]); } } return $filesModel; }
public function actionSetTemplate() { $this->requirePostRequest(); $this->requireAjaxRequest(); $templatePath = craft()->request->getRequiredPost('templatePath'); $folderContents = IOHelper::getFolderContents(craft()->path->getPluginsPath() . 'formbuilder2/templates/layouts/templates/'); $theFile = ''; if ($folderContents && $templatePath) { foreach ($folderContents as $key => $file) { $fileName = IOHelper::getFileName($file, false); if ($fileName == $templatePath) { $theFile = IOHelper::getFile($file); } } } if ($theFile == '') { $this->returnErrorJson('No template with that name.'); } else { $template = ['fileName' => $theFile->getFileName(false), 'fileOriginalName' => $theFile->getFileName(), 'fileNameCleaned' => IOHelper::cleanFilename(IOHelper::getFileName($theFile->getRealPath(), false)), 'fileExtension' => $theFile->getExtension(), 'filePath' => $theFile->getRealPath(), 'fileContents' => $theFile->getContents()]; $this->returnJson(['success' => true, 'message' => Craft::t('Template is set.'), 'layout' => $template]); } }
/** * @inheritDoc ISavableComponentType::getSettingsHtml() * * @return string|null */ public function getSettingsHtml() { $configOptions = array('' => Craft::t('Default')); $configPath = craft()->path->getConfigPath() . 'redactor/'; if (IOHelper::folderExists($configPath)) { $configFiles = IOHelper::getFolderContents($configPath, false, '\\.json$'); if (is_array($configFiles)) { foreach ($configFiles as $file) { $configOptions[IOHelper::getFileName($file)] = IOHelper::getFileName($file, false); } } } $columns = array('text' => Craft::t('Text (stores about 64K)'), 'mediumtext' => Craft::t('MediumText (stores about 4GB)')); $sourceOptions = array(); foreach (craft()->assetSources->getPublicSources() as $source) { $sourceOptions[] = array('label' => $source->name, 'value' => $source->id); } $transformOptions = array(); foreach (craft()->assetTransforms->getAllTransforms() as $transform) { $transformOptions[] = array('label' => $transform->name, 'value' => $transform->id); } return craft()->templates->render('redactori/settings', array('settings' => $this->getSettings(), 'configOptions' => $configOptions, 'assetSourceOptions' => $sourceOptions, 'transformOptions' => $transformOptions, 'columns' => $columns, 'existing' => !empty($this->model->id))); }
/** * @param $srcZip * @param $destFolder * * @return bool */ public static function unzip($srcZip, $destFolder) { craft()->config->maxPowerCaptain(); if (IOHelper::fileExists($srcZip)) { if (IOHelper::getExtension($srcZip) == 'zip') { if (!IOHelper::folderExists($destFolder)) { if (!IOHelper::createFolder($destFolder)) { Craft::log('Tried to create the unzip destination folder, but could not: ' . $destFolder, LogLevel::Error); return false; } } else { // If the destination folder exists and it has contents, clear them. if (($conents = IOHelper::getFolderContents($destFolder)) !== false) { // Begin the great purge. if (!IOHelper::clearFolder($destFolder)) { Craft::log('Tried to clear the contents of the unzip destination folder, but could not: ' . $destFolder, LogLevel::Error); return false; } } } $zip = static::_getZipInstance($srcZip); $result = $zip->unzip($srcZip, $destFolder); if ($result === true) { return $result; } else { Craft::log('There was an error unzipping the file: ' . $srcZip, LogLevel::Error); return false; } } else { Craft::log($srcZip . ' is not a zip file and cannot be unzipped.', LogLevel::Error); return false; } } else { Craft::log('Unzipping is only available for files.', LogLevel::Error); return false; } }
/** * Remove any temp files and/or folders that might have been created. * * @param string $unzipFolder * * @return null */ private function _cleanTempFiles($unzipFolder) { $appPath = craft()->path->getAppPath(); // Get rid of all the .bak files/folders. $filesToDelete = IOHelper::getFolderContents($appPath, true, ".*\\.bak\$"); // Now delete any files/folders that were marked for deletion in the manifest file. $manifestData = UpdateHelper::getManifestData($unzipFolder); if ($manifestData) { foreach ($manifestData as $row) { if (UpdateHelper::isManifestVersionInfoLine($row)) { continue; } $rowData = explode(';', $row); if ($rowData[1] == PatchManifestFileAction::Remove) { if (UpdateHelper::isManifestLineAFolder($rowData[0])) { $tempFilePath = UpdateHelper::cleanManifestFolderLine($rowData[0]); } else { $tempFilePath = $rowData[0]; } $filesToDelete[] = $appPath . $tempFilePath; } } foreach ($filesToDelete as $fileToDelete) { if (IOHelper::fileExists($fileToDelete)) { if (IOHelper::isWritable($fileToDelete)) { Craft::log('Deleting file: ' . $fileToDelete, LogLevel::Info, true); IOHelper::deleteFile($fileToDelete, true); } } else { if (IOHelper::folderExists($fileToDelete)) { if (IOHelper::isWritable($fileToDelete)) { Craft::log('Deleting .bak folder:' . $fileToDelete, LogLevel::Info, true); IOHelper::clearFolder($fileToDelete, true); IOHelper::deleteFolder($fileToDelete, true); } } } } } // Clear the temp folder. IOHelper::clearFolder(craft()->path->getTempPath(), true); }
/** * Returns the path to a rebrand image by type or false if it hasn't ben uploaded. * * @param string $type logo or image. * * @return string */ private function _getImagePath($type) { if (!isset($this->_paths[$type])) { $files = IOHelper::getFolderContents(craft()->path->getRebrandPath() . $type . '/', false); if (!empty($files)) { $this->_paths[$type] = $files[0]; } else { $this->_paths[$type] = false; } } return $this->_paths[$type]; }
/** * Get translations by criteria. * * @param ElementCriteriaModel $criteria * * @return array */ public function get(ElementCriteriaModel $criteria) { // Ensure source is an array if (!is_array($criteria->source)) { $criteria->source = array($criteria->source); } // Gather all translatable strings $occurences = array(); // Loop through paths foreach ($criteria->source as $path) { // Check if this is a folder or a file $isFile = IOHelper::fileExists($path); // If its not a file if (!$isFile) { // Set filter - no vendor folders, only template files $filter = '^((?!vendor|node_modules).)*(\\.(php|html|twig|js|json|atom|rss)?)$'; // Get files $files = IOHelper::getFolderContents($path, true, $filter); // Loop through files and find translate occurences foreach ($files as $file) { // Parse file $elements = $this->_parseFile($path, $file, $criteria); // Collect in array $occurences = array_merge($occurences, $elements); } } else { // Parse file $elements = $this->_parseFile($path, $path, $criteria); // Collect in array $occurences = array_merge($occurences, $elements); } } return $occurences; }
/** * @inheritDoc IZip::add() * * @param string $sourceZip * @param string $pathToAdd * @param string $basePath * @param null $pathPrefix * * @return bool */ public function add($sourceZip, $pathToAdd, $basePath, $pathPrefix = null) { $zip = new \ZipArchive(); $zipContents = $zip->open($sourceZip); if ($zipContents !== true) { Craft::log('Unable to open zip file: ' . $sourceZip, LogLevel::Error); return false; } if (IOHelper::fileExists($pathToAdd)) { $folderContents = array($pathToAdd); } else { $folderContents = IOHelper::getFolderContents($pathToAdd, true); } foreach ($folderContents as $itemToZip) { if (IOHelper::isReadable($itemToZip)) { // Figure out the relative path we'll be adding to the zip. $relFilePath = mb_substr($itemToZip, mb_strlen($basePath)); if ($pathPrefix) { $pathPrefix = IOHelper::normalizePathSeparators($pathPrefix); $relFilePath = $pathPrefix . $relFilePath; } if (IOHelper::folderExists($itemToZip)) { if (IOHelper::isFolderEmpty($itemToZip)) { $zip->addEmptyDir($relFilePath); } } elseif (IOHelper::fileExists($itemToZip)) { // We can't use $zip->addFile() here but it's a terrible, horrible, POS method that's buggy on Windows. $fileContents = IOHelper::getFileContents($itemToZip); if (!$zip->addFromString($relFilePath, $fileContents)) { Craft::log('There was an error adding the file ' . $itemToZip . ' to the zip: ' . $itemToZip, LogLevel::Error); } } } } $zip->close(); return true; }
/** * Creates a new support ticket for the GetHelp widget. * * @return null */ public function actionSendSupportRequest() { $this->requirePostRequest(); craft()->config->maxPowerCaptain(); $success = false; $errors = array(); $zipFile = null; $tempFolder = null; $widgetId = craft()->request->getPost('widgetId'); $namespace = craft()->request->getPost('namespace'); $namespace = $namespace ? $namespace . '.' : ''; $getHelpModel = new GetHelpModel(); $getHelpModel->fromEmail = craft()->request->getPost($namespace . 'fromEmail'); $getHelpModel->message = trim(craft()->request->getPost($namespace . 'message')); $getHelpModel->attachLogs = (bool) craft()->request->getPost($namespace . 'attachLogs'); $getHelpModel->attachDbBackup = (bool) craft()->request->getPost($namespace . 'attachDbBackup'); $getHelpModel->attachTemplates = (bool) craft()->request->getPost($namespace . 'attachTemplates'); $getHelpModel->attachment = UploadedFile::getInstanceByName($namespace . 'attachAdditionalFile'); if ($getHelpModel->validate()) { $user = craft()->userSession->getUser(); // Add some extra info about this install $message = $getHelpModel->message . "\n\n" . "------------------------------\n\n" . 'Craft ' . craft()->getEditionName() . ' ' . craft()->getVersion() . '.' . craft()->getBuild(); $plugins = craft()->plugins->getPlugins(); if ($plugins) { $pluginNames = array(); foreach ($plugins as $plugin) { $pluginNames[] = $plugin->getName() . ' ' . $plugin->getVersion() . ' (' . $plugin->getDeveloper() . ')'; } $message .= "\nPlugins: " . implode(', ', $pluginNames); } $requestParamDefaults = array('sFirstName' => $user->getFriendlyName(), 'sLastName' => $user->lastName ? $user->lastName : 'Doe', 'sEmail' => $getHelpModel->fromEmail, 'tNote' => $message); $requestParams = $requestParamDefaults; $hsParams = array('helpSpotApiURL' => 'https://support.pixelandtonic.com/api/index.php'); try { if ($getHelpModel->attachLogs || $getHelpModel->attachDbBackup) { if (!$zipFile) { $zipFile = $this->_createZip(); } if ($getHelpModel->attachLogs && IOHelper::folderExists(craft()->path->getLogPath())) { // Grab it all. $logFolderContents = IOHelper::getFolderContents(craft()->path->getLogPath()); foreach ($logFolderContents as $file) { // Make sure it's a file. if (IOHelper::fileExists($file)) { Zip::add($zipFile, $file, craft()->path->getStoragePath()); } } } if ($getHelpModel->attachDbBackup && IOHelper::folderExists(craft()->path->getDbBackupPath())) { // Make a fresh database backup of the current schema/data. We want all data from all tables // for debugging. craft()->db->backup(); $backups = IOHelper::getLastModifiedFiles(craft()->path->getDbBackupPath(), 3); foreach ($backups as $backup) { if (IOHelper::getExtension($backup) == 'sql') { Zip::add($zipFile, $backup, craft()->path->getStoragePath()); } } } } if ($getHelpModel->attachment) { // If we don't have a zip file yet, create one now. if (!$zipFile) { $zipFile = $this->_createZip(); } $tempFolder = craft()->path->getTempPath() . StringHelper::UUID() . '/'; if (!IOHelper::folderExists($tempFolder)) { IOHelper::createFolder($tempFolder); } $tempFile = $tempFolder . $getHelpModel->attachment->getName(); $getHelpModel->attachment->saveAs($tempFile); // Make sure it actually saved. if (IOHelper::fileExists($tempFile)) { Zip::add($zipFile, $tempFile, $tempFolder); } } if ($getHelpModel->attachTemplates) { // If we don't have a zip file yet, create one now. if (!$zipFile) { $zipFile = $this->_createZip(); } if (IOHelper::folderExists(craft()->path->getLogPath())) { // Grab it all. $templateFolderContents = IOHelper::getFolderContents(craft()->path->getSiteTemplatesPath()); foreach ($templateFolderContents as $file) { // Make sure it's a file. if (IOHelper::fileExists($file)) { $templateFolderName = IOHelper::getFolderName(craft()->path->getSiteTemplatesPath(), false); $siteTemplatePath = craft()->path->getSiteTemplatesPath(); $tempPath = substr($siteTemplatePath, 0, strlen($siteTemplatePath) - strlen($templateFolderName) - 1); Zip::add($zipFile, $file, $tempPath); } } } } if ($zipFile) { $requestParams['File1_sFilename'] = 'SupportAttachment-' . IOHelper::cleanFilename(craft()->getSiteName()) . '.zip'; $requestParams['File1_sFileMimeType'] = 'application/zip'; $requestParams['File1_bFileBody'] = base64_encode(IOHelper::getFileContents($zipFile)); // Bump the default timeout because of the attachment. $hsParams['callTimeout'] = 120; } // Grab the license.key file. if (IOHelper::fileExists(craft()->path->getLicenseKeyPath())) { $requestParams['File2_sFilename'] = 'license.key'; $requestParams['File2_sFileMimeType'] = 'text/plain'; $requestParams['File2_bFileBody'] = base64_encode(IOHelper::getFileContents(craft()->path->getLicenseKeyPath())); } } catch (\Exception $e) { Craft::log('Tried to attach debug logs to a support request and something went horribly wrong: ' . $e->getMessage(), LogLevel::Warning); // There was a problem zipping, so reset the params and just send the email without the attachment. $requestParams = $requestParamDefaults; } require_once craft()->path->getLibPath() . 'HelpSpotAPI.php'; $hsapi = new \HelpSpotAPI($hsParams); $result = $hsapi->requestCreate($requestParams); if ($result) { if ($zipFile) { if (IOHelper::fileExists($zipFile)) { IOHelper::deleteFile($zipFile); } } if ($tempFolder) { IOHelper::clearFolder($tempFolder); IOHelper::deleteFolder($tempFolder); } $success = true; } else { $hsErrors = array_filter(preg_split("/(\r\n|\n|\r)/", $hsapi->errors)); $errors = array('Support' => $hsErrors); } } else { $errors = $getHelpModel->getErrors(); } $this->renderTemplate('_components/widgets/GetHelp/response', array('success' => $success, 'errors' => JsonHelper::encode($errors), 'widgetId' => $widgetId)); }
/** * Remove any temp files and/or folders that might have been created. * * @param string $unzipFolder * @param string $handle * * @return null */ private function _cleanTempFiles($unzipFolder, $handle) { $path = $handle == 'craft' ? craft()->path->getAppPath() : craft()->path->getPluginsPath() . $handle . '/'; // Get rid of all the .bak files/folders. $filesToDelete = IOHelper::getFolderContents($path, true, ".*\\.bak\$"); // Now delete any files/folders that were marked for deletion in the manifest file. $manifestData = UpdateHelper::getManifestData($unzipFolder, $handle); if ($manifestData) { foreach ($manifestData as $row) { if (UpdateHelper::isManifestVersionInfoLine($row)) { continue; } $rowData = explode(';', $row); if ($rowData[1] == PatchManifestFileAction::Remove) { if (UpdateHelper::isManifestLineAFolder($rowData[0])) { $tempFilePath = UpdateHelper::cleanManifestFolderLine($rowData[0]); } else { $tempFilePath = $rowData[0]; } $filesToDelete[] = $path . $tempFilePath; } // In case we did the whole app folder if ($rowData[0][0] == '*') { $filesToDelete[] = rtrim(IOHelper::normalizePathSeparators($path), '/') . '.bak/'; } } foreach ($filesToDelete as $fileToDelete) { if (IOHelper::fileExists($fileToDelete)) { if (IOHelper::isWritable($fileToDelete)) { Craft::log('Deleting file: ' . $fileToDelete, LogLevel::Info, true); IOHelper::deleteFile($fileToDelete, true); // If that was the last file in this folder, nuke the folder. if (IOHelper::isFolderEmpty(IOHelper::getFolderName($fileToDelete))) { IOHelper::deleteFolder(IOHelper::getFolderName($fileToDelete)); } } } else { if (IOHelper::folderExists($fileToDelete)) { if (IOHelper::isWritable($fileToDelete)) { Craft::log('Deleting .bak folder:' . $fileToDelete, LogLevel::Info, true); IOHelper::clearFolder($fileToDelete, true); IOHelper::deleteFolder($fileToDelete, true); } } } } } // Clear the temp folder. IOHelper::clearFolder(craft()->path->getTempPath(), true); }
/** * Populates the migrations table with the base migration plus any existing ones from app/migrations. * * @throws Exception * @return null */ private function _populateMigrationTable() { $migrations = array(); // Add the base one. $migration = new MigrationRecord(); $migration->version = craft()->migrations->getBaseMigration(); $migration->applyTime = DateTimeHelper::currentUTCDateTime(); $migrations[] = $migration; $migrationsFolder = craft()->path->getAppPath() . 'migrations/'; $migrationFiles = IOHelper::getFolderContents($migrationsFolder, false, "(m(\\d{6}_\\d{6})_.*?)\\.php"); if ($migrationFiles) { foreach ($migrationFiles as $file) { if (IOHelper::fileExists($file)) { $migration = new MigrationRecord(); $migration->version = IOHelper::getFileName($file, false); $migration->applyTime = DateTimeHelper::currentUTCDateTime(); $migrations[] = $migration; } } foreach ($migrations as $migration) { if (!$migration->save()) { Craft::log('Could not populate the migration table.', LogLevel::Error); throw new Exception(Craft::t('There was a problem saving to the migrations table: ') . $this->_getFlattenedErrors($migration->getErrors())); } } } Craft::log('Migration table populated successfully.'); }
/** * Remove any temp files and/or folders that might have been created. */ private function _cleanTempFiles($unzipFolder) { // Get rid of all the .bak files/folders. $baks = IOHelper::getFolderContents(craft()->path->getAppPath(), true, ".*\\.bak\$"); foreach ($baks as $bak) { if (IOHelper::fileExists($bak)) { if (IOHelper::isWritable($bak)) { Craft::log('Deleting .bak file: ' . $bak, LogLevel::Info, true); IOHelper::deleteFile($bak, true); } } else { if (IOHelper::folderExists($bak)) { if (IOHelper::isWritable($bak)) { Craft::log('Deleting .bak folder:' . $bak, LogLevel::Info, true); IOHelper::clearFolder($bak, true); IOHelper::deleteFolder($bak, true); } } } } // Now delete any files/folders that were marked for deletion in the manifest file. $manifestData = UpdateHelper::getManifestData($unzipFolder); if ($manifestData) { foreach ($manifestData as $row) { if (UpdateHelper::isManifestVersionInfoLine($row)) { continue; } $rowData = explode(';', $row); $folder = false; if (UpdateHelper::isManifestLineAFolder($rowData[0])) { $folder = true; $tempFilePath = UpdateHelper::cleanManifestFolderLine($rowData[0]); } else { $tempFilePath = $rowData[0]; } $fullPath = ''; switch (trim($rowData[1])) { // If the file/folder was set to be deleted, there is no backup and we go ahead and remove it now. case PatchManifestFileAction::Remove: if ($tempFilePath == '') { $fullPath = IOHelper::normalizePathSeparators(craft()->path->getAppPath()); } else { $fullPath = IOHelper::normalizePathSeparators(craft()->path->getAppPath() . $tempFilePath); } break; } // Delete any files/folders we backed up. if ($folder) { if (($folder = IOHelper::getFolder($fullPath)) !== false) { Craft::log('Deleting folder: ' . $folder->getRealPath(), LogLevel::Info, true); $folder->delete(); } } else { if (($file = IOHelper::getFile($fullPath)) !== false) { Craft::log('Deleting file: ' . $file->getRealPath(), LogLevel::Info, true); $file->delete(); } } } } // Clear the temp folder. IOHelper::clearFolder(craft()->path->getTempPath(), true); }
/** * Logs * * @param array $variables * * @return null */ public function actionLogs(array $variables = array()) { craft()->config->maxPowerCaptain(); if (IOHelper::folderExists(craft()->path->getLogPath())) { $dateTimePattern = '/^[0-9]{4}\\/[0-9]{2}\\/[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/'; $logFileNames = array(); // Grab it all. $logFolderContents = IOHelper::getFolderContents(craft()->path->getLogPath()); foreach ($logFolderContents as $logFolderContent) { // Make sure it's a file.` if (IOHelper::fileExists($logFolderContent)) { $logFileNames[] = IOHelper::getFileName($logFolderContent); } } $logEntriesByRequest = array(); $currentLogFileName = isset($variables['currentLogFileName']) ? $variables['currentLogFileName'] : 'craft.log'; $currentFullPath = craft()->path->getLogPath() . $currentLogFileName; if (IOHelper::fileExists($currentFullPath)) { // Different parsing logic for phperrors.log if ($currentLogFileName !== 'phperrors.log') { // Split the log file's contents up into arrays of individual logs, where each item is an array of // the lines of that log. $contents = IOHelper::getFileContents(craft()->path->getLogPath() . $currentLogFileName); $requests = explode('******************************************************************************************************', $contents); foreach ($requests as $request) { $logEntries = array(); $logChunks = preg_split('/^(\\d{4}\\/\\d{2}\\/\\d{2} \\d{2}:\\d{2}:\\d{2}) \\[(.*?)\\] \\[(.*?)\\] /m', $request, null, PREG_SPLIT_DELIM_CAPTURE); // Ignore the first chunk array_shift($logChunks); // Loop through them $totalChunks = count($logChunks); for ($i = 0; $i < $totalChunks; $i += 4) { $logEntryModel = new LogEntryModel(); $logEntryModel->dateTime = DateTime::createFromFormat('Y/m/d H:i:s', $logChunks[$i]); $logEntryModel->level = $logChunks[$i + 1]; $logEntryModel->category = $logChunks[$i + 2]; $message = $logChunks[$i + 3]; $rowContents = explode("\n", $message); // Find a few new markers $cookieStart = array_search('$_COOKIE=array (', $rowContents); $sessionStart = array_search('$_SESSION=array (', $rowContents); $serverStart = array_search('$_SERVER=array (', $rowContents); $postStart = array_search('$_POST=array (', $rowContents); // If we found any of these, we know this is a devMode log. if ($cookieStart || $sessionStart || $serverStart || $postStart) { $cookieStart = $cookieStart ? $cookieStart + 1 : $cookieStart; $sessionStart = $sessionStart ? $sessionStart + 1 : $sessionStart; $serverStart = $serverStart ? $serverStart + 1 : $serverStart; $postStart = $postStart ? $postStart + 1 : $postStart; if (!$postStart) { if (!$cookieStart) { if (!$sessionStart) { $start = $serverStart; } else { $start = $sessionStart; } } else { $start = $cookieStart; } } else { $start = $postStart; } // Check to see if it's GET or POST if (mb_substr($rowContents[0], 0, 5) == '$_GET') { // Grab GET $logEntryModel->get = $this->_cleanUpArray(array_slice($rowContents, 1, $start - 4)); } if (mb_substr($rowContents[0], 0, 6) == '$_POST') { // Grab POST $logEntryModel->post = $this->_cleanUpArray(array_slice($rowContents, 1, $start - 4)); } // We need to do a little more work to find out what element profiling info starts on. $tempArray = array_slice($rowContents, $serverStart, null, true); $profileStart = false; foreach ($tempArray as $key => $tempArrayRow) { if (preg_match($dateTimePattern, $tempArrayRow)) { $profileStart = $key; break; } } // Grab the cookie, session and server sections. if ($cookieStart) { if (!$sessionStart) { $start = $serverStart; } else { $start = $sessionStart; } $logEntryModel->cookie = $this->_cleanUpArray(array_slice($rowContents, $cookieStart, $start - $cookieStart - 3)); } if ($sessionStart) { $logEntryModel->session = $this->_cleanUpArray(array_slice($rowContents, $sessionStart, $serverStart - $sessionStart - 3)); } // Build out the $_SERVER array. Not exactly sure when this should end so just scan through the lines until the array has been closed. $serverArray = []; for ($line = $serverStart; isset($rowContents[$line]); $line++) { if (strncmp($rowContents[$line], ')', 1) === 0) { break; } $serverArray[] = $rowContents[$line]; } $logEntryModel->server = $this->_cleanUpArray($serverArray); // We can't just grab the profile info, we need to do some extra processing on it. $tempProfile = array_slice($rowContents, $profileStart); $profile = array(); $profileArr = array(); foreach ($tempProfile as $tempProfileRow) { if (preg_match($dateTimePattern, $tempProfileRow)) { if (!empty($profileArr)) { $profile[] = $profileArr; $profileArr = array(); } } $profileArr[] = rtrim(trim($tempProfileRow), ','); } // Grab the last one. $profile[] = $profileArr; // Finally save the profile. $logEntryModel->profile = $profile; } else { // This is a non-devMode log entry. $logEntryModel->message = $rowContents[0]; } // And save the log entry. $logEntries[] = $logEntryModel; } if ($logEntries) { // Put these logs at the top array_unshift($logEntriesByRequest, $logEntries); } } } else { $logEntry = new LogEntryModel(); $contents = IOHelper::getFileContents(craft()->path->getLogPath() . $currentLogFileName); $contents = str_replace("\n", "<br />", $contents); $logEntry->message = $contents; $logEntriesByRequest[] = array($logEntry); } } $this->renderTemplate('utils/logs', array('logEntriesByRequest' => $logEntriesByRequest, 'logFileNames' => $logFileNames, 'currentLogFileName' => $currentLogFileName)); } }
/** * @param $recursive * @param $filter * @return mixed */ public function getContents($recursive, $filter) { return IOHelper::getFolderContents($this->getRealPath(), $recursive, $filter); }
/** * Logs * * @param array $variables * * @return null */ public function actionLogs(array $variables = array()) { craft()->config->maxPowerCaptain(); if (IOHelper::folderExists(craft()->path->getLogPath())) { $dateTimePattern = '/^[0-9]{4}\\/[0-9]{2}\\/[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/'; $logFileNames = array(); // Grab it all. $logFolderContents = IOHelper::getFolderContents(craft()->path->getLogPath()); foreach ($logFolderContents as $logFolderContent) { // Make sure it's a file.` if (IOHelper::fileExists($logFolderContent)) { $logFileNames[] = IOHelper::getFileName($logFolderContent); } } $logEntries = array(); $currentLogFileName = isset($variables['currentLogFileName']) ? $variables['currentLogFileName'] : 'craft.log'; $currentFullPath = craft()->path->getLogPath() . $currentLogFileName; if (IOHelper::fileExists($currentFullPath)) { // Different parsing logic for phperrors.log if ($currentLogFileName !== 'phperrors.log') { $contents = IOHelper::getFileContents(craft()->path->getLogPath() . $currentLogFileName); // Split on the new log entry line. $contents = preg_split('/(\\*){102}/', $contents); foreach ($contents as $rowChunk) { $logEntryModel = new LogEntryModel(); $rowChunk = trim($rowChunk); // Split on the newlines $rowContents = preg_split("/\n/", $rowChunk); // Grab the date and time $logEntryModel->dateTime = rtrim(trim(mb_substr($rowContents[0], 0, 19)), ','); // Grab the level $rowContents[0] = mb_substr($rowContents[0], 21); $stop = mb_strpos($rowContents[0], ']'); $logEntryModel->level = rtrim(trim(mb_substr($rowContents[0], 0, $stop)), ','); // Grab the category. $rowContents[0] = mb_substr($rowContents[0], $stop + 3); $stop = mb_strpos($rowContents[0], ']'); $logEntryModel->category = rtrim(trim(mb_substr($rowContents[0], 0, $stop)), ','); // Find a few new markers $rowContents[0] = mb_substr($rowContents[0], $stop + 2); $cookieStart = array_search('$_COOKIE=array (', $rowContents); $sessionStart = array_search('$_SESSION=array (', $rowContents); $serverStart = array_search('$_SERVER=array (', $rowContents); $postStart = array_search('$_POST=array (', $rowContents); // If we found any of these, we know this is a devMode log. if ($cookieStart || $sessionStart || $serverStart || $postStart) { $cookieStart = $cookieStart ? $cookieStart + 1 : $cookieStart; $sessionStart = $sessionStart ? $sessionStart + 1 : $sessionStart; $serverStart = $serverStart ? $serverStart + 1 : $serverStart; $postStart = $postStart ? $postStart + 1 : $postStart; if (!$postStart) { if (!$cookieStart) { if (!$sessionStart) { $start = $serverStart; } else { $start = $sessionStart; } } else { $start = $cookieStart; } } else { $start = $postStart; } // Check to see if it's GET or POST if (mb_substr($rowContents[0], 0, 5) == '$_GET') { // Grab GET $logEntryModel->get = $this->_cleanUpArray(array_slice($rowContents, 1, $start - 4)); } if (mb_substr($rowContents[0], 0, 6) == '$_POST') { // Grab POST $logEntryModel->post = $this->_cleanUpArray(array_slice($rowContents, 1, $start - 4)); } // We need to do a little more work to find out what element profiling info starts on. $tempArray = array_slice($rowContents, $serverStart, null, true); $profileStart = false; foreach ($tempArray as $key => $tempArrayRow) { if (preg_match($dateTimePattern, $tempArrayRow)) { $profileStart = $key; break; } } // Grab the cookie, session and server sections. if ($cookieStart) { if (!$sessionStart) { $start = $serverStart; } else { $start = $sessionStart; } $logEntryModel->cookie = $this->_cleanUpArray(array_slice($rowContents, $cookieStart, $start - $cookieStart - 3)); } if ($sessionStart) { $logEntryModel->session = $this->_cleanUpArray(array_slice($rowContents, $sessionStart, $serverStart - $sessionStart - 3)); } $logEntryModel->server = $this->_cleanUpArray(array_slice($rowContents, $serverStart, $profileStart - $serverStart - 1)); // We can't just grab the profile info, we need to do some extra processing on it. $tempProfile = array_slice($rowContents, $profileStart); $profile = array(); $profileArr = array(); foreach ($tempProfile as $tempProfileRow) { if (preg_match($dateTimePattern, $tempProfileRow)) { if (!empty($profileArr)) { $profile[] = $profileArr; $profileArr = array(); } } $profileArr[] = rtrim(trim($tempProfileRow), ','); } // Grab the last one. $profile[] = $profileArr; // Finally save the profile. $logEntryModel->profile = $profile; } else { // This is a non-devMode log entry. $logEntryModel->message = $rowContents[0]; } // And save the log entry. $logEntries[] = $logEntryModel; } // Because I'm lazy. array_pop($logEntries); } else { $logEntry = new LogEntryModel(); $contents = IOHelper::getFileContents(craft()->path->getLogPath() . $currentLogFileName); $contents = str_replace("\n", "<br />", $contents); $logEntry->message = $contents; $logEntries[] = $logEntry; } } // Because ascending order is stupid. $logEntries = array_reverse($logEntries); $this->renderTemplate('utils/logs', array('logEntries' => $logEntries, 'logFileNames' => $logFileNames, 'currentLogFileName' => $currentLogFileName)); } }
/** * Creates a new support ticket for the GetHelp widget. */ public function actionSendSupportRequest() { $this->requirePostRequest(); $this->requireAjaxRequest(); craft()->config->maxPowerCaptain(); $getHelpModel = new GetHelpModel(); $getHelpModel->fromEmail = craft()->request->getPost('fromEmail'); $getHelpModel->message = craft()->request->getPost('message'); $getHelpModel->attachDebugFiles = (bool) craft()->request->getPost('attachDebugFiles'); if ($getHelpModel->validate()) { $user = craft()->userSession->getUser(); $requestParamDefaults = array('sFirstName' => $user->getFriendlyName(), 'sLastName' => $user->lastName ? $user->lastName : 'Doe', 'sEmail' => $getHelpModel->fromEmail, 'tNote' => $getHelpModel->message); $requestParams = $requestParamDefaults; $hsParams = array('helpSpotApiURL' => 'https://support.pixelandtonic.com/api/index.php'); try { if ($getHelpModel->attachDebugFiles) { $tempZipFile = craft()->path->getTempPath() . StringHelper::UUID() . '.zip'; IOHelper::createFile($tempZipFile); if (IOHelper::folderExists(craft()->path->getLogPath())) { // Grab the latest log file. Zip::add($tempZipFile, craft()->path->getLogPath() . 'craft.log', craft()->path->getStoragePath()); // Grab the most recent rolled-over log file, if one exists. if (IOHelper::fileExists(craft()->path->getLogPath() . 'craft.log.1')) { Zip::add($tempZipFile, craft()->path->getLogPath() . 'craft.log.1', craft()->path->getStoragePath()); } // Grab the phperrors log file, if it exists. if (IOHelper::fileExists(craft()->path->getLogPath() . 'phperrors.log')) { Zip::add($tempZipFile, craft()->path->getLogPath() . 'phperrors.log', craft()->path->getStoragePath()); } } if (IOHelper::folderExists(craft()->path->getDbBackupPath())) { // Make a fresh database backup of the current schema/data. craft()->db->backup(); $contents = IOHelper::getFolderContents(craft()->path->getDbBackupPath()); rsort($contents); // Only grab the most recent 3 sorted by timestamp. for ($counter = 0; $counter <= 2; $counter++) { if (isset($contents[$counter])) { Zip::add($tempZipFile, $contents[$counter], craft()->path->getStoragePath()); } } } $requestParams['File1_sFilename'] = 'SupportAttachment.zip'; $requestParams['File1_sFileMimeType'] = 'application/zip'; $requestParams['File1_bFileBody'] = base64_encode(IOHelper::getFileContents($tempZipFile)); // Bump the default timeout because of the attachment. $hsParams['callTimeout'] = 120; } } catch (\Exception $e) { Craft::log('Tried to attach debug logs to a support request and something went horribly wrong: ' . $e->getMessage(), LogLevel::Warning); // There was a problem zipping, so reset the params and just send the email without the attachment. $requestParams = $requestParamDefaults; } require_once craft()->path->getLibPath() . 'HelpSpotAPI.php'; $hsapi = new \HelpSpotAPI($hsParams); $result = $hsapi->requestCreate($requestParams); if ($result) { if ($getHelpModel->attachDebugFiles) { if (IOHelper::fileExists($tempZipFile)) { IOHelper::deleteFile($tempZipFile); } } $this->returnJson(array('success' => true)); } else { $hsErrors = array_filter(preg_split("/(\r\n|\n|\r)/", $hsapi->errors)); $this->returnJson(array('errors' => array('Support' => $hsErrors))); } } else { $this->returnJson(array('errors' => $getHelpModel->getErrors())); } }
/** * Delete all the generated images for this file. * * @param AssetFileModel $file The assetFileModel representing the file to delete any generated thumbnails for. * * @return null */ protected function deleteGeneratedThumbnails(AssetFileModel $file) { $thumbFolders = IOHelper::getFolderContents(craft()->path->getAssetsThumbsPath()); foreach ($thumbFolders as $folder) { if (is_dir($folder)) { IOHelper::deleteFile($folder . '/' . $file->id . '.' . IOHelper::getExtension($file->filename)); } } }
/** * Will add either a file or a folder to an existing zip file. If it is a folder, it will add the contents recursively. * * @param string $sourceZip The zip file to be added to. * @param string $pathToAdd A file or a folder to add. If it is a folder, it will recursively add the contents of the folder to the zip. * @param string $basePath The root path of the file(s) to be added that will be removed before adding. * @param string $pathPrefix A path to be prepended to each file before it is added to the zip. * @return bool */ public function add($sourceZip, $pathToAdd, $basePath, $pathPrefix = null) { $zip = new \PclZip($sourceZip); if (IOHelper::fileExists($pathToAdd)) { $folderContents = array($pathToAdd); } else { $folderContents = IOHelper::getFolderContents($pathToAdd, true); } $filesToAdd = array(); foreach ($folderContents as $itemToZip) { if (IOHelper::isReadable($itemToZip)) { if (IOHelper::folderExists($itemToZip) && IOHelper::isFolderEmpty($itemToZip) || IOHelper::fileExists($itemToZip)) { $filesToAdd[] = $itemToZip; } } } if (!$pathPrefix) { $pathPrefix = ''; } $result = $zip->add($filesToAdd, PCLZIP_OPT_ADD_PATH, $pathPrefix, PCLZIP_OPT_REMOVE_PATH, $basePath); if ($result == 0) { Craft::log('Unable to add to zip file: ' . $sourceZip, LogLevel::Error); return false; } return true; }
/** * Define the sources. * * @param string $context * * @return array */ public function getSources($context = null) { // Get plugin sources $pluginSources = array(); $plugins = craft()->plugins->getPlugins(); foreach ($plugins as $path => $plugin) { $pluginSources['plugins:' . $path] = array('label' => $plugin->classHandle, 'criteria' => array('source' => craft()->path->getPluginsPath() . $path)); } // Get template sources $templateSources = array(); $templates = IOHelper::getFolderContents(craft()->path->getSiteTemplatesPath(), false); foreach ($templates as $template) { // Get path/name of template files and folders if (preg_match('/(.*)\\/(.*?)(\\.(html|twig|js|json|atom|rss)|\\/)$/', $template, $matches)) { // If matches, get template name $path = $matches[2]; // Add template source $templateSources['templates:' . $path] = array('label' => $path, 'criteria' => array('source' => $template)); } } // Get default sources $sources = array('*' => array('label' => Craft::t('All translations'), 'criteria' => array('source' => array(craft()->path->getPluginsPath(), craft()->path->getSiteTemplatesPath()))), array('heading' => Craft::t('Default')), 'plugins' => array('label' => Craft::t('Plugins'), 'criteria' => array('source' => craft()->path->getPluginsPath()), 'nested' => $pluginSources), 'templates' => array('label' => Craft::t('Templates'), 'criteria' => array('source' => craft()->path->getSiteTemplatesPath()), 'nested' => $templateSources)); // Get sources by hook $plugins = craft()->plugins->call('registerTranslateSources'); if (count($plugins)) { $sources[] = array('heading' => Craft::t('Custom')); foreach ($plugins as $plugin) { // Add as own source $sources = array_merge($sources, $plugin); // Add to "All translations" foreach ($plugin as $key => $values) { $sources['*']['criteria']['source'][] = $values['criteria']['source']; } } } // Return sources return $sources; }
/** * Delete all the generated thumbnails for the file. * * @param AssetFileModel $file * * @return null */ public function deleteThumbnailsForFile(AssetFileModel $file) { $thumbFolders = IOHelper::getFolderContents(craft()->path->getAssetsThumbsPath()); foreach ($thumbFolders as $folder) { if (is_dir($folder)) { IOHelper::deleteFile($folder . '/' . $file->id . '.' . $this->_getThumbExtension($file)); } } }
/** * If the plugin already had a migrations folder with migrations in it, let's save them in the db. * * @param int $pluginId * @param string $pluginHandle * * @throws Exception */ private function _savePluginMigrations($pluginId, $pluginHandle) { $migrationsFolder = craft()->path->getPluginsPath() . mb_strtolower($pluginHandle) . '/migrations/'; if (IOHelper::folderExists($migrationsFolder)) { $migrations = array(); $migrationFiles = IOHelper::getFolderContents($migrationsFolder, false, "(m(\\d{6}_\\d{6})_.*?)\\.php"); if ($migrationFiles) { foreach ($migrationFiles as $file) { if (IOHelper::fileExists($file)) { $migration = new MigrationRecord(); $migration->version = IOHelper::getFileName($file, false); $migration->applyTime = DateTimeHelper::currentUTCDateTime(); $migration->pluginId = $pluginId; $migrations[] = $migration; } } foreach ($migrations as $migration) { if (!$migration->save()) { throw new Exception(Craft::t('There was a problem saving to the migrations table: ') . $this->_getFlattenedErrors($migration->getErrors())); } } } } }
/** * @inheritDoc BaseAssetSourceType::getNameReplacement() * * @param AssetFolderModel $folder * @param string $fileName * * @return string */ protected function getNameReplacement(AssetFolderModel $folder, $fileName) { $fileList = IOHelper::getFolderContents($this->getSourceFileSystemPath() . $folder->path, false); $existingFiles = array(); foreach ($fileList as $file) { $existingFiles[mb_strtolower(IOHelper::getFileName($file))] = true; } // Double-check if (!isset($existingFiles[mb_strtolower($fileName)])) { return $fileName; } $fileParts = explode(".", $fileName); $extension = array_pop($fileParts); $fileName = join(".", $fileParts); for ($i = 1; $i <= 50; $i++) { if (!isset($existingFiles[mb_strtolower($fileName . '_' . $i . '.' . $extension)])) { return $fileName . '_' . $i . '.' . $extension; } } return false; }