Created
April 30, 2012 17:22
-
-
Save roderik/2560255 to your computer and use it in GitHub Desktop.
BillSplitCommand v7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace Kunstmaan\Hosting\BillSplitBundle\Command; | |
| use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; | |
| use Ddeboer\DataImportBundle\Writer\CsvWriter; | |
| use SimpleXMLElement; | |
| use SplFileObject; | |
| use SplFileInfo; | |
| use Symfony\Component\Console\Input\InputArgument; | |
| use Symfony\Component\Console\Input\InputInterface; | |
| use Symfony\Component\Console\Input\InputOption; | |
| use Symfony\Component\Console\Output\OutputInterface; | |
| use Symfony\Component\Yaml\Parser; | |
| class BillSplitCommand extends ContainerAwareCommand | |
| { | |
| /** | |
| * @var Parser $parser | |
| */ | |
| private $parser; | |
| /** | |
| * @var string $nagiosPath | |
| */ | |
| private $nagiosPath; | |
| protected function configure() | |
| { | |
| $this | |
| ->setName('bill:split') | |
| ->setDescription('Split the bill') | |
| ->addArgument('billpath', InputArgument::REQUIRED, 'The path to the bill yml file') | |
| ->addArgument('nagiospath', InputArgument::REQUIRED, 'The path to the nagios.xml file') | |
| ->addArgument('resultpath', InputArgument::REQUIRED, 'The path to the result file'); | |
| } | |
| protected function execute(InputInterface $input, OutputInterface $output) | |
| { | |
| $this->parser = new Parser(); | |
| $this->nagiosPath = $input->getArgument('nagiospath'); | |
| $bill = $this->parseBill($input->getArgument('billpath'), $output); | |
| $ymlServers = $this->parseServers($output); | |
| $ymlProjects = $this->parseProjects($output); | |
| $globalCost = $this->calculateGlobalCosts($bill, $output); | |
| $remoteServers = $this->createServerArray($bill, $ymlServers, $output); | |
| $remoteProjects = $this->createProjectArray($remoteServers, $ymlProjects, $output); | |
| $allProjects = $this->createCompleteProjectArray($ymlServers, $ymlProjects, $output); | |
| $resultArray = array(); | |
| foreach ($ymlServers["servers"] as $hostname => $server) { | |
| if ($server["type"] == 'dedicated') { | |
| $resultArray[$hostname] = array( | |
| "hostname" => $hostname, | |
| "maconomy" => $server["maconomy"], | |
| "cost" => 0.0 | |
| ); | |
| } else { | |
| foreach ($allProjects[$hostname] as $name => $project) { | |
| $resultArray[$name] = array( | |
| "hostname" => $hostname, | |
| "maconomy" => $project["maconomy"], | |
| "cost" => 0.0 | |
| ); | |
| } | |
| } | |
| } | |
| $globalCostPerItem = bcdiv($globalCost,count($resultArray),2); | |
| $output->writeln(" - Assigning <info>all items</info> <question>$globalCostPerItem</question> of global costs because of $globalCost / " . count($resultArray)); | |
| array_walk($resultArray, function(&$item, $key) use ($globalCostPerItem) | |
| { | |
| $item["cost"] = bcadd($item["cost"],$globalCostPerItem,2); | |
| }); | |
| foreach($remoteServers as $hostname => $server){ | |
| if($server["type"] == 'dedicated'){ | |
| $resultArray[$hostname]["cost"] = bcadd($resultArray[$hostname]["cost"] , $server["amount"],2); | |
| $output->writeln(" - Assigning <info>$hostname</info> a cost of <question>" . $server["amount"] . "</question> making a total of " . $resultArray[$hostname]["cost"]); | |
| } else { | |
| $numberOfProjects = count($remoteProjects[$hostname]); | |
| $costPerProject = bcdiv($server["amount"], $numberOfProjects,2); | |
| foreach($remoteProjects[$hostname] as $name => $project){ | |
| $resultArray[$name]["cost"] = bcadd($resultArray[$name]["cost"] , $costPerProject,2); | |
| $output->writeln(" - Assigning <info>$name</info> a cost of <question>" . $costPerProject . "</question> because of " .$server["amount"] ." / ". $numberOfProjects. " making a total of " . $resultArray[$name]["cost"]); | |
| } | |
| } | |
| } | |
| $total = 0.0; | |
| array_walk($resultArray, function(&$item, $key) use (&$total) | |
| { | |
| $total = bcadd($total , $item["cost"],2); | |
| }); | |
| $diff = 0.0; | |
| if ($total != $bill["bill"]["total"]){ | |
| $output->writeln("<error> !!! Bill total = " . $bill["bill"]["total"] . " and our total is " . $total . " !!!</error>"); | |
| $diff = $bill["bill"]["total"] - $total; | |
| } | |
| $file = new SplFileObject($input->getArgument('resultpath'), "w+"); | |
| $writer = new CsvWriter($file); | |
| $writer->writeItem(array( | |
| "Project", | |
| "Maconomy", | |
| "Cost" | |
| )); | |
| foreach ($resultArray AS $name => $row) { | |
| $writer->writeItem(array( | |
| "Project" => $name, | |
| "Maconomy" => $row["maconomy"], | |
| "Cost" => number_format($row["cost"], 2, ',', '') | |
| )); | |
| } | |
| $writer->writeItem(array( | |
| "Total:", | |
| "", | |
| number_format($total, 2, ',', '') | |
| )); | |
| $writer->writeItem(array( | |
| "Diff:", | |
| "", | |
| number_format($diff, 2, ',', '') | |
| )); | |
| } | |
| /** | |
| * Creates an array of all the projects it can find on the shared servers. | |
| * @param array $ymlServers | |
| * @param array $ymlProjects | |
| * @param OutputInterface $output | |
| * @return array an array of all the projects it can find on the shared servers. | |
| */ | |
| private function createCompleteProjectArray(array $ymlServers, array $ymlProjects, OutputInterface $output) | |
| { | |
| $projects = array(); | |
| foreach ($ymlServers["servers"] as $hostname => $server) { | |
| if ($server["type"] == 'shared') { | |
| $server["hostname"] = $hostname; | |
| $projects = array_merge($projects, $this->getNagiosProjects($server, $ymlProjects, $output)); | |
| } | |
| } | |
| return $projects; | |
| } | |
| /** | |
| * Prepares an array of all the projects in this bill with their billing ID's | |
| * | |
| * @param array $remoteServers | |
| * @param array $ymlProjects | |
| * @param OutputInterface $output | |
| * @return array all the projects in this bill with their billing ID's | |
| */ | |
| private function createProjectArray(array $remoteServers, array $ymlProjects, OutputInterface $output) | |
| { | |
| $output->writeln(" - Preparing projects array"); | |
| $remoteProjects = array(); | |
| foreach ($remoteServers as $server) { | |
| if ($server["type"] == 'shared') { | |
| $remoteProjects = array_merge($remoteProjects, $this->getNagiosProjects($server, $ymlProjects, $output)); | |
| } | |
| } | |
| return $remoteProjects; | |
| } | |
| private function getNagiosProjects($server, $ymlProjects, $output) | |
| { | |
| $remoteProjects = array(); | |
| $nagios = $this->parseNagios("http://" . $server["hostname"] . $this->nagiosPath, $output); | |
| foreach ($nagios as $project) { | |
| $remoteProjects[$server["hostname"]][$project] = array( | |
| "hostname" => $server["hostname"], | |
| "name" => $project, | |
| "maconomy" => (isset($ymlProjects["projects"][$project]) ? $ymlProjects["projects"][$project] : "")); | |
| } | |
| return $remoteProjects; | |
| } | |
| /** | |
| * Calculates the sum of all the global costs | |
| * | |
| * @param array $bill | |
| * @param OutputInterface $output | |
| * @return float the sum of all the global costs | |
| */ | |
| private function calculateGlobalCosts(array $bill, OutputInterface $output) | |
| { | |
| $output->writeln(" - Calculation global costs"); | |
| $cost = 0.0; | |
| foreach ($bill["bill"]["items"] as $item) { | |
| if (isset($item["type"]) && $item["type"] == 'global') { | |
| foreach ($item["amount"] as $amount) { | |
| $cost = bcadd($cost,$amount,2); | |
| } | |
| } | |
| } | |
| return $cost; | |
| } | |
| /** | |
| * Prepares an array of all the servers in this bill with amounts and billing ID's | |
| * | |
| * @param array $bill | |
| * @param array $ymlServers | |
| * @param OutputInterface $output | |
| * @return array an array of all the servers in this bill with amounts and billing ID's | |
| */ | |
| private function createServerArray(array $bill, array $ymlServers, OutputInterface $output) | |
| { | |
| $output->writeln(" - Preparing servers array"); | |
| $remoteServers = array(); | |
| foreach ($bill["bill"]["items"] as $item) { | |
| if (isset($item["server"])) { | |
| $cost = 0.0; | |
| foreach ($item["amount"] as $amount) { | |
| $cost = bcadd($cost,$amount,2); | |
| } | |
| $remoteServers[$item["server"]] = array( | |
| "hostname" => $item["server"], | |
| "amount" => $cost, | |
| "type" => $ymlServers["servers"][$item["server"]]["type"], | |
| "maconomy" => (isset($ymlServers["servers"][$item["server"]]["maconomy"]) ? $ymlServers["servers"][$item["server"]]["maconomy"] : "") | |
| ); | |
| } | |
| } | |
| return $remoteServers; | |
| } | |
| /** | |
| * Parses the YAML file containing the bill content into an array. | |
| * | |
| * @param string $billpath | |
| * @param OutputInterface $output | |
| * @return array a multidimensional array with the bill.yml content | |
| */ | |
| private function parseBill($billpath, OutputInterface $output) | |
| { | |
| $output->writeln(" - Locating and parsing the bill input file: " . $billpath); | |
| $bill = $this->parseYML($billpath); | |
| $total = 0.0; | |
| foreach($bill["bill"]["items"] as $key => $item){ | |
| $subtotal = 0.0; | |
| foreach($item["amount"] as $amount){ | |
| $subtotal = bcadd($subtotal, $amount, 2); | |
| } | |
| $output->writeln(" - Found <info>$key</info> with a cost of <question>" . $subtotal . "</question>"); | |
| $total = bcadd($total, $subtotal, 2); | |
| } | |
| if ($bill["bill"]["total"] == $total){ | |
| $output->writeln("<info> !!! Bill total = " . $bill["bill"]["total"] . " and our total is " . $total . " !!!</info>"); | |
| } else { | |
| $output->writeln("<error> !!! Bill total = " . $bill["bill"]["total"] . " and our total is " . $total . " !!!</error>"); | |
| } | |
| return $bill; | |
| } | |
| /** | |
| * Parses the YAML file containing the servers into an array. | |
| * | |
| * @param OutputInterface $output | |
| * @return array a multidimensional array with the servers.yml content | |
| */ | |
| private function parseServers(OutputInterface $output) | |
| { | |
| $output->writeln(" - Locating and parsing the servers input file: servers.yml"); | |
| return $this->parseYML("maconomy/servers.yml"); | |
| } | |
| /** | |
| * Parses the YAML file containing the projects into an array. | |
| * | |
| * @param OutputInterface $output | |
| * @return array a multidimensional array with the projects.yml content | |
| */ | |
| private function parseProjects(OutputInterface $output) | |
| { | |
| $output->writeln(" - Locating and parsing the projects input file: projects.yml"); | |
| return $this->parseYML("maconomy/projects.yml"); | |
| } | |
| /** | |
| * Parses a YAML file to an array | |
| * | |
| * @param string $path | |
| * @return array a multidimensional array with the yml content | |
| */ | |
| private function parseYML($path) | |
| { | |
| $content = file_get_contents($path); | |
| return $this->parser->parse($content); | |
| } | |
| /** | |
| * Parses the XML file containing the projects on a server into an array. | |
| * | |
| * @param string $nagiospath | |
| * @param OutputInterface $output | |
| * @return array a multidimensional array with the nagios.xml content | |
| */ | |
| private function parseNagios($nagiospath, OutputInterface $output) | |
| { | |
| $output->writeln(" - Locating and parsing the nagios input file: " . $nagiospath); | |
| $content = file_get_contents($nagiospath); | |
| $result = array(); | |
| $xml = new SimpleXMLElement($content); | |
| foreach ($xml->children() as $project) { | |
| if ($project->monitor != "false") { | |
| $result[(string)$project->name] = (string)$project->name; | |
| } | |
| } | |
| return $result; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment