/** * Checks if the given value is a valid string (or can be cast to a string * if an object is given) and its length is between minimum and maximum * specified in the validation options. * * @param mixed $value The value that should be validated * @return void * @throws InvalidValidationOptionsException * @api */ protected function isValid($value) { if ($this->options['maximum'] < $this->options['minimum']) { throw new InvalidValidationOptionsException('The \'maximum\' is less than the \'minimum\' in the StringLengthValidator.', 1238107096); } if (is_object($value)) { if (!method_exists($value, '__toString')) { $this->addError('The given object could not be converted to a string.', 1238110957); return; } } elseif (!is_string($value)) { $this->addError('The given value was not a valid string.', 1269883975); return; } $stringLength = Unicode\Functions::strlen($value); $isValid = true; if ($stringLength < $this->options['minimum']) { $isValid = false; } if ($stringLength > $this->options['maximum']) { $isValid = false; } if ($isValid === false) { if ($this->options['minimum'] > 0 && $this->options['maximum'] < PHP_INT_MAX) { $this->addError('The length of this text must be between %1$d and %2$d characters.', 1238108067, [$this->options['minimum'], $this->options['maximum']]); } elseif ($this->options['minimum'] > 0) { $this->addError('This field must contain at least %1$d characters.', 1238108068, [$this->options['minimum']]); } else { $this->addError('This text may not exceed %1$d characters.', 1238108069, [$this->options['maximum']]); } } }
/** * Returns a random string with alpha-numeric characters. * * @param integer $count Number of characters to generate * @param string $characters Allowed characters, defaults to alpha-numeric (a-zA-Z0-9) * @return string A random string */ public static function generateRandomString($count, $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') { $characterCount = \Neos\Utility\Unicode\Functions::strlen($characters); $string = ''; for ($i = 0; $i < $count; $i++) { $string .= \Neos\Utility\Unicode\Functions::substr($characters, random_int(0, $characterCount - 1), 1); } return $string; }
/** * Render a node label * * @param NodeInterface $node * @param boolean $crop This argument is deprecated as of Neos 1.2 and will be removed. Don't rely on this behavior and crop labels in the view. * @return string */ public function getLabel(NodeInterface $node, $crop = true) { $label = Utility::evaluateEelExpression($this->getExpression(), $this->eelEvaluator, array('node' => $node), $this->defaultContextConfiguration); if ($crop === false) { return $label; } $croppedLabel = Functions::substr($label, 0, 30); return $croppedLabel . (strlen($croppedLabel) < strlen($label) ? ' …' : ''); }
/** * @param array $arguments * @param callable $renderChildrenClosure * @param RenderingContextInterface $renderingContext * @return string */ public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) { $value = $arguments['value']; if ($value === null) { $value = $renderChildrenClosure(); } if (UnicodeUtilityFunctions::strlen($value) > $arguments['maxCharacters']) { return UnicodeUtilityFunctions::substr($value, 0, $arguments['maxCharacters']) . $arguments['append']; } return $value; }
/** * Render a node label * * @param AbstractNodeData $nodeData * @param boolean $crop This argument is deprecated as of Neos 1.2 and will be removed. Don't rely on this behavior and crop labels in the view. * @return string */ public function getLabel(AbstractNodeData $nodeData, $crop = true) { if ($nodeData->hasProperty('title') === true && $nodeData->getProperty('title') !== '') { $label = strip_tags($nodeData->getProperty('title')); } elseif ($nodeData->hasProperty('text') === true && $nodeData->getProperty('text') !== '') { $label = strip_tags($nodeData->getProperty('text')); } else { $label = ($nodeData->getNodeType()->getLabel() ?: $nodeData->getNodeType()->getName()) . ' (' . $nodeData->getName() . ')'; } if ($crop === false) { return $label; } $croppedLabel = trim(Functions::substr($label, 0, 30)); return $croppedLabel . (strlen($croppedLabel) < strlen($label) ? ' …' : ''); }
/** * Return all Objects stored in this storage filtered by the given directory / filename pattern * * @param string $pattern A glob compatible directory / filename pattern * @param callable $callback Function called after each object * @return \Generator<StorageObject> */ public function getObjectsByPathPattern($pattern, callable $callback = null) { $directories = []; if (strpos($pattern, '/') !== false) { list($packageKeyPattern, $directoryPattern) = explode('/', $pattern, 2); } else { $packageKeyPattern = $pattern; $directoryPattern = '*'; } // $packageKeyPattern can be used in a future implementation to filter by package key $packages = $this->packageManager->getActivePackages(); foreach ($packages as $packageKey => $package) { /** @var PackageInterface $package */ if ($directoryPattern === '*') { $directories[$packageKey][] = $package->getPackagePath(); } else { $directories[$packageKey] = glob($package->getPackagePath() . $directoryPattern, GLOB_ONLYDIR); } } $iteration = 0; foreach ($directories as $packageKey => $packageDirectories) { foreach ($packageDirectories as $directoryPath) { foreach (Files::getRecursiveDirectoryGenerator($directoryPath) as $resourcePathAndFilename) { $pathInfo = UnicodeFunctions::pathinfo($resourcePathAndFilename); $object = new StorageObject(); $object->setFilename($pathInfo['basename']); $object->setSha1(sha1_file($resourcePathAndFilename)); $object->setMd5(md5_file($resourcePathAndFilename)); $object->setFileSize(filesize($resourcePathAndFilename)); if (isset($pathInfo['dirname'])) { list(, $path) = explode('/', str_replace($packages[$packageKey]->getResourcesPath(), '', $pathInfo['dirname']), 2); $object->setRelativePublicationPath($packageKey . '/' . $path . '/'); } $object->setStream(function () use($resourcePathAndFilename) { return fopen($resourcePathAndFilename, 'r'); }); (yield $object); if (is_callable($callback)) { call_user_func($callback, $iteration, $object); } $iteration++; } } } }
/** * Publishes the given source stream to this target, with the given relative path. * * @param resource $sourceStream Stream of the source to publish * @param string $relativeTargetPathAndFilename relative path and filename in the target directory * @throws TargetException * @throws \Exception */ protected function publishFile($sourceStream, $relativeTargetPathAndFilename) { $pathInfo = UnicodeFunctions::pathinfo($relativeTargetPathAndFilename); if (isset($pathInfo['extension']) && array_key_exists(strtolower($pathInfo['extension']), $this->extensionBlacklist) && $this->extensionBlacklist[strtolower($pathInfo['extension'])] === true) { throw new TargetException(sprintf('Could not publish "%s" into resource publishing target "%s" because the filename extension "%s" is blacklisted.', $sourceStream, $this->name, strtolower($pathInfo['extension'])), 1447152230); } $streamMetaData = stream_get_meta_data($sourceStream); if ($streamMetaData['wrapper_type'] !== 'plainfile' || $streamMetaData['stream_type'] !== 'STDIO') { throw new TargetException(sprintf('Could not publish stream "%s" into resource publishing target "%s" because the source is not a local file.', $streamMetaData['uri'], $this->name), 1416242392); } $sourcePathAndFilename = $streamMetaData['uri']; $targetPathAndFilename = $this->path . $relativeTargetPathAndFilename; if (@stat($sourcePathAndFilename) === false) { throw new TargetException(sprintf('Could not publish "%s" into resource publishing target "%s" because the source file is not accessible (file stat failed).', $sourcePathAndFilename, $this->name), 1415716366); } if (!file_exists(dirname($targetPathAndFilename))) { Files::createDirectoryRecursively(dirname($targetPathAndFilename)); } try { if (Files::is_link($targetPathAndFilename)) { Files::unlink($targetPathAndFilename); } if ($this->relativeSymlinks) { $result = Files::createRelativeSymlink($sourcePathAndFilename, $targetPathAndFilename); } else { $temporaryTargetPathAndFilename = uniqid($targetPathAndFilename . '.') . '.tmp'; symlink($sourcePathAndFilename, $temporaryTargetPathAndFilename); $result = rename($temporaryTargetPathAndFilename, $targetPathAndFilename); } } catch (\Exception $exception) { $result = false; } if ($result === false) { throw new TargetException(sprintf('Could not publish "%s" into resource publishing target "%s" because the source file could not be symlinked at target location.', $sourcePathAndFilename, $this->name), 1415716368, isset($exception) ? $exception : null); } $this->systemLogger->log(sprintf('FileSystemSymlinkTarget: Published file. (target: %s, file: %s)', $this->name, $relativeTargetPathAndFilename), LOG_DEBUG); }
/** * Evaluates the absolute path and filename of the resource file specified * by the given path. * * @param string $requestedPath * @param boolean $checkForExistence Whether a (non-hash) path should be checked for existence before being returned * @return mixed The full path and filename or FALSE if the file doesn't exist * @throws \InvalidArgumentException|ResourceException */ protected function evaluateResourcePath($requestedPath, $checkForExistence = true) { if (substr($requestedPath, 0, strlen(self::SCHEME)) !== self::SCHEME) { throw new \InvalidArgumentException('The ' . __CLASS__ . ' only supports the \'' . self::SCHEME . '\' scheme.', 1256052544); } $uriParts = Functions::parse_url($requestedPath); if (!is_array($uriParts) || !isset($uriParts['host'])) { return false; } if (preg_match('/^[0-9a-f]{40}$/i', $uriParts['host']) === 1) { $resource = $this->resourceManager->getResourceBySha1($uriParts['host']); return $this->resourceManager->getStreamByResource($resource); } if (!$this->packageManager->isPackageAvailable($uriParts['host'])) { throw new ResourceException(sprintf('Invalid resource URI "%s": Package "%s" is not available.', $requestedPath, $uriParts['host']), 1309269952); } $package = $this->packageManager->getPackage($uriParts['host']); $resourceUri = Files::concatenatePaths([$package->getResourcesPath(), $uriParts['path']]); if ($checkForExistence === false || file_exists($resourceUri)) { return $resourceUri; } return false; }
/** * Get the length of a string * * @param string $string The input string * @return integer Length of the string */ public function length($string) { return UnicodeFunctions::strlen($string); }
/** * Adds a tag built from the given key and value. * * @param string $key * @param string $value * @return void * @throws Exception */ public function addTag($key, $value) { $key = trim($key); if ($key === '') { throw new Exception('Tag Key must not be empty', 1448264366); } $value = trim($value); if ($value === '') { throw new Exception('Tag Value must not be empty', 1448264367); } $tag = Functions::ucfirst($key) . 'DynamicTag_' . $value; $this->tags[$tag] = true; }
/** * Find nodes by a value in properties * * This method is internal and will be replaced with better search capabilities. * * @param string|array $term Search term * @param string $nodeTypeFilter Node type filter * @param Workspace $workspace * @param array $dimensions * @param string $pathStartingPoint * @return array<\Neos\ContentRepository\Domain\Model\NodeData> */ public function findByProperties($term, $nodeTypeFilter, $workspace, $dimensions, $pathStartingPoint = null) { if (empty($term)) { throw new \InvalidArgumentException('"term" cannot be empty: provide a term to search for.', 1421329285); } $workspaces = $this->collectWorkspaceAndAllBaseWorkspaces($workspace); $queryBuilder = $this->createQueryBuilder($workspaces); $this->addDimensionJoinConstraintsToQueryBuilder($queryBuilder, $dimensions); $this->addNodeTypeFilterConstraintsToQueryBuilder($queryBuilder, $nodeTypeFilter); if (is_array($term)) { if (count($term) !== 1) { throw new \InvalidArgumentException('Currently only a 1-dimensional key => value array term is supported.', 1460437584); } // Build the like parameter as "key": "value" to search by a specific key and value $likeParameter = '%' . UnicodeFunctions::strtolower(trim(json_encode($term, JSON_PRETTY_PRINT | JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE), "{}\n\t ")) . '%'; } else { // Convert to lowercase, then to json, and then trim quotes from json to have valid JSON escaping. $likeParameter = '%' . trim(json_encode(UnicodeFunctions::strtolower($term), JSON_UNESCAPED_UNICODE), '"') . '%'; } $queryBuilder->andWhere("LOWER(NEOSCR_TOSTRING(n.properties)) LIKE :term")->setParameter('term', $likeParameter); if (strlen($pathStartingPoint) > 0) { $pathStartingPoint = strtolower($pathStartingPoint); $queryBuilder->andWhere($queryBuilder->expr()->orx()->add($queryBuilder->expr()->eq('n.parentPathHash', ':parentPathHash'))->add($queryBuilder->expr()->eq('n.pathHash', ':pathHash'))->add($queryBuilder->expr()->like('n.parentPath', ':parentPath')))->setParameter('parentPathHash', md5($pathStartingPoint))->setParameter('pathHash', md5($pathStartingPoint))->setParameter('parentPath', rtrim($pathStartingPoint, '/') . '/%'); } $query = $queryBuilder->getQuery(); $foundNodes = $query->getResult(); $foundNodes = $this->reduceNodeVariantsByWorkspacesAndDimensions($foundNodes, $workspaces, $dimensions); $foundNodes = $this->filterRemovedNodes($foundNodes, false); return $foundNodes; }
/** * Helper function to do the splitting by sentence. Note: one punctuations * mark belongs to the preceding sentence. Whitespace between sentences is * marked as boundary. * * @return void */ private function parseSubjectBySentence() { $i = 0; $j = 0; $count = 0; $delimitersMatches = []; preg_match_all('/' . self::REGEXP_SENTENCE_DELIMITERS . '/', $this->subject, $delimitersMatches); $splittedSentence = preg_split('/' . self::REGEXP_SENTENCE_DELIMITERS . '/', $this->subject); if (count($splittedSentence) == 1) { $this->iteratorCache->append(new TextIteratorElement($splittedSentence[0], 0, Unicode\Functions::strlen($splittedSentence[0]), false)); return; } foreach ($splittedSentence as $currentPart) { $currentPart = preg_replace('/^\\s|\\s$/', '', $currentPart, -1, $count); $whiteSpace = ''; for ($k = 0; $k < $count; $k++) { $whiteSpace .= ' '; } if ($whiteSpace != '') { $this->iteratorCache->append(new TextIteratorElement($whiteSpace, $i, $count, true)); } $i += $count; if ($currentPart != '' && $j < count($delimitersMatches[0])) { $this->iteratorCache->append(new TextIteratorElement($currentPart . $delimitersMatches[0][$j], $i, Unicode\Functions::strlen($currentPart . $delimitersMatches[0][$j]), false)); $i += Unicode\Functions::strlen($currentPart . $delimitersMatches[0][$j]); $j++; } elseif ($j < count($delimitersMatches[0])) { $this->iteratorCache->append(new TextIteratorElement($delimitersMatches[0][$j], $i, 1, true)); $i++; $j++; } } }
/** * Returns a like criterion used for matching objects against a query. * Matches if the property named $propertyName is like the $operand, using * standard SQL wildcards. * * @param string $propertyName The name of the property to compare against * @param string $operand The value to compare with * @param boolean $caseSensitive Whether the matching should be done case-sensitive * @return object * @throws InvalidQueryException if used on a non-string property * @api */ public function like($propertyName, $operand, $caseSensitive = true) { $aliasedPropertyName = $this->getPropertyNameWithAlias($propertyName); if ($caseSensitive === true) { return $this->queryBuilder->expr()->like($aliasedPropertyName, $this->getParamNeedle($operand)); } return $this->queryBuilder->expr()->like($this->queryBuilder->expr()->lower($aliasedPropertyName), $this->getParamNeedle(UnicodeFunctions::strtolower($operand))); }
/** * Sets the filename which is used when this resource is downloaded or saved as a file * * @param string $filename * @return void * @api */ public function setFilename($filename) { $this->throwExceptionIfProtected(); $pathInfo = UnicodeFunctions::pathinfo($filename); $extension = isset($pathInfo['extension']) ? '.' . strtolower($pathInfo['extension']) : ''; $this->filename = $pathInfo['filename'] . $extension; $this->mediaType = Utility\MediaTypes::getMediaTypeFromFilename($this->filename); }
/** * Constructs the URI object from a string * * @param string $uriString String representation of the URI * @throws \InvalidArgumentException * @api */ public function __construct($uriString) { if (!is_string($uriString)) { throw new \InvalidArgumentException('The URI must be a valid string.', 1176550571); } $parseUrlException = null; try { $uriParts = Unicode\Functions::parse_url($uriString); } catch (FlowError\Exception $exception) { $parseUrlException = $exception; } if (is_array($uriParts)) { $this->scheme = isset($uriParts['scheme']) ? $uriParts['scheme'] : null; $this->username = isset($uriParts['user']) ? $uriParts['user'] : null; $this->password = isset($uriParts['pass']) ? $uriParts['pass'] : null; $this->host = isset($uriParts['host']) ? $uriParts['host'] : null; $this->port = isset($uriParts['port']) ? $uriParts['port'] : null; if ($this->port === null) { switch ($this->scheme) { case 'http': $this->port = 80; break; case 'https': $this->port = 443; break; } } $this->path = isset($uriParts['path']) ? $uriParts['path'] : null; if (isset($uriParts['query'])) { $this->setQuery($uriParts['query']); } $this->fragment = isset($uriParts['fragment']) ? $uriParts['fragment'] : null; } else { throw new \InvalidArgumentException('The given URI "' . $uriString . '" is not a valid one.', 1351594202, $parseUrlException); } }
/** * Prepare an uploaded file to be imported as resource object. Will check the validity of the file, * move it outside of upload folder if open_basedir is enabled and check the filename. * * @param array $uploadInfo * @return array Array of string with the two keys "filepath" (the path to get the filecontent from) and "filename" the filename of the originally uploaded file. * @throws Exception */ protected function prepareUploadedFileForImport(array $uploadInfo) { $openBasedirEnabled = (bool) ini_get('open_basedir'); $temporaryTargetPathAndFilename = $uploadInfo['tmp_name']; $pathInfo = UnicodeFunctions::pathinfo($uploadInfo['name']); if (!is_uploaded_file($temporaryTargetPathAndFilename)) { throw new Exception('The given upload file "' . strip_tags($pathInfo['basename']) . '" was not uploaded through PHP. As it could pose a security risk it cannot be imported.', 1422461503); } if (isset($pathInfo['extension']) && array_key_exists(strtolower($pathInfo['extension']), $this->settings['resource']['uploadExtensionBlacklist']) && $this->settings['resource']['uploadExtensionBlacklist'][strtolower($pathInfo['extension'])] === true) { throw new Exception('The extension of the given upload file "' . strip_tags($pathInfo['basename']) . '" is blacklisted. As it could pose a security risk it cannot be imported.', 1447148472); } if ($openBasedirEnabled === true) { // Move uploaded file to a readable folder before trying to read sha1 value of file $newTemporaryTargetPathAndFilename = $this->environment->getPathToTemporaryDirectory() . 'ResourceUpload.' . uniqid() . '.tmp'; if (move_uploaded_file($temporaryTargetPathAndFilename, $newTemporaryTargetPathAndFilename) === false) { throw new Exception(sprintf('The uploaded file "%s" could not be moved to the temporary location "%s".', $temporaryTargetPathAndFilename, $newTemporaryTargetPathAndFilename), 1375199056); } $temporaryTargetPathAndFilename = $newTemporaryTargetPathAndFilename; } if (!is_file($temporaryTargetPathAndFilename)) { throw new Exception(sprintf('The temporary file "%s" of the file upload does not exist (anymore).', $temporaryTargetPathAndFilename), 1375198998); } return ['filepath' => $temporaryTargetPathAndFilename, 'filename' => $pathInfo['basename']]; }
/** * @param PersistentResource $originalResource * @param array $adjustments * @return array resource, width, height as keys * @throws ImageFileException * @throws InvalidConfigurationException * @throws Exception */ public function processImage(PersistentResource $originalResource, array $adjustments) { $additionalOptions = array(); $adjustmentsApplied = false; // TODO: Special handling for SVG should be refactored at a later point. if ($originalResource->getMediaType() === 'image/svg+xml') { $originalResourceStream = $originalResource->getStream(); $resource = $this->resourceManager->importResource($originalResourceStream, $originalResource->getCollectionName()); fclose($originalResourceStream); $resource->setFilename($originalResource->getFilename()); return ['width' => null, 'height' => null, 'resource' => $resource]; } $resourceUri = $originalResource->createTemporaryLocalCopy(); $resultingFileExtension = $originalResource->getFileExtension(); $transformedImageTemporaryPathAndFilename = $this->environment->getPathToTemporaryDirectory() . uniqid('ProcessedImage-') . '.' . $resultingFileExtension; if (!file_exists($resourceUri)) { throw new ImageFileException(sprintf('An error occurred while transforming an image: the resource data of the original image does not exist (%s, %s).', $originalResource->getSha1(), $resourceUri), 1374848224); } $imagineImage = $this->imagineService->open($resourceUri); $convertCMYKToRGB = $this->getOptionsMergedWithDefaults()['convertCMYKToRGB']; if ($convertCMYKToRGB && $imagineImage->palette() instanceof CMYK) { $imagineImage->usePalette(new RGB()); } if ($this->imagineService instanceof Imagine && $originalResource->getFileExtension() === 'gif' && $this->isAnimatedGif(file_get_contents($resourceUri)) === true) { $imagineImage->layers()->coalesce(); $layers = $imagineImage->layers(); $newLayers = array(); foreach ($layers as $index => $imagineFrame) { $imagineFrame = $this->applyAdjustments($imagineFrame, $adjustments, $adjustmentsApplied); $newLayers[] = $imagineFrame; } $imagineImage = array_shift($newLayers); $layers = $imagineImage->layers(); foreach ($newLayers as $imagineFrame) { $layers->add($imagineFrame); } $additionalOptions['animated'] = true; } else { $imagineImage = $this->applyAdjustments($imagineImage, $adjustments, $adjustmentsApplied); } if ($adjustmentsApplied === true) { $imagineImage->save($transformedImageTemporaryPathAndFilename, $this->getOptionsMergedWithDefaults($additionalOptions)); $imageSize = $imagineImage->getSize(); // TODO: In the future the collectionName of the new resource should be configurable. $resource = $this->resourceManager->importResource($transformedImageTemporaryPathAndFilename, $originalResource->getCollectionName()); if ($resource === false) { throw new ImageFileException('An error occurred while importing a generated image file as a resource.', 1413562208); } unlink($transformedImageTemporaryPathAndFilename); $pathInfo = UnicodeFunctions::pathinfo($originalResource->getFilename()); $resource->setFilename(sprintf('%s-%ux%u.%s', $pathInfo['filename'], $imageSize->getWidth(), $imageSize->getHeight(), $pathInfo['extension'])); } else { $originalResourceStream = $originalResource->getStream(); $resource = $this->resourceManager->importResource($originalResourceStream, $originalResource->getCollectionName()); fclose($originalResourceStream); $resource->setFilename($originalResource->getFilename()); $imageSize = $this->getImageSize($originalResource); $imageSize = new Box($imageSize['width'], $imageSize['height']); } $this->imageSizeCache->set($resource->getCacheEntryIdentifier(), array('width' => $imageSize->getWidth(), 'height' => $imageSize->getHeight())); $result = array('width' => $imageSize->getWidth(), 'height' => $imageSize->getHeight(), 'resource' => $resource); return $result; }
/** * Read the xliff file and create the desired json * * @param string $xliffPathAndFilename The file to read * @param string $packageKey * @param string $sourceName * @return array * * @todo remove the override handling once Flow takes care of that, see FLOW-61 */ public function parseXliffToArray($xliffPathAndFilename, $packageKey, $sourceName) { /** @var array $parsedData */ $parsedData = $this->xliffParser->getParsedData($xliffPathAndFilename); $arrayData = array(); foreach ($parsedData['translationUnits'] as $key => $value) { $valueToStore = !empty($value[0]['target']) ? $value[0]['target'] : $value[0]['source']; if ($this->scrambleTranslatedLabels) { $valueToStore = str_repeat('#', UnicodeFunctions::strlen($valueToStore)); } $this->setArrayDataValue($arrayData, str_replace('.', '_', $packageKey) . '.' . str_replace('/', '_', $sourceName) . '.' . str_replace('.', '_', $key), $valueToStore); } return $arrayData; }
/** * Set the suggested filename of this Object * * @param string $filename * @return void */ public function setFilename($filename) { $pathInfo = UnicodeFunctions::pathinfo($filename); $extension = isset($pathInfo['extension']) ? '.' . strtolower($pathInfo['extension']) : ''; $this->filename = $pathInfo['filename'] . $extension; $this->mediaType = MediaTypes::getMediaTypeFromFilename($this->filename); }
/** * @Flow\Around("setting(Neos.Neos.userInterface.scrambleTranslatedLabels) && method(Neos\Flow\I18n\Translator->translate.*())") * @param \Neos\Flow\Aop\JoinPointInterface $joinPoint The current join point * @return string A scrambled translation string */ public function scrambleTranslatedStrings(JoinPointInterface $joinPoint) { $translatedString = $joinPoint->getAdviceChain()->proceed($joinPoint); return str_repeat('#', UnicodeFunctions::strlen($translatedString)); }
/** * Publishes the given source stream to this target, with the given relative path. * * @param resource $sourceStream Stream of the source to publish * @param string $relativeTargetPathAndFilename relative path and filename in the target directory * @return void * @throws TargetException */ protected function publishFile($sourceStream, $relativeTargetPathAndFilename) { $pathInfo = UnicodeFunctions::pathinfo($relativeTargetPathAndFilename); if (isset($pathInfo['extension']) && array_key_exists(strtolower($pathInfo['extension']), $this->extensionBlacklist) && $this->extensionBlacklist[strtolower($pathInfo['extension'])] === true) { throw new TargetException(sprintf('Could not publish "%s" into resource publishing target "%s" because the filename extension "%s" is blacklisted.', $sourceStream, $this->name, strtolower($pathInfo['extension'])), 1447148472); } $targetPathAndFilename = $this->path . $relativeTargetPathAndFilename; if (@fstat($sourceStream) === false) { throw new TargetException(sprintf('Could not publish "%s" into resource publishing target "%s" because the source file is not accessible (file stat failed).', $sourceStream, $this->name), 1375258499); } if (!file_exists(dirname($targetPathAndFilename))) { Files::createDirectoryRecursively(dirname($targetPathAndFilename)); } if (!is_writable(dirname($targetPathAndFilename))) { throw new Exception(sprintf('Could not publish "%s" into resource publishing target "%s" because the target file "%s" is not writable.', $sourceStream, $this->name, $targetPathAndFilename), 1428917322, isset($exception) ? $exception : null); } try { $targetFileHandle = fopen($targetPathAndFilename, 'w'); $result = stream_copy_to_stream($sourceStream, $targetFileHandle); fclose($targetFileHandle); } catch (\Exception $exception) { $result = false; } if ($result === false) { throw new TargetException(sprintf('Could not publish "%s" into resource publishing target "%s" because the source file could not be copied to the target location.', $sourceStream, $this->name), 1375258399, isset($exception) ? $exception : null); } $this->systemLogger->log(sprintf('FileSystemTarget: Published file. (target: %s, file: %s)', $this->name, $relativeTargetPathAndFilename), LOG_DEBUG); }
/** * Checks if our version of pathinfo can handle some common special characters * * @test */ public function pathinfoWorksWithCertainSpecialChars() { $testString = 'кириллическийПуть/кириллическоеИмя.расширение'; $this->assertEquals('кириллическийПуть', Functions::pathinfo($testString, PATHINFO_DIRNAME), 'pathinfo() did not return the correct dirname for a unicode path.'); $this->assertEquals('кириллическоеИмя.расширение', Functions::pathinfo($testString, PATHINFO_BASENAME), 'pathinfo() did not return the correct basename for a unicode path.'); $this->assertEquals('расширение', Functions::pathinfo($testString, PATHINFO_EXTENSION), 'pathinfo() did not return the correct extension for a unicode path.'); $this->assertEquals('кириллическоеИмя', Functions::pathinfo($testString, PATHINFO_FILENAME), 'pathinfo() did not return the correct filename for a unicode path.'); }