Start.php 14.1 KB
Newer Older
1 2
<?php
// Dobrado Content Management System
3
// Copyright (C) 2018 Malcolm Blaney
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

class Start extends Base {

  public function Add($id) {

  }

  public function Callback() {
25 26
    if ($_POST['action'] === 'tooltip') return $this->Tooltip();
    return ['error' => 'Unknown action'];
27 28 29
  }

  public function CanAdd($page) {
30 31 32 33 34
    if ($this->owner === 'admin' &&
        $page === $this->Substitute('indieauth-page') &&
        $this->user->group === $this->Substitute('indieauth-group')) {
      return true;
    }
35 36
    // Add start module for all users on Unicyclic, but only want to add it for
    // admin users otherwise.
37
    if ($this->owner === $this->user->name &&
38 39
        ($this->GroupMember('admin', 'admin') ||
         $this->Substitute('start-profile') === 'unicyclic')) {
40 41 42
      return true;
    }
    return false;
43 44 45 46 47 48 49 50 51 52 53
  }

  public function CanEdit($id) {
    return false;
  }

  public function CanRemove($id) {
    return true;
  }

  public function Content($id) {
54
    $content = '';
55 56 57
    if ($this->owner === 'admin' &&
        $this->user->page === $this->Substitute('indieauth-page') &&
        $this->user->group === $this->Substitute('indieauth-group')) {
58 59
      $content = $this->Substitute('start-indieauth');
    }
60
    else if ($this->owner === $this->user->name &&
61 62
             ($this->GroupMember('admin', 'admin') ||
             $this->Substitute('start-profile') === 'unicyclic')) {
63 64 65 66
      $content = '<div class="start-show ui-state-highlight ui-corner-all">' .
        '<input type="checkbox" id="start-show-message" checked="checked">' .
        '<label for="start-show-message">Show this message and navigation ' .
          'tips when I log in.</label></div>' .
67
        $this->Substitute('start-content');
68
    }
69 70 71 72 73
    else {
      return false;
    }
    // This session variable is checked by init.php
    $_SESSION['start'] = true;
74 75
    // Wrap the content to go in a dialog, otherwise placing the whole module
    // in a dialog that gets added to the page messes with the layout editor.
76
    return '<div class="content">' . $content . '</div>';
77 78 79 80 81 82 83 84 85 86 87
  }

  public function Copy($id, $new_page, $old_owner, $old_id) {

  }

  public function Cron() {

  }

  public function Factory($fn, $p = NULL) {
88
    if ($fn === 'Tooltip') {
89 90
      return $this->Tooltip();
    }
91 92 93
    if ($fn === 'Settings') {
      return $this->Settings();
    }
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
  }

  public function Group() {

  }

  public function IncludeScript() {
    return true;
  }

  public function Install($path) {
    // Append dobrado.start.js to the existing dobrado.js file.
    // Note that this module is only available when logged in.
    $this->AppendScript($path, 'dobrado.start.js', false);

109 110 111 112 113 114 115
    $us_content = '<p>Thanks for creating an account on ' .
        $this->user->config->ServerName() . '!</p>' .
      '<p>When you uncheck the option above, you can always bring back this ' .
        'dialog and the navigation tips on each page by clicking on the ' .
        'account button and selecting <b>Help</b> from the menu.</p>' .
      '<p>You will see navigation tips on some pages. If at any time you\'re ' .
        'not sure what to do, please use the <a href="/contact">contact</a> ' .
116 117
        'page to ask questions.</p>';

118 119 120
    $us_indieauth = '<p>Thanks for logging in at ' .
        $this->user->config->ServerName() . '!</p>' .
      '<p>If you need any help please use the <a href="/contact">contact</a> ' .
121
        'page to ask questions.</p>';
122 123

    $mysqli = connect_db();
124 125 126 127
    $template = ['"start-content","","' .
                   $mysqli->escape_string($us_content) . '"',
                 '"start-indieauth","","' .
                   $mysqli->escape_string($us_indieauth) . '"'];
128 129 130 131
    $mysqli->close();

    $this->AddTemplate($template);

132
    $site_style = ['"",".start","display","none"',
133
                   '"",".start-show","padding","5px"',
134
                   '"","#start-show-message","float","none"'];
135 136 137 138
    $this->AddSiteStyle($site_style);
  }

  public function Placement() {
139 140 141 142 143 144
    // This allows users logged in with indieauth to view the Start module.
    if ($this->owner === 'admin' &&
        $this->user->page === $this->Substitute('indieauth-page') &&
        $this->user->group === $this->Substitute('indieauth-group')) {
      return 'outside';
    }
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
    return 'middle';
  }

  public function Publish($id, $update) {

  }

  public function Remove($id) {
    unset($_SESSION['start']);
  }

  public function SetContent($id, $us_content) {

  }

  public function Update() {
161

162 163 164 165 166 167 168 169 170 171
  }

  public function UpdateScript($path) {
    $this->AppendScript($path, 'dobrado.start.js', false);
  }

  // Private functions below here ////////////////////////////////////////////

  private function Lettuceshare() {
    // First set of tooltips are for when a user is on their home page.
172
    if ($this->user->name === $this->owner && $this->user->page === 'index') {
173 174
      // The first thing they should do is visit the stock page.
      if (can_view_page('admin/stock') || can_edit_page('admin/stock')) {
175
        return ['selector' => '#page-select-button',
176
                'content' => 'To update your product list, choose ' .
177 178
                  'stock from the menu to go to the stock page.',
                'arrow' => '250px'];
179 180 181
      }
      // Otherwise let admin users know how to create accounts.
      if ($this->GroupMember('admin', 'admin')) {
182
        return ['selector' => '.account-button',
183
                'content' => 'To create new accounts, click the ' .
184 185
                  'account button and select Manage Accounts.',
                'arrow' => '5px'];
186 187 188
      }
    }
    // Show some tooltips once the user has navigated to the stock page. 
189
    if ($this->owner === 'admin' && $this->user->page === 'stock') {
190 191 192 193
      // First check if they have created any suppliers.
      $stock = new Module($this->user, $this->owner, 'stock');
      if ($stock->IsInstalled()) {
        if (count($stock->Factory('AllSuppliers')) === 0) {
194
          return ['selector' => '#stock-open-product-form',
195 196
                  'content' => 'To add products, you first need to create an ' .
                    'account for each supplier. To do this open the product ' .
197 198
                    'form and click Add Supplier.',
                  'arrow' => '150px'];
199 200
        }
        else {
201
          return ['selector' => 'label[for=stock-show-import]',
202 203 204 205
                  'content' => 'You can import a product list by clicking ' .
                    'Import and selecting a file from your computer, or by ' .
                    'opening the product form to the right and creating ' .
                    'products manually. Click the help button for more ' .
206
                    'information.'];
207 208 209
        }
      }
    }
210
    if ($this->owner === 'admin' && $this->user->page === 'payments') {
211
      return ['selector' => '#payment-import-input',
212 213 214 215
              'content' => 'You can add payments by filling in this form, or ' .
                'click the import button and select a file from your ' .
                'computer. If you\'re not sure if your bank\'s file format ' .
                'is supported by Lettuceshare, please email: ' .
216
                'info@lettuceshare.org.'];
217 218 219
    }
  }

220 221 222
  private function PageCreated($page) {
    $created = true;
    $mysqli = connect_db();
223 224
    $query = 'SELECT box_id FROM modules WHERE user = "' . $this->owner . '" ' .
      'AND page = "' . $page . '"';
225 226 227 228 229
    if ($result = $mysqli->query($query)) {
      $created = $result->num_rows !== 0;
      $result->close();
    }
    else {
230
      $this->Log('Start->PageCreated: ' . $mysqli->error);
231 232 233 234 235
    }
    $mysqli->close();
    return $created;
  }

236 237
  private function Settings() {
    $profile = $this->Substitute('start-profile');
238
    if ($profile === 'lettuceshare' || $profile === 'hidden') {
239 240
      return ['control' => ['displayMessageButton' => 'hidden',
                            'displayToolsButton' => 'hidden']];
241
    }
242 243
    if ($profile === 'unicyclic') {
      return ['control' => ['displayMessageButton' => 'hidden',
244 245 246
                            'displayToolsButton' => 'display'],
              'reader' => ['defaultChannel' => 'all',
                           'showChannels' => 'yes']];
247
    }
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
    return [];
  }

  private function Tooltip() {
    // Since tooltips are very design dependent, at least allow different
    // profiles to be added.
    $profile = $this->Substitute('start-profile');
    if ($profile === 'lettuceshare') {
      return $this->Lettuceshare();
    }
    if ($profile === 'unicyclic') {
      return $this->Unicyclic();
    }
  }

263
  private function Unicyclic() {
264
    if ($this->user->name === $this->owner && $this->user->page === 'index') {
265 266
      // Use this profile to create some default pages for a new user if they
      // don't already exist. The blog page is where new posts are published.
267 268 269
      if (!$this->PageCreated('blog')) {
        copy_page('default_blog', 'admin', 'blog', $this->owner);
      }
270 271 272 273 274 275 276 277
      // By default likes and replies are not published to the users blog.
      // Instead separate pages are created to list each of these.
      if (!$this->PageCreated('likes')) {
        copy_page('default_likes', 'admin', 'likes', $this->owner);
      }
      if (!$this->PageCreated('replies')) {
        copy_page('default_replies', 'admin', 'replies', $this->owner);
      }
278 279 280 281
      // The default_post page is used as a template for permalink pages.
      if (!$this->PageCreated('default_post')) {
        copy_page('default_post', 'admin', 'default_post', $this->owner);
      }
282 283 284 285
      // The default_pager page is used as a template for 'pager' pages.
      if (!$this->PageCreated('default_pager')) {
        copy_page('default_pager', 'admin', 'default_pager', $this->owner);
      }
286 287 288 289
      // The reader page contains both reader and writer modules, so to ensure
      // that posts on this page are visible on their own, designate that they
      // get posted to the blog page. Then also subscribe to the blog page so
      // that they show up on the reader page too.
290 291 292 293
      if (!$this->PageCreated('reader')) {
        copy_page('default_reader', 'admin', 'reader', $this->owner);
        $writer = new Module($this->user, $this->owner, 'writer');
        if ($writer->IsInstalled()) {
294 295 296 297
          $writer->Factory('Designate', ['post', 'reader', 'blog']);
          $writer->Factory('Designate', ['share', 'reader', 'blog']);
          $writer->Factory('Designate', ['like', 'reader', 'likes']);
          $writer->Factory('Designate', ['reply', 'reader', 'replies']);
298
          // Also need to redirect likes and replies on the blog page.
299 300
          $writer->Factory('Designate', ['like', 'blog', 'likes']);
          $writer->Factory('Designate', ['reply', 'blog', 'replies']);
301 302 303 304 305
        }
        $reader = new Module($this->user, $this->owner, 'reader');
        if ($reader->IsInstalled()) {
          $id = 0;
          $mysqli = connect_db();
306 307 308
          $query = 'SELECT box_id FROM modules WHERE ' .
            'user = "' . $this->owner . '" AND label = "reader" AND ' .
            'page="reader"';
309 310 311 312 313 314 315
          if ($result = $mysqli->query($query)) {
            if ($modules = $result->fetch_assoc()) {
              $id = (int)$modules['box_id'];
            }
            $result->close();
          }
          else {
316
            $this->Log('Start->Unicyclic: ' . $mysqli->error);
317 318 319
          }
          $mysqli->close();
          if ($id !== 0) {
320 321 322 323 324 325 326 327 328 329 330 331 332
            $scheme = $this->user->config->Secure() ? 'https://' : 'http://';
            $server = $this->user->config->ServerName();
            $feed = $scheme . $server .
              $this->Url('', 'blog', $this->user->name);
            $reader->Factory('AddFeed', [$id, $feed, true]);
            // Also add a default follow for this server if set.
            $follow_user = $this->Substitute('start-follow-user');
            $follow_page = $this->Substitute('start-follow-page');
            if ($follow_user !== '' && $follow_page !== '') {
              $feed = $scheme . $server .
                $this->Url('', $follow_page, $follow_user);
              $reader->Factory('AddFeed', [$id, $feed, true]);
            }
333 334 335 336 337
          }
        }
      }

      // Show a tool tip on their home page.
338
      return ['selector' => '#page-input',
339
              'content' => 'Type reader here to get to your page where ' .
340 341
                'you can manage feeds, and also write content.',
              'arrow' => '250px'];
342 343
    }
    // Show a tooltip once the user has navigated to their reader page. 
344 345 346
    if ($this->user->page === 'reader') {
      if ($this->user->name === $this->owner) {
        return ['selector' => '.writer-edit-settings',
347 348
                'content' => 'Click the edit button to manage your feeds.' .
                  'You are already subscribed to your own posts, they are ' .
349 350 351 352 353
                  'currently saved to your blog page.'];
      }
      else {
        // This can be seen by users logged in via indieauth.
        return ['selector' => '.writer-edit-settings',
354 355
                'content' => 'Click the edit button to manage your feeds.' .
                  'You might already be subscribed to your own, if a feed ' .
356 357
                  'was found on your site when you logged in.'];
      }
358 359
    }
    // Show a tooltip once the user has navigated to their blog page. 
360
    if ($this->user->name === $this->owner && $this->user->page === 'blog') {
361 362 363 364
      return ['selector' => '.writer-options-add',
              'content' => 'Your posts can be written either here or on your ' .
                'reader page (they will be displayed on both). Try clicking ' .
                'the add button to add a title or a different author to a ' .
365
                'post.'];
366 367 368
    }
  }

369
}