/**
  * Parses shortcode - parent or single
  * @param ctShortcode $code
  * @param string $result
  * @return string
  */
 protected function handleShortcode($code, $result = '', $withHtml = false)
 {
     $child = $code->getChildShortcodeInfo();
     if (!$child || !$child['name']) {
         $attributes = $code->getAttributesNormalized();
         //remove builtin queryable data
         if ($code instanceof ctShortcodeQueryable) {
             $default = $code->getQueryAllAttributes();
             $attributes = array_diff_key($attributes, $default);
         }
         $combs = $this->parseAttributes($code, $attributes);
         $data = $this->combinations($this->filterAttributes($code, $combs));
         if (!$data) {
             $data[] = array('');
         }
         $content = '';
         //content - let's find it
         if (isset($attributes['content'])) {
             $content = $this->getDefaultFromAttributes($attributes['content'], $this->getTextareaValue());
         }
         foreach ($data as $e) {
             $params = '';
             if ($e) {
                 if (is_array($e)) {
                     $params = ' ' . implode(' ', $e);
                 } else {
                     $params = $e ? ' ' . $e : '';
                 }
             }
             if (!isset($this->childShortcodes[$code->getShortcodeName()])) {
                 $result .= '<pre class="shortcodeTest">&#91;' . $code->getShortcodeName() . $params . '&#93;</pre>';
             }
             $s = '[' . $code->getShortcodeName() . $params . ']';
             if ($content) {
                 $s .= $content . '[/' . $code->getShortcodeName() . ']';
             }
             $result .= $s;
             // konfiguracja Tidy
             $config = array('indent' => true, 'output-xhtml' => true, 'wrap' => 200, 'fix-backslash' => false, 'fix-bad-comments' => false, 'fix-uri' => false, 'join-styles' => false, 'lower-literals' => false, 'show-body-only' => true);
             $sCode = do_shortcode($s);
             if (class_exists('tidy')) {
                 // przetwarzanie Tidy
                 $tidy = new tidy();
                 $tidy->parseString($sCode, $config, 'utf8');
                 $tidy->cleanRepair();
                 $sCode = (string) $tidy;
             }
             if ($withHtml) {
                 $result .= '<div class="htmlTest">HTML:<pre class="htmlTest">' . htmlentities($sCode) . '</pre></div>';
                 $result .= '<hr class="htmlTest" style="margin-bottom:50px">';
             }
             //$result .= "\n";
         }
         return $result;
     } else {
         $result = '[' . $code->getShortcodeName() . ']' . "\n";
         $c = $code->getChildShortcode();
         for ($x = 0; $x < 3; $x++) {
             $result .= $this->handleShortcode($c);
         }
         $result .= '[/' . $code->getShortcodeName() . ']';
     }
     return $result;
 }
 /**
  * Handles shortcode form
  * @param ctShortcode $shortcode
  * @param null $containerName
  * @param null $defaults
  * @throws Exception
  * @return bool|string
  */
 protected function appendShortcodeForm($shortcode, $containerName = null, $defaults = null)
 {
     $containerName = $containerName ? $containerName : 'container_' . ++$this->counter;
     $this->form->addBreak($containerName);
     $attributes = array_diff_key($shortcode->getAttributesNormalized(), $this->bannedAttributes);
     $defaults = $defaults ? $defaults : $this->defaults;
     foreach ($attributes as $name => $attribute) {
         $attribute = $this->normalizeAttribute($name, $attribute, $defaults);
         //may be false
         if ($attribute['type'] && $attribute['type'] != 'false') {
             if (!method_exists($this, $attribute['type'])) {
                 throw new Exception("Cannot handle " . $attribute['type'] . ' type');
             }
             $this->{$attribute}['type']($name, $attribute);
         }
     }
     return false;
 }