/**
  * Compiles a source, if source is not compiled, it should throw a RuntimeException
  *
  * @param SourceInterface $source
  * @param MetadataInterface|null $metadata
  * @return MetadataInterface
  * @throws RuntimeException
  */
 public function compile(SourceInterface $source, MetadataInterface $metadata = null)
 {
     if ($metadata !== null) {
         if ($metadata->validate($source)) {
             return $metadata;
         }
         foreach ($metadata->getHandles() as $handleName) {
             @unlink($metadata->getHandlePath($handleName));
         }
     }
     $items = $source->load();
     $result = array();
     foreach ($items as $key => $value) {
         $compiled = $this->parseElements($value);
         if ($compiled) {
             $result[$key] = $compiled;
         }
     }
     $metadata = $this->metadataFactory->createFromSource($source, array_keys($result));
     foreach ($metadata->getHandles() as $handle) {
         if (isset($result[$handle])) {
             $fileToSave = $metadata->getHandlePath($handle);
             if (!is_dir(dirname($fileToSave))) {
                 mkdir(dirname($fileToSave), 0755, true);
             }
             file_put_contents($fileToSave, sprintf("<?php %s", implode("\n", array_map(function ($item) {
                 if ($item instanceof ExpressionInterface) {
                     return sprintf('%s;', (string) $item);
                 }
                 return sprintf('$this->addItem(%s);', $item);
             }, $result[$handle]))));
         }
     }
     return $metadata;
 }
 /**
  * Adds a metadata object into index
  *
  * @param MetadataInterface $metadata
  * @return $this
  */
 public function addMetadata(MetadataInterface $metadata)
 {
     $id = $metadata->getId();
     $metadataItem = array($id => $metadata);
     $this->metadata += $metadataItem;
     foreach ($metadata->getHandles() as $handle) {
         if (!isset($this->metadataByHandle[$handle])) {
             $this->metadataByHandle[$handle] = array();
         }
         $this->metadataByHandle[$handle] += $metadataItem;
     }
     return $this;
 }