I just wrote a function like this
/**
* Send an asynchronous GET request
*
* #param string $url
* #param array $options
*
* #return \React\Promise\ExtendedPromiseInterface
*/
public function getAsync( $url, array $options = [] );
but when making docblock, I realized that #return \React\Promise\ExtendedPromiseInterface is very generic and doesn't really help client understand what returns are to be expected in case of rejection or fulfillment.
Is there some established convention for documenting which values or exception are expected as a result of this function so that the client could chain on this function by looking at the interface only?
For exceptions you can add:
/**
* #throws customException if the bad thing happens
*/
You could add as many of these as you like too. After the #return you can add a type before and a short description of what it is after.
Not having found anything, I ended up making this up
/**
* Send an asynchronous GET request
*
* #param string $url
* #param array $options
*
* #return \React\Promise\ExtendedPromiseInterface
*
* #promise.resolve \MyApp\Interfaces\ResponseInterface
* #promise.reject \MyApp\Exceptions\RequestException
*/
public function getAsync( $url, array $options = [] );
I got an data file from a mainframe. I handled already the EBCDIC conversion to latin1 with PHP. But now are this packed decimal fields left.
For examle the number 12345 is packed into 3 Bytes and looks like: x'12345C'
Negative would be like: x'12345D'
So the right half Byte telling the sign. Is there a way to do this easily with PHP?
Now I do that like:
$bin = "\x12\x34\x5C";
var_dump(
unpack("H*", $bin)
);
It results in:
array(1) {
[1]=>
string(4) "123c"
}
Now I could check if last sign is C or D and do all by hand. But maybe there is a nicer solution?
As Bill said, get the mainframe people to convert the file to Text on the Mainframe and send the Text file, utilities like sort etc can do this on the mainframe. Also is it just packed decimal in the file or do you have either binary or Zoned Decimal as well ???
If you insist on doing it in PHP, you need to do the Packed Decimal conversion before you do the EBCDIC conversion because for a Packed-decimal like x'400c'
the EBCDIC converter will look at the x'40' and say that is a space and convert it to x'20', so your x'400c' becomes x'200c'.
Also the final nyble in a Packed-decimal can be f - unsigned as well as c and d.
Finally if you have the Cobol Copybook, my project JRecord has Cobol to Csv && Cobol to Xml conversion programs (Written in java). See
Cobol to Csv notes
Cobol To Xml notes
Ok, because I did not find any nicer solution, I made a php-class for handle a record from this dataset:
<?php
namespace Mainframe;
/**
* Mainframe main function
*
* #author vp1zag4
*
*/
class Mainframe
{
/**
* Data string for reading
*
* #var string | null
*/
protected $data = null;
/**
* Default ouput charset
*
* #var string
*/
const OUTPUT_CHARSET = 'latin1';
/**
* Record length of dataset
*
* #var integer
*/
protected $recordLength = 10;
/**
* Inits the
*
* #param unknown $data
*/
public function __construct($data = null)
{
if (! is_null($data)) {
$this->setData($data);
}
}
/**
* Sets the data string and validates
*
* #param unknown $data
* #throws \LengthException
*/
public function setData($data)
{
if (strlen($data) != $this->recordLength) {
throw new \LengthException('Given data does not fit to dataset record length');
}
$this->data = $data;
}
/**
* Unpack packed decimal (BCD) from mainframe format to integer
*
* #param unknown $str
* #return number
*/
public static function unpackBCD($str)
{
$num = unpack('H*', $str);
$num = array_shift($num);
$sign = strtoupper(substr($num, - 1));
$num = (int) substr($num, 0, - 1);
if ($sign == 'D') {
$num = $num * - 1;
}
return (int) $num;
}
/**
* convert EBCDIC to default output charset
*
* #param string $str
* #return string
*/
public static function conv($str, $optionalCharset = null)
{
$charset = (is_string($optionalCharset)) ? $optionalCharset : self::OUTPUT_CHARSET;
return iconv('IBM037', $charset, $str);
}
/**
* Reads part of data string and converts or unpacks
*
* #param integer $start
* #param integer $length
* #param bool $unpack
* #param bool | string $conv
*/
public function read($start, $length, $unpack = false, $conv = true)
{
if (empty($this->data)) {
return null;
}
$result = substr($this->data, $start, $length);
if($unpack) {
return self::unpackBCD($result);
}
if ($conv) {
return self::conv($result, $conv);
}
return $result;
}
}
With $class->read(1, 3, True) it is possible to read part of the data and convert/unpack it on same time.
Maybe it will help anybody anytime, too.
But of course I will try to setup some Job which will do that for me directly on mainframe with some JSON data as output.
I set up an local TYPO3 7.2 environment with xampp.
The installation works fine and everything else too.
At the beginning I installed the FluidTYPO3 site kickstarter distribution because I wanted to work with FLUID there. The distribution created all extensions needed for that (vhs, flux, fluidpages, fluidcontent) and then I created my provider extension with the builder.
It also created 4 pages or 1 page and 3 subpages. As I wanted to rename them I got the following error/exception:
PHP Warning: file_get_contents(): Filename cannot be empty in F:\xampp\htdocs\src\typo3_src-7.2.0\typo3\sysext\fluid\Classes\View\TemplateView.php line 318
I tried to var_dump() that in that file but it didn't help. I get the correct path and filename on other modules but not on the "page"-module where the error appeared. I can not rename, delete or edit the pages.
It seems that something is null there, mh.
Later I saw that the extensions were not for my TYPO3 version 7.2, only for 6.2.99 I think. So I deinstalled all extensions and downloaded the development extensions from Github (https://github.com/FluidTYPO3).
I installed them with an error that my version is too high. The extensions are only for 7.1.99. I thought that it would not be a problem and it should work with it anyway.
As I tested it there was the same error again, again and again.
I don't know where the problem is. Everything works fine on 6.x installations.
Could that be a bug or did I forget something?
PHP Version: 5.6.3 /
TYPO3 Version: 7.2
Would be very nice if anyone knows about the problem or could help me to solve it. I don't know which information is needed. Feel free to ask if something is needed.
<?php
namespace TYPO3\CMS\Fluid\View;
/* *
* This script is backported from the TYPO3 Flow package "TYPO3.Fluid". *
* *
* It is free software; you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License, either version 3 *
* of the License, or (at your option) any later version. *
* *
* The TYPO3 project - inspiring people to share! *
* */
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Fluid\Compatibility\TemplateParserBuilder;
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3\CMS\Fluid\Fluid;
/**
* The main template view. Should be used as view if you want Fluid Templating
*
* #api
*/
class TemplateView extends AbstractTemplateView {
/**
* Pattern to be resolved for "#templateRoot" in the other patterns.
* Following placeholders are supported:
* - "#packageResourcesPath"
*
* #var string
*/
protected $templateRootPathPattern = '#packageResourcesPath/Private/Templates';
/**
* Pattern to be resolved for "#partialRoot" in the other patterns.
* Following placeholders are supported:
* - "#packageResourcesPath"
*
* #var string
*/
protected $partialRootPathPattern = '#packageResourcesPath/Private/Partials';
/**
* Pattern to be resolved for "#layoutRoot" in the other patterns.
* Following placeholders are supported:
* - "#packageResourcesPath"
*
* #var string
*/
protected $layoutRootPathPattern = '#packageResourcesPath/Private/Layouts';
/**
* Path(s) to the template root. If NULL, then $this->templateRootPathPattern will be used.
*
* #var array
*/
protected $templateRootPaths = NULL;
/**
* Path(s) to the partial root. If NULL, then $this->partialRootPathPattern will be used.
*
* #var array
*/
protected $partialRootPaths = NULL;
/**
* Path(s) to the layout root. If NULL, then $this->layoutRootPathPattern will be used.
*
* #var array
*/
protected $layoutRootPaths = NULL;
/**
* File pattern for resolving the template file
* Following placeholders are supported:
* - "#templateRoot"
* - "#partialRoot"
* - "#layoutRoot"
* - "#subpackage"
* - "#action"
* - "#format"
*
* #var string
*/
protected $templatePathAndFilenamePattern = '#templateRoot/#subpackage/#controller/#action.#format';
/**
* Directory pattern for global partials. Not part of the public API, should not be changed for now.
* Following placeholders are supported:
* - "#templateRoot"
* - "#partialRoot"
* - "#layoutRoot"
* - "#subpackage"
* - "#partial"
* - "#format"
*
* #var string
*/
private $partialPathAndFilenamePattern = '#partialRoot/#subpackage/#partial.#format';
/**
* File pattern for resolving the layout
* Following placeholders are supported:
* - "#templateRoot"
* - "#partialRoot"
* - "#layoutRoot"
* - "#subpackage"
* - "#layout"
* - "#format"
*
* #var string
*/
protected $layoutPathAndFilenamePattern = '#layoutRoot/#layout.#format';
/**
* Path and filename of the template file. If set, overrides the templatePathAndFilenamePattern
*
* #var string
*/
protected $templatePathAndFilename = NULL;
/**
* Path and filename of the layout file. If set, overrides the layoutPathAndFilenamePattern
*
* #var string
*/
protected $layoutPathAndFilename = NULL;
/**
* Constructor
*/
public function __construct() {
$this->templateParser = TemplateParserBuilder::build();
$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$this->setRenderingContext($this->objectManager->get(RenderingContextInterface::class));
}
/**
* Init view
*/
public function initializeView() {
}
// Here, the backporter can insert a constructor method, which is needed for the TYPO3 CMS extension
/**
* Sets the path and name of of the template file. Effectively overrides the
* dynamic resolving of a template file.
*
* #param string $templatePathAndFilename Template file path
* #return void
* #api
*/
public function setTemplatePathAndFilename($templatePathAndFilename) {
$this->templatePathAndFilename = $templatePathAndFilename;
}
/**
* Sets the path and name of the layout file. Overrides the dynamic resolving of the layout file.
*
* #param string $layoutPathAndFilename Path and filename of the layout file
* #return void
* #api
*/
public function setLayoutPathAndFilename($layoutPathAndFilename) {
$this->layoutPathAndFilename = $layoutPathAndFilename;
}
/**
* Set the root path to the templates.
* If set, overrides the one determined from $this->templateRootPathPattern
*
* #param string $templateRootPath Root path to the templates. If set, overrides the one determined from $this->templateRootPathPattern
* #return void
* #api
* #see setTemplateRootPaths()
*/
public function setTemplateRootPath($templateRootPath) {
$this->setTemplateRootPaths(array($templateRootPath));
}
/**
* Resolves the template root to be used inside other paths.
*
* #return array Path(s) to template root directory
*/
public function getTemplateRootPaths() {
if ($this->templateRootPaths !== NULL) {
return $this->templateRootPaths;
}
/** #var $actionRequest \TYPO3\CMS\Extbase\Mvc\Request */
$actionRequest = $this->controllerContext->getRequest();
return array(str_replace('#packageResourcesPath', ExtensionManagementUtility::extPath($actionRequest->getControllerExtensionKey()) . 'Resources/', $this->templateRootPathPattern));
}
/**
* Set the root path(s) to the templates.
* If set, overrides the one determined from $this->templateRootPathPattern
*
* #param array $templateRootPaths Root path(s) to the templates. If set, overrides the one determined from $this->templateRootPathPattern
* #return void
* #api
*/
public function setTemplateRootPaths(array $templateRootPaths) {
$this->templateRootPaths = $templateRootPaths;
}
/**
* Set the root path to the partials.
* If set, overrides the one determined from $this->partialRootPathPattern
*
* #param string $partialRootPath Root path to the partials. If set, overrides the one determined from $this->partialRootPathPattern
* #return void
* #api
* #see setPartialRootPaths()
*/
public function setPartialRootPath($partialRootPath) {
$this->setPartialRootPaths(array($partialRootPath));
}
/**
* Set the root path(s) to the partials.
* If set, overrides the one determined from $this->partialRootPathPattern
*
* #param array $partialRootPaths Root paths to the partials. If set, overrides the one determined from $this->partialRootPathPattern
* #return void
* #api
*/
public function setPartialRootPaths(array $partialRootPaths) {
$this->partialRootPaths = $partialRootPaths;
}
/**
* Resolves the partial root to be used inside other paths.
*
* #return array Path(s) to partial root directory
*/
protected function getPartialRootPaths() {
if ($this->partialRootPaths !== NULL) {
return $this->partialRootPaths;
}
/** #var $actionRequest \TYPO3\CMS\Extbase\Mvc\Request */
$actionRequest = $this->controllerContext->getRequest();
return array(str_replace('#packageResourcesPath', ExtensionManagementUtility::extPath($actionRequest->getControllerExtensionKey()) . 'Resources/', $this->partialRootPathPattern));
}
/**
* Set the root path to the layouts.
* If set, overrides the one determined from $this->layoutRootPathPattern
*
* #param string $layoutRootPath Root path to the layouts. If set, overrides the one determined from $this->layoutRootPathPattern
* #return void
* #api
* #see setLayoutRootPaths()
*/
public function setLayoutRootPath($layoutRootPath) {
$this->setLayoutRootPaths(array($layoutRootPath));
}
/**
* Set the root path(s) to the layouts.
* If set, overrides the one determined from $this->layoutRootPathPattern
*
* #param array $layoutRootPaths Root path to the layouts. If set, overrides the one determined from $this->layoutRootPathPattern
* #return void
* #api
*/
public function setLayoutRootPaths(array $layoutRootPaths) {
$this->layoutRootPaths = $layoutRootPaths;
}
/**
* Resolves the layout root to be used inside other paths.
*
* #return string Path(s) to layout root directory
*/
protected function getLayoutRootPaths() {
if ($this->layoutRootPaths !== NULL) {
return $this->layoutRootPaths;
}
/** #var $actionRequest \TYPO3\CMS\Extbase\Mvc\Request */
$actionRequest = $this->controllerContext->getRequest();
return array(str_replace('#packageResourcesPath', ExtensionManagementUtility::extPath($actionRequest->getControllerExtensionKey()) . 'Resources/', $this->layoutRootPathPattern));
}
/**
* Returns a unique identifier for the resolved template file
* This identifier is based on the template path and last modification date
*
* #param string $actionName Name of the action. If NULL, will be taken from request.
* #return string template identifier
*/
protected function getTemplateIdentifier($actionName = NULL) {
$templatePathAndFilename = $this->getTemplatePathAndFilename($actionName);
if ($actionName === NULL) {
/** #var $actionRequest \TYPO3\CMS\Extbase\Mvc\Request */
$actionRequest = $this->controllerContext->getRequest();
$actionName = $actionRequest->getControllerActionName();
}
$prefix = 'action_' . $actionName;
return $this->createIdentifierForFile($templatePathAndFilename, $prefix);
}
/**
* Resolve the template path and filename for the given action. If $actionName
* is NULL, looks into the current request.
*
* #param string $actionName Name of the action. If NULL, will be taken from request.
* #return string Full path to template
* #throws Exception\InvalidTemplateResourceException
*/
protected function getTemplateSource($actionName = NULL) {
$templatePathAndFilename = $this->getTemplatePathAndFilename($actionName);
$templateSource = file_get_contents($templatePathAndFilename);
if ($templateSource === FALSE) {
throw new Exception\InvalidTemplateResourceException('"' . $templatePathAndFilename . '" is not a valid template resource URI.', 1257246929);
}
return $templateSource;
}
/**
* Resolve the template path and filename for the given action. If $actionName
* is NULL, looks into the current request.
*
* #param string $actionName Name of the action. If NULL, will be taken from request.
* #return string Full path to template
* #throws Exception\InvalidTemplateResourceException
*/
protected function getTemplatePathAndFilename($actionName = NULL) {
if ($this->templatePathAndFilename !== NULL) {
return $this->resolveFileNamePath($this->templatePathAndFilename);
}
if ($actionName === NULL) {
/* #var $actionRequest \TYPO3\CMS\Extbase\Mvc\Request */
$actionRequest = $this->controllerContext->getRequest();
$actionName = $actionRequest->getControllerActionName();
}
$paths = $this->expandGenericPathPattern($this->templatePathAndFilenamePattern, FALSE, FALSE);
$possibleFileNames = $this->buildListOfTemplateCandidates($actionName, $paths, '#action');
foreach ($possibleFileNames as $templatePathAndFilename) {
if ($this->testFileExistence($templatePathAndFilename)) {
return $templatePathAndFilename;
}
}
throw new Exception\InvalidTemplateResourceException('Template could not be loaded. I tried "' . implode('", "', $possibleFileNames) . '"', 1225709595);
}
/**
* Returns a unique identifier for the resolved layout file.
* This identifier is based on the template path and last modification date
*
* #param string $layoutName The name of the layout
* #return string layout identifier
*/
protected function getLayoutIdentifier($layoutName = 'Default') {
$layoutPathAndFilename = $this->getLayoutPathAndFilename($layoutName);
$prefix = 'layout_' . $layoutName;
return $this->createIdentifierForFile($layoutPathAndFilename, $prefix);
}
/**
* Resolve the path and file name of the layout file, based on
* $this->layoutPathAndFilename and $this->layoutPathAndFilenamePattern.
*
* In case a layout has already been set with setLayoutPathAndFilename(),
* this method returns that path, otherwise a path and filename will be
* resolved using the layoutPathAndFilenamePattern.
*
* #param string $layoutName Name of the layout to use. If none given, use "Default"
* #return string contents of the layout template
* #throws Exception\InvalidTemplateResourceException
*/
protected function getLayoutSource($layoutName = 'Default') {
$layoutPathAndFilename = $this->getLayoutPathAndFilename($layoutName);
$layoutSource = file_get_contents($layoutPathAndFilename);
if ($layoutSource === FALSE) {
throw new Exception\InvalidTemplateResourceException('"' . $layoutPathAndFilename . '" is not a valid template resource URI.', 1257246930);
}
return $layoutSource;
}
/**
* Resolve the path and file name of the layout file, based on
* $this->layoutPathAndFilename and $this->layoutPathAndFilenamePattern.
*
* In case a layout has already been set with setLayoutPathAndFilename(),
* this method returns that path, otherwise a path and filename will be
* resolved using the layoutPathAndFilenamePattern.
*
* #param string $layoutName Name of the layout to use. If none given, use "Default"
* #return string Path and filename of layout files
* #throws Exception\InvalidTemplateResourceException
*/
protected function getLayoutPathAndFilename($layoutName = 'Default') {
if ($this->layoutPathAndFilename !== NULL) {
return $this->resolveFileNamePath($this->layoutPathAndFilename);
}
$paths = $this->expandGenericPathPattern($this->layoutPathAndFilenamePattern, TRUE, TRUE);
$possibleFileNames = $this->buildListOfTemplateCandidates($layoutName, $paths, '#layout');
foreach ($possibleFileNames as $layoutPathAndFilename) {
if ($this->testFileExistence($layoutPathAndFilename)) {
return $layoutPathAndFilename;
}
}
throw new Exception\InvalidTemplateResourceException('The layout files "' . implode('", "', $possibleFileNames) . '" could not be loaded.', 1225709596);
}
/**
* Returns a unique identifier for the resolved partial file.
* This identifier is based on the template path and last modification date
*
* #param string $partialName The name of the partial
* #return string partial identifier
*/
protected function getPartialIdentifier($partialName) {
$partialPathAndFilename = $this->getPartialPathAndFilename($partialName);
$prefix = 'partial_' . $partialName;
return $this->createIdentifierForFile($partialPathAndFilename, $prefix);
}
/**
* Figures out which partial to use.
*
* #param string $partialName The name of the partial
* #return string contents of the partial template
* #throws Exception\InvalidTemplateResourceException
*/
protected function getPartialSource($partialName) {
$partialPathAndFilename = $this->getPartialPathAndFilename($partialName);
$partialSource = file_get_contents($partialPathAndFilename);
if ($partialSource === FALSE) {
throw new Exception\InvalidTemplateResourceException('"' . $partialPathAndFilename . '" is not a valid template resource URI.', 1257246931);
}
return $partialSource;
}
/**
* Resolve the partial path and filename based on $this->partialPathAndFilenamePattern.
*
* #param string $partialName The name of the partial
* #return string the full path which should be used. The path definitely exists.
* #throws Exception\InvalidTemplateResourceException
*/
protected function getPartialPathAndFilename($partialName) {
$paths = $this->expandGenericPathPattern($this->partialPathAndFilenamePattern, TRUE, TRUE);
$possibleFileNames = $this->buildListOfTemplateCandidates($partialName, $paths, '#partial');
foreach ($possibleFileNames as $partialPathAndFilename) {
if ($this->testFileExistence($partialPathAndFilename)) {
return $partialPathAndFilename;
}
}
throw new Exception\InvalidTemplateResourceException('The partial files "' . implode('", "', $possibleFileNames) . '" could not be loaded.', 1225709597);
}
/**
* Builds a list of possible candidates for a given template name
*
* #param string $templateName
* #param array $paths Paths to search in
* #param string $marker Marker to replace in the $templateName
* #return array Array of paths to search for the template file
*/
protected function buildListOfTemplateCandidates($templateName, $paths, $marker) {
$upperCasedTemplateName = $this->ucFileNameInPath($templateName);
$possibleFileNames = array();
foreach ($paths as $partialPathAndFilename) {
$possibleFileNames[] = $this->resolveFileNamePath(str_replace($marker, $upperCasedTemplateName, $partialPathAndFilename));
if ($templateName !== $upperCasedTemplateName) {
$possibleFileNames[] = $this->resolveFileNamePath(str_replace($marker, $templateName, $partialPathAndFilename));
}
}
return $possibleFileNames;
}
/**
* Checks whether a template can be resolved for the current request context.
*
* #param ControllerContext $controllerContext Controller context which is available inside the view
* #return bool
* #api
*/
public function canRender(ControllerContext $controllerContext) {
$this->setControllerContext($controllerContext);
try {
$this->getTemplateSource();
return TRUE;
} catch (Exception\InvalidTemplateResourceException $e) {
return FALSE;
}
}
/**
* Processes following placeholders inside $pattern:
* - "#templateRoot"
* - "#partialRoot"
* - "#layoutRoot"
* - "#subpackage"
* - "#controller"
* - "#format"
*
* This method is used to generate "fallback chains" for file system locations where a certain Partial can reside.
*
* If $bubbleControllerAndSubpackage is FALSE and $formatIsOptional is FALSE, then the resulting array will only have one element
* with all the above placeholders replaced.
*
* If you set $bubbleControllerAndSubpackage to TRUE, then you will get an array with potentially many elements:
* The first element of the array is like above. The second element has the # controller part set to "" (the empty string)
* The third element now has the # controller part again stripped off, and has the last subpackage part stripped off as well.
* This continues until both "#subpackage" and "#controller" are empty.
*
* Example for $bubbleControllerAndSubpackage is TRUE, we have the Tx_MyExtension_MySubPackage_Controller_MyController
* as Controller Object Name and the current format is "html"
*
* If pattern is "#templateRoot/#subpackage/#controller/#action.#format", then the resulting array is:
* - "Resources/Private/Templates/MySubPackage/My/#action.html"
* - "Resources/Private/Templates/MySubPackage/#action.html"
* - "Resources/Private/Templates/#action.html"
*
* If you set $formatIsOptional to TRUE, then for any of the above arrays, every element will be duplicated - once with "#format"
* replaced by the current request format, and once with ."#format" stripped off.
*
* #param string $pattern Pattern to be resolved
* #param bool $bubbleControllerAndSubpackage if TRUE, then we successively split off parts from "#controller" and "#subpackage" until both are empty.
* #param bool $formatIsOptional if TRUE, then half of the resulting strings will have ."#format" stripped off, and the other half will have it.
* #return array unix style paths
*/
protected function expandGenericPathPattern($pattern, $bubbleControllerAndSubpackage, $formatIsOptional) {
$paths = array($pattern);
$this->expandPatterns($paths, '#templateRoot', $this->getTemplateRootPaths());
$this->expandPatterns($paths, '#partialRoot', $this->getPartialRootPaths());
$this->expandPatterns($paths, '#layoutRoot', $this->getLayoutRootPaths());
/** #var $actionRequest \TYPO3\CMS\Extbase\Mvc\Request */
$actionRequest = $this->controllerContext->getRequest();
$subpackageKey = $actionRequest->getControllerSubpackageKey();
$controllerName = $actionRequest->getControllerName();
if ($subpackageKey !== NULL) {
if (strpos($subpackageKey, Fluid::NAMESPACE_SEPARATOR) !== FALSE) {
$namespaceSeparator = Fluid::NAMESPACE_SEPARATOR;
} else {
$namespaceSeparator = Fluid::LEGACY_NAMESPACE_SEPARATOR;
}
$subpackageKeyParts = explode($namespaceSeparator, $subpackageKey);
} else {
$subpackageKeyParts = array();
}
if ($bubbleControllerAndSubpackage) {
$numberOfPathsBeforeSubpackageExpansion = count($paths);
$numberOfSubpackageParts = count($subpackageKeyParts);
$subpackageReplacements = array();
for ($i = 0; $i <= $numberOfSubpackageParts; $i++) {
$subpackageReplacements[] = implode('/', ($i < 0 ? $subpackageKeyParts : array_slice($subpackageKeyParts, $i)));
}
$this->expandPatterns($paths, '#subpackage', $subpackageReplacements);
for ($i = ($numberOfPathsBeforeSubpackageExpansion - 1) * ($numberOfSubpackageParts + 1); $i >= 0; $i -= ($numberOfSubpackageParts + 1)) {
array_splice($paths, $i, 0, str_replace('#controller', $controllerName, $paths[$i]));
}
$this->expandPatterns($paths, '#controller', array(''));
} else {
$i = $controllerName === NULL ? 0 : -1;
$this->expandPatterns($paths, '#subpackage', array(implode('/', $i < 0 ? $subpackageKeyParts :
array_slice($subpackageKeyParts, $i))));
$this->expandPatterns($paths, '#controller', array($controllerName));
}
if ($formatIsOptional) {
$this->expandPatterns($paths, '.#format', array('.' . $actionRequest->getFormat(), ''));
$this->expandPatterns($paths, '#format', array($actionRequest->getFormat(), ''));
} else {
$this->expandPatterns($paths, '.#format', array('.' . $actionRequest->getFormat()));
$this->expandPatterns($paths, '#format', array($actionRequest->getFormat()));
}
return array_values(array_unique($paths));
}
/**
* Expands the given $patterns by adding an array element for each $replacement
* replacing occurrences of $search.
*
* #param array $patterns
* #param string $search
* #param array $replacements
* #return void
*/
protected function expandPatterns(array &$patterns, $search, array $replacements) {
$patternsWithReplacements = array();
foreach ($patterns as $pattern) {
foreach ($replacements as $replacement) {
$patternsWithReplacements[] = GeneralUtility::fixWindowsFilePath(str_replace($search, $replacement, $pattern));
}
}
$patterns = $patternsWithReplacements;
}
/**
* Returns a unique identifier for the given file in the format
* <PackageKey>_<SubPackageKey>_<ControllerName>_<prefix>_<SHA1>
* The SH1 hash is a checksum that is based on the file path and last modification date
*
* #param string $pathAndFilename
* #param string $prefix
* #return string
*/
protected function createIdentifierForFile($pathAndFilename, $prefix) {
/** #var $actionRequest \TYPO3\CMS\Extbase\Mvc\Request */
$actionRequest = $this->controllerContext->getRequest();
$extensionName = $actionRequest->getControllerExtensionName();
$subPackageKey = $actionRequest->getControllerSubpackageKey();
if ($subPackageKey !== NULL) {
$extensionName .= '_' . $subPackageKey;
}
$controllerName = $actionRequest->getControllerName();
$templateModifiedTimestamp = filemtime($pathAndFilename);
$templateIdentifier = sprintf('%s_%s_%s_%s', $extensionName, $controllerName, $prefix, sha1($pathAndFilename . '|' . $templateModifiedTimestamp));
return $templateIdentifier;
}
/**
* Wrapper method to make the static call to GeneralUtility mockable in tests
*
* #param string $pathAndFilename
*
* #return string absolute pathAndFilename
*/
protected function resolveFileNamePath($pathAndFilename) {
return GeneralUtility::getFileAbsFileName(GeneralUtility::fixWindowsFilePath($pathAndFilename), TRUE);
}
}
$templatePathAndFilename = $this->getTemplatePathAndFilename($actionName);
This is the bad one in the function "getTemplateSource".
I downgraded the php version to 5.5 (new xampp installation) and it didn't work. :-(
Hoping for help,
thanks!
Okay I think the problem is solved.
The problem was that the column "tx_fluidpages_layout" of the table "pages" in the database had no entry. It was NULL.
Because I could not change and save it in the page properties without calling that error I changed it with phpmyadmin.
To fix that error you have to manually go to the table "pages" in the database f.e. with phpmyadmin and then to the column "tx_fluidpages_layout". There you have to edit the value and change it to "fluidpages__fluidpages". After that you can save it and reload the backend.
Now you should edit the page properties and set your page layout which comes from your provider extension.
I think it is a bug anyway, that should not happened. In TYPO3 6.x it was inserted automatically.
)
I start to use PEAR Number_Word class, and it works greate! It convert numbers to a string by this way:
<?php
include_once 'Numbers/Words.php';
$number = 100254;
$nw = new Numbers_Words();
$numw = $nw->toWords($number);
print $numw;
?>
But now I need to convert the same number to a different languages at the same time.
For exemple: I have number 100 and I need to convert it in the same time to English and French. I was trying to pass in the argument an array of two languages, but it's not work:
/**
* Default Locale name
* #var string
* #access public
*/
public $locale = 'en_US'; //__her I was try to pass an array, but no result__
/**
* Default decimal mark
* #var string
* #access public
*/
public $decimalPoint = '.';
// }}}
// {{{ toWords()
/**
* Converts a number to its word representation
*
* #param integer $num An integer between -infinity and infinity inclusive :)
* that should be converted to a words representation
* #param string $locale Language name abbreviation. Optional. Defaults to
* current loaded driver or en_US if any.
* #param array $options Specific driver options
*
* #access public
* #author Piotr Klaban <makler#man.torun.pl>
* #since PHP 4.2.3
* #return string The corresponding word representation
*/
function toWords($num, $locale = '', $options = array())
{
if (empty($locale) && isset($this) && $this instanceof Numbers_Words) {
$locale = $this->locale;
}
if (empty($locale)) {
$locale = 'en_US';
}
$classname = self::loadLocale($locale, '_toWords');
$obj = new $classname;
if (!is_int($num)) {
$num = $obj->normalizeNumber($num);
// cast (sanitize) to int without losing precision
$num = preg_replace('/(.*?)('.preg_quote($obj->decimalPoint).'.*?)?$/', '$1', $num);
}
if (empty($options)) {
return trim($obj->_toWords($num));
}
return trim($obj->_toWords($num, $options));
}
Please, halp me if you know how! Thank you in advance!
Numbers_Words does not support multiple languages at once.
You need to create a new Numbers_Words instance for every language.
Hi i am trying to set a a test to test my database calls. I want to pass a variables in url but cant seem to get it to work.
I wanted to do this
public function testDb()
{
$response = $this->call('GET', '/searchAvailability?keyword=test product');
$content = $response->getContent();
$this->assertEquals('[{"name":"test product"}]',$content );
}
But i keep getting "Undefined variable : keyword" when i try. It works in the browser just not when i run phpunit. Anyone got any ideas on why this is not working thanks.
The answer here is you need to specify the parameters differently in your call method:
$this->call('GET', '/searchAvailability', array('keyword' => 'test product'));
Below is the implementation of Illuminate\Foundation\Testing\TestCase::call method:
/**
* Call the given URI and return the Response.
*
* #param string $method
* #param string $uri
* #param array $parameters
* #param array $files
* #param array $server
* #param string $content
* #param bool $changeHistory
* #return \Illuminate\Http\Response
*/
public function call()
{
call_user_func_array(array($this->client, 'request'), func_get_args());
return $this->client->getResponse();
}