├── .gitignore ├── src └── BeerXML │ ├── Exception │ ├── InvalidRecord.php │ └── BadData.php │ ├── Generator │ ├── IWaterDisplay.php │ ├── IMiscDisplay.php │ ├── IHopDisplay.php │ ├── IMashProfileDisplay.php │ ├── IFermentableDisplay.php │ ├── IMashProfile.php │ ├── Water.php │ ├── IYeastDisplay.php │ ├── Hop.php │ ├── Misc.php │ ├── MashProfile.php │ ├── MashStep.php │ ├── IMashStepDisplay.php │ ├── IWater.php │ ├── Fermentable.php │ ├── IMisc.php │ ├── IEquipmentDisplay.php │ ├── IMashStep.php │ ├── Equipment.php │ ├── IStyleDisplay.php │ ├── Style.php │ ├── IStyle.php │ ├── Yeast.php │ ├── IHop.php │ ├── IYeast.php │ ├── IEquipment.php │ ├── IRecipeDisplay.php │ ├── IFermentable.php │ ├── Record.php │ ├── Recipe.php │ └── IRecipe.php │ ├── Parser │ ├── IWaterDisplay.php │ ├── IMiscDisplay.php │ ├── IHopDisplay.php │ ├── IMashProfileDisplay.php │ ├── IFermentableDisplay.php │ ├── Water.php │ ├── IMashProfile.php │ ├── IYeastDisplay.php │ ├── MashStep.php │ ├── Misc.php │ ├── Hop.php │ ├── MashProfile.php │ ├── IWater.php │ ├── IMashStepDisplay.php │ ├── IMisc.php │ ├── RecordFactory.php │ ├── IMashStep.php │ ├── Fermentable.php │ ├── IEquipmentDisplay.php │ ├── Yeast.php │ ├── IStyleDisplay.php │ ├── Equipment.php │ ├── Style.php │ ├── IStyle.php │ ├── IHop.php │ ├── IYeast.php │ ├── Recipe.php │ ├── IEquipment.php │ ├── IRecipeDisplay.php │ ├── IFermentable.php │ └── IRecipe.php │ ├── Parser.php │ ├── Generator.php │ └── Record │ └── Water.php ├── CHANGELOG.md ├── .travis.yml ├── tests ├── fixtures │ ├── hop-example.xml │ ├── yeast-culture-date.xml │ ├── recipe-simplest.xml │ ├── hop-with-self-closing-tag.xml │ ├── recipe-record.xml │ ├── generated-recipe.xml │ └── generated-recipe-with-display.xml ├── Parser │ ├── RecordTest.php │ ├── RecipeTest.php │ ├── HopTest.php │ └── YeastTest.php ├── Generator │ ├── EquipmentTest.php │ ├── MiscTest.php │ └── MashProfileTest.php ├── Record │ └── RecipeTest.php └── ParserTest.php ├── composer.json ├── phpunit.xml.dist └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | bin/ 3 | build/ 4 | phpunit.xml 5 | vendor/ 6 | composer.phar -------------------------------------------------------------------------------- /src/BeerXML/Exception/InvalidRecord.php: -------------------------------------------------------------------------------- 1 | 2 | 0.050 3 | 1 4 | Mash 5 | 4.5 6 | Shortened for unit tests 7 | 8 | 5.5 9 | Super Hops 10 | Planet Krypton 11 | Goldings, Fuggles, Super Alpha 12 | 24.4 13 | 30 14 |
Leaf
15 | Bittering 16 | 13.2 17 | 14 18 | 4.1 19 | 20 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/IMiscDisplay.php: -------------------------------------------------------------------------------- 1 | =5.3.0", 19 | "ext-xmlreader": "*" 20 | }, 21 | "require-dev": { 22 | "phpunit/phpunit": "3.7.*", 23 | "satooshi/php-coveralls": "dev-master" 24 | }, 25 | "autoload": { 26 | "psr-0": { 27 | "BeerXML": "src/" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/IMashProfileDisplay.php: -------------------------------------------------------------------------------- 1 | 2 | Nottingham Yeast 3 | 1 4 | Ale 5 |
Dry
6 | 0.0236590 7 | FALSE 8 | Lallemand 9 | - 10 | 16.6666667 11 | 22.2222222 12 | Very High 13 | 75.0000000 14 | High flocculation - settles quickly. Very good reputation as a fast starter and quick fermenter. Clean and only slightly fruity. Some nutty flavor in bottled version. Relatively high attenuation. 15 | Ales 16 | 5 17 | 0 18 | FALSE 19 | 23.66 ml 20 | 16.7 C 21 | 22.2 C 22 | 0.0 pkg 23 | 13/06/2003 24 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/IFermentableDisplay.php: -------------------------------------------------------------------------------- 1 | setRecordFactory(new RecordFactory()); 26 | $parser->setXmlString('foo'); 27 | $parser->parse(); 28 | } 29 | 30 | /** 31 | * @expectedException \BeerXML\Exception\BadData 32 | */ 33 | public function testThrowsExceptionOnTruncatedRecordSet() 34 | { 35 | $parser = new Recipe(); 36 | $parser->setRecordFactory(new RecordFactory()); 37 | $parser->setXmlString('foo'); 38 | $parser->parse(); 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/IMashProfile.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dry Stout 5 | 1 6 | Extract 7 | Brad Smith 8 | 18.93 9 | 20.82 10 | 60.0 11 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/Water.php: -------------------------------------------------------------------------------- 1 | => getterMethod 18 | * 19 | * @var array 20 | */ 21 | protected $simpleValues = array( 22 | 'NAME' => 'getName', 23 | 'VERSION' => 'getVersion', 24 | 'AMOUNT' => 'getAmount', 25 | 'CALCIUM' => 'getCalcium', 26 | 'BICARBONATE' => 'getBicarbonate', 27 | 'SULFATE' => 'getSulfate', 28 | 'CHLORIDE' => 'getChloride', 29 | 'SODIUM' => 'getSodium', 30 | 'MAGNESIUM' => 'getMagnesium', 31 | ); 32 | 33 | /** 34 | * => getterMethod 35 | * 36 | * @var array 37 | */ 38 | protected $optionalSimpleValues = array( 39 | 'PH' => 'getPH', 40 | 'NOTES' => 'getNotes', 41 | ); 42 | 43 | protected $displayInterface = 'BeerXML\Generator\IWaterDisplay'; 44 | 45 | protected $displayValues = array( 46 | 'DISPLAY_AMOUNT' => 'getDisplayAmount', 47 | ); 48 | 49 | } -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | tests 27 | 28 | 29 | 30 | 31 | 32 | src/ 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/BeerXML/Parser/IFermentableDisplay.php: -------------------------------------------------------------------------------- 1 | 'setName', 18 | 'VERSION' => 'setVersion', 19 | 'AMOUNT' => 'setAmount', 20 | 'CALCIUM' => 'setCalcium', 21 | 'BICARBONATE' => 'setBicarbonate', 22 | 'SULFATE' => 'setSulfate', 23 | 'CHLORIDE' => 'setChloride', 24 | 'SODIUM' => 'setSodium', 25 | 'MAGNESIUM' => 'setMagnesium', 26 | 'PH' => 'setPH', 27 | 'NOTES' => 'setNotes', 28 | ); 29 | 30 | /** 31 | * @return IWater 32 | */ 33 | protected function createRecord() 34 | { 35 | $water = $this->recordFactory->getWater(); 36 | if ($water instanceof IWaterDisplay) { 37 | $this->simpleProperties = array_merge( 38 | $this->simpleProperties, 39 | array( 40 | 'DISPLAY_AMOUNT' => 'setDisplayAmount', 41 | ) 42 | ); 43 | } 44 | return $water; 45 | } 46 | } -------------------------------------------------------------------------------- /src/BeerXML/Parser/IMashProfile.php: -------------------------------------------------------------------------------- 1 | generator = new Equipment(); 29 | $this->xml = new \XMLWriter(); 30 | $this->xml->openMemory(); 31 | $this->generator->setXmlWriter($this->xml); 32 | $this->record = new \BeerXML\Record\Equipment(); 33 | $this->generator->setRecord($this->record); 34 | parent::setUp(); 35 | } 36 | 37 | public function testConvertsBooleanToString() 38 | { 39 | $this->record->setCalcBoilVolume(true); 40 | $this->generator->build(); 41 | $xml = $this->xml->outputMemory(true); 42 | $this->assertTag(array('tag' => 'CALC_BOIL_VOLUME', 'content' => 'TRUE'), $xml, '', false); 43 | 44 | $this->record->setCalcBoilVolume(false); 45 | $this->generator->build(); 46 | $xml = $this->xml->outputMemory(true); 47 | $this->assertTag(array('tag' => 'CALC_BOIL_VOLUME', 'content' => 'FALSE'), $xml, '', false); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/Generator/MiscTest.php: -------------------------------------------------------------------------------- 1 | gen = new Misc(); 29 | $this->record = new \BeerXML\Record\Misc(); 30 | $this->gen->setRecord($this->record); 31 | $this->xmlWriter = new \XMLWriter(); 32 | $this->xmlWriter->openMemory(); 33 | $this->gen->setXmlWriter($this->xmlWriter); 34 | } 35 | 36 | public function testBooleanFieldRendersCorrectly() 37 | { 38 | $this->record->setAmountIsWeight(true); 39 | $this->gen->build(); 40 | $xml = $this->xmlWriter->outputMemory(true); 41 | $this->assertTag(array('tag' => 'AMOUNT_IS_WEIGHT', 'content' => 'TRUE'), $xml, '', false); 42 | } 43 | 44 | public function testAmountIsWeightIsOmmittedIfFalse() 45 | { 46 | $this->record->setAmountIsWeight(false); 47 | $this->gen->build(); 48 | $xml = $this->xmlWriter->outputMemory(true); 49 | $this->assertNotTag(array('tag' => 'AMOUNT_IS_WEIGHT'), $xml, '', false); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/Hop.php: -------------------------------------------------------------------------------- 1 | => getterMethod 18 | * 19 | * @var array 20 | */ 21 | protected $simpleValues = array( 22 | 'NAME' => 'getName', 23 | 'VERSION' => 'getVersion', 24 | 'ALPHA' => 'getAlpha', 25 | 'AMOUNT' => 'getAmount', 26 | 'USE' => 'getUse', 27 | 'TIME' => 'getTime', 28 | ); 29 | 30 | protected $optionalSimpleValues = array( 31 | 'NOTES' => 'getNotes', 32 | 'TYPE' => 'getType', 33 | 'FORM' => 'getForm', 34 | 'BETA' => 'getBeta', 35 | 'HSI' => 'getHsi', 36 | 'ORIGIN' => 'getOrigin', 37 | 'SUBSTITUTES' => 'getSubstitutes', 38 | 'HUMULENE' => 'getHumulene', 39 | 'CARYOPHYLLENE' => 'getCaryophyllene', 40 | 'COHUMULONE' => 'getCohumulone', 41 | 'MYRCENE' => 'getMyrcene', 42 | ); 43 | 44 | protected $displayInterface = 'BeerXML\Generator\IHopDisplay'; 45 | 46 | protected $displayValues = array( 47 | 'DISPLAY_AMOUNT' => 'getDisplayAmount', 48 | 'INVENTORY' => 'getInventory', 49 | 'DISPLAY_TIME' => 'getDisplayTime', 50 | ); 51 | } -------------------------------------------------------------------------------- /src/BeerXML/Parser/IYeastDisplay.php: -------------------------------------------------------------------------------- 1 | => getterMethod 18 | * 19 | * @var array 20 | */ 21 | protected $simpleValues = array( 22 | 'NAME' => 'getName', 23 | 'VERSION' => 'getVersion', 24 | 'TYPE' => 'getType', 25 | 'USE' => 'getUse', 26 | 'TIME' => 'getTime', 27 | 'AMOUNT' => 'getAmount', 28 | 29 | ); 30 | 31 | /** 32 | * => getterMethod 33 | * 34 | * @var array 35 | */ 36 | protected $optionalSimpleValues = array( 37 | 'USE_FOR' => 'getUseFor', 38 | 'NOTES' => 'getNotes', 39 | ); 40 | 41 | protected $displayInterface = 'BeerXML\Generator\IMiscDisplay'; 42 | 43 | protected $displayValues = array( 44 | 'DISPLAY_AMOUNT' => 'getDisplayAmount', 45 | 'INVENTORY' => 'getInventory', 46 | 'DISPLAY_TIME' => 'getDisplayTime', 47 | ); 48 | 49 | /** 50 | * @{inheritDoc} 51 | */ 52 | protected function additionalFields() 53 | { 54 | if ($amountIsWeight = $this->record->getAmountIsWeight()) { 55 | $this->xmlWriter->writeElement('AMOUNT_IS_WEIGHT', $this->boolToString($amountIsWeight)); 56 | } 57 | 58 | parent::additionalFields(); 59 | } 60 | 61 | 62 | } -------------------------------------------------------------------------------- /src/BeerXML/Parser/MashStep.php: -------------------------------------------------------------------------------- 1 | 'setName', 18 | 'VERSION' => 'setVersion', 19 | 'TYPE' => 'setType', 20 | 'INFUSE_AMOUNT' => 'setInfuseAmount', 21 | 'STEP_TEMP' => 'setStepTemp', 22 | 'STEP_TIME' => 'setStepTime', 23 | 'RAMP_TIME' => 'setRampTime', 24 | 'END_TEMP' => 'setEndTemp', 25 | ); 26 | 27 | /** 28 | * @return IMashStep 29 | */ 30 | protected function createRecord() 31 | { 32 | $mashStep = $this->recordFactory->getMashStep(); 33 | if ($mashStep instanceof IMashStepDisplay) { 34 | $this->simpleProperties = array_merge( 35 | $this->simpleProperties, 36 | array( 37 | 'DESCRIPTION' => 'setDescription', 38 | 'WATER_GRAIN_RATIO' => 'setWaterGrainRatio', 39 | 'DECOCTION_AMT' => 'setDecoctionAmt', 40 | 'INFUSE_TEMP' => 'setInfuseTemp', 41 | 'DISPLAY_STEP_TEMP' => 'setDisplayStepTemp', 42 | 'DISPLAY_INFUSE_AMT' => 'setDisplayInfuseAmt', 43 | ) 44 | ); 45 | } 46 | return $mashStep; 47 | } 48 | } -------------------------------------------------------------------------------- /src/BeerXML/Parser/Misc.php: -------------------------------------------------------------------------------- 1 | 'setName', 18 | 'VERSION' => 'setVersion', 19 | 'TYPE' => 'setType', 20 | 'USE' => 'setUse', 21 | 'TIME' => 'setTime', 22 | 'AMOUNT' => 'setAmount', 23 | 'USE_FOR' => 'setUseFor', 24 | 'NOTES' => 'setNotes', 25 | ); 26 | 27 | /** 28 | * @return IMisc 29 | */ 30 | protected function createRecord() 31 | { 32 | $misc = $this->recordFactory->getMisc(); 33 | if ($misc instanceof IMiscDisplay) { 34 | $this->simpleProperties = array_merge( 35 | $this->simpleProperties, 36 | array( 37 | 'DISPLAY_AMOUNT' => 'setDisplayAmount', 38 | 'INVENTORY' => 'setInventory', 39 | 'DISPLAY_TIME' => 'setDisplayTime', 40 | ) 41 | ); 42 | } 43 | return $misc; 44 | } 45 | 46 | /** 47 | * @param IMisc $record 48 | */ 49 | protected function otherElementEncountered($record) 50 | { 51 | if ('AMOUNT_IS_WEIGHT' == $this->xmlReader->name) { 52 | $value = ($this->xmlReader->readString() == 'TRUE'); 53 | $record->setAmountIsWeight($value); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/Parser/RecipeTest.php: -------------------------------------------------------------------------------- 1 | parser->setXmlString('TRUE'); 26 | $recipe = $this->parser->parse(); 27 | /** @var $recipe \BeerXML\Record\Recipe */ 28 | $this->assertTrue($recipe->getForcedCarbonation()); 29 | } 30 | 31 | protected function setUp() 32 | { 33 | $this->parser = new Recipe(); 34 | $this->parser->setRecordFactory(new RecordFactory()); 35 | } 36 | 37 | public function testReturnsRecipe() 38 | { 39 | $this->parser->setXmlString(file_get_contents(dirname(dirname(__FILE__)) . '/fixtures/recipe-record.xml')); 40 | $recipe = $this->parser->parse(); 41 | $this->assertInstanceOf('BeerXML\Record\Recipe', $recipe); 42 | } 43 | 44 | public function testDateIsParsedIntoDateTime() 45 | { 46 | $this->parser->setXmlString(file_get_contents(__DIR__ . '/../fixtures/recipe-record.xml')); 47 | $recipe = $this->parser->parse(); 48 | /** @var $recipe \BeerXML\Record\Recipe */ 49 | $date = $recipe->getDate(); 50 | $this->assertInstanceOf('\DateTime', $date); 51 | $this->assertEquals(new \DateTime('2004-01-03'), $date); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/MashProfile.php: -------------------------------------------------------------------------------- 1 | => getterMethod 18 | * 19 | * @var array 20 | */ 21 | protected $simpleValues = array( 22 | 'NAME' => 'getName', 23 | 'VERSION' => 'getVersion', 24 | 'GRAIN_TEMP' => 'getGrainTemp', 25 | ); 26 | 27 | protected $optionalSimpleValues = array( 28 | 'NOTES' => 'getNotes', 29 | 'TUN_TEMP' => 'getTunTemp', 30 | 'SPARGE_TEMP' => 'getSpargeTemp', 31 | 'PH' => 'getPH', 32 | 'TUN_WEIGHT' => 'getTunWeight', 33 | 'TUN_SPECIFIC_HEAT' => 'getTunSpecificHeat', 34 | ); 35 | 36 | protected $complexValueSets = array( 37 | 'MASH_STEPS' => array('generator' => 'BeerXML\Generator\MashStep', 'values' => 'getMashSteps'), 38 | ); 39 | 40 | protected $displayInterface = 'BeerXML\Generator\IMashProfileDisplay'; 41 | 42 | protected $displayValues = array( 43 | 'DISPLAY_GRAIN_TEMP' => 'getDisplayGrainTemp', 44 | 'DISPLAY_TUN_TEMP' => 'getDisplayTunTemp', 45 | 'DISPLAY_SPARGE_TEMP' => 'getDisplaySpargeTemp', 46 | 'DISPLAY_TUN_WEIGHT' => 'getDisplayTunWeight', 47 | ); 48 | 49 | /** 50 | * @{inheritDoc} 51 | */ 52 | protected function additionalFields() 53 | { 54 | $this->xmlWriter->writeElement('EQUIP_ADJUST', $this->boolToString($this->record->getEquipAdjust())); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/BeerXML/Parser/Hop.php: -------------------------------------------------------------------------------- 1 | 'setName', 18 | 'VERSION' => 'setVersion', 19 | 'ALPHA' => 'setAlpha', 20 | 'AMOUNT' => 'setAmount', 21 | 'USE' => 'setUse', 22 | 'TIME' => 'setTime', 23 | 'NOTES' => 'setNotes', 24 | 'TYPE' => 'setType', 25 | 'FORM' => 'setForm', 26 | 'BETA' => 'setBeta', 27 | 'HSI' => 'setHsi', 28 | 'ORIGIN' => 'setOrigin', 29 | 'SUBSTITUTES' => 'setSubstitutes', 30 | 'HUMULENE' => 'setHumulene', 31 | 'CARYOPHYLLENE' => 'setCaryophyllene', 32 | 'COHUMULONE' => 'setCohumulone', 33 | 'MYRCENE' => 'setMyrcene', 34 | ); 35 | 36 | /** 37 | * @return IHop 38 | */ 39 | protected function createRecord() 40 | { 41 | $hop = $this->recordFactory->getHop(); 42 | if ($hop instanceof IHopDisplay) { 43 | $this->simpleProperties = array_merge( 44 | $this->simpleProperties, 45 | array( 46 | 'DISPLAY_AMOUNT' => 'setDisplayAmount', 47 | 'INVENTORY' => 'setInventory', 48 | 'DISPLAY_TIME' => 'setDisplayTime', 49 | ) 50 | ); 51 | } 52 | return $hop; 53 | } 54 | } -------------------------------------------------------------------------------- /src/BeerXML/Generator/MashStep.php: -------------------------------------------------------------------------------- 1 | => getterMethod 18 | * 19 | * @var array 20 | */ 21 | protected $simpleValues = array( 22 | 'NAME' => 'getName', 23 | 'VERSION' => 'getVersion', 24 | 'TYPE' => 'getType', 25 | 'INFUSE_AMOUNT' => 'getInfuseAmount', 26 | 'STEP_TEMP' => 'getStepTemp', 27 | 'STEP_TIME' => 'getStepTime', 28 | ); 29 | 30 | /** 31 | * => getterMethod 32 | * 33 | * @var array 34 | */ 35 | protected $optionalSimpleValues = array( 36 | 'RAMP_TIME' => 'getRampTime', 37 | 'END_TEMP' => 'getEndTemp', 38 | ); 39 | 40 | protected $displayInterface = 'BeerXML\Generator\IMashStepDisplay'; 41 | 42 | protected $displayValues = array( 43 | 'DESCRIPTION' => 'getDescription', 44 | 'WATER_GRAIN_RATIO' => 'getWaterGrainRatio', 45 | 'DECOCTION_AMT' => 'getDecoctionAmt', 46 | 'INFUSE_TEMP' => 'getInfuseTemp', 47 | 'DISPLAY_STEP_TEMP' => 'getDisplayStepTemp', 48 | 'DISPLAY_INFUSE_AMT' => 'getDisplayInfuseAmt', 49 | ); 50 | 51 | /** 52 | * @{inheritDoc} 53 | */ 54 | protected function additionalFields() 55 | { 56 | if (\BeerXML\Record\MashStep::TYPE_DECOCTION != $this->record->getType()) { 57 | $this->xmlWriter->writeElement('INFUSE_AMOUNT', $this->record->getInfuseAmount()); 58 | } 59 | 60 | return parent::additionalFields(); 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /tests/fixtures/hop-with-self-closing-tag.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dry Stout 5 | 1 6 | Extract 7 | Brad Smith 8 | 18.93 9 | 20.82 10 | 60.0 11 | 12 | 13 | 30 | 31 | 32 | Columbus 33 | United States 34 | 16.0 35 | 36 | 0.0680388555 37 | 0.0680388555 kg 38 | Boil 39 |
Pellet
40 | 41 | 60.0 min 42 | Pleasant, with pungent aroma. 43 |
44 |
45 | 46 | 47 | 48 | 49 |
50 |
51 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/IMashStepDisplay.php: -------------------------------------------------------------------------------- 1 | profile. For example "1.5 qt/lb" or "3.0 l/kg" 54 | * @return string 55 | */ 56 | public function getWaterGrainRatio(); 57 | } -------------------------------------------------------------------------------- /src/BeerXML/Generator/IWater.php: -------------------------------------------------------------------------------- 1 | => getterMethod 19 | * 20 | * @var array 21 | */ 22 | protected $simpleValues = array( 23 | 'NAME' => 'getName', 24 | 'VERSION' => 'getVersion', 25 | 'TYPE' => 'getType', 26 | 'AMOUNT' => 'getAmount', 27 | 'YIELD' => 'getYield', 28 | 'COLOR' => 'getColor', 29 | ); 30 | 31 | protected $optionalSimpleValues = array( 32 | 'ORIGIN' => 'getOrigin', 33 | 'SUPPLIER' => 'getSupplier', 34 | 'NOTES' => 'getNotes', 35 | 'COARSE_FINE_DIFF' => 'getCoarseFineDiff', 36 | 'MOISTURE' => 'getMoisture', 37 | 'DIASTATIC_POWER' => 'getDiastaticPower', 38 | 'PROTEIN' => 'getProtein', 39 | 'MAX_IN_BATCH' => 'getMaxInBatch', 40 | 'IBU_GAL_PER_LB' => 'getIbuGalPerLb', 41 | ); 42 | 43 | protected $displayInterface = 'BeerXML\Generator\IFermentableDisplay'; 44 | 45 | protected $displayValues = array( 46 | 'DISPLAY_AMOUNT' => 'getDisplayAmount', 47 | 'POTENTIAL' => 'getPotential', 48 | 'INVENTORY' => 'getInventory', 49 | 'DISPLAY_COLOR' => 'getDisplayColor', 50 | ); 51 | 52 | /** 53 | * @{inheritDoc} 54 | */ 55 | protected function additionalFields() 56 | { 57 | $this->xmlWriter->writeElement('ADD_AFTER_BOIL', $this->boolToString($this->record->getAddAfterBoil())); 58 | $this->xmlWriter->writeElement('MAX_IN_BATCH', $this->boolToString($this->record->getRecommendMash())); 59 | 60 | return parent::additionalFields(); 61 | } 62 | } -------------------------------------------------------------------------------- /src/BeerXML/Parser/MashProfile.php: -------------------------------------------------------------------------------- 1 | 'setName', 17 | 'VERSION' => 'setVersion', 18 | 'GRAIN_TEMP' => 'setGrainTemp', 19 | 'NOTES' => 'setNotes', 20 | 'TUN_TEMP' => 'setTunTemp', 21 | 'SPARGE_TEMP' => 'setSpargeTemp', 22 | 'PH' => 'setPH', 23 | 'TUN_WEIGHT' => 'setTunWeight', 24 | 'TUN_SPECIFIC_HEAT' => 'setTunSpecificHeat', 25 | ); 26 | 27 | /** 28 | * @return IMashProfile 29 | */ 30 | protected function createRecord() 31 | { 32 | $mashProfile = $this->recordFactory->getMashProfile(); 33 | if ($mashProfile instanceof IMashProfileDisplay) { 34 | $this->simpleProperties = array_merge( 35 | $this->simpleProperties, 36 | array( 37 | 'DISPLAY_GRAIN_TEMP' => 'setDisplayGrainTemp', 38 | 'DISPLAY_TUN_TEMP' => 'setDisplayTunTemp', 39 | 'DISPLAY_SPARGE_TEMP' => 'setDisplaySpargeTemp', 40 | 'DISPLAY_TUN_WEIGHT' => 'setDisplayTunWeight', 41 | ) 42 | ); 43 | } 44 | return $mashProfile; 45 | } 46 | 47 | /** 48 | * @param IMashProfile $record 49 | */ 50 | protected function otherElementEncountered($record) 51 | { 52 | if ('EQUIP_ADJUST' == $this->xmlReader->name) { 53 | $value = ($this->xmlReader->readString() == 'TRUE'); 54 | $record->setEquipAdjust($value); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tests/Parser/HopTest.php: -------------------------------------------------------------------------------- 1 | parser = new Hop(); 25 | $this->parser->setRecordFactory(new RecordFactory()); 26 | } 27 | 28 | public function testHopFieldsAreParsed() 29 | { 30 | $this->parser->setXmlString(file_get_contents(dirname(dirname(__FILE__)) . '/fixtures/hop-example.xml')); 31 | $hop = $this->parser->parse(); 32 | /** @var $hop \BeerXML\Record\Hop */ 33 | $this->assertEquals(0.050, $hop->getAmount()); 34 | $this->assertEquals(1, $hop->getVersion()); 35 | $this->assertEquals(\BeerXML\Record\Hop::USE_MASH, $hop->getUse()); 36 | $this->assertEquals(4.5, $hop->getAlpha()); 37 | $this->assertEquals('Shortened for unit tests', $hop->getNotes()); 38 | $this->assertEquals(45, $hop->getTime()); 39 | $this->assertEquals(5.5, $hop->getBeta()); 40 | $this->assertEquals('Super Hops', $hop->getName()); 41 | $this->assertEquals('Planet Krypton', $hop->getOrigin()); 42 | $this->assertEquals('Goldings, Fuggles, Super Alpha', $hop->getSubstitutes()); 43 | $this->assertEquals(24.4, $hop->getMyrcene()); 44 | $this->assertEquals(30, $hop->getHsi()); 45 | $this->assertEquals(\BeerXML\Record\Hop::FORM_LEAF, $hop->getForm()); 46 | $this->assertEquals(\BeerXML\Record\Hop::TYPE_BITTERING, $hop->getType()); 47 | $this->assertEquals(13.2, $hop->getCohumulone()); 48 | $this->assertEquals(14, $hop->getHumulene()); 49 | $this->assertEquals(4.1, $hop->getCaryophyllene()); 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/IMisc.php: -------------------------------------------------------------------------------- 1 | setName('Infusion'); 30 | $infusion->setType(MashStep::TYPE_INFUSION); 31 | $infusion->setStepTemp(68); 32 | $infusion->setStepTime(60); 33 | $infusion->setInfuseAmount(14); 34 | $this->record->addMashStep($infusion); 35 | 36 | $mashOut = new MashStep(); 37 | $mashOut->setName('Mash Out'); 38 | $infusion->setType(MashStep::TYPE_INFUSION); 39 | $infusion->setStepTemp(100); 40 | $infusion->setStepTime(10); 41 | $infusion->setInfuseAmount(4); 42 | $this->record->addMashStep($mashOut); 43 | 44 | $this->generator->build(); 45 | $xml = $this->xml->outputMemory(true); 46 | 47 | $this->assertTag(array( 48 | 'tag' => 'MASH_STEPS', 49 | 'children' => array( 50 | 'count' => 2, 51 | 'only' => array('tag' => 'MASH_STEP'), 52 | ), 53 | ), $xml, '', false); 54 | } 55 | 56 | protected function setUp() 57 | { 58 | $this->generator = new MashProfile(); 59 | $this->xml = new \XMLWriter(); 60 | $this->xml->openMemory(); 61 | $this->generator->setXmlWriter($this->xml); 62 | $this->record = new \BeerXML\Record\MashProfile(); 63 | $this->generator->setRecord($this->record); 64 | parent::setUp(); 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/BeerXML/Parser/IWater.php: -------------------------------------------------------------------------------- 1 | profile. For example "1.5 qt/lb" or "3.0 l/kg" 54 | * 55 | * @param string $waterGrainRatio 56 | */ 57 | public function setWaterGrainRatio($waterGrainRatio); 58 | } -------------------------------------------------------------------------------- /src/BeerXML/Parser/IMisc.php: -------------------------------------------------------------------------------- 1 | => getterMethod 18 | * 19 | * @var array 20 | */ 21 | protected $simpleValues = array( 22 | 'NAME' => 'getName', 23 | 'VERSION' => 'getVersion', 24 | 'BATCH_SIZE' => 'getBatchSize', 25 | 'BOIL_SIZE' => 'getBoilSize', 26 | ); 27 | 28 | protected $optionalSimpleValues = array( 29 | 'BOIL_TIME' => 'getBoilTime', 30 | 'TUN_VOLUME' => 'getTunVolume', 31 | 'TUN_VOLUME' => 'getTunVolume', 32 | 'TUN_WEIGHT' => 'getTunWeight', 33 | 'TUN_SPECIFIC_HEAT' => 'getTunSpecificHeat', 34 | 'TOP_UP_WATER' => 'getTopUpWater', 35 | 'TRUB_CHILLER_LOSS' => 'getTrubChillerLoss', 36 | 'EVAP_RATE' => 'getEvapRate', 37 | 'LAUTER_DEADSPACE' => 'getLauterDeadspace', 38 | 'TOP_UP_KETTLE' => 'getTopUpKettle', 39 | 'HOP_UTILIZATION' => 'getHopUtilization', 40 | 'NOTES' => 'getNotes', 41 | ); 42 | 43 | protected $displayInterface = 'BeerXML\Generator\IEquipmentDisplay'; 44 | 45 | protected $displayValues = array( 46 | 'DISPLAY_BOIL_SIZE' => 'getDisplayBoilSize', 47 | 'DISPLAY_BATCH_SIZE' => 'getDisplayBatchSize', 48 | 'DISPLAY_TUN_VOLUME' => 'getDisplayTunVolume', 49 | 'DISPLAY_TUN_WEIGHT' => 'getDisplayTunWeight', 50 | 'DISPLAY_TOP_UP_WATER' => 'getDisplayTopUpWater', 51 | 'DISPLAY_TRUB_CHILLER_LOSS' => 'getDisplayTrubChillerLoss', 52 | 'DISPLAY_LAUTER_DEADSPACE' => 'getDisplayLauterDeadspace', 53 | 'DISPLAY_TOP_UP_KETTLE' => 'getDisplayTopUpKettle', 54 | ); 55 | 56 | protected function additionalFields() 57 | { 58 | $this->xmlWriter->writeElement('CALC_BOIL_VOLUME', $this->boolToString($this->record->getCalcBoilVolume())); 59 | 60 | return parent::additionalFields(); 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /src/BeerXML/Generator/IStyleDisplay.php: -------------------------------------------------------------------------------- 1 | recipe = new Recipe(); 24 | } 25 | 26 | 27 | public function testHasGettersAndSetters() 28 | { 29 | $accessors = array( 30 | "Age" => 24.0, 31 | "AgeTemp" => 17.0, 32 | "AsstBrewer" => "Yoshi Scooter", 33 | "BatchSize" => 18.93, 34 | "BoilSize" => 20.82, 35 | "BoilTime" => 60.0, 36 | "Brewer" => "George Hotelling", 37 | "Carbonation" => 2.1, 38 | "CarbonationTemp" => 4.0, 39 | "Date" => "3 Jan 04", 40 | "Efficiency" => 72.0, 41 | "FermentationStages" => 2, 42 | "Fg" => 1.012, 43 | "ForcedCarbonation" => false, 44 | "KegPrimingFactor" => 0.5, 45 | "Name" => "BenderBrau", 46 | "Notes" => "Cold fusion steam beer", 47 | "Og" => 1.036, 48 | "PrimaryAge" => 4, 49 | "PrimaryTemp" => 20.000, 50 | "PrimingSugarEquiv" => 1.4, 51 | "PrimingSugarName" => "DME", 52 | "SecondaryAge" => 7, 53 | "SecondaryTemp" => 20.000, 54 | "TasteNotes" => "Meh", 55 | "TasteRating" => 35, 56 | "TertiaryAge" => 14, 57 | "TertiaryTemp" => 19.999, 58 | "Type" => Recipe::TYPE_ALL_GRAIN, 59 | "Version" => 2, 60 | ); 61 | foreach ($accessors as $method => $value) { 62 | $getter = "get" . $method; 63 | $setter = "set" . $method; 64 | $this->recipe->{$setter}($value); 65 | $this->assertEquals($value, $this->recipe->{$getter}()); 66 | } 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/BeerXML/Parser/Fermentable.php: -------------------------------------------------------------------------------- 1 | 'setName', 18 | 'VERSION' => 'setVersion', 19 | 'TYPE' => 'setType', 20 | 'AMOUNT' => 'setAmount', 21 | 'YIELD' => 'setYield', 22 | 'COLOR' => 'setColor', 23 | 'ORIGIN' => 'setOrigin', 24 | 'SUPPLIER' => 'setSupplier', 25 | 'NOTES' => 'setNotes', 26 | 'COARSE_FINE_DIFF' => 'setCoarseFineDiff', 27 | 'MOISTURE' => 'setMoisture', 28 | 'DIASTATIC_POWER' => 'setDiastaticPower', 29 | 'PROTEIN' => 'setProtein', 30 | 'MAX_IN_BATCH' => 'setMaxInBatch', 31 | 'IBU_GAL_PER_LB' => 'setIbuGalPerLb', 32 | ); 33 | 34 | /** 35 | * @return IFermentable 36 | */ 37 | public function createRecord() 38 | { 39 | $fermentable = $this->recordFactory->getFermentable(); 40 | if ($fermentable instanceof IFermentableDisplay) { 41 | $this->simpleProperties = array_merge( 42 | $this->simpleProperties, 43 | array( 44 | 'DISPLAY_AMOUNT' => 'setDisplayAmount', 45 | 'POTENTIAL' => 'setPotential', 46 | 'INVENTORY' => 'setInventory', 47 | 'DISPLAY_COLOR' => 'setDisplayColor', 48 | ) 49 | ); 50 | } 51 | return $fermentable; 52 | } 53 | 54 | /** 55 | * @param IFermentable $record 56 | */ 57 | protected function otherElementEncountered($record) 58 | { 59 | if ('ADD_AFTER_BOIL' == $this->xmlReader->name) { 60 | $value = ($this->xmlReader->readString() == 'TRUE'); 61 | $record->setAddAfterBoil($value); 62 | } 63 | if ('RECOMMEND_MASH' == $this->xmlReader->name) { 64 | $value = ($this->xmlReader->readString() == 'TRUE'); 65 | $record->setRecommendMash($value); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/Style.php: -------------------------------------------------------------------------------- 1 | => getterMethod 18 | * 19 | * @var array 20 | */ 21 | protected $simpleValues = array( 22 | 'NAME' => 'getName', 23 | 'VERSION' => 'getVersion', 24 | 'CATEGORY' => 'getCategory', 25 | 'CATEGORY_NUMBER' => 'getCategoryNumber', 26 | 'STYLE_LETTER' => 'getStyleLetter', 27 | 'STYLE_GUIDE' => 'getStyleGuide', 28 | 'TYPE' => 'getType', 29 | 'OG_MIN' => 'getOgMin', 30 | 'OG_MAX' => 'getOgMax', 31 | 'FG_MIN' => 'getFgMin', 32 | 'FG_MAX' => 'getFgMax', 33 | 'IBU_MIN' => 'getIbuMin', 34 | 'IBU_MAX' => 'getIbuMax', 35 | 'COLOR_MIN' => 'getColorMin', 36 | 'COLOR_MAX' => 'getColorMax', 37 | 'ABV_MIN' => 'getAbvMin', 38 | 'ABV_MAX' => 'getAbvMax', 39 | ); 40 | 41 | /** 42 | * => getterMethod 43 | * 44 | * @var array 45 | */ 46 | protected $optionalSimpleValues = array( 47 | 'CARB_MIN' => 'getCarbMin', 48 | 'CARB_MAX' => 'getCarbMax', 49 | 'NOTES' => 'getNotes', 50 | 'PROFILE' => 'getProfile', 51 | 'INGREDIENTS' => 'getIngredients', 52 | 'EXAMPLES' => 'getExamples', 53 | ); 54 | 55 | protected $displayInterface = 'BeerXML\Generator\IStyleDisplay'; 56 | 57 | protected $displayValues = array( 58 | 'DISPLAY_OG_MIN' => 'getDisplayOgMin', 59 | 'DISPLAY_OG_MAX' => 'getDisplayOgMax', 60 | 'DISPLAY_FG_MIN' => 'getDisplayFgMin', 61 | 'DISPLAY_FG_MAX' => 'getDisplayFgMax', 62 | 'DISPLAY_COLOR_MIN' => 'getDisplayColorMin', 63 | 'DISPLAY_COLOR_MAX' => 'getDisplayColorMax', 64 | 'OG_RANGE' => 'getOgRange', 65 | 'FG_RANGE' => 'getFgRange', 66 | 'IBU_RANGE' => 'getIbuRange', 67 | 'CARB_RANGE' => 'getCarbRange', 68 | 'COLOR_RANGE' => 'getColorRange', 69 | 'ABV_RANGE' => 'getAbvRange', 70 | ); 71 | 72 | } -------------------------------------------------------------------------------- /src/BeerXML/Generator/IStyle.php: -------------------------------------------------------------------------------- 1 | 'setName', 18 | 'VERSION' => 'setVersion', 19 | 'TYPE' => 'setType', 20 | 'FORM' => 'setForm', 21 | 'AMOUNT' => 'setAmount', 22 | 'LABORATORY' => 'setLaboratory', 23 | 'PRODUCT_ID' => 'setProductId', 24 | 'MIN_TEMPERATURE' => 'setMinTemperature', 25 | 'FLOCCULATION' => 'setFlocculation', 26 | 'ATTENUATION' => 'setAttenuation', 27 | 'NOTES' => 'setNotes', 28 | 'BEST_FOR' => 'setBestFor', 29 | 'TIMES_CULTURED' => 'setTimesCultured', 30 | 'MAX_REUSE' => 'setMaxReuse', 31 | 'MAX_TEMPERATURE' => 'setMaxTemperature', 32 | ); 33 | 34 | /** 35 | * @return IYeast 36 | */ 37 | protected function createRecord() 38 | { 39 | $yeast = $this->recordFactory->getYeast(); 40 | if ($yeast instanceof IYeastDisplay) { 41 | $this->simpleProperties = array_merge( 42 | $this->simpleProperties, 43 | array( 44 | 'DISPLAY_AMOUNT' => 'setDisplayAmount', 45 | 'DISP_MIN_TEMP' => 'setDispMinTemp', 46 | 'DISP_MAX_TEMP' => 'setDispMaxTemp', 47 | 'INVENTORY' => 'setInventory', 48 | ) 49 | ); 50 | } 51 | return $yeast; 52 | } 53 | 54 | /** 55 | * @param IYeast $record 56 | */ 57 | protected function otherElementEncountered($record) 58 | { 59 | if ('AMOUNT_IS_WEIGHT' == $this->xmlReader->name) { 60 | $value = ($this->xmlReader->readString() == 'TRUE'); 61 | $record->setAmountIsWeight($value); 62 | } elseif ('ADD_TO_SECONDARY' == $this->xmlReader->name) { 63 | $value = ($this->xmlReader->readString() == 'TRUE'); 64 | $record->setAddToSecondary($value); 65 | } elseif ('CULTURE_DATE' == $this->xmlReader->name && $record instanceof IYeastDisplay) { 66 | $dateTimeString = $this->xmlReader->readString(); 67 | $record->setCultureDate($this->parseDateString($dateTimeString)); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/BeerXML/Parser/IStyleDisplay.php: -------------------------------------------------------------------------------- 1 | 'setName', 18 | 'VERSION' => 'setVersion', 19 | 'BOIL_SIZE' => 'setBoilSize', 20 | 'BATCH_SIZE' => 'setBatchSize', 21 | 'TUN_VOLUME' => 'setTunVolume', 22 | 'TUN_WEIGHT' => 'setTunWeight', 23 | 'TUN_SPECIFIC_HEAT' => 'setTunSpecificHeat', 24 | 'TOP_UP_WATER' => 'setTopUpWater', 25 | 'TRUB_CHILLER_LOSS' => 'setTrubChillerLoss', 26 | 'EVAP_RATE' => 'setEvapRate', 27 | 'BOIL_TIME' => 'setBoilTime', 28 | 'LAUTER_DEADSPACE' => 'setLauterDeadspace', 29 | 'TOP_UP_KETTLE' => 'setTopUpKettle', 30 | 'HOP_UTILIZATION' => 'setHopUtilization', 31 | 'NOTES' => 'setNotes', 32 | ); 33 | 34 | /** 35 | * @return IEquipment 36 | */ 37 | protected function createRecord() 38 | { 39 | $equipment = $this->recordFactory->getEquipment(); 40 | if ($equipment instanceof IEquipmentDisplay) { 41 | $this->simpleProperties = array_merge( 42 | $this->simpleProperties, 43 | array( 44 | 'DISPLAY_BOIL_SIZE' => 'setDisplayBoilSize', 45 | 'DISPLAY_BATCH_SIZE' => 'setDisplayBatchSize', 46 | 'DISPLAY_TUN_VOLUME' => 'setDisplayTunVolume', 47 | 'DISPLAY_TUN_WEIGHT' => 'setDisplayTunWeight', 48 | 'DISPLAY_TOP_UP_WATER' => 'setDisplayTopUpWater', 49 | 'DISPLAY_TRUB_CHILLER_LOSS' => 'setDisplayTrubChillerLoss', 50 | 'DISPLAY_LAUTER_DEADSPACE' => 'setDisplayLauterDeadspace', 51 | 'DISPLAY_TOP_UP_KETTLE' => 'setDisplayTopUpKettle', 52 | ) 53 | ); 54 | } 55 | return $equipment; 56 | } 57 | 58 | /** 59 | * @param IEquipment $record 60 | */ 61 | protected function otherElementEncountered($record) 62 | { 63 | if ('CALC_BOIL_VOLUME' == $this->xmlReader->name) { 64 | $value = ($this->xmlReader->readString() == 'TRUE'); 65 | $record->setCalcBoilVolume($value); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/BeerXML/Parser/Style.php: -------------------------------------------------------------------------------- 1 | 'setName', 18 | 'VERSION' => 'setVersion', 19 | 'CATEGORY' => 'setCategory', 20 | 'CATEGORY_NUMBER' => 'setCategoryNumber', 21 | 'STYLE_LETTER' => 'setStyleLetter', 22 | 'STYLE_GUIDE' => 'setStyleGuide', 23 | 'TYPE' => 'setType', 24 | 'OG_MIN' => 'setOgMin', 25 | 'OG_MAX' => 'setOgMax', 26 | 'FG_MIN' => 'setFgMin', 27 | 'FG_MAX' => 'setFgMax', 28 | 'IBU_MIN' => 'setIbuMin', 29 | 'IBU_MAX' => 'setIbuMax', 30 | 'COLOR_MIN' => 'setColorMin', 31 | 'COLOR_MAX' => 'setColorMax', 32 | 'ABV_MIN' => 'setAbvMin', 33 | 'ABV_MAX' => 'setAbvMax', 34 | 'CARB_MIN' => 'setCarbMin', 35 | 'CARB_MAX' => 'setCarbMax', 36 | 'NOTES' => 'setNotes', 37 | 'PROFILE' => 'setProfile', 38 | 'INGREDIENTS' => 'setIngredients', 39 | 'EXAMPLES' => 'setExamples', 40 | ); 41 | 42 | /** 43 | * @return IStyle 44 | */ 45 | protected function createRecord() 46 | { 47 | $style = $this->recordFactory->getStyle(); 48 | if ($style instanceof IStyleDisplay) { 49 | $this->simpleProperties = array_merge( 50 | $this->simpleProperties, 51 | array( 52 | 'DISPLAY_OG_MIN' => 'setDisplayOgMin', 53 | 'DISPLAY_OG_MAX' => 'setDisplayOgMax', 54 | 'DISPLAY_FG_MIN' => 'setDisplayFgMin', 55 | 'DISPLAY_FG_MAX' => 'setDisplayFgMax', 56 | 'DISPLAY_COLOR_MIN' => 'setDisplayColorMin', 57 | 'DISPLAY_COLOR_MAX' => 'setDisplayColorMax', 58 | 'OG_RANGE' => 'setOgRange', 59 | 'FG_RANGE' => 'setFgRange', 60 | 'IBU_RANGE' => 'setIbuRange', 61 | 'CARB_RANGE' => 'setCarbRange', 62 | 'COLOR_RANGE' => 'setColorRange', 63 | 'ABV_RANGE' => 'setAbvRange', 64 | ) 65 | ); 66 | } 67 | return $style; 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /src/BeerXML/Generator/Yeast.php: -------------------------------------------------------------------------------- 1 | => getterMethod 18 | * 19 | * @var array 20 | */ 21 | protected $simpleValues = array( 22 | 'NAME' => 'getName', 23 | 'VERSION' => 'getVersion', 24 | 'TYPE' => 'getType', 25 | 'FORM' => 'getForm', 26 | 'AMOUNT' => 'getAmount', 27 | ); 28 | 29 | /** 30 | * => getterMethod 31 | * 32 | * @var array 33 | */ 34 | protected $optionalSimpleValues = array( 35 | 'AMOUNT_IS_WEIGHT' => 'getAmountIsWeight', 36 | 'LABORATORY' => 'getLaboratory', 37 | 'PRODUCT_ID' => 'getProductId', 38 | 'MIN_TEMPERATURE' => 'getMinTemperature', 39 | 'FLOCCULATION' => 'getFlocculation', 40 | 'ATTENUATION' => 'getAttenuation', 41 | 'NOTES' => 'getNotes', 42 | 'BEST_FOR' => 'getBestFor', 43 | 'TIMES_CULTURED' => 'getTimesCultured', 44 | 'MAX_REUSE' => 'getMaxReuse', 45 | 'MAX_TEMPERATURE' => 'getMaxTemperature', 46 | 'ADD_TO_SECONDARY' => 'getAddToSecondary', 47 | ); 48 | 49 | protected $displayInterface = 'BeerXML\Generator\IYeastDisplay'; 50 | 51 | protected $displayValues = array( 52 | 'DISPLAY_AMOUNT' => 'getDisplayAmount', 53 | 'DISP_MIN_TEMP' => 'getDispMinTemp', 54 | 'DISP_MAX_TEMP' => 'getDispMaxTemp', 55 | 'INVENTORY' => 'getInventory', 56 | ); 57 | 58 | 59 | /** 60 | * @{inheritDoc} 61 | */ 62 | protected function additionalFields() 63 | { 64 | $amountIsWeight = $this->record->getAmountIsWeight(); 65 | if (!is_null($amountIsWeight)) { 66 | $this->xmlWriter->writeElement('AMOUNT_IS_WEIGHT', $this->boolToString($amountIsWeight)); 67 | } 68 | 69 | $addToSecondary = $this->record->getAddToSecondary(); 70 | if (!is_null($addToSecondary)) { 71 | $this->xmlWriter->writeElement('ADD_TO_SECONDARY', $this->boolToString($addToSecondary)); 72 | } 73 | 74 | if ($this->record instanceof $this->displayInterface) { 75 | $cultureDate = $this->record->getCultureDate(); 76 | if ($cultureDate instanceof \DateTime) { 77 | $this->xmlWriter->writeElement('CULTURE_DATE', $cultureDate->format('d M y')); 78 | } 79 | } 80 | 81 | parent::additionalFields(); 82 | } 83 | } -------------------------------------------------------------------------------- /src/BeerXML/Parser/IStyle.php: -------------------------------------------------------------------------------- 1 | parser = new Yeast(); 22 | $this->parser->setRecordFactory(new RecordFactory()); 23 | } 24 | 25 | public function testParseYeastWithCultureDate() 26 | { 27 | // Dates are defined very loosely in the beerxml standard 28 | $this->parser->setXmlString(file_get_contents(dirname(dirname(__FILE__)) . '/fixtures/yeast-culture-date.xml')); 29 | $yeast = $this->parser->parse(); 30 | /** @var $yeast \BeerXML\Record\Yeast */ 31 | $this->assertEquals("Nottingham Yeast", $yeast->getName()); 32 | $this->assertEquals(1, $yeast->getVersion()); 33 | $this->assertEquals("Ale", $yeast->getType()); 34 | $this->assertEquals("Dry", $yeast->getForm()); 35 | // Allow a little room floating point 36 | $amount = $yeast->getAmount(); 37 | $this->assertTrue($amount < 0.02366 && $amount > 0.02365); 38 | $this->assertFalse($yeast->getAmountIsWeight()); 39 | $this->assertEquals("Lallemand", $yeast->getLaboratory()); 40 | $this->assertEquals("-", $yeast->getProductId()); 41 | 42 | $minTemperature = $yeast->getMinTemperature(); 43 | $this->assertTrue($minTemperature < 16.66667 && $minTemperature > 16.66666); 44 | $maxTemperature = $yeast->getMaxTemperature(); 45 | $this->assertTrue($maxTemperature < 22.2223 && $maxTemperature > 22.2222); 46 | $this->assertEquals("Very High", $yeast->getFlocculation()); 47 | $this->assertEquals(75, $yeast->getAttenuation()); 48 | $this->assertEquals("High flocculation - settles quickly. Very good reputation as a fast starter and quick fermenter. Clean and only slightly fruity. Some nutty flavor in bottled version. Relatively high attenuation.", 49 | $yeast->getNotes()); 50 | $this->assertEquals("Ales", $yeast->getBestFor()); 51 | $this->assertEquals(5, $yeast->getMaxReuse()); 52 | $this->assertEquals(0, $yeast->getTimesCultured()); 53 | $this->assertFalse($yeast->getAddToSecondary()); 54 | $this->assertEquals("23.66 ml", $yeast->getDisplayAmount()); 55 | $this->assertEquals("16.7 C", $yeast->getDispMinTemp()); 56 | $this->assertEquals("22.2 C", $yeast->getDispMaxTemp()); 57 | $this->assertEquals("0.0 pkg", $yeast->getInventory()); 58 | $cultureDateString = $yeast->getCultureDate()->format("Ymd"); 59 | $this->assertEquals("20030613", $cultureDateString); 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /src/BeerXML/Parser.php: -------------------------------------------------------------------------------- 1 | 23 | * parse(file_get_contents('http://www.beerxml.com/recipes.xml')); 26 | * foreach ($result as $recipe) { 27 | * echo "Found beer recipe " . $recipe->getName() . "\n"; 28 | * } 29 | * 30 | * 31 | * @package BeerXML 32 | */ 33 | class Parser 34 | { 35 | /** 36 | * @var \XMLReader 37 | */ 38 | private $xmlReader; 39 | 40 | /** 41 | * @var RecordFactory 42 | */ 43 | private $recordFactory; 44 | 45 | /** 46 | * @var Parser\Record 47 | */ 48 | private $recipeParser; 49 | 50 | private $tagParsers = array( 51 | 'RECIPE' => '\BeerXML\Parser\Recipe', 52 | 'HOP' => '\BeerXML\Parser\Hop', 53 | 'FERMENTABLE' => '\BeerXML\Parser\Fermentable', 54 | 'YEAST' => '\BeerXML\Parser\Yeast', 55 | 'MISC' => '\BeerXML\Parser\Misc', 56 | 'WATER' => '\BeerXML\Parser\Water', 57 | 'EQUIPMENT' => '\BeerXML\Parser\Equipment', 58 | 'STYLE' => '\BeerXML\Parser\Style', 59 | 'MASH_STEP' => '\BeerXML\Parser\MashStep', 60 | 'MASH' => '\BeerXML\Parser\Mash' 61 | ); 62 | 63 | /** 64 | * @param RecordFactory $factory 65 | */ 66 | public function __construct(RecordFactory $factory = null) 67 | { 68 | $this->xmlReader = new \XMLReader(); 69 | if (is_null($factory)) { 70 | $factory = new RecordFactory(); 71 | } 72 | $this->recordFactory = $factory; 73 | } 74 | 75 | /** 76 | * Parse a beer XML, returning an array of the record objects found 77 | * 78 | * @param string $xml 79 | * @return IRecipe[]|IEquipment[]|IFermentable[]|IHop[]|IMashProfile[]|IMisc[]|IStyle[]|IWater[]|IYeast[] 80 | */ 81 | public function parse($xml) 82 | { 83 | $this->xmlReader->XML($xml); 84 | $records = array(); 85 | 86 | while ($this->xmlReader->read()) { 87 | // Find records 88 | if ($this->xmlReader->nodeType == \XMLReader::ELEMENT && isset($this->tagParsers[$this->xmlReader->name])) { 89 | $recordParser = new $this->tagParsers[$this->xmlReader->name]; 90 | /** @var $recordParser Record */ 91 | $recordParser->setXmlReader($this->xmlReader); 92 | $recordParser->setRecordFactory($this->recordFactory); 93 | $records[] = $recordParser->parse(); 94 | } 95 | } 96 | 97 | $this->xmlReader->close(); 98 | 99 | return $records; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /tests/ParserTest.php: -------------------------------------------------------------------------------- 1 | parser = new Parser(); 23 | } 24 | 25 | public function testReturnsRecords() 26 | { 27 | $xml = file_get_contents(dirname(__FILE__) . '/fixtures/recipe-simplest.xml'); 28 | $result = $this->parser->parse($xml); 29 | $this->assertEquals(1, count($result)); 30 | $this->assertInstanceOf('BeerXML\Record\Recipe', $result[0]); 31 | } 32 | 33 | public function testReturnsComplexRecords() 34 | { 35 | $xml = file_get_contents(dirname(__FILE__) . '/fixtures/recipe-record.xml'); 36 | $result = $this->parser->parse($xml); 37 | $this->assertEquals(1, count($result)); 38 | $recipe = $result[0]; 39 | /** @var $recipe Recipe */ 40 | $this->assertInstanceOf('BeerXML\Record\Recipe', $recipe); 41 | $this->assertEquals('Dry Stout', $recipe->getStyle()->getName()); 42 | 43 | $this->assertEquals(1, count($recipe->getHops())); 44 | list($hop) = $recipe->getHops(); 45 | /** @var $hop Hop */ 46 | $this->assertEquals(5.0, $hop->getAlpha()); 47 | 48 | $this->assertEquals(3, count($recipe->getFermentables())); 49 | } 50 | 51 | public function testCanDealWithOfficialExample() 52 | { 53 | $xml = file_get_contents(dirname(__FILE__) . '/fixtures/recipes-4fromweb.xml'); 54 | $result = $this->parser->parse($xml); 55 | $this->assertEquals(4, count($result)); 56 | 57 | $burtonAle = $result[0]; 58 | /** @var $burtonAle Recipe */ 59 | 60 | $this->assertEquals($burtonAle->getType(), Recipe::TYPE_ALL_GRAIN); 61 | 62 | $miscs = $burtonAle->getMiscs(); 63 | $this->assertEquals(2, count($miscs)); 64 | $polyclar = $miscs[1]; 65 | /** @var $polyclar Misc */ 66 | $this->assertEquals('Chill Haze', $polyclar->getUseFor() ); 67 | 68 | list($burtonYeast) = $burtonAle->getYeasts(); 69 | /** @var $burtonYeast \BeerXML\Record\Yeast */ 70 | $this->assertEquals('Burton-on-trent yeast produces a complex character. Flavors include apple, pear, and clover honey.', $burtonYeast->getNotes() ); 71 | $this->assertEquals(Yeast::TYPE_ALE, $burtonYeast->getType()); 72 | 73 | list($water) = $burtonAle->getWaters(); 74 | /** @var $water \BeerXML\Record\Water */ 75 | $this->assertEquals('Burton On Trent, UK', $water->getName()); 76 | $this->assertEquals(300, $water->getBicarbonate()); 77 | 78 | $equipment = $burtonAle->getEquipment(); 79 | /** @var $equipment \BeerXML\Record\Equipment */ 80 | $this->assertEquals('Brew Pot (6+gal) and Igloo/Gott Cooler (5 Gal)', $equipment->getName()); 81 | $this->assertEquals(60, $equipment->getBoilTime()); 82 | } 83 | 84 | public function testSelfClosingTagsDontError() 85 | { 86 | list($recipe) = $this->parser->parse(file_get_contents(__DIR__ . '/fixtures/hop-with-self-closing-tag.xml')); 87 | /** @var $recipe Recipe */ 88 | list($hop) = $recipe->getHops(); 89 | $this->assertEmpty($hop->getBeta()); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/IHop.php: -------------------------------------------------------------------------------- 1 | 'setAge', 20 | 'AGE_TEMP' => 'setAgeTemp', 21 | 'ASST_BREWER' => 'setAsstBrewer', 22 | 'BATCH_SIZE' => 'setBatchSize', 23 | 'BOIL_SIZE' => 'setBoilSize', 24 | 'BOIL_TIME' => 'setBoilTime', 25 | 'BREWER' => 'setBrewer', 26 | 'CARBONATION' => 'setCarbonation', 27 | 'CARBONATION_TEMP' => 'setCarbonationTemp', 28 | 'EFFICIENCY' => 'setEfficiency', 29 | 'FERMENTATION_STAGES' => 'setFermentationStages', 30 | 'FG' => 'setFg', 31 | 'KEG_PRIMING_FACTOR' => 'setKegPrimingFactor', 32 | 'NAME' => 'setName', 33 | 'NOTES' => 'setNotes', 34 | 'OG' => 'setOg', 35 | 'PRIMARY_AGE' => 'setPrimaryAge', 36 | 'PRIMARY_TEMP' => 'setPrimaryTemp', 37 | 'PRIMING_SUGAR_EQUIV' => 'setPrimingSugarEquiv', 38 | 'PRIMING_SUGAR_NAME' => 'setPrimingSugarName', 39 | 'SECONDARY_AGE' => 'setSecondaryAge', 40 | 'SECONDARY_TEMP' => 'setSecondaryTemp', 41 | 'TASTE_NOTES' => 'setTasteNotes', 42 | 'TASTE_RATING' => 'setTasteRating', 43 | 'TERTIARY_AGE' => 'setTertiaryAge', 44 | 'TERTIARY_TEMP' => 'setTertiaryTemp', 45 | 'TYPE' => 'setType', 46 | 'VERSION' => 'setVersion', 47 | ); 48 | 49 | /** 50 | * @return IRecipe 51 | */ 52 | protected function createRecord() 53 | { 54 | $recipe = $this->recordFactory->getRecipe(); 55 | if ($recipe instanceof IRecipeDisplay) { 56 | $this->simpleProperties = array_merge( 57 | $this->simpleProperties, 58 | array( 59 | 'EST_OG' => 'setEstOg', 60 | 'EST_FG' => 'setEstFg', 61 | 'EST_COLOR' => 'setEstColor', 62 | 'IBU' => 'setIbu', 63 | 'IBU_METHOD' => 'setIbuMethod', 64 | 'EST_ABV' => 'setEstAbv', 65 | 'ABV' => 'setAbv', 66 | 'ACTUAL_EFFICIENCY' => 'setActualEfficiency', 67 | 'CALORIES' => 'setCalories', 68 | 'DISPLAY_BATCH_SIZE' => 'setDisplayBatchSize', 69 | 'DISPLAY_BOIL_SIZE' => 'setDisplayBoilSize', 70 | 'DISPLAY_OG' => 'setDisplayOg', 71 | 'DISPLAY_FG' => 'setDisplayFg', 72 | 'DISPLAY_PRIMARY_TEMP' => 'setDisplayPrimaryTemp', 73 | 'DISPLAY_SECONDARY_TEMP' => 'setDisplaySecondaryTemp', 74 | 'DISPLAY_TERTIARY_TEMP' => 'setDisplayTertiaryTemp', 75 | 'DISPLAY_AGE_TEMP' => 'setDisplayAgeTemp', 76 | 'CARBONATION_USED' => 'setCarbonationUsed', 77 | 'DISPLAY_CARB_TEMP' => 'setDisplayCarbTemp', 78 | ) 79 | ); 80 | } 81 | return $recipe; 82 | } 83 | 84 | /** 85 | * @param IRecipe $record 86 | */ 87 | protected function otherElementEncountered($record) 88 | { 89 | if ('FORCED_CARBONATION' == $this->xmlReader->name) { 90 | $carb = ($this->xmlReader->readString() == 'TRUE'); 91 | $record->setForcedCarbonation($carb); 92 | } elseif ('DATE' == $this->xmlReader->name) { 93 | $dateTimeString = $this->xmlReader->readString(); 94 | $record->setDate($this->parseDateString($dateTimeString)); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/IRecipeDisplay.php: -------------------------------------------------------------------------------- 1 | 25 | * setName('My Brew'); 28 | * 29 | * $generator = new \BeerXML\Generator(); 30 | * $generator->addRecord($recipe); 31 | * $xml = $generator->render(); 32 | * echo $xml; 33 | * 34 | */ 35 | class Generator 36 | { 37 | 38 | /** 39 | * @var \XMLWriter 40 | */ 41 | private $xmlWriter; 42 | 43 | /** 44 | * Mapping classes to set tags 45 | * 46 | * @var array 47 | */ 48 | private $recordSetTags = array( 49 | '\BeerXML\Generator\IHop' => array('tag' => 'HOPS', 'generator' => 'BeerXML\Generator\Hop'), 50 | '\BeerXML\Generator\IFermentable' => array( 51 | 'tag' => 'FERMENTABLES', 52 | 'generator' => 'BeerXML\Generator\Fermentable' 53 | ), 54 | '\BeerXML\Generator\IYeast' => array('tag' => 'YEASTS', 'generator' => 'BeerXML\Generator\Yeast'), 55 | '\BeerXML\Generator\IMisc' => array('tag' => 'MISCS', 'generator' => 'BeerXML\Generator\Misc'), 56 | '\BeerXML\Generator\IWater' => array('tag' => 'WATERS', 'generator' => 'BeerXML\Generator\Water'), 57 | '\BeerXML\Generator\IStyle' => array('tag' => 'STYLES', 'generator' => 'BeerXML\Generator\Style'), 58 | '\BeerXML\Generator\IMashStep' => array('tag' => 'MASH_STEPS', 'generator' => 'BeerXML\Generator\MashStep'), 59 | '\BeerXML\Generator\IMash' => array('tag' => 'MASHS', 'generator' => 'BeerXML\Generator\MashProfile'), 60 | '\BeerXML\Generator\IRecipe' => array('tag' => 'RECIPES', 'generator' => 'BeerXML\Generator\Recipe'), 61 | '\BeerXML\Generator\IEquipment' => array('tag' => 'EQUIPMENTS', 'generator' => 'BeerXML\Generator\Equipment'), 62 | ); 63 | 64 | /** 65 | * Records to build 66 | * 67 | * @var array 68 | */ 69 | private $records = array(); 70 | 71 | public function __construct() 72 | { 73 | $this->xmlWriter = new \XMLWriter(); 74 | } 75 | 76 | 77 | /** 78 | * @param $record 79 | */ 80 | public function addRecord($record) 81 | { 82 | $this->records[] = $record; 83 | } 84 | 85 | /** 86 | * Creates the XML 87 | * 88 | * @return string BeerXML 89 | */ 90 | public function render() 91 | { 92 | $this->xmlWriter->openMemory(); 93 | $this->xmlWriter->startDocument('1.0', 'UTF-8'); 94 | $this->xmlWriter->writeComment('Created with php-beerxml: https://github.com/georgeh/php-beerxml'); 95 | 96 | list($setTag, $generator) = $this->getTagGeneratorForObject($this->records[0]); 97 | /** @var $generator Record */ 98 | $generator->setXmlWriter($this->xmlWriter); 99 | $this->xmlWriter->startElement($setTag); 100 | foreach ($this->records as $record) { 101 | $generator->setRecord($record); 102 | $generator->build(); 103 | } 104 | $this->xmlWriter->endElement(); 105 | return $this->xmlWriter->outputMemory(true); 106 | } 107 | 108 | /** 109 | * @param IHop|IFermentable|IEquipment|IYeast|IMisc|IWater|IStyle|IMashStep|IMashProfile|IRecipe $record 110 | * @return array(string, Record) 111 | * @throws Exception\InvalidRecord 112 | */ 113 | private function getTagGeneratorForObject($record) 114 | { 115 | foreach ($this->recordSetTags as $interface => $tagGen) { 116 | if ($record instanceof $interface) { 117 | $tag = $tagGen['tag']; 118 | $generatorClass = $tagGen['generator']; 119 | $generator = new $generatorClass(); 120 | return array($tag, $generator); 121 | } 122 | } 123 | 124 | throw new InvalidRecord('Record did not implement a valid Reader interface'); 125 | } 126 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | php-beerxml 2 | =========== 3 | 4 | [![Build Status](https://travis-ci.org/georgeh/php-beerxml.png?branch=master)](https://travis-ci.org/georgeh/php-beerxml) 5 | [![Coverage Status](https://coveralls.io/repos/georgeh/php-beerxml/badge.png?branch=master)](https://coveralls.io/r/georgeh/php-beerxml) 6 | 7 | A PHP parser and generator for the [BeerXML 1.0](http://www.beerxml.com/) standard. 8 | 9 | Usage 10 | ===== 11 | 12 | Full API documentation is at http://georgeh.github.io/php-beerxml/ 13 | 14 | The unit tests in the tests/ directory provides some good examples as well. 15 | 16 | Parser 17 | ------ 18 | 19 | ```php 20 | $parser = new \BeerXML\Parser(); 21 | $result = $parser->parse(file_get_contents('http://www.beerxml.com/recipes.xml')); 22 | foreach ($result as $recipe) { 23 | /** @var $recipe \BeerXML\Record\Recipe **/ 24 | echo "Found beer recipe " . $recipe->getName() . "\n"; 25 | } 26 | ``` 27 | 28 | If you don't want to use the basic record classes from the `BeerXML\Record` namespace (say, you want to add some ABV 29 | math or some Doctrine annotations so your recipe can easily save to a database) it's possible to specify the classes 30 | that get generated. You'll need to implement the `BeerXML\Parser\I*Writer` interfaces in your classes, then subclass 31 | `BeerXML\Parser\RecordFactory` to have it create your classes. Once you've got your objects set up, you can pass it into 32 | the constructor of `BeerXML\Parser` 33 | 34 | Generator 35 | --------- 36 | 37 | ```php 38 | $recipe = new \BeerXML\Record\Recipe(); 39 | $recipe->setName('My Brew'); 40 | 41 | $generator = new \BeerXML\Generator(); 42 | $generator->addRecord($recipe); 43 | $xml = $generator->render(); 44 | echo $xml; 45 | ``` 46 | 47 | `BeerXML\Generator` will accept any record that implements the `BeerXML\Generator\I*Reader` interfaces. 48 | 49 | Records 50 | ------- 51 | There are a record classes for all the record types in the BeerXML specification that contain getter and setter methods. 52 | They implement the extended "Display" interfaces for the parser and generator, which means that include getters and 53 | setters from Appendix A of the spec. They do not include any math or compute any fields, as that is outside the scope 54 | of this project. 55 | 56 | ```php 57 | $recipe = new \BeerXML\Record\Recipe(); 58 | $recipe->setName('Imperial Session'); 59 | $recipe->setOg(1.105); 60 | $recipe->setFg(1.002); 61 | $recipe->setIbu(99); 62 | ``` 63 | 64 | Installation 65 | ============ 66 | 67 | Requires **PHP 5.3.0** or higher. 68 | 69 | The easiest way is to install php-beerxml with [Composer](http://getcomposer.org/doc/00-intro.md). 70 | 71 | Create a file named `composer.json` in your project root: 72 | 73 | ```json 74 | { 75 | "require": { 76 | "georgeh/php-beerxml": "*", 77 | } 78 | } 79 | ``` 80 | 81 | Then, run the following commands: 82 | 83 | ```bash 84 | $ curl -s http://getcomposer.org/installer | php 85 | $ php composer.phar install 86 | ``` 87 | 88 | If you don't use Composer, you can directly [download](https://github.com/georgeh/php-beerxml) the sources and configure 89 | it with your PSR-0 compatible autoloader. 90 | 91 | License 92 | ======= 93 | 94 | This software is free to use under the MIT license, but if you are happy with it I wouldn't mind one of your homebrews. 95 | 96 | Copyright (c) 2013 George Hotelling 97 | 98 | Permission is hereby granted, free of charge, to any person obtaining a copy 99 | of this software and associated documentation files (the "Software"), to deal 100 | in the Software without restriction, including without limitation the rights 101 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 102 | copies of the Software, and to permit persons to whom the Software is 103 | furnished to do so, subject to the following conditions: 104 | 105 | The above copyright notice and this permission notice shall be included in 106 | all copies or substantial portions of the Software. 107 | 108 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 109 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 110 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 111 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 112 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 113 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 114 | THE SOFTWARE. 115 | 116 | ![Devtroit](http://devtroit.com/img/badges/badge-medium.png) 117 | -------------------------------------------------------------------------------- /src/BeerXML/Parser/IRecipeDisplay.php: -------------------------------------------------------------------------------- 1 | => getterMethod() 25 | * 26 | * @var array 27 | */ 28 | protected $simpleValues = array(); 29 | 30 | /** 31 | * => getterMethod() 32 | * 33 | * @var array 34 | */ 35 | protected $optionalSimpleValues = array(); 36 | 37 | protected $complexValues = array(); 38 | 39 | /** 40 | * => array('generator' => 'BeerXML\Generator\Class', 'values' => 'getRecords') 41 | * 42 | * @var array 43 | */ 44 | protected $complexValueSets = array(); 45 | 46 | /** 47 | * The interface for the optional display fields in Appendix A of the spec 48 | * 49 | * @var string 50 | */ 51 | protected $displayInterface; 52 | 53 | /** 54 | * => getterMethod() 55 | * 56 | * For the optional tags from the display fields in Appendix A of the spec 57 | * 58 | * @var array 59 | */ 60 | protected $displayValues = array(); 61 | 62 | /** 63 | * @param \XMLWriter $xmlWriter 64 | */ 65 | public function setXmlWriter($xmlWriter) 66 | { 67 | $this->xmlWriter = $xmlWriter; 68 | } 69 | 70 | /** 71 | * @param IHop|IFermentable|IEquipment|IYeast|IMisc|IWater|IStyle|IMashStep|IMashProfile|IRecipe $record 72 | */ 73 | public function setRecord($record) 74 | { 75 | $this->record = $record; 76 | } 77 | 78 | /** 79 | * Construct the record in XMLWriter 80 | * 81 | * @return null 82 | */ 83 | public function build() 84 | { 85 | $this->xmlWriter->startElement($this->tagName); 86 | // Simple required elements 87 | foreach ($this->simpleValues as $tag => $method) { 88 | $this->xmlWriter->writeElement($tag, $this->record->{$method}()); 89 | } 90 | 91 | foreach ($this->optionalSimpleValues as $tag => $method) { 92 | $value = $this->record->{$method}(); 93 | if (!empty($value)) { 94 | $this->xmlWriter->writeElement($tag, $value); 95 | } 96 | } 97 | 98 | foreach ($this->complexValues as $generatorClass => $method) { 99 | $value = $this->record->{$method}(); 100 | if ($value) { 101 | /** @var Record $generator */ 102 | $generator = new $generatorClass(); 103 | $generator->setXmlWriter($this->xmlWriter); 104 | $generator->setRecord($value); 105 | $generator->build(); 106 | } 107 | } 108 | 109 | foreach ($this->complexValueSets as $tag => $complex) { 110 | $this->xmlWriter->startElement($tag); 111 | $method = $complex['values']; // getter method, should return an array 112 | $generatorClass = $complex['generator']; // Should be a subclass of BeerXML\Generator\Record 113 | 114 | $values = $this->record->{$method}(); 115 | $generator = new $generatorClass(); 116 | $generator->setXmlWriter($this->xmlWriter); 117 | foreach ($values as $record) { 118 | $generator->setRecord($record); 119 | $generator->build(); 120 | } 121 | $this->xmlWriter->endElement(); 122 | } 123 | 124 | // If the given record implements the interface for the display fields, write those too 125 | if ($this->record instanceof $this->displayInterface) { 126 | foreach ($this->displayValues as $tag => $method) { 127 | $value = $this->record->{$method}(); 128 | if (!empty($value)) { 129 | $this->xmlWriter->writeElement($tag, $value); 130 | } 131 | } 132 | } 133 | 134 | // Call the parser to allow it to add any other weird fields 135 | $this->additionalFields(); 136 | 137 | $this->xmlWriter->endElement(); 138 | } 139 | 140 | /** 141 | * Converts a boolean to the string format expected by BeerXML 142 | * 143 | * @param boolean $bool 144 | * @return string 'TRUE' or 'FALSE' 145 | */ 146 | protected function boolToString($bool) 147 | { 148 | return ($bool) ? 'TRUE' : 'FALSE'; 149 | } 150 | 151 | /** 152 | * Runs before closing out the build sequence, to add fields that require logic 153 | */ 154 | protected function additionalFields() 155 | { 156 | 157 | } 158 | } -------------------------------------------------------------------------------- /src/BeerXML/Generator/Recipe.php: -------------------------------------------------------------------------------- 1 | => getterMethod 18 | * 19 | * @var array 20 | */ 21 | protected $simpleValues = array( 22 | 'NAME' => 'getName', 23 | 'VERSION' => 'getVersion', 24 | 'TYPE' => 'getType', 25 | 'BREWER' => 'getBrewer', 26 | 'BATCH_SIZE' => 'getBatchSize', 27 | 'BOIL_SIZE' => 'getBoilSize', 28 | 'BOIL_TIME' => 'getBoilTime', 29 | ); 30 | 31 | /** 32 | * => getterMethod 33 | * 34 | * @var array 35 | */ 36 | protected $optionalSimpleValues = array( 37 | 'ASST_BREWER' => 'getAsstBrewer', 38 | 'NOTES' => 'getNotes', 39 | 'TASTE_NOTES' => 'getTasteNotes', 40 | 'TASTE_RATING' => 'getTasteRating', 41 | 'OG' => 'getOg', 42 | 'FG' => 'getFg', 43 | 'FERMENTATION_STAGES' => 'getFermentationStages', 44 | 'PRIMARY_AGE' => 'getPrimaryAge', 45 | 'PRIMARY_TEMP' => 'getPrimaryTemp', 46 | 'SECONDARY_AGE' => 'getSecondaryAge', 47 | 'SECONDARY_TEMP' => 'getSecondaryTemp', 48 | 'TERTIARY_AGE' => 'getTertiaryAge', 49 | 'TERTIARY_TEMP' => 'getTertiaryTemp', 50 | 'AGE' => 'getAge', 51 | 'AGE_TEMP' => 'getAgeTemp', 52 | 'CARBONATION' => 'getCarbonation', 53 | 'PRIMING_SUGAR_NAME' => 'getPrimingSugarName', 54 | 'CARBONATION_TEMP' => 'getCarbonationTemp', 55 | 'PRIMING_SUGAR_EQUIV' => 'getPrimingSugarEquiv', 56 | 'KEG_PRIMING_FACTOR' => 'getKegPrimingFactor', 57 | ); 58 | 59 | protected $complexValues = array( 60 | 'BeerXML\Generator\Style' => 'getStyle', 61 | 'BeerXML\Generator\MashProfile' => 'getMash', 62 | ); 63 | 64 | protected $complexValueSets = array( 65 | 'HOPS' => array('generator' => 'BeerXML\Generator\Hop', 'values' => 'getHops'), 66 | 'FERMENTABLES' => array('generator' => 'BeerXML\Generator\Fermentable', 'values' => 'getFermentables'), 67 | 'MISCS' => array('generator' => 'BeerXML\Generator\Misc', 'values' => 'getMiscs'), 68 | 'YEASTS' => array('generator' => 'BeerXML\Generator\Yeast', 'values' => 'getYeasts'), 69 | 'WATERS' => array('generator' => 'BeerXML\Generator\Water', 'values' => 'getWaters'), 70 | ); 71 | 72 | protected $displayInterface = 'BeerXML\Generator\IRecipeDisplay'; 73 | 74 | protected $displayValues = array( 75 | 'EST_OG' => 'getEstOg', 76 | 'EST_FG' => 'getEstFg', 77 | 'EST_COLOR' => 'getEstColor', 78 | 'IBU' => 'getIbu', 79 | 'IBU_METHOD' => 'getIbuMethod', 80 | 'EST_ABV' => 'getEstAbv', 81 | 'ABV' => 'getAbv', 82 | 'ACTUAL_EFFICIENCY' => 'getActualEfficiency', 83 | 'CALORIES' => 'getCalories', 84 | 'DISPLAY_BATCH_SIZE' => 'getDisplayBatchSize', 85 | 'DISPLAY_BOIL_SIZE' => 'getDisplayBoilSize', 86 | 'DISPLAY_OG' => 'getDisplayOg', 87 | 'DISPLAY_FG' => 'getDisplayFg', 88 | 'DISPLAY_PRIMARY_TEMP' => 'getDisplayPrimaryTemp', 89 | 'DISPLAY_SECONDARY_TEMP' => 'getDisplaySecondaryTemp', 90 | 'DISPLAY_TERTIARY_TEMP' => 'getDisplayTertiaryTemp', 91 | 'DISPLAY_AGE_TEMP' => 'getDisplayAgeTemp', 92 | 'CARBONATION_USED' => 'getCarbonationUsed', 93 | 'DISPLAY_CARB_TEMP' => 'getDisplayCarbTemp', 94 | ); 95 | 96 | /** 97 | * @{inheritDoc} 98 | */ 99 | protected function additionalFields() 100 | { 101 | $efficiency = $this->record->getEfficiency(); 102 | if (!empty($efficiency) || 103 | \BeerXML\Record\Recipe::TYPE_ALL_GRAIN == $this->record->getType() || 104 | \BeerXML\Record\Recipe::TYPE_PARTIAL_MASH == $this->record->getType() 105 | ) { 106 | $this->xmlWriter->writeElement('EFFICIENCY', $efficiency); 107 | } 108 | 109 | if ($forcedCarb = $this->record->getForcedCarbonation()) { 110 | $this->xmlWriter->writeElement('FORCED_CARBONATION', $this->boolToString($forcedCarb)); 111 | } 112 | 113 | $date = $this->record->getDate(); 114 | if ($date instanceof \DateTime) { 115 | $this->xmlWriter->writeElement('DATE', $date->format('d M y')); 116 | } 117 | 118 | parent::additionalFields(); 119 | } 120 | 121 | 122 | } -------------------------------------------------------------------------------- /src/BeerXML/Parser/IRecipe.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dry Stout 4 | 1 5 | All Grain 6 | Brad Smith 7 | 18.93 8 | 20.82 9 | 60.0 10 | 72.0 11 | Nice dry Irish stout with a warm body but low starting gravity much like the famous drafts. 12 | 13 | 41 14 | 3 Jan 04 15 | 1.036 16 | 1.012 17 | 2.1 18 | Kegged 19 | 24.0 20 | 17.0 21 | 2 22 | 46 | 47 | 48 | Goldings, East Kent 49 | 1 50 | 5.0 51 | 0.0638 52 | Boil 53 | 54 | Great all purpose UK hop for ales, stouts, porters 55 | 56 | 57 | 58 | 59 | Pale Malt (2 row) UK 60 | 1 61 | 2.27 62 | Grain 63 | 78.0 64 | 3.0 65 | United Kingdom 66 | Fussybrewer Malting 67 | All purpose base malt for English styles 68 | 1.5 69 | 4.0 70 | 45.0 71 | 10.2 72 | 100.0 73 | 74 | 75 | Barley, Flaked 76 | 1 77 | 0.91 78 | Grain 79 | 70.0 80 | 2.0 81 | United Kingdom 82 | Fussybrewer Malting 83 | Adds body to porters and stouts, must be mashed 84 | 1.5 85 | 9.0 86 | 0.0 87 | 13.2 88 | 20.0 89 | TRUE 90 | 91 | 92 | Black Barley 93 | 1 94 | 0.45 95 | Grain 96 | 78.0 97 | 500.0 98 | United Kingdom 99 | Fussybrewer Malting 100 | Unmalted roasted barley for stouts, porters 101 | 1.5 102 | 5.0 103 | 0.0 104 | 13.2 105 | 10.0 106 | 107 | 108 | 109 | 110 | Irish Moss 111 | 1 112 | Fining 113 | Boil 114 | 115 | 0.010 116 | Used as a clarifying agent during the last few minutes of the boil 117 | 118 | 119 | 120 | 121 | Burton on Trent, UK 122 | 1 123 | 20.0 124 | 295.0 125 | 45.0 126 | 55.0 127 | 725.0 128 | 25.0 129 | 300.0 130 | 8.0 131 | Use for distinctive pale ales strongly hopped. Very hard water accentuates the hops flavor. Example: 132 | Bass Ale 133 | 134 | 135 | 136 | 137 | 138 | Irish Ale 139 | Ale 140 | 1 141 |
Liquid
142 | 0.250 143 | Wyeast Labs 144 | 1084 145 | 16.7 146 | 22.2 147 | 73.0 148 | Dry, fruity flavor characteristic of stouts. Full bodied, dry, clean flavor. 149 | Irish Dry Stouts 150 | Medium 151 |
152 |
153 | 154 | Single Step Infusion, 68 C 155 | 1 156 | 22.0 157 | 158 | 159 | Conversion Step, 68C 160 | 1 161 | Infusion 162 | 68.0 163 | 60.0 164 | 10.0 165 | 166 | 167 | 168 | FALSE 169 |
-------------------------------------------------------------------------------- /tests/fixtures/generated-recipe.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Dry Stout 6 | 1 7 | All Grain 8 | Brad Smith 9 | 18.93 10 | 20.82 11 | 60 12 | Nice dry Irish stout with a warm body but low starting gravity much like the famous drafts. 13 | 41 14 | 1.036 15 | 1.012 16 | 2 17 | 24 18 | 17 19 | 2.1 20 | 42 | 43 | Single Step Infusion, 68 C 44 | 1 45 | 22 46 | 47 | 48 | Conversion Step, 68C 49 | 1 50 | Infusion 51 | 10 52 | 68 53 | 60 54 | 10 55 | 56 | 57 | FALSE 58 | 59 | 60 | 61 | Goldings, East Kent 62 | 1 63 | 5 64 | 0.0638 65 | Boil 66 | 67 | Great all purpose UK hop for ales, stouts, porters 68 | 69 | 70 | 71 | 72 | Pale Malt (2 row) UK 73 | 1 74 | Grain 75 | 2.27 76 | 78 77 | 3 78 | United Kingdom 79 | Fussybrewer Malting 80 | All purpose base malt for English styles 81 | 1.5 82 | 4 83 | 45 84 | 10.2 85 | 100 86 | FALSE 87 | FALSE 88 | 89 | 90 | Barley, Flaked 91 | 1 92 | Grain 93 | 0.91 94 | 70 95 | 2 96 | United Kingdom 97 | Fussybrewer Malting 98 | Adds body to porters and stouts, must be mashed 99 | 1.5 100 | 9 101 | 13.2 102 | 20 103 | FALSE 104 | TRUE 105 | 106 | 107 | Pale Malt (2 row) UK 108 | 1 109 | Grain 110 | 0.45 111 | 78 112 | 500 113 | United Kingdom 114 | Fussybrewer Malting 115 | Unmalted roasted barley for stouts, porters 116 | 1.5 117 | 5 118 | 13.2 119 | 10 120 | FALSE 121 | FALSE 122 | 123 | 124 | 125 | 126 | Irish Moss 127 | 1 128 | Fining 129 | Boil 130 | 131 | 0.01 132 | Used as a clarifying agent during the last few minutes of the boil 133 | 134 | 135 | 136 | 137 | Irish Ale 138 | 1 139 | Ale 140 |
Liquid
141 | 0.25 142 | Wyeast Labs 143 | 1084 144 | 16.7 145 | Medium 146 | 73 147 | Dry, fruity flavor characteristic of stouts. Full bodied, dry, clean flavor. 148 | Irish Dry Stouts 149 | 22.2 150 | FALSE 151 | FALSE 152 |
153 |
154 | 155 | 156 | Burton on Trent, UK 157 | 1 158 | 20 159 | 295 160 | 300 161 | 725 162 | 25 163 | 55 164 | 45 165 | 8 166 | Use for distinctive pale ales strongly hopped. Very hard water accentuates the hops flavor. Example: Bass Ale 167 | 168 | 169 | 72 170 | TRUE 171 |
172 |
173 | -------------------------------------------------------------------------------- /tests/fixtures/generated-recipe-with-display.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Dry Stout 6 | 1 7 | All Grain 8 | Brad Smith 9 | 18.93 10 | 20.82 11 | 60 12 | Nice dry Irish stout with a warm body but low starting gravity much like the famous drafts. 13 | 41 14 | 1.036 15 | 1.012 16 | 2 17 | 24 18 | 17 19 | 2.1 20 | 42 | 43 | Single Step Infusion, 68 C 44 | 1 45 | 22 46 | 47 | 48 | Conversion Step, 68C 49 | 1 50 | Infusion 51 | 10 52 | 68 53 | 60 54 | 10 55 | 56 | 57 | FALSE 58 | 59 | 60 | 61 | Goldings, East Kent 62 | 1 63 | 5 64 | 0.0638 65 | Boil 66 | 67 | Great all purpose UK hop for ales, stouts, porters 68 | 69 | 70 | 71 | 72 | Pale Malt (2 row) UK 73 | 1 74 | Grain 75 | 2.27 76 | 78 77 | 3 78 | United Kingdom 79 | Fussybrewer Malting 80 | All purpose base malt for English styles 81 | 1.5 82 | 4 83 | 45 84 | 10.2 85 | 100 86 | FALSE 87 | FALSE 88 | 89 | 90 | Barley, Flaked 91 | 1 92 | Grain 93 | 0.91 94 | 70 95 | 2 96 | United Kingdom 97 | Fussybrewer Malting 98 | Adds body to porters and stouts, must be mashed 99 | 1.5 100 | 9 101 | 13.2 102 | 20 103 | FALSE 104 | TRUE 105 | 106 | 107 | Pale Malt (2 row) UK 108 | 1 109 | Grain 110 | 0.45 111 | 78 112 | 500 113 | United Kingdom 114 | Fussybrewer Malting 115 | Unmalted roasted barley for stouts, porters 116 | 1.5 117 | 5 118 | 13.2 119 | 10 120 | FALSE 121 | FALSE 122 | 123 | 124 | 125 | 126 | Irish Moss 127 | 1 128 | Fining 129 | Boil 130 | 131 | 0.01 132 | Used as a clarifying agent during the last few minutes of the boil 133 | 134 | 135 | 136 | 137 | Irish Ale 138 | 1 139 | Ale 140 |
Liquid
141 | 0.25 142 | Wyeast Labs 143 | 1084 144 | 16.7 145 | Medium 146 | 73 147 | Dry, fruity flavor characteristic of stouts. Full bodied, dry, clean flavor. 148 | Irish Dry Stouts 149 | 22.2 150 | FALSE 151 | FALSE 152 |
153 |
154 | 155 | 156 | Burton on Trent, UK 157 | 1 158 | 20 159 | 295 160 | 300 161 | 725 162 | 25 163 | 55 164 | 45 165 | 8 166 | Use for distinctive pale ales strongly hopped. Very hard water accentuates the hops flavor. Example: Bass Ale 167 | 168 | 169 | 1.056 170 | 1.010 171 | 30 172 | Tinseth 173 | 72 174 | TRUE 175 |
176 |
177 | -------------------------------------------------------------------------------- /src/BeerXML/Record/Water.php: -------------------------------------------------------------------------------- 1 | amount = $amount; 104 | } 105 | 106 | /** 107 | * Volume of water to use in a recipe in liters. 108 | * 109 | * @return number 110 | */ 111 | public function getAmount() 112 | { 113 | return $this->amount; 114 | } 115 | 116 | /** 117 | * The amount of bicarbonate (HCO3) in parts per million. 118 | * 119 | * @param float $bicarbonate 120 | */ 121 | public function setBicarbonate($bicarbonate) 122 | { 123 | $this->bicarbonate = $bicarbonate; 124 | } 125 | 126 | /** 127 | * The amount of bicarbonate (HCO3) in parts per million. 128 | * 129 | * @return float 130 | */ 131 | public function getBicarbonate() 132 | { 133 | return $this->bicarbonate; 134 | } 135 | 136 | /** 137 | * The amount of calcium (Ca) in parts per million. 138 | * 139 | * @param float $calcium 140 | */ 141 | public function setCalcium($calcium) 142 | { 143 | $this->calcium = $calcium; 144 | } 145 | 146 | /** 147 | * The amount of calcium (Ca) in parts per million. 148 | * 149 | * @return float 150 | */ 151 | public function getCalcium() 152 | { 153 | return $this->calcium; 154 | } 155 | 156 | /** 157 | * @param float $chloride 158 | */ 159 | public function setChloride($chloride) 160 | { 161 | $this->chloride = $chloride; 162 | } 163 | 164 | /** 165 | * @return float 166 | */ 167 | public function getChloride() 168 | { 169 | return $this->chloride; 170 | } 171 | 172 | /** 173 | * The amount of Magnesium (Mg) in parts per million. 174 | * 175 | * @param float $magnesium 176 | */ 177 | public function setMagnesium($magnesium) 178 | { 179 | $this->magnesium = $magnesium; 180 | } 181 | 182 | /** 183 | * The amount of Magnesium (Mg) in parts per million. 184 | * 185 | * @return float 186 | */ 187 | public function getMagnesium() 188 | { 189 | return $this->magnesium; 190 | } 191 | 192 | /** 193 | * Name of the water profile – usually the city and country of the water profile. 194 | * 195 | * @param string $name 196 | */ 197 | public function setName($name) 198 | { 199 | $this->name = $name; 200 | } 201 | 202 | /** 203 | * Name of the water profile – usually the city and country of the water profile. 204 | * 205 | * @return string 206 | */ 207 | public function getName() 208 | { 209 | return $this->name; 210 | } 211 | 212 | /** 213 | * Notes about the water profile. May be multiline. 214 | * 215 | * @param string $notes 216 | */ 217 | public function setNotes($notes) 218 | { 219 | $this->notes = $notes; 220 | } 221 | 222 | /** 223 | * Notes about the water profile. May be multiline. 224 | * 225 | * @return string 226 | */ 227 | public function getNotes() 228 | { 229 | return $this->notes; 230 | } 231 | 232 | /** 233 | * The PH of the water. 234 | * 235 | * @param float $pH 236 | */ 237 | public function setPH($pH) 238 | { 239 | $this->pH = $pH; 240 | } 241 | 242 | /** 243 | * The PH of the water. 244 | * 245 | * @return float 246 | */ 247 | public function getPH() 248 | { 249 | return $this->pH; 250 | } 251 | 252 | /** 253 | * The amount of Sodium (Na) in parts per million. 254 | * 255 | * @param float $sodium 256 | */ 257 | public function setSodium($sodium) 258 | { 259 | $this->sodium = $sodium; 260 | } 261 | 262 | /** 263 | * The amount of Sodium (Na) in parts per million. 264 | * 265 | * @return float 266 | */ 267 | public function getSodium() 268 | { 269 | return $this->sodium; 270 | } 271 | 272 | /** 273 | * The amount of Sulfate (SO4) in parts per million. 274 | * 275 | * @param float $sulfate 276 | */ 277 | public function setSulfate($sulfate) 278 | { 279 | $this->sulfate = $sulfate; 280 | } 281 | 282 | /** 283 | * The amount of Sulfate (SO4) in parts per million. 284 | * 285 | * @return float 286 | */ 287 | public function getSulfate() 288 | { 289 | return $this->sulfate; 290 | } 291 | 292 | /** 293 | * Version of the water record. Should always be "1" for this version of the XML standard. 294 | * 295 | * @param int $version 296 | */ 297 | public function setVersion($version) 298 | { 299 | $this->version = $version; 300 | } 301 | 302 | /** 303 | * Version of the water record. Should always be "1" for this version of the XML standard. 304 | * 305 | * @return int 306 | */ 307 | public function getVersion() 308 | { 309 | return $this->version; 310 | } 311 | 312 | /** 313 | * The amount of water in this record along with the units formatted for easy display in the current user defined 314 | * units. For example "5.0 gal" or "20.0 l". 315 | * 316 | * @param string $displayAmount 317 | */ 318 | public function setDisplayAmount($displayAmount) 319 | { 320 | $this->displayAmount = $displayAmount; 321 | } 322 | 323 | /** 324 | * The amount of water in this record along with the units formatted for easy display in the current user defined 325 | * units. For example "5.0 gal" or "20.0 l". 326 | * 327 | * @return string 328 | */ 329 | public function getDisplayAmount() 330 | { 331 | return $this->displayAmount; 332 | } 333 | 334 | } 335 | -------------------------------------------------------------------------------- /src/BeerXML/Generator/IRecipe.php: -------------------------------------------------------------------------------- 1 | … tags. 105 | * 106 | * @return IFermentable[] 107 | */ 108 | public function getFermentables(); 109 | 110 | /** 111 | * The number of fermentation stages used – typically a number between one and three 112 | * 113 | * @return int 114 | */ 115 | public function getFermentationStages(); 116 | 117 | /** 118 | * The measured final gravity of the finished beer. 119 | * 120 | * @return float Specific Gravity 121 | */ 122 | public function getFg(); 123 | 124 | /** 125 | * TRUE if the batch was force carbonated using CO2 pressure, FALSE if the batch was carbonated using a priming 126 | * agent. 127 | * 128 | * Default is FALSE 129 | * 130 | * @return boolean 131 | */ 132 | public function getForcedCarbonation(); 133 | 134 | /** 135 | * Zero or more HOP ingredient records may appear between the tags. 136 | * 137 | * @return IHop[] 138 | */ 139 | public function getHops(); 140 | 141 | /** 142 | * Used to factor in the smaller amount of sugar needed for large containers. 143 | * 144 | * For example, this might be 0.5 for a typical 5 gallon keg since naturally priming a keg requires about 50% as 145 | * much sugar as priming bottles. 146 | * 147 | * @return float 148 | */ 149 | public function getKegPrimingFactor(); 150 | 151 | /** 152 | * A MASH profile record containing one or more MASH_STEPs. 153 | * 154 | * NOTE: No Mash record is needed for "Extract" type brews. 155 | * 156 | * @return IMashProfile 157 | */ 158 | public function getMash(); 159 | 160 | /** 161 | * Zero or more MISC records may appear between 162 | * 163 | * @return IMisc[] 164 | */ 165 | public function getMiscs(); 166 | 167 | /** 168 | * Name of the recipe. 169 | * 170 | * @return string 171 | */ 172 | public function getName(); 173 | 174 | /** 175 | * Notes associated with this recipe – may be multiline. 176 | * 177 | * @return string 178 | */ 179 | public function getNotes(); 180 | 181 | /** 182 | * The measured original (pre-fermentation) specific gravity of the beer. 183 | * 184 | * @return float Specific Gravity 185 | */ 186 | public function getOg(); 187 | 188 | /** 189 | * Time spent in the primary in days 190 | * 191 | * @return number Time (days) 192 | */ 193 | public function getPrimaryAge(); 194 | 195 | /** 196 | * Temperature in degrees Celsius for the primary fermentation. 197 | * 198 | * @return number Temperature C 199 | */ 200 | public function getPrimaryTemp(); 201 | 202 | /** 203 | * Factor used to convert this priming agent to an equivalent amount of corn sugar for a bottled scenario. 204 | * 205 | * For example, "Dry Malt Extract" would have a value of 1.4 because it requires 1.4 times as much DME as corn sugar 206 | * to carbonate. To calculate the amount of DME needed, the program can calculate the amount of corn sugar needed 207 | * and then multiply by this factor. 208 | * 209 | * @return float 210 | */ 211 | public function getPrimingSugarEquiv(); 212 | 213 | /** 214 | * Text describing the priming agent such as "Honey" or "Corn Sugar" – used only if this is not a forced carbonation 215 | * 216 | * @return string 217 | */ 218 | public function getPrimingSugarName(); 219 | 220 | /** 221 | * Time spent in the secondary in days 222 | * 223 | * @return number Time (days) 224 | */ 225 | public function getSecondaryAge(); 226 | 227 | /** 228 | * Temperature in degrees Celsius for the secondary fermentation. 229 | * 230 | * @return number Temperature (C ) 231 | */ 232 | public function getSecondaryTemp(); 233 | 234 | /** 235 | * The style of the beer this recipe is associated with. All of the required items for a valid style should be 236 | * between the tags. 237 | * 238 | * @return \BeerXML\Record\Style 239 | */ 240 | public function getStyle(); 241 | 242 | /** 243 | * Tasting notes – may be multiline. 244 | * 245 | * @return string 246 | */ 247 | public function getTasteNotes(); 248 | 249 | /** 250 | * Number between zero and 50.0 denoting the taste rating – corresponds to the 50 point BJCP rating system. 251 | * 252 | * @return float 253 | */ 254 | public function getTasteRating(); 255 | 256 | /** 257 | * Time spent in the third fermenter in days. 258 | * 259 | * @return number Time (days) 260 | */ 261 | public function getTertiaryAge(); 262 | 263 | /** 264 | * Temperature in the tertiary fermenter. 265 | * 266 | * @return number Temperature C 267 | */ 268 | public function getTertiaryTemp(); 269 | 270 | /** 271 | * May be one of "Extract", "Partial Mash" or "All Grain" 272 | * 273 | * @return string 274 | */ 275 | public function getType(); 276 | 277 | /** 278 | * Version of the recipe record. Should always be "1" for this version of the XML standard. 279 | * 280 | * @return int 281 | */ 282 | public function getVersion(); 283 | 284 | /** 285 | * Zero or more WATER records may appear between 286 | * 287 | * @return IWater[] 288 | */ 289 | public function getWaters(); 290 | 291 | /** 292 | * Zero or more YEAST records may appear between 293 | * 294 | * @return IYeast[] 295 | */ 296 | public function getYeasts(); 297 | } --------------------------------------------------------------------------------