#!/usr/bin/php $store) { if (preg_match('/\b' . $key . '\b/', $line)) { if (array_key_exists($key, $loadedTokens)) { throw new ErrorException("TOKEN ALREADY EXISTS! : $key\n"); } $tokenFound = true; $loadedTokens[$key] = []; $currentTokenKey = $key; break; } } if (!$tokenFound && $line != false) { array_push($loadedTokens[$currentTokenKey], $line); } } fclose($fn); return $loadedTokens; } function save($file, $tokens) { echo "saving file " . $file . "\n"; $currentTokens = []; $fn = fopen($file, "r"); while (!feof($fn)) { $line = fgets($fn); foreach ($tokens as $key => $store) { if (preg_match('/\b' . $key . '_END\b/', $line)) { array_pop($currentTokens); break; } } $size = sizeof($currentTokens); if ($size > 0) { array_push($tokens[$currentTokens[$size - 1]], $line); } foreach ($tokens as $key => $store) { if (preg_match('/\b' . $key . '_START\b/', $line)) { array_push($currentTokens, $key); break; } } } fclose($fn); $saveFile =$file . '.saved'; $saved = []; $stores = []; foreach ($tokens as $key => $store) { if (sizeof($store) > 0) { $stores[$key] = $store; array_push($saved, $key . "\n"); foreach ($store as $line) { array_push($saved, $line); } } } file_put_contents($saveFile, $saved); echo "saved file $saveFile\n"; return [ $saveFile, $stores ]; } function deleteSavedFile($saveFile) { if ($saveFile) { unlink($saveFile); } else { echo "saved file was null"; } } function getWhitespace($contents, $token) { $matches = []; if (preg_match('/^\n*(\s*)\b' . $token . '\b/m', $contents, $matches)) { return [ 'white-space' => $matches[1], 'inline-comment' => false ]; } else { if (preg_match('/^\n*(\s*)\/\/\b' . $token . '\b/m', $contents, $matches)) { return [ 'white-space' => $matches[1], 'inline-comment' => true ]; } return null; } } function updateSection($file, $token, $updates, $separator = "") { if (getType($updates) === 'array') { $updates = implode($separator, $updates); } if (strlen($updates) <= 0) { echo "No contents to be updated for token $token\n"; return false; } if (substr($updates, -1) !== "\n") { $updates .= "\n"; } $contents = file_get_contents($file); $whiteSpaceObject = getWhitespace($contents, $token . '_END'); if ($whiteSpaceObject === null) { /** * This file does not contain the token which requires an update - we can return here */ echo "Skipping token $token because it was not found but it could be generated soon...\n"; return $token; } $endToken = $token . "_END"; if ($whiteSpaceObject['inline-comment']) { $endToken = '//' . $endToken; } $whiteSpace = $whiteSpaceObject['white-space']; $contents = preg_replace( '/\b' . $token . '_START\b.*?\b' . $token . '_END\b/s', $token . "_START\n" . $updates . $whiteSpace . $endToken, $contents ); file_put_contents($file, $contents); return true; } function generateInitOptions($file, $tokens) { $token = 'CUSTOM_OPTIONS'; $store = getTokenStore($token, $tokens); if (sizeof($store) <= 0) { return; } echo "Will be building options for $token\n"; $header = file_get_contents('src/templates/generate_custom_options_init_header.template'); $template = file_get_contents('src/templates/generate_custom_options_init.template'); $updates = $header; foreach ($store as $item) { $item = trim($item); $key_value = preg_split('/=/', $item); if ($key_value === false) { continue; } $key = $key_value[0]; $value = $key_value[1]; $updated = str_replace('KEY', $key, $template); $updated = str_replace('VALUE', $value, $updated); $updates .= $updated; } updateSection($file, 'GENERATE_OPTIONS_INIT' , $updates); } function getTokenStore($tokenName, $tokens) { if (array_key_exists($tokenName, $tokens)) { return $tokens[$tokenName]; } return []; } function getInstanceMappings($tokens) { $instanceMappings = []; foreach (getTokenStore('CUSTOM_INSTANCE_OPTIONS_MAPPING', $tokens) as $mapping) { $mapping = trim($mapping); $key_value = preg_split('/=/', $mapping); if ($key_value === false) { continue; } $key = $key_value[0]; $value = $key_value[1]; $instanceMappings[$key] = $value; } return $instanceMappings; } function isExcluded($key, $tokens) { if (array_key_exists('CUSTOM_EXCLUDED_FROM_INSTANCE_OPTIONS', $tokens)) { $excluded = []; foreach ($tokens['CUSTOM_EXCLUDED_FROM_INSTANCE_OPTIONS'] as $exclude) { array_push($excluded, trim($exclude)); } if (in_array($key, $excluded)) { return true; } } return false; } function doInstanceUpdate($template, $tokens, $asArray = false) { $token = 'CUSTOM_OPTIONS'; $store = getTokenStore($token, $tokens); if (sizeof($store) <= 0) { return null; } $instanceMappings = getInstanceMappings($tokens); $updates = ''; if ($asArray) { $updates = []; } foreach ($store as $item) { $item = trim($item); $key_value = preg_split('/=/', $item); if ($key_value === false) { continue; } $key = $key_value[0]; $value = $key_value[0]; if (array_key_exists($key, $instanceMappings)) { $value = $instanceMappings[$key]; } if (isExcluded($key, $tokens)){ continue; } $updated = str_replace('INSTANCE_KEY', $value, $template); $updated = str_replace('KEY', $key, $updated); if ($asArray) { array_push($updates, $updated); } else { $updates .= $updated; } } return $updates; } function generateCreateInstanceOptions($file, $tokens) { $template = file_get_contents('src/templates/generate_create_instance_options.template'); $updates = doInstanceUpdate($template, $tokens, true); if ($updates) { echo "Updating create instance options\n"; updateSection($file, 'GENERATE_CREATE_INSTANCE_OPTIONS', $updates, ",\n"); } else { echo "No create instance options found to generate\n"; } } /** * Process updateInstance options */ function generateUpdateInstanceOptions($file, $tokens) { $template = file_get_contents('src/templates/generate_update_instance_options.template'); $updates = doInstanceUpdate($template, $tokens); if ($updates) { echo "Updating update instance options\n"; updateSection($file, 'GENERATE_UPDATE_INSTANCE_OPTIONS', $updates); } else { echo "No update instance options found to generate\n"; } } /** * Process updateFromInstance options */ function generateUpdateFromInstanceOptions($file, $tokens) { $template = file_get_contents('src/templates/generate_update_from_instance_options.template'); $updates = doInstanceUpdate($template, $tokens); if ($updates) { echo "Updating update from instance options\n"; updateSection($file, 'GENERATE_UPDATE_FROM_INSTANCE_OPTIONS', $updates); } else { echo "No update from instance options found to generate\n"; } } function doMethodUpdate($template, $tokens, $token) { $store = getTokenStore($token, $tokens); if (sizeof($store) <= 0) { return null; } $updates = ''; foreach ($store as $item) { $item = trim($item); $methodName = $item; $matches = []; $result = preg_match('/^(.*?)\(/', $item, $matches); if ($result !== false && sizeof($matches) >= 2) { $methodName = $matches[1]; } $args = ''; $result = preg_match('/\((.*?)\)/', $item, $matches); if ($result !== false && sizeof($matches) >= 2) { $args = $matches[1]; } $params = $args; $argsArray = preg_split('/,(\s*)/', $args); if (sizeof($argsArray) > 1) { $args = implode(",\n\t\t", $argsArray); $args = "\n\t\t" . $args . "\n\t"; $params = implode("\n\t * @param ", $argsArray); $params = "@param " . $params; } $result = preg_match('/.*?\).*?(\w.*$)/', $item, $matches); if ($result !== false && sizeof($matches) >= 2) { $comment = $matches[1]; } if ($result === 0) { $comment = 'No comment'; } $returns = preg_split('/@return[s]*\s*/', $comment); if (sizeof($returns) > 1) { $comment = $returns[0]; $returns = '@returns ' . $returns[1]; } else { $returns = ''; } $methodTokenName = strtoupper(from_camel_case($methodName)); $spaces = ''; $length = strlen($methodName . '() - '); for ($i = 0; $i < $length; $i++) { $spaces = ' ' . $spaces; } $comment = wordwrap($comment, 100, "\n * " . $spaces); $updated = str_replace('METHOD_ARGS', $args, $template); $updated = str_replace('METHOD_NAME_UPPERCASE', $methodTokenName, $updated); $updated = str_replace('METHOD_NAME', $methodName, $updated); $updated = str_replace('COMMENT', $comment, $updated); $updated = str_replace('PARAMS', $params, $updated); $updated = str_replace('RETURNS', $returns, $updated); $updates .= $updated; } return $updates; } function generateStaticMethods($file, $tokens) { $token = 'CUSTOM_STATIC_METHODS'; $template = file_get_contents('src/templates/generate_static_methods.template'); $updates = doMethodUpdate($template, $tokens, $token); if ($updates) { echo "Updating static methods\n"; updateSection($file, 'GENERATE_STATIC_METHODS', $updates); } else { echo "No static methods found to generate\n"; } } function generateMethods($file, $tokens) { $token = 'CUSTOM_METHODS'; $template = file_get_contents('src/templates/generate_methods.template'); $updates = doMethodUpdate($template, $tokens, $token); if ($updates) { echo "Updating methods\n"; updateSection($file, 'GENERATE_METHODS', $updates); } else { echo "No methods found to generate\n"; } } $nodeList = []; /** * @throws ErrorException */ function buildGraph($file) { echo "loading file $file\n"; global $nodeList; $fn = fopen($file, "r"); $line = ''; $found = false; while (!feof($fn) && !$found) { $line = fgets($fn); if (preg_match('/^class\s+/', $line)) { $found = true; break; } } if ($found) { // echo $line . "\n"; $matches = []; $result = preg_match('/^class\s+(.*?)(\s+extends\s+(.*?)\s+|\s+?{)/', $line, $matches); if ($result === false) { throw new ErrorException('Could not match'); } $extends = null; if (sizeof($matches) === 4) { $class = $matches[1]; $extends = $matches[3]; } else if (sizeof($matches) === 3) { $class = $matches[1]; } else { throw new ErrorException('Unhandled case'); } $node = new Node( $file, $class, $extends ); array_push($nodeList, $node); } else { echo "not found\n"; } fclose($fn); } global $files; foreach ($files as $file) { $saveFile = null; if ($argv[2] == 'save') { $saveFile = $file . '.saved'; if (file_exists($saveFile)) { echo "A previous restore operation did not complete - please remove the saved file before trying this again\n"; echo "The save file is located at $saveFile\n"; echo "Remove easily with:\n"; echo "rm $saveFile\n"; exit(1); } $tokens = getTokens('CUSTOM'); $result = save($file, $tokens); exit(0); } else if ($argv[2] == 'restore') { $saveFile = $file . '.saved'; $restoreTokens = getTokens('CUSTOM'); $restoreTokenKeys = array_keys($restoreTokens); $tokens = loadSaved($file, $restoreTokens); $skipped = []; foreach ($tokens as $token => $store) { if (in_array($token, $restoreTokenKeys)) { updateSection($file, $token, $store); } } generateInitOptions($file, $tokens); generateCreateInstanceOptions($file, $tokens); generateUpdateInstanceOptions($file, $tokens); generateUpdateFromInstanceOptions($file, $tokens); generateMethods($file, $tokens); generateStaticMethods($file, $tokens); echo `r3 update-token-db`; /** * Try to restore the rest of the old data because now methods were generated. * If not all data restores now - a method name / token has changed and we need * to notify the user */ foreach ($tokens as $token => $store) { if (in_array($token, $restoreTokenKeys)) { $result = updateSection($file, $token, $store); if ($result !== true && $result !== false) { array_push($skipped, $result); } } } if (sizeof($skipped) !== 0) { echo "Some tokens could not be restored because they could not be found in the new version\n"; print_r($skipped); echo "Please restore them manually from the saved file :$saveFile\n"; echo "If you do not do it now - on the next template update code will be overwritten and you could lose code!!!\n"; exit(1); } else { deleteSavedFile($saveFile); exit(0); } } else if ($argv[2] == 'build-graph') { buildGraph($file); } } if ($argv[2] == 'build-graph') { $graph = new Graph( $nodeList ); } exit(0); ?>