/**
  * @param $hex_data
  * @return string
  */
 static function bin2str($hex_data)
 {
     return parent::bin2str($hex_data);
 }
Example #2
0
 /**
  * Int8Param constructor.
  * @param $io
  * @param $comment
  * @param string $varName
  * @param string $value
  * @param int $dimension
  * @param string $by
  * @param bool|false $isArray
  * @param null $labelSetLen
  */
 public function __construct($io, $comment, $varName = '', $value, $dimension = 0, $by = '', $isArray = false, $labelSetLen = null)
 {
     parent::__construct('3i0', $io, $comment, $varName, $value, 'off', $dimension, $by, $isArray, $labelSetLen, null);
     return $this;
 }
Example #3
0
 /**
  * pgmCall
  *
  * @param string $pgmName Name of program to call, without library
  * @param string $lib Library of program. Leave blank to use library list or current library
  * @param null $inputParam An array of ProgramParameter objects OR XML representing params, to be sent as-is.
  * @param null $returnParam ReturnValue Array of one parameter that's the return value parameter
  * @param null $options Array of other options. The most popular is 'func' indicating the name of a subprocedure or function.
  * @return array|bool
  */
 public function pgmCall($pgmName, $lib, $inputParam = NULL, $returnParam = NULL, $options = NULL)
 {
     $this->cpfErr = '';
     $this->error = '';
     $this->joblog = '';
     $function = NULL;
     ProgramParameter::initializeFallbackVarName();
     // If only one 'return' param, turn it into an array for later processing.
     if ($returnParam instanceof ProgramParameter) {
         $returnParam = array($returnParam);
     }
     $this->XMLWrapper = new XMLWrapper(array('encoding' => $this->getOption('encoding')), $this);
     // $optional handles special requests such as 'license'
     $disconnect = strcmp($pgmName, "OFF") === 0 ? true : false;
     $optional = strcmp($pgmName, "NONE") === 0 ? true : false;
     $outputParamArray = false;
     if (isset($options['func'])) {
         $function = $options['func'];
     }
     if ($disconnect || $optional) {
         $inputXml = $this->XMLWrapper->disconnectXMLIn();
     } else {
         $inputXml = $this->XMLWrapper->buildXmlIn($inputParam, $returnParam, $pgmName, $lib, $function);
     }
     // send XML to XMLSERVICE
     $outputXml = $this->sendXml($inputXml, $disconnect);
     if ($outputXml != '') {
         $outputParamArray = $this->XMLWrapper->getParamsFromXml($outputXml);
         // didn't get expected return, search logs to find out why
         if (!is_array($outputParamArray)) {
             // No real data. Look for errors. Retrieve details from joblog.
             $this->joblog = $this->XMLWrapper->getLastJoblog();
             // standard list of programs that provide CPF codes in joblog
             $programsToLookFor = array($pgmName, '< lveContext', '#mnrnrl', 'QRNXIE', '< allProgram');
             if (isset($this->_cpfMapping[$pgmName])) {
                 // list of other programs not called directly that might generate CPF codes in joblog.
                 $programsToLookFor = array_merge($programsToLookFor, $this->_cpfMapping[$pgmName]);
             }
             // put values in $this->cpfErr and $this->error
             $this->extractErrorFromJoblog($programsToLookFor);
         }
     }
     unset($this->XMLWrapper);
     // output array includes in/out parameters and return parameters.
     return $outputParamArray;
 }
 /**
  * Do all that's necessary to convert a single parameter into XML.
  * Can call itself recursively for infinitely deep data structures.
  * 
  * @param ProgramParameter $paramElement
  * @return string
  */
 protected function buildParamXml(ProgramParameter $paramElement)
 {
     $paramXml = '';
     $specialOuterDsName = '';
     // build start ds tag
     $props = $paramElement->getParamProperties();
     // optional by
     $by = $props['by'];
     $byStr = $by ? " by='{$by}'" : '';
     $name = $props['var'];
     // optional "array" attribute
     $isArray = $props['array'];
     $isArrayStr = $isArray ? " array='on'" : '';
     // optional dim (goes best with multi but could exist on its own, too)
     $dim = $props['dim'];
     $dimStr = $dim ? " dim='{$dim}'" : '';
     // if dim>0 and array integrity is specified
     $isMulti = $dim && $this->getOption('arrayIntegrity');
     /* if a multiple occurrence DS or scalar field.
      * later we will wrap an additional DS around it
      * The inner DS or scalar field will be a template with a 'dim' attribute to be expanded on output from XMLSERVICE.
      */
     /* if we add an outer DS that's "multi," don't bother to give the inner (original) ds a name.
      * The inner ds will be repeated many times and its name will be replaced on output by numeric indexes.
      *  So no need to include an inner ds name.
      */
     if ($isMulti) {
         $specialOuterDsName = $name;
         $innerName = '';
     } else {
         // not multi. Use normal inner name.
         $innerName = $name;
         // starts with space, directly following "<data"
     }
     // optional dou (do until)
     $dou = $props['dou'];
     $douStr = $dou ? " dou='{$dou}'" : '';
     // optional len that checks length of the structure/field to which it's appended
     $labelLen = $props['len'];
     $labelLenStr = $labelLen ? " len='{$labelLen}'" : '';
     // it's a data structure
     if ($props['type'] == 'ds') {
         // start ds tag with name and optional dim and by
         $innerNameStr = $innerName ? " var='{$innerName}'" : '';
         $paramXml .= "<ds{$innerNameStr}{$dimStr}{$douStr}{$isArrayStr}{$labelLenStr}>\n";
         // get the subfields
         $dsSubFields = $paramElement->getParamValue();
         if (is_array($dsSubFields) && count($dsSubFields)) {
             // recursively build XML from each data structure subfield
             foreach ($dsSubFields as $subField) {
                 $paramXml .= $this->buildParamXml($subField);
             }
         }
         // complete the ds tag
         $paramXml .= "</ds>\n";
     } else {
         // not a data structure. a regular single field
         $type = $props['type'];
         // optional varying
         // varying only inserted if set on/2/4 (default is off, so we can let XMLSERVICE supply the default behavior if off). The less XML we create and send, the more efficient we will be.
         $varyingStr = '';
         if (isset($props['varying'])) {
             // a valid non-off value, so add the varying attribute.
             if (in_array($props['varying'], $this->_varyingTypes)) {
                 $varyingStr = " varying='{$props['varying']}'";
             }
         }
         // optional enddo
         $enddo = $props['enddo'];
         $enddoStr = $enddo ? " enddo='{$enddo}'" : '';
         // optional setLen to set length value to a numeric field (see 'len' for where the length comes from)
         $labelSetLen = $props['setlen'];
         $labelSetLenStr = $labelSetLen ? " setlen='{$labelSetLen}'" : '';
         $data = $props['data'];
         if (is_object($data)) {
             // uh-oh. Something wrong
             echo "data is not a string. type is: {$type}. data is: " . var_export($data, true) . "<BR>";
         }
         // get hex/ccsid information to include in the data tag
         $this->processParamProps($props);
         $ccsidHexStr = "{$props['ccsidStr']}{$props['hexStr']}";
         $processedData = $props['processedData'];
         // Google Code issue 11
         // Use short type tag when it's empty
         if ($processedData === '') {
             $dataEndTag = " />";
         } else {
             $dataEndTag = ">{$processedData}</data>";
         }
         // use the old, inefficient "repeat item with sequential numbering of field name" technique if backwards compatibility is desired
         $useOldDimWay = $dim && !$isMulti;
         if ($useOldDimWay) {
             //  Backward compatibility technique
             // a flattened group of data fields with sequentially increasing names
             foreach (range(1, $dim) as $sequence) {
                 // only difference is the $sequence inserted after $innerNameStr
                 // and no $dimStr. Because we're physically repeating the line
                 // And always need the name specified with sequence.
                 $paramXml .= "<data var='{$innerName}{$sequence}' type='{$type}'{$ccsidHexStr}{$enddoStr}{$byStr}{$varyingStr}{$labelSetLenStr}{$dataEndTag}";
             }
         } else {
             // Not dim or perhaps dim and multi
             // Use new, efficient, good way. Only one line needed with $dimStr, which XMLSERVICE will expand for us.
             $innerNameStr = $innerName ? " var='{$innerName}'" : '';
             // only need name if exists. If not then it's probably a "multi" and doesn't need an inner name.
             $paramXml .= "<data{$innerNameStr} type='{$type}'{$ccsidHexStr}{$dimStr}{$enddoStr}{$byStr}{$varyingStr}{$labelSetLenStr}{$dataEndTag}";
         }
     }
     // if a multi-occurrence DS or scalar field, wrap in an identially named "array" DS shell.
     // The "array" indicator will help us parse the results on the way out.
     if ($isMulti) {
         $paramXml = "\n\n<ds var='{$specialOuterDsName}' comment='Multi-occur container' array='on'>\n{$paramXml}\n</ds>";
     } elseif ($dim) {
         // if not multi but regular old-style dim, an ordinary <ds> tag will do to contain all the <data> elements.
         $paramXml = "\n\n<ds comment='old-style repeated data array container'>\n{$paramXml}\n</ds>";
     }
     return $paramXml;
 }
Example #5
0
 /**
  * CW version. $param must be an array of ProgramParameter objects or a single ProgramParameter object.
  *
  * @param int $startPos
  * @param ProgramParameter $param
  * @return bool
  */
 public function WriteUserSpaceCw($startPos = 1, ProgramParameter $param)
 {
     /*
      if (!is_object($param) && !is_array($param)) {
         throw new \Exception('Parameter passed to WriteUserSpaceCw must be an array or ProgramParameter object.');
     }
     */
     // @todo any error, write to toolkit log.
     $labelForSizeOfInputData = 'dssize';
     $param->setParamLabelLen($labelForSizeOfInputData);
     //Size ($comment,  $varName = '', $labelFindLen = null) {
     $params[] = Toolkit::AddParameterChar('in', 20, "User space name and lib", 'usfullname', $this->getUSFullName());
     $params[] = Toolkit::AddParameterInt32('in', "Starting position", 'pos_from', $startPos);
     $params[] = Toolkit::AddParameterSize("Length of data", 'dataLen', $labelForSizeOfInputData);
     $params[] = $param;
     $params[] = Toolkit::AddParameterChar('in', 1, "Force changes to auxiliary storage", 'aux_storage', '0');
     $params[] = Toolkit::AddErrorDataStruct();
     $retPgmArr = $this->ToolkitSrvObj->PgmCall('QUSCHGUS', 'QSYS', $params);
     if ($this->ToolkitSrvObj->getErrorCode()) {
         return false;
     } else {
         return true;
     }
 }
Example #6
0
 /**
  * given a single ->data or ->struct element, return a parameter object in the new toolkit style.
  * 
  * @todo this needs more validation. It is possible that all parts are not set to create return
  * 
  * @param \SimpleXmlElement $dataElement
  * @return ProgramParameter
  */
 public function singlePcmlToParam(\SimpleXmlElement $dataElement)
 {
     $tagName = $dataElement->getName();
     // get attributes of this element.
     $attrs = $dataElement->attributes();
     // both struct and data have name, count (optional), usage
     $name = isset($attrs['name']) ? (string) $attrs['name'] : '';
     $count = isset($attrs['count']) ? (string) $attrs['count'] : '';
     $usage = isset($attrs['usage']) ? (string) $attrs['usage'] : '';
     $structName = isset($attrs['struct']) ? (string) $attrs['struct'] : '';
     // fill this if we have a struct
     $subElements = array();
     // each item should have tag name <data>
     if ($tagName != 'data') {
         return false;
     }
     $type = isset($attrs['type']) ? (string) $attrs['type'] : '';
     // Get initial value, if specified by PCML.
     $dataValue = isset($attrs['init']) ? (string) $attrs['init'] : '';
     // if a struct then we need to recurse.
     if ($type == 'struct') {
         $theStruct = null;
         // init
         // look for matching struct definition encountered earlier.
         if ($this->_pcmlStructs) {
             // @todo verify type with is_array and count
             foreach ($this->_pcmlStructs as $possibleStruct) {
                 $possStructAttrs = $possibleStruct->attributes();
                 if ($possStructAttrs['name'] == $structName) {
                     $theStruct = $possibleStruct;
                     $structAttrs = $possStructAttrs;
                     break;
                 }
             }
         }
         // if struct was not found, generate error for log
         if (!$theStruct) {
             // $this->getConnection->logThis("PCML structure '$structName' not found.");
             return null;
         }
         // count can also be defined at the structure level. If so, it will override count from data level)
         if (isset($structAttrs['count'])) {
             $count = (string) $structAttrs['count'];
         }
         // "usage" (in/out/inherit) can be defined here, at the structure level.
         $structUsage = isset($structAttrs['usage']) ? (string) $structAttrs['usage'] : '';
         // if we're not inheriting from our parent data element, but there is a struct usage, use the struct's usage (input, output, or inputoutput).
         if (!empty($structUsage) && $structUsage != 'inherit') {
             $usage = $structUsage;
         }
         $structSubDataElementsXmlObj = $theStruct->xpath('data');
         if ($structSubDataElementsXmlObj) {
             foreach ($structSubDataElementsXmlObj as $subDataElementXmlObj) {
                 if ($subDataElementXmlObj->attributes()->usage == 'inherit') {
                     // subdata is inheriting type from us. Give it to them.
                     $subDataElementXmlObj->attributes()->usage = $usage;
                 }
                 // here's where the recursion comes in. Convert data and add to array for our struct.
                 $subElements[] = $this->singlePcmlToParam($subDataElementXmlObj);
             }
         }
     }
     /* explanation of the terms "length" and "precision" in PCML:
      * http://publib.boulder.ibm.com/infocenter/iadthelp/v6r0/index.jsp?topic=/com.ibm.etools.iseries.webtools.doc/ref/rdtcattr.htm
      * 
      * For "int" values, length is the number of bytes; precision represents the number of bits. (Can be ignored here)
      * For zoned and packed values, length is the maximum number of digits; precision represents the maximum decimal places.
      * 
      */
     $length = isset($attrs['length']) ? (string) $attrs['length'] : '';
     $precision = isset($attrs['precision']) ? (string) $attrs['precision'] : '';
     $passBy = '';
     // default of blank will become 'ref'/Reference in XMLSERVICE. Blank is fine here.
     if (isset($attrs['passby']) && $attrs['passby'] == 'value') {
         $passBy = 'val';
         // rare. PCML calls it 'value'. XMLSERVICE calls it 'val'.
     }
     // find new toolkit equivalent of PCML data type
     if (isset($this->_pcmlTypeMap[$type])) {
         // a simple type mapping
         $newType = (string) $this->_pcmlTypeMap[$type];
     } elseif ($type == 'int') {
         // one of the integer types. Need to use length to determine which one.
         if ($length == '2') {
             $newType = '5i0';
             // short ints have two bytes
         } elseif ($length == '4') {
             $newType = '10i0';
             // normal ints have four bytes
         } else {
             $newType = '';
             // no match
         }
         //(length == 2, et al.)
     } else {
         $newType = '';
     }
     $newInout = isset($this->_pcmlInoutMap[$usage]) ? (string) $this->_pcmlInoutMap[$usage] : '';
     // @todo correct all this isArray business.
     // Can we manage without isArray?
     // well, it's already handled by toolkit....try and see, though.
     // poss. eliminate extra object levels, at least?
     if ($count > 1) {
         $isArray = true;
     } else {
         // no need for any dummy value.Could be 'init' from above, or leave the default.
         $isArray = false;
     }
     // @todo I think simply add 'counterLabel' and 'countedLabel'.
     // count
     $newCount = 0;
     // initialize
     // @todo deal with this. Really need a better way to find the counter data elements.
     // Allow a countref, too, in PCML??? Maybe! Count will be the dim (max) and countref is the actual name.
     // Some customers have done it wrong. Instead of specifying a field as count, gave max count.
     // "count can be a number where number defines a fixed, never-changing number of elements in a sized array.
     // OR a data-name where data-name defines the name of a <data> element within the PCML document that will contain, at runtime, the number of elements in the array. The data-name specified can be a fully qualified name or a name that is relative to the current element. In either case, the name must reference a <data> element that is defined with type="int". See Resolving Relative Names for more information about how relative names are resolved.
     // about finding the element: http://pic.dhe.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Frzahh%2Flengthprecisionrelative.htm
     // Names are resolved by seeing if the name can be resolved as a child or descendent of the tag containing the current tag. If the name cannot be resolved at this level, the search continues with the next highest containing tag. This resolution must eventually result in a match of a tag that is contained by either the <pcml> tag or the <rfml> tag, in which case the name is considered to be an absolute name, not a relative name.""
     // Let's simply use $countersAndCounted. If necessary, pre-process PCML to create $countersAndCounted.
     if (is_numeric($count) && $count > 0) {
         $newCount = $count;
     }
     // $subElements are if this is a struct.
     if (count($subElements)) {
         $dataValue = $subElements;
     }
     $param = new ProgramParameter(sprintf($newType, $length, $precision), $newInout, '', $name, $dataValue, 'off', $newCount, $passBy, $isArray);
     if ($this->_countersAndCounted) {
         // some counters were configured
         // counter item reference was specified.
         if (isset($this->_countersAndCounted[$name])) {
             $param->setParamLabelCounter($name);
         }
         // counted item reference was specified as value in array.
         // look for value ($name). if found, counter is key.
         if ($counter = array_search($name, $this->_countersAndCounted)) {
             $param->setParamLabelCounted($counter);
         }
     }
     return $param;
 }