/** * Call a program based on a prepare done before. * @param \ToolkitApi\CW\DataDescription $program Program object created in the preparation stage. * @param array $params Input params with key=>value pairs (possibly nested), * keys matching what was specified in prepare stage. * @param array $retvals Output params (optional) * Fields get created based on names of output parms. * @return boolean True if successful, false if not. */ function i5_program_call(\ToolkitApi\CW\DataDescription $program, $params, $retvals = array()) { // @todo check type of $program and give toolkit-like messages $inputValues = $params; // convert from old to new param format, inserting input values $newInputParams = $program->generateNewToolkitParams($inputValues); if ($program->callProgram($newInputParams)) { if ($retvals && is_array($retvals)) { $pgmOutput = $program->getPgmOutput(); $exportedThem = $program->getConnection()->setOutputVarsToExport($retvals, $pgmOutput); //$exportedThem = exportPgmOutputVars($retvals, $pgmOutput); if (!$exportedThem) { return false; } } noError(); return true; } else { // @todo if particular xml errors, // such as errnoxml = 1000005 or errnoile = 3025 means can't find program, // specify them. // Return "toolkit-style" CPF errno codes/messages // Set the i5error object based on this. $conn = $program->getConnection(); if ($conn->getErrorCode()) { i5CpfError($conn->getErrorCode(), $conn->getErrorMsg()); return false; } return false; } }
/** * Constructor takes a PCML string and converts to an array-based old toolkit data description string. * * @param string $pcml The string of PCML * @param Toolkit $connection connection object for toolkit * @throws \Exception */ public function __construct($pcml, Toolkit $connection) { $this->setConnection($connection); // Convert PCML from ANSI format (which old toolkit required) to UTF-8 (which SimpleXML requires). $encoding = $connection->getConfigValue('system', 'encoding', 'ISO-8859-1'); // XML encoding /* * Look for optionally set <?xml encoding attribute * and change encoding if attribute is set and not UTF-8 * or change encoding if attribute is not set and ini encoding is not UTF-8 */ $pcml = trim($pcml); $matches = array(); $regex = '/^<\\?xml\\s.*?encoding=["\']([^"\']+)["\'].*?\\?>/is'; if (preg_match($regex, $pcml, $matches) && $matches[1] != 'UTF-8') { //remove xml-tag $pcml = substr($pcml, strlen($matches[0])); $pcml = mb_convert_encoding($pcml, 'UTF-8', $matches[1]); } elseif ($encoding != 'UTF-8') { $pcml = mb_convert_encoding($pcml, 'UTF-8', $encoding); } //program name is stored as: /pcml/program name="/qsys.lib/eacdemo.lib/teststruc.pgm" $xmlObj = new \SimpleXMLElement($pcml); // get root node and make sure it's named 'pcml' if (!isset($xmlObj[0]) || $xmlObj[0]->getName() != 'pcml') { throw new \Exception("PCML file must contain pcml tag"); } $pcmlObj = $xmlObj[0]; // get program name, path, etc. if (!isset($pcmlObj->program) || !$pcmlObj->program) { throw new \Exception("PCML file must contain program tag"); } $programNode = $pcmlObj->program; $pgmAttrs = $programNode->attributes(); /** * sample: * <program name="name" * [ entrypoint="entry-point-name" ] * [ epccsid="ccsid" ] * [ path="path-name" ] * [ parseorder="name-list" ] * [ returnvalue="{ void | integer }" ] * [ threadsafe="{ true | false }" ]> * </program> */ // let's focus on name, path, and entrypoint, the only attributes likely to be used here. $path = isset($pgmAttrs['path']) ? $pgmAttrs['path'] : ''; $entrypoint = isset($pgmAttrs['entrypoint']) ? $pgmAttrs['entrypoint'] : ''; // Note: if entrypoint is supplied, it's the function in a service program. "name" will be the same as entrypoint. // if entrypoint is not supplied, name is the actual program name. // Therefore, "name" seems somewhat worthless. // break up path, separated now by slashes. can be varied lib and pgm. // remove the /qsys.lib that may be in front but only if it's simply qualifying another library. qsys may be the actual program library, too. $objArray = $this->splitPcmlProgramPath($path); if ($objArray['lib']) { $pgmName = "{$objArray['lib']}/{$objArray['obj']}"; } else { $pgmName = $objArray['obj']; } // now add the entrypoint, if any, as a procedure/function. if ($entrypoint) { // append the entry point enclosed in parentheses. $pgmName .= "({$entrypoint})"; } // Now create data description array. $dataDescriptionArray = $this->pcmlToArray($xmlObj); //Change the encoding back to the one wanted by the user, since SimpleXML encodes its output always in UTF-8 $pgmName = mb_convert_encoding($pgmName, $encoding, 'UTF-8'); mb_convert_variables($encoding, 'UTF-8', $dataDescriptionArray); // call parent's constructor with: //$descObj = new DataDescriptionPcml($description, $connection); parent::__construct($pgmName, $dataDescriptionArray, $connection); }