Deployed 256c1d6 to 5.4 with MkDocs 1.1.2 and mike 1.0.0
[GitHub/WoltLab/woltlab.github.io.git] / 5.3 / getting-started_quick-start.html
CommitLineData
d9cdc0cc
TD
1<!DOCTYPE html>
2<head>
3 <meta charset="utf-8">
4<meta http-equiv="X-UA-Compatible" content="IE=edge">
5<meta name="viewport" content="width=device-width, initial-scale=1">
6<meta name="description" content="">
7<meta name="keywords" content=" ">
8<title>Creating a simple package | WoltLab Suite 5.3 Documentation</title>
9
e2f8eee7 10<link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/syntax.css">
d9cdc0cc 11<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400,300,600">
e2f8eee7 12<link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/font-awesome.min.css">
d9cdc0cc 13<!--<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">-->
e2f8eee7
TD
14<link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/modern-business.css">
15<link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/lavish-bootstrap.css">
16<link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/customstyles.css">
17<link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/theme-blue.css?v=3">
d9cdc0cc 18
e2f8eee7
TD
19<script src="https://docs.woltlab.com/5.3/js/jquery.min.js"></script>
20<script src="https://docs.woltlab.com/5.3/js/jquery.cookie.min.js"></script>
21<script src="https://docs.woltlab.com/5.3/js/jquery.navgoco.min.js"></script>
22<script src="https://docs.woltlab.com/5.3/js/bootstrap.min.js"></script>
23<script src="https://docs.woltlab.com/5.3/js/anchor.min.js"></script>
24<script src="https://docs.woltlab.com/5.3/js/toc.js"></script>
25<script src="https://docs.woltlab.com/5.3/js/customscripts.js"></script>
d9cdc0cc 26
e2f8eee7 27<link rel="shortcut icon" href="https://docs.woltlab.com/5.3/images/favicon.ico">
d9cdc0cc 28
e2f8eee7 29<link rel="alternate" type="application/rss+xml" title="woltlab.github.io" href="https://docs.woltlab.com/5.3feed.xml">
d9cdc0cc
TD
30
31 <script>
32 $(document).ready(function() {
33 // Initialize navgoco with default options
34 $("#mysidebar").navgoco({
35 caretHtml: '',
36 accordion: true,
37 openClass: 'active', // open
38 save: false, // leave false or nav highlighting doesn't work right
39 cookie: {
40 name: 'navgoco',
41 expires: false,
42 path: '/'
43 },
44 slide: {
45 duration: 400,
46 easing: 'swing'
47 }
48 });
49
50 $("#collapseAll").click(function(e) {
51 e.preventDefault();
52 $("#mysidebar").navgoco('toggle', false);
53 });
54
55 $("#expandAll").click(function(e) {
56 e.preventDefault();
57 $("#mysidebar").navgoco('toggle', true);
58 });
59
60 });
61
62 </script>
63 <script>
64 $(function () {
65 $('[data-toggle="tooltip"]').tooltip()
66 })
67 </script>
68
69
70</head>
71<body>
72 <!-- Navigation -->
73<nav class="navbar navbar-inverse navbar-fixed-top">
74 <div class="container topnavlinks">
75 <div class="navbar-header">
76 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
77 <span class="sr-only">Toggle navigation</span>
78 <span class="icon-bar"></span>
79 <span class="icon-bar"></span>
80 <span class="icon-bar"></span>
81 </button>
82 <a class="fa fa-home fa-lg navbar-brand" href="index.html">&nbsp;<span class="projectTitle"> WoltLab Suite 5.3 Documentation</span></a>
83 </div>
84 <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
85 <ul class="nav navbar-nav navbar-right">
86 <!-- entries without drop-downs appear here -->
87
88
89
90 <li><a href="https://www.woltlab.com" target="_blank">woltlab.com</a></li>
91
92
93
94
95
96 <li><a href="https://github.com/WoltLab/WCF/" target="_blank">Code on github.com</a></li>
97
98
99
100 <!-- entries with drop-downs appear here -->
101 <!-- conditional logic to control which topnav appears for the audience defined in the configuration file.-->
102
103
104 <!--comment out this block if you want to hide search-->
105 <li>
106 <!--start search-->
107 <div id="search-demo-container">
108 <input type="text" id="search-input" placeholder="search...">
109 <ul id="results-container"></ul>
110 </div>
e2f8eee7 111 <script src="https://docs.woltlab.com/5.3/js/jekyll-search.js" type="text/javascript"></script>
d9cdc0cc
TD
112 <script type="text/javascript">
113 SimpleJekyllSearch.init({
114 searchInput: document.getElementById('search-input'),
115 resultsContainer: document.getElementById('results-container'),
e2f8eee7 116 dataSource: 'https://docs.woltlab.com/5.3/search.json',
d9cdc0cc
TD
117 searchResultTemplate: '<li><a href="{url}" title="Creating a simple package">{title}</a></li>',
118 noResultsText: 'No results found.',
119 limit: 10,
120 fuzzy: true,
121 })
122 </script>
123 <!--end search-->
124 </li>
125 </ul>
126 </div>
127 </div>
128 <!-- /.container -->
129</nav>
130
131
132 <div class="container">
133 <div class="col-lg-12">&nbsp;</div>
134
135 <div class="row">
136 <div class="col-md-3">
137
138
139
140<ul id="mysidebar" class="nav">
141 <li class="sidebarTitle">WoltLab Suite 5.3</li>
142
143
144
145 <li>
146 <a href="#">Getting Started</a>
147 <ul>
148
149
150
151
152 <li data-identifier="index"><a href="index.html">Introduction</a></li>
153
154
155
156
157
158
159
160
161 <li class="active" data-identifier="getting-started_quick-start"><a href="getting-started_quick-start.html">Quick Start</a></li>
162
163
164
165
166
167 </ul>
168 </li>
169
170 <li>
171 <a href="#">PHP API</a>
172 <ul>
173
174
175
176
177 <li data-identifier="php_pages"><a href="php_pages.html">Pages</a></li>
178
179
180
181
182
183
184
185
186 <li data-identifier="php_database-objects"><a href="php_database-objects.html">Database Objects</a></li>
187
188
189
190
191
192
193
194
195 <li data-identifier="php_database-access"><a href="php_database-access.html">Database Access</a></li>
196
197
198
199
200
201
202
203
204 <li data-identifier="php_exceptions"><a href="php_exceptions.html">Exceptions</a></li>
205
206
207
208
209
210
211
212
213 <li class="subfolders">
214 <a href="#">API</a>
215 <ul>
216
217
218
219 <li data-identifier="php_api_caches"><a href="php_api_caches.html">Caches</a></li>
220
221
222
223
224 <li data-identifier="php_api_comments"><a href="php_api_comments.html">Comments</a></li>
225
226
227
228
229 <li data-identifier="php_api_cronjobs"><a href="php_api_cronjobs.html">Cronjobs</a></li>
230
231
232
233
234 <li data-identifier="php_api_events"><a href="php_api_events.html">Events</a></li>
235
236
237
238
239 <li data-identifier="php_api_form_builder"><a href="php_api_form_builder.html">Form Builder</a></li>
240
241
242
243
244 <li data-identifier="php_api_package_installation_plugins"><a href="php_api_package_installation_plugins.html">Package Installation Plugins</a></li>
245
246
247
248
249 <li data-identifier="php_api_user_activity_points"><a href="php_api_user_activity_points.html">User Activity Points</a></li>
250
251
252
253
254 <li data-identifier="php_api_user_notifications"><a href="php_api_user_notifications.html">User Notifications</a></li>
255
256
257
258
259 <li data-identifier="php_api_sitemaps"><a href="php_api_sitemaps.html">Sitemaps</a></li>
260
261
262 </ul>
263 </li>
264
265
266
267
268
269 <li data-identifier="php_code-style"><a href="php_code-style.html">Code Style</a></li>
270
271
272
273
274
275
276
277
278 <li data-identifier="php_apps"><a href="php_apps.html">Apps</a></li>
279
280
281
282
283
284
285
286
287 <li data-identifier="php_gdpr"><a href="php_gdpr.html">GDPR</a></li>
288
289
290
291
292
293 </ul>
294 </li>
295
296 <li>
297 <a href="#">Languages, Templates & CSS</a>
298 <ul>
299
300
301
302
303 <li data-identifier="view_languages"><a href="view_languages.html">Languages</a></li>
304
305
306
307
308
309
310
311
312 <li data-identifier="view_templates"><a href="view_templates.html">Templates</a></li>
313
314
315
316
317
318
319
320
321 <li data-identifier="view_css"><a href="view_css.html">CSS</a></li>
322
323
324
325
326
327 </ul>
328 </li>
329
330 <li>
331 <a href="#">JavaScript API</a>
332 <ul>
333
334
335
336
337 <li data-identifier="javascript_general-usage"><a href="javascript_general-usage.html">General Usage</a></li>
338
339
340
341
342
343
344
345
346 <li class="subfolders">
347 <a href="#">New API</a>
348 <ul>
349
350
351
352 <li data-identifier="javascript_new-api_writing-a-module"><a href="javascript_new-api_writing-a-module.html">Writing a module</a></li>
353
354
355
356
357 <li data-identifier="javascript_new-api_data-structures"><a href="javascript_new-api_data-structures.html">Data Structures</a></li>
358
359
360
361
362 <li data-identifier="javascript_new-api_core"><a href="javascript_new-api_core.html">Core Functions</a></li>
363
364
365
366
367 <li data-identifier="javascript_new-api_dom"><a href="javascript_new-api_dom.html">DOM</a></li>
368
369
370
371
372 <li data-identifier="javascript_new-api_events"><a href="javascript_new-api_events.html">Event Handling</a></li>
373
374
375
376
377 <li data-identifier="javascript_new-api_ajax"><a href="javascript_new-api_ajax.html">Ajax</a></li>
378
379
380
381
382 <li data-identifier="javascript_new-api_dialogs"><a href="javascript_new-api_dialogs.html">Dialogs</a></li>
383
384
385
386
387 <li data-identifier="javascript_new-api_browser"><a href="javascript_new-api_browser.html">Browser and Screen Sizes</a></li>
388
389
390
391
392 <li data-identifier="javascript_new-api_ui"><a href="javascript_new-api_ui.html">User Interface</a></li>
393
394
395 </ul>
396 </li>
397
398
399
400
401
402 <li data-identifier="javascript_legacy-api"><a href="javascript_legacy-api.html">Legacy API</a></li>
403
404
405
406
407
408
409
410
411 <li data-identifier="javascript_helper-functions"><a href="javascript_helper-functions.html">Helper Functions</a></li>
412
413
414
415
416
417
418
419
420 <li data-identifier="javascript_code-snippets"><a href="javascript_code-snippets.html">Code Snippets</a></li>
421
422
423
424
425
426 </ul>
427 </li>
428
429 <li>
430 <a href="#">Package Components</a>
431 <ul>
432
433
434
435
436 <li data-identifier="package_package-xml"><a href="package_package-xml.html">package.xml</a></li>
437
438
439
440
441
442
443
444
445 <li data-identifier="package_pip"><a href="package_pip.html">PIPs</a></li>
446
447
448
449
450
451 </ul>
452 </li>
453
454 <li>
455 <a href="#">Migration</a>
456 <ul>
457
458
459
460
461 <li class="subfolders">
462 <a href="#">Migrating from WSC 5.2</a>
463 <ul>
464
465
466
467 <li data-identifier="migration_wsc-52_php"><a href="migration_wsc-52_php.html">PHP API</a></li>
468
469
470
471
472 <li data-identifier="migration_wsc-52_templates"><a href="migration_wsc-52_templates.html">Templates and Languages</a></li>
473
474
475
476
477 <li data-identifier="migration_wsc-52_libraries"><a href="migration_wsc-52_libraries.html">Third Party Libraries</a></li>
478
479
480 </ul>
481 </li>
482
483 <li class="subfolders">
484 <a href="#">Migrating from WSC 3.1</a>
485 <ul>
486
487
488
489 <li data-identifier="migration_wsc-31_php"><a href="migration_wsc-31_php.html">PHP API</a></li>
490
491
492 </ul>
493 </li>
494
495 <li class="subfolders">
496 <a href="#">Migrating from WSC 3.0</a>
497 <ul>
498
499
500
501 <li data-identifier="migration_wsc-30_php"><a href="migration_wsc-30_php.html">PHP API</a></li>
502
503
504
505
506 <li data-identifier="migration_wsc-30_javascript"><a href="migration_wsc-30_javascript.html">JavaScript API</a></li>
507
508
509
510
511 <li data-identifier="migration_wsc-30_templates"><a href="migration_wsc-30_templates.html">Templates</a></li>
512
513
514
515
516 <li data-identifier="migration_wsc-30_css"><a href="migration_wsc-30_css.html">CSS</a></li>
517
518
519
520
521 <li data-identifier="migration_wsc-30_package"><a href="migration_wsc-30_package.html">Package Components</a></li>
522
523
524 </ul>
525 </li>
526
527 <li class="subfolders">
528 <a href="#">Migrating from WCF 2.1</a>
529 <ul>
530
531
532
533 <li data-identifier="migration_wcf-21_php"><a href="migration_wcf-21_php.html">PHP API</a></li>
534
535
536
537
538 <li data-identifier="migration_wcf-21_templates"><a href="migration_wcf-21_templates.html">Templates</a></li>
539
540
541
542
543 <li data-identifier="migration_wcf-21_css"><a href="migration_wcf-21_css.html">CSS</a></li>
544
545
546
547
548 <li data-identifier="migration_wcf-21_package"><a href="migration_wcf-21_package.html">Package Components</a></li>
549
550
551 </ul>
552 </li>
553
554
555 </ul>
556 </li>
557
558 <li>
559 <a href="#">Tutorials</a>
560 <ul>
561
562
563
564
565 <li data-identifier="tutorial_tutorial-series"><a href="tutorial_tutorial-series.html">Tutorial Series</a></li>
566
567
568
569
570
571 </ul>
572 </li>
573
574
575</ul>
576
577<script>
578(function() {
579 var sidebar = $('#mysidebar');
580 var item = sidebar.find('.active');
581 if (item.length === 0) {
582 var parent = '';
583 if (parent) {
584 sidebar.find('li[data-identifier="' + parent + '"]').addClass('active');
585 }
586 }
587
588 sidebar.find(".active").parents('li').toggleClass("active");
589})();
590</script>
591
592 </div>
593
594 <div class="col-md-9">
595 <div class="post-header">
596 <h1 class="post-title-main">Creating a simple package</h1>
597</div>
598
599
600
601<div class="post-content">
602
603
604
605
606
607<!-- this handles the automatic toc. use ## for subheads to auto-generate the on-page minitoc. if you use html tags, you must supply an ID for the heading element in order for it to appear in the minitoc. -->
608<script>
609$( document ).ready(function() {
610 // Handler for .ready() called.
611
612$('#toc').toc({ minimumHeaders: 0, listType: 'ul', showSpeed: 0, headers: 'h2,h3,h4' });
613
614/* this offset helps account for the space taken up by the floating toolbar. */
615$('#toc').on('click', 'a', function() {
616 var target = $(this.getAttribute('href'))
617 , scroll_target = target.offset().top
618
619 $(window).scrollTop(scroll_target - 10);
620 return false
621})
622
623});
624</script>
625
626<div id="toc"></div>
627
628
629
630 <h2 id="setup-and-requirements">Setup and Requirements</h2>
631
632<p>This guide will help you to create a simple package that provides a simple test
633page. It is nothing too fancy, but you can use it as the foundation for your
634next project.</p>
635
636<p>There are some requirements you should met before starting:</p>
637
638<ul>
639 <li>Text editor with syntax highlighting for PHP, <a href="https://notepad-plus-plus.org/">Notepad++</a> is a solid pick</li>
640 <li><code class="language-plaintext highlighter-rouge">*.php</code> and <code class="language-plaintext highlighter-rouge">*.tpl</code> should be encoded with ANSI/ASCII</li>
641 <li><code class="language-plaintext highlighter-rouge">*.xml</code> are always encoded with UTF-8, but omit the BOM (byte-order-mark)</li>
642 <li>Use tabs instead of spaces to indent lines</li>
643 <li>It is recommended to set the tab width to <code class="language-plaintext highlighter-rouge">8</code> spaces, this is used in the entire software and will ease reading the source files</li>
644 <li>An active installation of WoltLab Suite 3</li>
645 <li>An application to create <code class="language-plaintext highlighter-rouge">*.tar</code> archives, e.g. <a href="http://www.7-zip.org/">7-Zip</a> on Windows</li>
646</ul>
647
648<h2 id="the-packagexml-file">The package.xml File</h2>
649
650<p>We want to create a simple page that will display the sentence “Hello World” embedded
651into the application frame. Create an empty directory in the workspace of your choice
652to start with.</p>
653
654<p>Create a new file called <code class="language-plaintext highlighter-rouge">package.xml</code> and insert the code below:</p>
655
656<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
657<span class="nt">&lt;package</span> <span class="na">xmlns=</span><span class="s">"http://www.woltlab.com"</span> <span class="na">xmlns:xsi=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span> <span class="na">xsi:schemaLocation=</span><span class="s">"http://www.woltlab.com http://www.woltlab.com/XSD/2019/package.xsd"</span> <span class="na">name=</span><span class="s">"com.example.test"</span><span class="nt">&gt;</span>
658 <span class="nt">&lt;packageinformation&gt;</span>
659 <span class="c">&lt;!-- com.example.test --&gt;</span>
660 <span class="nt">&lt;packagename&gt;</span>Simple Package<span class="nt">&lt;/packagename&gt;</span>
661 <span class="nt">&lt;packagedescription&gt;</span>A simple package to demonstrate the package system of WoltLab Suite Core<span class="nt">&lt;/packagedescription&gt;</span>
662 <span class="nt">&lt;version&gt;</span>1.0.0<span class="nt">&lt;/version&gt;</span>
663 <span class="nt">&lt;date&gt;</span>2019-04-28<span class="nt">&lt;/date&gt;</span>
664 <span class="nt">&lt;/packageinformation&gt;</span>
665 <span class="nt">&lt;authorinformation&gt;</span>
666 <span class="nt">&lt;author&gt;</span>Your Name<span class="nt">&lt;/author&gt;</span>
667 <span class="nt">&lt;authorurl&gt;</span>http://www.example.com<span class="nt">&lt;/authorurl&gt;</span>
668 <span class="nt">&lt;/authorinformation&gt;</span>
669 <span class="nt">&lt;excludedpackages&gt;</span>
670 <span class="nt">&lt;excludedpackage</span> <span class="na">version=</span><span class="s">"6.0.0 Alpha 1"</span><span class="nt">&gt;</span>com.woltlab.wcf<span class="nt">&lt;/excludedpackage&gt;</span>
671 <span class="nt">&lt;/excludedpackages&gt;</span>
672 <span class="nt">&lt;instructions</span> <span class="na">type=</span><span class="s">"install"</span><span class="nt">&gt;</span>
673 <span class="nt">&lt;instruction</span> <span class="na">type=</span><span class="s">"file"</span> <span class="nt">/&gt;</span>
674 <span class="nt">&lt;instruction</span> <span class="na">type=</span><span class="s">"template"</span> <span class="nt">/&gt;</span>
675 <span class="nt">&lt;instruction</span> <span class="na">type=</span><span class="s">"page"</span> <span class="nt">/&gt;</span>
676 <span class="nt">&lt;/instructions&gt;</span>
677<span class="nt">&lt;/package&gt;</span>
678</code></pre></div></div>
679
680<p>There is an <a href="package_package-xml.html">entire chapter</a> on the package system that explains what the code above
681does and how you can adjust it to fit your needs. For now we’ll keep it as it is.</p>
682
683<h2 id="the-php-class">The PHP Class</h2>
684
685<p>The next step is to create the PHP class which will serve our page:</p>
686
687<ol>
688 <li>Create the directory <code class="language-plaintext highlighter-rouge">files</code> in the same directory where <code class="language-plaintext highlighter-rouge">package.xml</code> is located</li>
689 <li>Open <code class="language-plaintext highlighter-rouge">files</code> and create the directory <code class="language-plaintext highlighter-rouge">lib</code></li>
690 <li>Open <code class="language-plaintext highlighter-rouge">lib</code> and create the directory <code class="language-plaintext highlighter-rouge">page</code></li>
691 <li>Within the directory <code class="language-plaintext highlighter-rouge">page</code>, please create the file <code class="language-plaintext highlighter-rouge">TestPage.class.php</code></li>
692</ol>
693
694<p>Copy and paste the following code into the <code class="language-plaintext highlighter-rouge">TestPage.class.php</code>:</p>
695
696<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
697<span class="kn">namespace</span> <span class="nn">wcf\page</span><span class="p">;</span>
698<span class="kn">use</span> <span class="nn">wcf\system\WCF</span><span class="p">;</span>
699
700<span class="cd">/**
701 * A simple test page for demonstration purposes.
702 *
703 * @author YOUR NAME
704 * @license GNU Lesser General Public License &lt;http://opensource.org/licenses/lgpl-license.php&gt;
705 */</span>
706<span class="kd">class</span> <span class="nc">TestPage</span> <span class="k">extends</span> <span class="nx">AbstractPage</span> <span class="p">{</span>
707 <span class="cd">/**
708 * @var string
709 */</span>
710 <span class="k">protected</span> <span class="nv">$greet</span> <span class="o">=</span> <span class="s1">''</span><span class="p">;</span>
711
712 <span class="cd">/**
713 * @inheritDoc
714 */</span>
715 <span class="k">public</span> <span class="k">function</span> <span class="nf">readParameters</span><span class="p">()</span> <span class="p">{</span>
716 <span class="k">parent</span><span class="o">::</span><span class="na">readParameters</span><span class="p">();</span>
717
718 <span class="k">if</span> <span class="p">(</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'greet'</span><span class="p">]))</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">greet</span> <span class="o">=</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s1">'greet'</span><span class="p">];</span>
719 <span class="p">}</span>
720
721 <span class="cd">/**
722 * @inheritDoc
723 */</span>
724 <span class="k">public</span> <span class="k">function</span> <span class="nf">readData</span><span class="p">()</span> <span class="p">{</span>
725 <span class="k">parent</span><span class="o">::</span><span class="na">readData</span><span class="p">();</span>
726
727 <span class="k">if</span> <span class="p">(</span><span class="k">empty</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">greet</span><span class="p">))</span> <span class="p">{</span>
728 <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">greet</span> <span class="o">=</span> <span class="s1">'World'</span><span class="p">;</span>
729 <span class="p">}</span>
730 <span class="p">}</span>
731
732 <span class="cd">/**
733 * @inheritDoc
734 */</span>
735 <span class="k">public</span> <span class="k">function</span> <span class="nf">assignVariables</span><span class="p">()</span> <span class="p">{</span>
736 <span class="k">parent</span><span class="o">::</span><span class="na">assignVariables</span><span class="p">();</span>
737
738 <span class="nx">WCF</span><span class="o">::</span><span class="na">getTPL</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">assign</span><span class="p">([</span>
739 <span class="s1">'greet'</span> <span class="o">=&gt;</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">greet</span>
740 <span class="p">]);</span>
741 <span class="p">}</span>
742<span class="p">}</span>
743
744</code></pre></div></div>
745
746<p>The class inherits from <a href="https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/page/AbstractPage.class.php">wcf\page\AbstractPage</a>, the default implementation of pages without form controls. It
747defines quite a few methods that will be automatically invoked in a specific order, for example <code class="language-plaintext highlighter-rouge">readParameters()</code> before <code class="language-plaintext highlighter-rouge">readData()</code> and finally <code class="language-plaintext highlighter-rouge">assignVariables()</code> to pass arbitrary values to the template.</p>
748
749<p>The property <code class="language-plaintext highlighter-rouge">$greet</code> is defined as <code class="language-plaintext highlighter-rouge">World</code>, but can optionally be populated through a GET variable (<code class="language-plaintext highlighter-rouge">index.php?test/&amp;greet=You</code> would output <code class="language-plaintext highlighter-rouge">Hello You!</code>). This extra code illustrates the separation of data
750processing that takes place within all sort of pages, where all user-supplied data is read from within a single method. It helps organizing the code, but most of all it enforces a clean class logic that does not
751start reading user input at random places, including the risk to only escape the input of variable <code class="language-plaintext highlighter-rouge">$_GET['foo']</code> 4 out of 5 times.</p>
752
753<p>Reading and processing the data is only half the story, now we need a template to display the actual content for our page. You don’t need to specify it yourself, it will be automatically guessed based on your
754namespace and class name, you can <a href="#appendixTemplateGuessing">read more about it later</a>.</p>
755
756<p>Last but not least, you must not include the closing PHP tag <code class="language-plaintext highlighter-rouge">?&gt;</code> at the end, it can cause PHP to break on whitespaces and is not required at all.</p>
757
758<h2 id="the-template">The Template</h2>
759
760<p>Navigate back to the root directory of your package until you see both the <code class="language-plaintext highlighter-rouge">files</code> directory and the <code class="language-plaintext highlighter-rouge">package.xml</code>. Now create a directory called <code class="language-plaintext highlighter-rouge">templates</code>, open it and create the file <code class="language-plaintext highlighter-rouge">test.tpl</code>.</p>
761
762<div class="language-smarty highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">{</span><span class="nb">include</span> <span class="na">file</span><span class="o">=</span><span class="s1">'header'</span><span class="k">}</span>
763
764<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"section"</span><span class="nt">&gt;</span>
765 Hello <span class="k">{</span><span class="nv">$greet</span><span class="k">}</span>!
766<span class="nt">&lt;/div&gt;</span>
767
768<span class="k">{</span><span class="nb">include</span> <span class="na">file</span><span class="o">=</span><span class="s1">'footer'</span><span class="k">}</span>
769</code></pre></div></div>
770
771<p>Templates are a mixture of HTML and Smarty-like template scripting to overcome the static nature of raw HTML. The above code will display the phrase <code class="language-plaintext highlighter-rouge">Hello World!</code> in the application frame, just as any other
772page would render. The included templates <code class="language-plaintext highlighter-rouge">header</code> and <code class="language-plaintext highlighter-rouge">footer</code> are responsible for the majority of the overall page functionality, but offer a whole lot of customization abilities to influence their behavior and appearance.</p>
773
774<h2 id="the-page-definition">The Page Definition</h2>
775
776<p>The package now contains the PHP class and the matching template, but it is still missing the page definition. Please create the file <code class="language-plaintext highlighter-rouge">page.xml</code> in your project’s root directory, thus on the same level as the <code class="language-plaintext highlighter-rouge">package.xml</code>.</p>
777
778<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
779<span class="nt">&lt;data</span> <span class="na">xmlns=</span><span class="s">"http://www.woltlab.com"</span> <span class="na">xmlns:xsi=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span> <span class="na">xsi:schemaLocation=</span><span class="s">"http://www.woltlab.com http://www.woltlab.com/XSD/2019/page.xsd"</span><span class="nt">&gt;</span>
780 <span class="nt">&lt;import&gt;</span>
781 <span class="nt">&lt;page</span> <span class="na">identifier=</span><span class="s">"com.example.test.Test"</span><span class="nt">&gt;</span>
782 <span class="nt">&lt;controller&gt;</span>wcf\page\TestPage<span class="nt">&lt;/controller&gt;</span>
783 <span class="nt">&lt;name</span> <span class="na">language=</span><span class="s">"en"</span><span class="nt">&gt;</span>Test Page<span class="nt">&lt;/name&gt;</span>
784 <span class="nt">&lt;pageType&gt;</span>system<span class="nt">&lt;/pageType&gt;</span>
785 <span class="nt">&lt;/page&gt;</span>
786 <span class="nt">&lt;/import&gt;</span>
787<span class="nt">&lt;/data&gt;</span>
788</code></pre></div></div>
789
790<p>You can provide a lot more data for a page, including logical nesting and dedicated handler classes for display in menus.</p>
791
792<h2 id="building-the-package">Building the Package</h2>
793
794<p>If you have followed the above guidelines carefully, your package directory should now look like this:</p>
795
796<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>├── files
797│   └── lib
798│   ├── page
799│   │   ├── TestPage.class.php
800├── package.xml
801├── page.xml
802├── templates
803│   └── test.tpl
804</code></pre></div></div>
805
806<p>Both files and templates are archive-based package components, that deploy their payload using tar archives rather than adding the raw files to the package file. Please create the archive <code class="language-plaintext highlighter-rouge">files.tar</code> and add the contents of the <code class="language-plaintext highlighter-rouge">files/*</code> directory, but not the directory <code class="language-plaintext highlighter-rouge">files/</code> itself. Repeat the same process for the <code class="language-plaintext highlighter-rouge">templates</code> directory, but this time with the file name <code class="language-plaintext highlighter-rouge">templates.tar</code>. Place both files in the root of your project.</p>
807
808<p>Last but not least, create the package archive <code class="language-plaintext highlighter-rouge">com.example.test.tar</code> and add all the files listed below.</p>
809
810<ul>
811 <li><code class="language-plaintext highlighter-rouge">files.tar</code></li>
812 <li><code class="language-plaintext highlighter-rouge">package.xml</code></li>
813 <li><code class="language-plaintext highlighter-rouge">page.xml</code></li>
814 <li><code class="language-plaintext highlighter-rouge">templates.tar</code></li>
815</ul>
816
817<p>The archive’s filename can be anything you want, all though it is the general convention to use the package name itself for easier recognition.</p>
818
819<h2 id="installation">Installation</h2>
820
821<p>Open the Administration Control Panel and navigate to <code class="language-plaintext highlighter-rouge">Configuration &gt; Packages &gt; Install Package</code>, click on <code class="language-plaintext highlighter-rouge">Upload Package</code> and select the file <code class="language-plaintext highlighter-rouge">com.example.test.tar</code> from your disk. Follow the on-screen instructions until it has been successfully installed.</p>
822
823<p>Open a new browser tab and navigate to your newly created page. If WoltLab Suite is installed at <code class="language-plaintext highlighter-rouge">https://example.com/wsc/</code>, then the URL should read <code class="language-plaintext highlighter-rouge">https://example.com/wsc/index.php?test/</code>.</p>
824
825<p>Congratulations, you have just created your first package!</p>
826
827<h2 id="developer-tools">Developer Tools</h2>
828
829<div class="bs-callout bs-callout-warning">This feature is available with WoltLab Suite 3.1 or newer only.</div>
830
831<p>The developer tools provide an interface to synchronize the data of an installed package with a bare repository on the local disk. You can re-import most PIPs at any time and have the changes applied without crafting a manual update. This process simulates a regular package update with a single PIP only, and resets the cache after the import has been completed.</p>
832
833<h3 id="registering-a-project">Registering a Project</h3>
834
835<p>Projects require the absolute path to the package directory, that is, the directory where it can find the <code class="language-plaintext highlighter-rouge">package.xml</code>. It is not required to install an package to register it as a project, but you have to install it in order to work with it. It does not install the package by itself!</p>
836
837<p>There is a special button on the project list that allows for a mass-import of projects based on a search path. Each direct child directory of the provided path will be tested and projects created this way will use the identifier extracted from the <code class="language-plaintext highlighter-rouge">package.xml</code>.</p>
838
839<h3 id="synchronizing">Synchronizing</h3>
840
841<p>The install instructions in the <code class="language-plaintext highlighter-rouge">package.xml</code> are ignored when offering the PIP imports, the detection works entirely based on the default filename for each PIP. On top of that, only PIPs that implement the interface <code class="language-plaintext highlighter-rouge">wcf\system\devtools\pip\IIdempotentPackageInstallationPlugin</code> are valid for import, as it indicates that importing the PIP multiple times will have no side-effects and that the result is deterministic regardless of the number of times it has been imported.</p>
842
843<p>Some built-in PIPs, such as <code class="language-plaintext highlighter-rouge">sql</code> or <code class="language-plaintext highlighter-rouge">script</code>, do not qualify for this step and remain unavailable at all times. However, you can still craft and perform an actual package update to have these PIPs executed.</p>
844
845<h2 id="appendix">Appendix</h2>
846
847<h3 id="appendixTemplateGuessing">Template Guessing</h3>
848
849<p>The class name including the namespace is used to automatically determine the path to the template and its name. The example above used the page class name <code class="language-plaintext highlighter-rouge">wcf\page\TestPage</code> that is then split into four distinct parts:</p>
850
851<ol>
852 <li><code class="language-plaintext highlighter-rouge">wcf</code>, the internal abbreviation of WoltLab Suite Core (previously known as WoltLab Community Framework)</li>
853 <li><code class="language-plaintext highlighter-rouge">\page\</code> (ignored)</li>
854 <li><code class="language-plaintext highlighter-rouge">Test</code>, the actual name that is used for both the template and the URL</li>
855 <li><code class="language-plaintext highlighter-rouge">Page</code> (page type, ignored)</li>
856</ol>
857
858<p>The fragments <code class="language-plaintext highlighter-rouge">1.</code> and <code class="language-plaintext highlighter-rouge">3.</code> from above are used to construct the path to the template: <code class="language-plaintext highlighter-rouge">&lt;installDirOfWSC&gt;/templates/test.tpl</code> (the first letter of <code class="language-plaintext highlighter-rouge">Test</code> is being converted to lower-case).</p>
859
860
861
862 <div class="tags">
863
864 </div>
865
866
867
868</div>
869
870 </div>
871 </div>
872 </div>
873
874 <div class="footerBox">
875 <div class="container">
876 <div class="footerBoxLeft">
877
878 <a target="_blank" href="https://github.com/woltlab/woltlab.github.io/blob/master/pages/getting-started/getting-started_quick-start.md" class="btn btn-default githubEditButton no_icon" role="button"><i class="fa fa-github fa-lg"></i> Edit on GitHub</a>
e2f8eee7 879 <p>Site last generated: Mar 5, 2021</p>
d9cdc0cc
TD
880 </div>
881 <div class="footerBoxRight">
e2f8eee7 882 <a class="no_icon" href="https://www.woltlab.com"><img src="https://docs.woltlab.com/5.3/images/woltlab-black.png" srcset="https://docs.woltlab.com/5.3/images/woltlab-black@2x.png 2x" height="40" width="204" alt=""></a>
d9cdc0cc
TD
883 </div>
884 </div>
885 </div>
886
887 <div class="pageFooter">
888 <div class="container">
889 &copy; 2001 ‐ 2021 <a class="no_icon" href="https://www.woltlab.com">WoltLab GmbH</a>. All rights reserved. | <a class="no_icon" href="https://www.woltlab.com/legal-notice/">Legal Notice</a> | <a class="no_icon" href="https://www.woltlab.com/privacy-policy/">Privacy Policy</a>
890 </div>
891 </div>
892</body>
893
894</html>