# WebCalendar Developer Guide

## Table of Contents

- Introduction
- System Requirements
- Getting The Code
- Naming Conventions
- Coding Standards
- Submitting Changes
- Translations and Languages
- FAQ
- Resources

## Introduction

WebCalendar is written in PHP. A minimum of PHP 7.4 is required.

↑ top

## Tools

The following tools will be helpful in WebCalendar development:

perl
  Perl is used to check translation files to see what translations are missing. If you are using Windows, perl is included as part of the Cygwin package.
make
  The "make" command is used when generating WebCalendar documentation in the docs directory. The "make" command is standard on Linux if you install certain development packages. If you are using Windows, make is included as part of the Cygwin package.
patch
Internet Explorer, Mozilla/Firefox, and Apple Safari
  We try to test on all three of these platforms whenever we make any HTML or JavaScript changes. If you do not have access to all these, please test your changes on as many of these browsers as you can.

TIP If you are developing on a Windows system, the Cygwin package will provide command line tools that include perl, make, patch, diff and cvs.

↑ top

## System Requirements

- PHP 7.4 or later: PHP 7.0-7.3 and 5.X are no longer supported since they have reach end-of-life status. Expect only PHP 8 support sometime soon.
- Database (see below)
- CSS-enabled browser:
  - Mozilla Firefox
  - Opera
  - Microsoft Internet Explorer
  - Microsoft Edge
  - Apple Safari
- JavaScript-enabled browser
- If not using HTTP-based authentication, then browser cookies are required

You must have one of the following databases installed:

- MySQL/MariaDB
- IBM DB2
- Interbase
- MS SQL Server
- ODBC
- Oracle 8+
- PostgreSQL
- SQLite

TIP PHP comes bundled with SQLite support. SQLite is an embedded file-based database. If your hosting service supports PHP, you should be able to create as many SQLite databases as you like (since each database is just a file).

For the database you choose, you must have its drivers built into PHP. For example, to use MySQL, PHP must be compiled with MySQL support (which is the default setting when installing PHP). See the PHP pages (php.net) for more information on setting up PHP.

TIP If you want to use gradient background images, PHP must be compiled with the GD library.

You can run PHP either as a CGI or an Apache module. You'll get better performance with PHP setup as a module. Not only will you not have to deal with the CGI performance hit, but you'll be able to use PHP's database connection pooling. Additionally, this application can use a form/cookie-based authentication or traditional HTTP authentication. For traditional HTTP authentication, PHP must be built as an Apache module.

If you are planning on using email reminders, you will need to build PHP as a CGI in order to run the send_reminders.php script. It is recommended to have a module-based PHP for your web server and then a second PHP build to create the CGI version.

TIP Some Linux distributions come with both a module-based PHP with Apache and a standalone PHP binary. Check for /usr/bin/php to see if you already have the PHP standalone executable. If it's there, you can use the following command to see what version of PHP you have:
/usr/bin/php -v

↑ top

## Getting The Code

You should always be using the latest code from git: WebCalendar

To obtain the code from your command line using the git command:

    git clone https://github.com/craigk5n/webcalendar.git

↑ top

## Naming Conventions

The following conventions have been adopted by WebCalendar (although they have not been 100% enforced, so you will see exceptions):

Class Names
  Classes should be named using descriptive, full words. Abbreviations should be avoided except in cases of standard acronyms such as HTML, HTTP, etc. Names should be in UpperCamelCaps. Examples:
  - RepeatingEvent
  - WebCalendarSettings
  Classes should be defined in files contained in includes/classes/. Filenames should be of the form ClassName.php. There should only be one class defined per file.
  If incorporating a class from another project (i.e. phpMailer ), it is acceptable to use the original naming conventions and filenames. This will allow for easy upgrading and help avoid any GNU license issues.
Method/Function Names
  Methods and functions should be named with short verb phrases. Methods/functions which return a boolean should begin with a verb which implies a yes/no answer (e.g. 'is' or 'has'). Names should be in lowerCamelCaps. Examples:
  - getPostValue()
  - saveEvent()
  - isAllDay()
Variable Names
  Variable names should be descriptive noun phrases. Counter variables should be single letters (commonly 'i', 'j', or 'k'). Names should be in lowerCamelCaps. Examples:
  - $passwordHash
  - $monthName
  - $i
Constant Names
  Constants (declared with define()) should be named with descriptive noun phrases. Names should be in uppercase with WORDS_SEPARATED_BY_UNDERSCORES. Examples:
  - ONE_DAY
  - EXTRA_REMINDER
Database Table Names
  Database table names should be prefixed with 'webcal_'. Names should be in lowercase with words_separated_by_underscores. Examples:
  - webcal_user_pref
  - webcal_entry
Preference Value Names
  These are variables stored in webcal_config and webcal_user_pref tables. Names should be in uppercase with words_separated_by_underscores. Examples:
  - ALLOW_HTML_DESCRIPTION
  - DISABLE_ACCESS_FIELD
  Administrators can find the defaults in install/default_config.php.

↑ top

## Coding Standards

The following coding standards have been adopted by WebCalendar (although they have not been 100% implemented).

Indenting
  Two spaces (ASCII 0x20) for each level. Wrapped lines should also be indented 2 spaces if these spaces will not affect output. Tabs (ASCII 0x09) will not be used. Replace all occurrences with ASCII 0x20. This may affect indenting, so please double check before committing to git or posting.
File Format
  Unix format only (LF ASCII 0x0A), no Windows or Mac format files.
PHP file comments
  Each file, at least the major ones, should have a comment header in the format:

      /**
       * short description (3 lines max)
       * (ends with a period or a blank line).
       *
       * long description (whatever it takes).
       *
       * @tags
       * @package should be one of them
       */
      /**
       * short description for the next
       * $variable, define(), constant, function(), etc.
       * to positively indicate that the page header is finished.
       *
       * long description if needed.
       */

PHP function comments
  Function documentation is generated using phpDocumentor. Each class and function, at least, should be preceded by a DocBlock. Constants, define()s and $variables may also benefit from DocBlocks. See the phpDocumentor website for information about DocBlocks syntax.
XHTML
  All XHTML should conform to XHTML 1.0 Transitional. Use double quotes around HTML attributes.
If/Else
  Use the ternary operator (?:) whenever possible. Curly brackets, {}, are only required around multi-statement blocks. However, please use them around all statements to reduce errors when we start to minify the code. Any of the following is acceptable based on logic complexity:

      normal if/else
      if ( $foo === 1 ) {
        $pro = true;
      } else {
        $con = true;
      }

      or, nested
      if ( $bar > 0 ) {
        $drink++;
        $glass = 'full';
      } else {
        $fun--;

        if ( $fun < 1 ) {
          echo 'Party is over!';
        }
      }

      the ternary operator
      If $foo is not undefined.
      $a = ( $foo === 1 );
      or, since 'true' is the default here:
      $a = ( $foo === 1 );

      or, the 'elvis' short version
      $b = ( $a ?: $c ); // $a if isset($a) && ! empty($a) else $c

  See PHP short ternary (elvis) vs null coalescing operator.

      the null coalescing operator
      $b = ( $a ?? 'Y' ); // $a is set and not null then $a else 'Y'

      and the null coalescing assignment operator
      $a ??= 1; // if $a is set and not null then $a else 1

  Elvis and null coalescing operators can be combined as needed.
  See PHP null coalescing operator for more information.
Function Calls/Declarations
  Use one space both inside and outside of parenthesis '()'

      Declaration: function getGetValue ( $name ) {
      Call: $bar = getGetValue ( $name );

Single quotes vs double quotes
  With the exception of HTML and XHTML attributes, use single quotes where possible.

      echo 'This is an example of single quoting. ';
      echo 'But, sometimes it\'s not possible without escaping. ';
      echo "Also it's not possible with $embedded variables. ";
      echo 'Control characters such as linefeed "\n" and tab "\t" don\'t work either. ';
      echo 'We used to prefer to concatenate' . $variables . 'like this. '
      echo 'However, PHP has gotten faster in the last few years. ';
      echo "Now interpolating $variables, inside double quotes, is faster than concatenating. ";
      echo 'As long as the line is still readable. ';
      echo '"Nested quotes", she said, "are also acceptable where needed.
           Just try to use single quotes as the outer set."';

Use of the dot connector. Also called concatenation.
  The above example is faster if written this way:

      echo 'This is an example of single quoting. '
       . 'But, sometimes it\'s not possible without escaping. '
       . "Also it's not possible with $embedded variables. "
       . 'Control characters such as "\n" (linefeed) and "\t" (tab) don\'t work either. '
       . 'We used to prefer to concatenate' . $variables . 'like this. '
       . 'However, PHP has gotten faster in the last few years. '
       . "Now interpolating $variables, inside double quotes, is faster than concatenating. "
       . 'As long as the line is still readable. '
       . '"Nested quotes", she said, "are also acceptable where needed.
          Just try to use single quotes as the outer set."'

↑ top

## Submitting Changes

Please use github's pull request feature to contribute changes to WebCalendar. You'll need to make an account on github and fork the repository you want to 'patch'.

↑ top

## Translations and Languages

When adding or modifying WebCalendar code, all displayed text should be translatable. The following tips will ensure new text can be translated quickly and efficiently.

Translate
  All displayable text should be sent to the translate() function, which returns the text translated in the user's language of choice. A variation of this function is etranslate(), which includes and echo command. When translating text within javascript, always set the decode flag to true. This will allow proper decoding of htmlentities.
Htmlentities
  When used, this function tag should include the current charset when displaying database results. This will be most important when dealing with languages such as Japanese that tend to contain characters that would otherwise be non-displayable. Although this is not the perfect solution, it seems to suffice for our purposes. Possibly, a better technique would be to use the charset of the original creator of the data, but this is beyond current capabilities.
  For reference see: http://us3.php.net/manual/en/function.htmlentities.php
Updating Language Files
  When text is added or updated, requiring new translations, the translations/English-US.txt file should be updated as a minimum. This file will be used as the basis for updating the other language files and needs to be up to date. From within the tools directory, the following command will search through the WebCalendar source files and update the language file specified. Language files should always be committed to CVS in Unix format to save space.

      perl update_translation.pl English-US.txt

↑ top

## Frequently Asked Questions

Why aren't you using PHP sessions?
  The install/index.php page does use PHP sessions. The cookie-based solution that WebCalendar uses is simple, and it will work with all versions of PHP.
Why aren't you using ADODB for database access?
  Again, this would be overkill for what we need. ADODB is a fairly large project, so I'm partial to my leaner dbi4php.php solution.
Why aren't you using the PEAR database functions?
  WebCalendar pre-dates the PEAR database functions. There does not seem to be sufficient reason to switch from our existing code at this point.
Why aren't you using a template engine like smarty?
  WebCalendar pre-dates most of the template engines out there. We are currently evaluating some of the templating options and may consider moving to one of the template systems in the future.
How do I install a patch?
  Different patches are applied differently. Some patches just contain an updated file. In that case, you should be able to just replace the old file with the new (assuming the new file and your install are based on the same version of WebCalendar).
  Others are patch files, which usually have a .diff or .patch file extension. In order to use one of these files, you need the GNU patch program. (This should be installed on all Linux systems and you can get a version for Windows. I use the patch program that comes with Cygwin on windows.) I would recommend testing the patch on your install first using the --dry-run option.
  For example, if the patch file is called calmods.diff, then you would use:

      patch --dry-run < calmods.diff

  If the program says it cannot determine which file to patch, try adding -p1:

      patch --dry-run -p1 < calmods.diff

  If it goes through all the changes successfully, do the same command without the --dry-run option to install the patch. If it says "hunk failed", then the patch cannot be applied without hand-merging files. This essentially means that the patch was based on a version of WebCalendar that is too different than the version that you have installed, so it was unable to determine how to apply some of the changes in the patch file.

↑ top

## Resources

The following resources may be helpful:

- WebCalendar Function Documentation
- WebCalendar-Database.html describes the WebCalendar database schema
- WebCalendar-Styling.html describes how WebCalendar uses CSS

↑ top