public function execute()
 {
     if ($this->thread_id = waRequest::get('thread_id', false)) {
         $cache = new waSerializeCache($this->getApp() . '.' . $this->thread_id);
         $this->urls = $cache->get();
         $cache->delete();
     }
     if ($this->urls) {
         wa()->getStorage()->close();
         ob_start();
         try {
             $this->model = new waAppSettingsModel();
             $log_level = waSystemConfig::isDebug() ? waInstaller::LOG_DEBUG : waInstaller::LOG_WARNING;
             $updater = new waInstaller($log_level, $this->thread_id);
             $this->getStorage()->close();
             $updater->init();
             $this->model->ping();
             $storage = wa()->getStorage();
             $storage->close();
             $this->urls = $updater->update($this->urls);
             if (waRequest::request('install')) {
                 $this->install();
             }
             $this->response['sources'] = $this->getResult();
             $this->response['current_state'] = $updater->getState();
             $this->response['state'] = $updater->getFullState(waRequest::get('mode', 'apps'));
             //cleanup cache
             $this->cleanup();
             //update themes
             foreach ($this->urls as $url) {
                 if (preg_match('@(wa-apps/)?(.+)/themes/(.+)@', $url['slug'], $matches)) {
                     try {
                         $theme = new waTheme($matches[3], $matches[2]);
                         $theme->update();
                     } catch (Exception $ex) {
                         waLog::log(sprintf('Error during theme %s@%s update: %s', $matches[3], $matches[2], $ex->getMessage()));
                     }
                 }
             }
             //and again cleanup
             $this->cleanup();
             $this->getConfig()->setCount(false);
             $response = $this->getResponse();
             $response->addHeader('Content-Type', 'application/json; charset=utf-8');
             $response->sendHeaders();
         } catch (Exception $ex) {
             $this->setError($ex->getMessage());
         }
         if ($ob = ob_get_clean()) {
             $this->response['warning'] = $ob;
             waLog::log('Output at ' . __METHOD__ . ': ' . $ob);
         }
     } else {
         throw new Exception('nothing to update');
     }
 }
 /**
  *
  * Render html block 'stack-navigation-panel' with json-data for RIA UI
  *
  * @param array $stack. Array of photos
  * @param array $current_photo. Array represented current photo
  *
  * @return string $html rendered html with 'photo-stream-cache' json data for RIA UI
  */
 public function getStackNavigationPanel($stack, $current_photo)
 {
     $theme_url = $this->theme->getUrl();
     $current = 0;
     $count = count($stack);
     $prev_in_stack = null;
     $next_in_stack = null;
     foreach ($stack as $photo) {
         if ($photo['id'] == $current_photo['id']) {
             if ($current > 0) {
                 $prev_in_stack = $stack[$current - 1];
                 //$prev_in_stack['url'] = str_replace('%url%', $prev_in_stack['url'], $url_template);
             }
             if ($current < $count - 1) {
                 $next_in_stack = $stack[$current + 1];
                 //$next_in_stack['url'] = str_replace('%url%', $next_in_stack['url'], $url_template);
             }
             break;
         }
         $current++;
     }
     $offset = $current + 1;
     $html = "<div class='stack-nav' data-photo-id='{$current_photo['id']}'>";
     $html .= '  <a href="' . ($prev_in_stack ? isset($prev_in_stack['full_url']) ? $prev_in_stack['full_url'] : $prev_in_stack['url'] : 'javascript:void(0);') . '" class="rewind"><img src="' . $theme_url . 'img/stack-rewind.png"></a>';
     $html .= "  <strong class='offset'>{$offset}</strong> / {$count}";
     $html .= '  <a href="' . ($next_in_stack ? isset($next_in_stack['full_url']) ? $next_in_stack['full_url'] : $next_in_stack['url'] : 'javascript:void(0);') . '" class="ff"><img src="' . $theme_url . 'img/stack-ff.png"></a>';
     // hidden stack-stream with class thumb need for rich gradual loading photo effect when go next/prev photo in stack
     $html .= '  <ul class="photostream" style="display:none;">';
     for ($i = 0; $i < $count; ++$i) {
         $html .= "  <li data-photo-id='{$stack[$i]['id']}' " . ($i == $current ? 'class="selected"' : '') . ">";
         $html .= "    <a href='{$stack[$i]['url']}'><img class='thumb' src='{$stack[$i]['thumb']['url']}" . (!is_null($stack[$i]['edit_datetime']) ? '?' . strtotime($stack[$i]['edit_datetime']) : '') . "'></a>";
         $html .= "  </li>";
     }
     $html .= '  </ul>';
     $html .= '</div>';
     $html .= '<script>';
     $html .= '    var __photo_stack_data = __photo_stack_data || {};';
     $html .= "    __photo_stack_data['{$current_photo['id']}'] = " . json_encode($stack);
     $html .= '</script>';
     return $html;
 }
 public function update($only_if_not_modified = true)
 {
     if (!$this->path_custom || $this->type != self::OVERRIDDEN) {
         return true;
     }
     $files = $this->getFiles();
     $modified = array();
     foreach ($files as $f_id => $f) {
         if (!empty($f['modified'])) {
             $modified[] = $f_id;
             break;
         }
     }
     if ($only_if_not_modified && $modified) {
         return false;
     }
     $img_files = array();
     foreach ($this->getSettings() as $s) {
         if (ifset($s['control_type']) == 'image' && !empty($s['value'])) {
             $img_files[] = $s['value'];
         }
     }
     $source_path = $this->path_original;
     $target_path = $this->path_custom;
     $list_files = waFiles::listdir($source_path);
     $skip_pattern = '/\\.(files\\.md5|cvs|svn|git|php\\d*)$/';
     foreach ($list_files as $f) {
         // ignore files
         if ($f !== 'build.php') {
             foreach ((array) $skip_pattern as $pattern) {
                 if (preg_match($pattern, $f)) {
                     continue 2;
                 }
             }
         }
         // ignore image settings and modified
         if ($f == 'theme.xml' || in_array($f, $img_files) || in_array($f, $modified)) {
             continue;
         }
         try {
             waFiles::copy($source_path . '/' . $f, $target_path . '/' . $f);
         } catch (waException $e) {
         }
     }
     if ($this->type == self::OVERRIDDEN) {
         $theme_original = new waTheme($this->id, $this->app_id, self::ORIGINAL);
         $this->version = $theme_original->version;
         foreach ($theme_original->getFiles(true) as $f_id => $f) {
             if (empty($files[$f_id])) {
                 $this->setFiles(array($f_id => $f));
             }
         }
         foreach ($theme_original->getSettings('full') as $var => $s) {
             if (!isset($this->info['settings'][$var])) {
                 $this->info['settings'][$var] = $s;
                 $this->settings[$var]['value'] = ifset($s['value'], '');
                 $this->changed['settings'][$var] = true;
             } else {
                 $old_s = $this->info['settings'][$var];
                 if (ifset($old_s['control_type']) != ifset($s['control_type']) || ifset($old_s['options']) != ifset($s['options'])) {
                     $s['value'] = ifset($old_s['value'], '');
                     $this->info['settings'][$var] = $s;
                     $this->settings[$var]['value'] = $s['value'];
                     $this->changed['settings'][$var] = true;
                 }
             }
         }
         $this->save();
     }
     return true;
 }
 /**
  * @param string $theme_id
  * @return string
  */
 public function themeUrl($theme_id)
 {
     $app_id = $this->wa->getConfig()->getApplication();
     $theme = new waTheme($theme_id, $app_id);
     return $theme->path ? $theme->getUrl() : null;
 }
 public function viewOriginalAction()
 {
     $theme_id = waRequest::get('theme_id');
     $template = $this->getConfig()->getRootPath() . '/wa-system/design/templates/DesignViewOriginal.html';
     $file = array();
     if ($theme_id && ($f = waRequest::get('file'))) {
         $app_id = $this->getAppId();
         $theme = new waTheme($theme_id, $app_id);
         $file = $theme->getFile($f);
         if ($file['parent']) {
             $theme = $theme->parent_theme;
             $theme_id = $theme->id;
             $app_id = $theme->app_id;
         }
         $theme_path = wa()->getAppPath('themes/' . $theme_id, $app_id) . '/';
         $path = $theme_path . $f;
         if ($theme['type'] == waTheme::OVERRIDDEN && file_exists($path)) {
             $file = $theme->getFile($f);
             $file['id'] = $f;
             $file['content'] = file_get_contents($path);
             $file['theme_path'] = str_replace(wa()->getConfig()->getRootPath(), '', $theme_path);
         }
     }
     $this->display(array('file' => $file), $template);
 }
 /**
  * Set template directory and global valiables.
  *
  * @param  waTheme $theme    Instance of theme object
  * @param  string  $template Path to template or resource string specifying template
  * @return bool
  */
 public function setThemeTemplate($theme, $template)
 {
     $this->assign('wa_active_theme_path', $theme->path);
     $this->assign('wa_active_theme_url', $this->getStaticUrl($theme->url));
     $theme_settings = $theme->getSettings(true);
     $theme_settings_config = $theme->getSettings();
     $locales = $theme->getLocales();
     $version = $theme->version(true);
     $file = $theme->getFile($template);
     if ($parent_theme = $theme->parent_theme) {
         $edition = $theme->edition + $parent_theme->edition;
         if (!empty($file['parent'])) {
             if ($parent_theme->version($edition) > $version) {
                 $version = $parent_theme->version($edition);
             } else {
                 $version = $theme->version($edition);
             }
             $theme = $parent_theme;
         }
         $this->assign('wa_parent_theme_url', $this->getStaticUrl($parent_theme->url));
         $this->assign('wa_parent_theme_path', $parent_theme->path);
         if ($parent_settings = $parent_theme->getSettings(true)) {
             $theme_settings = $theme_settings + $parent_settings;
             foreach ($parent_theme->getSettings() as $k => $v) {
                 if (!isset($theme_settings_config[$k])) {
                     $v['parent'] = 1;
                     $theme_settings_config[$k] = $v;
                 }
             }
         }
         if ($parent_theme->getLocales()) {
             $locales += $parent_theme->getLocales();
         }
     }
     $this->assign('wa_theme_version', $version);
     waLocale::setStrings($locales);
     $this->assign('theme_settings', $theme_settings);
     $this->assign('theme_settings_config', $theme_settings_config);
     $this->assign('wa_theme_url', $this->getStaticUrl($theme->url));
     $this->assign('wa_real_theme_url', $theme->url);
     $this->setTemplateDir($theme->path);
     return file_exists($theme->path . '/' . $template);
 }
 /**
  * @param string $theme_id
  * @return array
  */
 public function themeSettings($theme_id)
 {
     $app_id = $this->wa->getConfig()->getApplication();
     $theme = new waTheme($theme_id, $app_id);
     return $theme->getSettings(true);
 }
 protected function create($app_id, $path, $params = array())
 {
     if (!file_exists($path)) {
         $path .= '/';
         mkdir($path);
         mkdir($path . 'css');
         touch($path . 'css/' . $app_id . '.css');
         mkdir($path . 'js');
         touch($path . 'js/' . $app_id . '.js');
         mkdir($path . 'img');
         // lib
         mkdir($path . 'lib');
         waFiles::protect($path . 'lib');
         mkdir($path . 'lib/actions');
         // backend controller
         mkdir($path . 'lib/actions/backend');
         // api
         if (isset($params['api'])) {
             mkdir($path . 'lib/api');
             if ($params['api'] !== true) {
                 mkdir($path . 'lib/api/' . $params['api']);
             }
         }
         // cli
         if (isset($params['cli'])) {
             mkdir($path . 'lib/cli');
         }
         mkdir($path . 'lib/classes');
         mkdir($path . 'lib/models');
         // config
         mkdir($path . 'lib/config');
         // app description
         $app = array('name' => empty($params['name']) ? ucfirst($app_id) : $params['name'], 'icon' => 'img/' . $app_id . '.gif', 'version' => $version = empty($params['version']) ? '0.1' : $params['version']);
         if (isset($params['frontend'])) {
             $app['frontend'] = true;
             if (isset($params['themes'])) {
                 $app['themes'] = true;
             }
             $routing = array('*' => 'frontend');
             waUtils::varExportToFile($routing, $path . 'lib/config/routing.php');
             // frontend controller
             mkdir($path . 'lib/actions/frontend');
         }
         // plugins
         if (isset($params['plugins'])) {
             $app['plugins'] = true;
             mkdir($path . 'plugins');
         }
         waUtils::varExportToFile($app, $path . 'lib/config/app.php');
         // templates
         mkdir($path . 'templates');
         waFiles::protect($path . 'templates');
         mkdir($path . 'templates/actions');
         mkdir($path . 'templates/actions/backend');
         // backend template
         if (isset($params['frontend'])) {
             // frontend template
             mkdir($path . 'templates/actions/frontend');
         }
         // locale
         mkdir($path . 'locale');
         if (isset($params['frontend']) && isset($params['themes'])) {
             // themes
             mkdir($path . 'themes');
             mkdir($path . 'themes/default');
             $theme = new waTheme('default', $app_id, true);
             $theme->name = 'Default theme';
             $theme->description = 'Auto generated default theme';
             $theme->system = 1;
             $theme->addFile('index.html', 'Frontend index file');
             touch($path . 'themes/default/index.html');
             $theme->addFile('default.css', 'Frontend CSS file');
             touch($path . 'themes/default/default.css');
             $theme->version = $version;
             $theme->save();
         }
         print "App with id {$app_id} created";
     } else {
         print "App with id {$app_id} already exists";
     }
 }
 /**
  * @param waTheme $theme
  * @param string $template
  * @return bool
  */
 public function setThemeTemplate($theme, $template)
 {
     $this->assign('wa_active_theme_path', $theme->path);
     $this->assign('wa_active_theme_url', $theme->url);
     $file = $theme->getFile($template);
     if ($parent_theme = $theme->parent_theme) {
         if ($file['parent']) {
             $theme = $parent_theme;
         } else {
             $this->assign('wa_parent_theme_url', $parent_theme->url);
         }
     }
     $this->assign('wa_theme_url', $theme->url);
     $this->setTemplateDir($theme->path);
     return file_exists($theme->path . '/' . $template);
 }
Example #10
0
    protected function create($app_id, $path, $params = array())
    {
        $report = '';
        if (!file_exists($path)) {
            $path .= '/';
            mkdir($path);
            mkdir($path . 'css');
            touch($path . 'css/' . $app_id . '.css');
            mkdir($path . 'js');
            touch($path . 'js/' . $app_id . '.js');
            mkdir($path . 'img');
            // lib
            mkdir($path . 'lib');
            waFiles::protect($path . 'lib');
            mkdir($path . 'lib/actions');
            // backend controller
            mkdir($path . 'lib/actions/backend');
            // api
            if (isset($params['api'])) {
                mkdir($path . 'lib/api');
                if ($params['api'] !== true) {
                    mkdir($path . 'lib/api/' . $params['api']);
                } else {
                    mkdir($path . 'lib/api/v1');
                }
            }
            // cli
            if (isset($params['cli'])) {
                mkdir($path . 'lib/cli');
            }
            mkdir($path . 'lib/classes');
            mkdir($path . 'lib/models');
            // config
            mkdir($path . 'lib/config');
            // app description
            $app = array('name' => empty($params['name']) ? ucfirst($app_id) : $params['name'], 'icon' => 'img/' . $app_id . '.gif', 'version' => $version = empty($params['version']) ? '0.1' : $params['version'], 'vendor' => $vendor = empty($params['vendor']) ? '--' : $params['vendor']);
            if (isset($params['frontend'])) {
                $app['frontend'] = true;
                if (isset($params['themes'])) {
                    $app['themes'] = true;
                }
                $routing = array('*' => 'frontend');
                waUtils::varExportToFile($routing, $path . 'lib/config/routing.php');
                // frontend controller
                mkdir($path . 'lib/actions/frontend');
            }
            // plugins
            if (isset($params['plugins'])) {
                $app['plugins'] = true;
                mkdir($path . 'plugins');
            }
            waUtils::varExportToFile($app, $path . 'lib/config/app.php');
            // templates
            mkdir($path . 'templates');
            waFiles::protect($path . 'templates');
            mkdir($path . 'templates/actions');
            mkdir($path . 'templates/actions/backend');
            // backend template
            if (isset($params['frontend'])) {
                // frontend template
                mkdir($path . 'templates/actions/frontend');
            }
            // locale
            mkdir($path . 'locale');
            waFiles::protect($path . 'locale');
            if (isset($params['frontend']) && isset($params['themes'])) {
                // themes
                mkdir($path . 'themes');
                mkdir($path . 'themes/default');
                $theme = new waTheme('default', $app_id, true);
                $theme->name = 'Default theme';
                $theme->description = 'Auto generated default theme';
                $theme->vendor = $vendor;
                $theme->system = 1;
                $theme->addFile('index.html', 'Frontend index file');
                touch($path . 'themes/default/index.html');
                $theme->addFile('default.css', 'Frontend CSS file');
                touch($path . 'themes/default/default.css');
                $theme->version = $version;
                $theme->save();
                waFiles::move($theme->path . '/theme.xml', $path . 'themes/default/theme.xml');
            }
            $report .= <<<REPORT
App with id "{$app_id}" created!

Useful commands:
    #generate app's database description file db.php
    php wa.php generateDb {$app_id}

    #generate app's locale files
    php wa-system/locale/locale.php {$app_id}
REPORT;
            if (isset($params['plugins'])) {
                $report .= "\n\n" . <<<REPORT
    #create a plugin with specified 'plugin_id' for your app
    php wa.php createPlugin {$app_id} plugin_id
REPORT;
            }
            //TODO add hint about compress command
        } else {
            $report .= <<<REPORT
App with id "{$app_id}" already exists.
REPORT;
        }
        print $report . "\n";
    }
 /**
  * Set template directory and global valiables.
  *
  * @param  waTheme $theme    Instance of theme object
  * @param  string  $template Path to template or resource string specifying template
  * @return bool
  */
 public function setThemeTemplate($theme, $template)
 {
     $this->assign('wa_active_theme_path', $theme->path);
     $this->assign('wa_active_theme_url', $theme->url);
     $this->assign('wa_theme_version', $theme->version());
     $theme_settings = $theme->getSettings(true);
     $locales = $theme->getLocales();
     $file = $theme->getFile($template);
     if ($parent_theme = $theme->parent_theme) {
         if (!empty($file['parent'])) {
             $theme = $parent_theme;
         }
         $this->assign('wa_parent_theme_url', $parent_theme->url);
         $this->assign('wa_parent_theme_path', $parent_theme->path);
         if ($parent_settings = $parent_theme->getSettings(true)) {
             $theme_settings = $theme_settings + $parent_settings;
         }
         if ($parent_theme->getLocales()) {
             $locales += $parent_theme->getLocales();
         }
     }
     waLocale::setStrings($locales);
     $this->assign('theme_settings', $theme_settings);
     $this->assign('wa_theme_url', $theme->url);
     $this->setTemplateDir($theme->path);
     return file_exists($theme->path . '/' . $template);
 }
Example #12
0
 /**
  * Returns id of design theme used in current frontend page.
  *
  * @return string
  */
 public static function getTheme()
 {
     $app_id = wa()->getConfig()->getApplication();
     $key = wa()->getRouting()->getDomain() . '/theme';
     if (($theme_hash = self::get('theme_hash')) && ($theme = self::get('set_force_theme')) !== null) {
         $app_settings_model = new waAppSettingsModel();
         $hash = $app_settings_model->get($app_id, 'theme_hash');
         $global_hash = $app_settings_model->get('webasyst', 'theme_hash');
         if ($theme_hash == md5($hash)) {
             if ($theme && waTheme::exists($theme)) {
                 wa()->getStorage()->set($app_id . '/' . $key, $theme);
                 return $theme;
             } else {
                 wa()->getStorage()->del($app_id . '/' . $key);
             }
         } elseif ($global_hash && $theme_hash == md5($global_hash)) {
             if ($theme && waTheme::exists($theme)) {
                 wa()->getStorage()->set($key, $theme);
                 return $theme;
             } else {
                 wa()->getStorage()->del($key);
             }
         }
     } elseif ((($theme = wa()->getStorage()->get($app_id . '/' . $key)) || ($theme = wa()->getStorage()->get($key))) && waTheme::exists($theme)) {
         return $theme;
     }
     if (self::isMobile()) {
         return self::param('theme_mobile', 'default');
     }
     return self::param('theme', 'default');
 }
Example #13
0
    /**
     * Returns the list of previously added JavaScript file URLs.
     *
     * @param  bool  $html   Determines whether method must return an HTML string for including JavaScript files or an array of URLs
     * @param  bool  $strict  Determines whether XHTML format must be used instead of default HTML
     * @return  string|array  HTML string or array of URLs
     */
    public function getJs($html = true, $strict = false)
    {
        if (!$html) {
            return $this->js;
        }
        $result = '';
        foreach ($this->js as $url) {
            $result .= '<script' . ($strict ? ' type="text/javascript"' : '') . ' src="' . $url . '"></script>' . PHP_EOL;
        }
        if (wa()->getEnv() == 'frontend') {
            $app_id = wa()->getApp();
            $key = wa()->getRouting()->getDomain() . '/theme';
            $hash = false;
            if (waRequest::get('theme_hash') && ($theme = waRequest::get('set_force_theme')) !== null) {
                $hash = waRequest::get('theme_hash');
            } elseif (($theme = wa()->getStorage()->get($app_id . '/' . $key)) || ($theme = wa()->getStorage()->get($key))) {
                $app_settings_model = new waAppSettingsModel();
                $hash = $app_settings_model->get($app_id, 'theme_hash');
                if (!$hash) {
                    $hash = $app_settings_model->get('webasyst', 'theme_hash');
                }
                if ($hash) {
                    $hash = md5($hash);
                }
            }
            if (!$hash || !$theme || !waTheme::exists($theme)) {
                return $result;
            }
            $theme = new waTheme($theme, $app_id);
            $theme = $theme['name'];
            $url = '?theme_hash=' . $hash . '&set_force_theme=';
            $result .= '
<script type="text/javascript">
$(function () {
    var div = $("<div></div>");
    div.css({
        position: "fixed",
        bottom: 0,
        left: 0,
        right: 0,
        opacity: 0.9,
        padding: "15px",
        "text-align": "center",
        background: "#ffd",
        "border-top": "4px solid #eea",
        "border-image": "url(\'' . wa()->getUrl() . 'wa-content/img/recovery-mode-background.png\') 10 10 10 10 repeat",
        "font-family": "Lucida Grande",
        "font-size": "14px",
        "z-index": 100500,
    });
    div.html("' . sprintf(_ws('<strong>%s</strong> theme preview in action'), $theme) . '");';
            if (wa()->getUser()->isAuth() && wa()->getUser()->getRights('shop')) {
                $result .= '
    div.prepend(\'<a href="' . $url . '" style="float: right;">' . _ws('Stop preview session') . '</a>\');
    div.find("a").click(function () {
        $("body").append($(\'<iframe style="display:none" src="\' + $(this).attr("href") + \'" />\').load(function () {
            $(this).remove();
            div.remove();
            if (location.href.indexOf("theme_hash") != -1) {
                location.href = location.href.replace(/(theme_hash|set_force_theme)=[^&]*&?/g, "");
            }
        }));
        return false;
    });';
            }
            $result .= '
    $("body").append(div);
});
</script>';
        }
        return $result;
    }
    protected function create($params = array())
    {
        //TODO layout|ajax|simple mode
        $structure = array("css/{$this->app_id}.css", "js/{$this->app_id}.js", "img/", "img/{$this->app_id}48.png" => $this->root_path . 'wa-content/img/dummy-app-icon-48.png', "img/{$this->app_id}96.png" => $this->root_path . 'wa-content/img/dummy-app-icon-96.png', "lib/", "lib/actions/backend/", "lib/actions/backend/{$this->app_id}Backend.action.php" => $this->getActionCode(), "templates/actions/backend/Backend.html" => $this->getDefaultTemplate(), "lib/classes/", "lib/models/", "lib/config/", "locale/");
        $features = array_map('trim', preg_split('@[,\\s]+@', ifset($params['features'], $this->getDefaults('features'))));
        // api
        if (in_array('api', $features, true)) {
            $structure = array_merge($structure, array("lib/api/v1/"));
        }
        if (in_array('cli', $features, true)) {
            $structure = array_merge($structure, array("lib/cli/", "lib/cli/{$this->app_id}Example.cli.php" => $this->getCliController()));
        }
        $protect = array('lib', 'templates');
        // app description
        $app = array('name' => empty($params['name']) ? ucfirst($this->app_id) : $params['name'], 'icon' => array(48 => "img/{$this->app_id}48.png", 96 => "img/{$this->app_id}96.png"), 'version' => ifempty($params['version'], $this->getDefaults('version')), 'vendor' => ifempty($params['vendor'], $this->getDefaults('vendor')));
        if (isset($params['frontend'])) {
            $app['frontend'] = true;
            if ($params['frontend'] == 'themes') {
                $app['themes'] = true;
            }
            $routing = array('*' => 'frontend');
            $structure['lib/config/routing.php'] = $routing;
            $structure = array_merge($structure, array('lib/actions/frontend/', "lib/actions/frontend/{$this->app_id}Frontend.action.php" => $this->getActionCode('default', false, $app)));
            if (!empty($app['themes'])) {
                $structure = array_merge($structure, array('themes/.htaccess' => '
<FilesMatch "\\.(php\\d*|html?|xml)$">
    Deny from all
</FilesMatch>
', 'themes/default/index.html' => $this->getFrontendTemplate(), 'themes/default/css/default.css'));
            } else {
                $structure = array_merge($structure, array("templates/actions/frontend/Frontend.html" => $this->getFrontendTemplate(), "css/frontend/{$this->app_id}.css"));
            }
        }
        if (isset($params['plugins'])) {
            $structure = array_merge($structure, array("plugins/"));
            $app['plugins'] = true;
        }
        $structure['lib/config/app.php'] = $app;
        $this->createStructure($structure);
        $this->protect($protect);
        if (!empty($app['themes'])) {
            waFiles::delete(wa()->getDataPath('themes/default', true, $this->app_id));
            $theme = new waTheme('default', $this->app_id, true);
            $theme->name = 'Default theme';
            $theme->description = 'Auto generated default theme';
            $theme->vendor = $app['vendor'];
            $theme->version = $app['version'];
            $theme->addFile('index.html', 'Frontend index file');
            $theme->addFile('css/default.css', 'Frontend CSS file');
            $theme->save();
            waFiles::move($theme->path . '/theme.xml', $this->path . 'themes/default/theme.xml');
        }
        if (!isset($params['disable'])) {
            $this->installApp();
            $errors = $this->flushCache();
            if ($errors) {
                print "Error during delete cache files:\n\t" . implode("\n\t", $errors) . "\n";
            }
        }
        return $app;
    }