diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 8b13789..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ - diff --git a/css/guestbook.css b/css/guestbook.css new file mode 100644 index 0000000..5df5073 --- /dev/null +++ b/css/guestbook.css @@ -0,0 +1,67 @@ +/* Messages style. */ +.guestbook-message { + border-radius: 10px; + border: 1px solid #bac1ff; + background: #e7e6ff; +} + +.guestbook-message-text { + margin: 5px; + font-weight: bold; +} + +.guestbook-user-date { + margin: 5px; + font-style: italic; +} + +/* Button style. */ +.guestbook-button { + background: -webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ededed), color-stop(1, #bab1ba)); + background: -moz-linear-gradient(top, #ededed 5%, #bab1ba 100%); + background: -webkit-linear-gradient(top, #ededed 5%, #bab1ba 100%); + background: -o-linear-gradient(top, #ededed 5%, #bab1ba 100%); + background: -ms-linear-gradient(top, #ededed 5%, #bab1ba 100%); + background: linear-gradient(to bottom, #ededed 5%, #bab1ba 100%); + filter:progid: DXImageTransform.Microsoft.gradient(startColorstr = '#ededed', endColorstr = '#bab1ba', GradientType = 0); + background-color: #ededed; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + border: 1px solid #d6bcd6; + display: inline-block; + cursor: pointer; + color: #3a8a9e; + font-family: arial; + font-size: 14px; + padding: 5px; + text-decoration: none; + text-shadow: 0px 1px 0px #e1e2ed; + margin: 5px; +} + +.guestbook-button:hover { + background: -webkit-gradient(linear, left top, left bottom, color-stop(0.05, #bab1ba), color-stop(1, #ededed)); + background: -moz-linear-gradient(top, #bab1ba 5%, #ededed 100%); + background: -webkit-linear-gradient(top, #bab1ba 5%, #ededed 100%); + background: -o-linear-gradient(top, #bab1ba 5%, #ededed 100%); + background: -ms-linear-gradient(top, #bab1ba 5%, #ededed 100%); + background: linear-gradient(to bottom, #bab1ba 5%, #ededed 100%); + filter:progid: DXImageTransform.Microsoft.gradient(startColorstr = '#bab1ba', endColorstr = '#ededed',GradientType = 0); + background-color: #bab1ba; +} + +.guestbook-button:active { + position: relative; + top: 1px; +} + +/* Weather style. */ +.guestbook-weather-city { + margin: 5px; + font-weight: bold; +} + +.guestbook-weather-date { + margin: 10px; +} diff --git a/guestbook.info b/guestbook.info new file mode 100644 index 0000000..53fc3d0 --- /dev/null +++ b/guestbook.info @@ -0,0 +1,4 @@ +name = Guest Book +description = In guest book you can leave your messages, edit them and delete. Also you can see the weather for today into a separate block. +core = 7.x +version = 7.x-1.0 diff --git a/guestbook.install b/guestbook.install new file mode 100644 index 0000000..4cff6a1 --- /dev/null +++ b/guestbook.install @@ -0,0 +1,50 @@ + 'The base table for guestbook.', + 'fields' => array( + 'id' => array( + 'description' => 'The primary identifier for a message.', + 'type' => 'serial', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), + 'uid' => array( + 'description' => 'Identifier for a user.', + 'type' => 'int', + 'not null' => TRUE, + ), + 'sid' => array( + 'description' => 'Identifier for a session id.', + 'type' => 'varchar', + 'length' => 100, + 'not null' => TRUE, + 'default' => '', + ), + 'date' => array( + 'description' => 'Message date.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), + 'message' => array( + 'description' => 'The message by user.', + 'type' => 'varchar', + 'length' => 100, + 'not null' => TRUE, + 'default' => '', + ), + ), + ); + + return $schema; +} diff --git a/guestbook.module b/guestbook.module new file mode 100644 index 0000000..f0b8874 --- /dev/null +++ b/guestbook.module @@ -0,0 +1,145 @@ + array( + 'title' => t('Show messages for the Guestbook module'), + ), + 'access guestbook content' => array( + 'title' => t('Access to edit and delete for the Guestbook module'), + ), + ); +} + +/** +* Implements hook_menu(). +*/ +function guestbook_menu() { + // Main page. + $items['guestbook-page'] = array( + 'title' => 'Guestbook', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('guestbook_page_form'), + 'access arguments' => array('access guestbook messages'), + ); + // Edit message. + $items['guestbook-page/%guestbook_mid/edit'] = array( + 'title' => 'Guestbook', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('guestbook_page_form', 1), + 'access arguments' => array('access guestbook content'), + ); + // Delete message. + $items['guestbook-page/%guestbook_mid/delete'] = array( + 'title' => 'Delete message', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('guestbook_message_form_delete', 1), + 'access arguments' => array('access guestbook content'), + ); + + return $items; +} + +/** + * Loads a message info. + * + * @param $mid + * Integer specifying the message id to load. + * + * @return array + * A fully-loaded array of message info ('id', 'uid', 'sid', 'date', 'message'). + * - id: message id; + * - uid: user id; + * - sid: session id; + * - date: message creation date; + * - message: message text. + */ +function guestbook_mid_load($mid) { + return guestbook_info_by_mid($mid); +} + +/* + * Implements hook_cron(). + */ +function guestbook_cron() { + guestbook_get_xml_weather(); +} + +/* + * Implements hook_block_info(). + */ +function guestbook_block_info() { + // Build weather block. + $blocks['weather'] = array( + 'title' => t('Weather in Vitebsk'), + 'info' => t('The Weather'), + 'cache' => DRUPAL_CACHE_GLOBAL, + 'status' => TRUE, + 'weight' => -10, + ); + + return $blocks; +} + +/* + * Implements hook_block_view(). + */ +function guestbook_block_view($delta = '') { + $block = array(); + switch ($delta) { + case 'weather': + $block['subject'] = t('Vitebsk Weather'); + $block['content'] = array( + '#markup' => theme('guestbook_weather_template', + array( + 'weather' => guestbook_weather(), + ) + ), + '#attached' => array( + 'css' => array( + drupal_get_path('module', 'guestbook') . '/css/guestbook.css', + ), + ) + ); + break; + } + + return $block; +} + +/* + * Implements hook_theme(). + */ +function guestbook_theme() { + return array( + 'guestbook_message_template' => array( + 'variables' => array( + 'body' => NULL, + ), + 'template' => 'templates/guestbook_message_template', + ), + 'guestbook_weather_template' => array( + 'variables' => array( + 'weather' => NULL, + ), + 'template' => 'templates/guestbook_weather_template', + ), + ); +} diff --git a/include/guestbook.core.inc b/include/guestbook.core.inc new file mode 100644 index 0000000..3a9bd2d --- /dev/null +++ b/include/guestbook.core.inc @@ -0,0 +1,86 @@ +getTimestamp(); +} + +/** + * Gets xml file by url. + * + * The file is saved in the root folder of the module. + */ +function guestbook_get_xml_weather() { + // Get xml file by url. + $xml = file_get_contents(GUESTBOOK_WEATHER_URL); + + // Store xml file in locale file for weather block. + if (isset($xml)) { + $path = drupal_get_path('module', 'guestbook'); + file_put_contents($path . '/weather.xml', $xml); + } +} + +/** + * Reading data from an xml file for weather block. + * + * @return array + * An array containing the following data: + * - 'city': current city; + * - 'date': weather day, month, year; + * - 'temp_max': maximum temperature on the specified date; + * - 'temp_min': minimum temperature on the specified date; + * - 'weather_error': message 'The weather temporarily unavailable'. + */ +function guestbook_weather() { + + $path = drupal_get_path('module', 'guestbook'); + + libxml_use_internal_errors(true); + $xml = new DOMDocument(); + + // Generates data of weather if 'weather.xml' file is uploaded and valid. + if (!file_exists($path . '/weather.xml') || !$xml->load($path . '/weather.xml')) { + $weather['weather_error'] = t('The weather temporarily unavailable'); + return $weather; + } + else { + // Loads simple xml object. + $xml = simplexml_load_file($path . '/weather.xml'); + + // Gets information from object. + $tmax = $xml->REPORT->TOWN->FORECAST->TEMPERATURE['max']; + $tmin = $xml->REPORT->TOWN->FORECAST->TEMPERATURE['min']; + $date = $xml->REPORT->TOWN->FORECAST[0]['day']; + $date .= '.' . $xml->REPORT->TOWN->FORECAST[0]['month']; + $date .= '.' . $xml->REPORT->TOWN->FORECAST[0]['year']; + + $city = t('Vitebsk'); + $tmax = t('Max temp.') . '  ' . $tmax . '°'; + $tmin = t('Min temp.') . '  ' . $tmin . '°'; + + // Stores information in array. + $weather = array( + 'city' => $city, + 'date' => $date, + 'temp_max' => $tmax, + 'temp_min' => $tmin, + ); + } + + return $weather; +} diff --git a/include/guestbook.db.inc b/include/guestbook.db.inc new file mode 100644 index 0000000..0ab7c8b --- /dev/null +++ b/include/guestbook.db.inc @@ -0,0 +1,127 @@ +extend('PagerDefault') + ->fields('t', array('id', 'uid', 'sid', 'date', 'message')) + ->orderBy($order, $direction) + ->limit($limit) + ->execute(); + + while ($value = $query->fetchAssoc()) { + $rows[] = array( + 'id' => $value['id'], + 'uid' => $value['uid'], + 'sid' => $value['sid'], + 'date' => $value['date'], + 'message' => check_plain($value['message']), + 'user_name' => guestbook_name_by_id($value['uid']), + 'formatted_date' => format_date($value['date']), + ); + } + + return $rows; +} + +/** + * Saves or edits message. + * + * @param $form_state + * An associative array containing the current state of the form. + */ +function guestbook_save_edit_db($form_state) { + global $user; + + $table = 'guestbook_drupal'; + $record = array( + 'uid' => $user->uid, + 'sid' => $user->sid, + 'date' => guestbook_time(), + 'message' => $form_state['values']['message'], + 'id' => !empty ($form_state['values']['info_by_id']['id']) ? $form_state['values']['info_by_id']['id'] : NULL, + ); + + // If exists 'id', then edit the message, otherwise - save as a new message. + if ($record['id']) { + drupal_write_record($table, $record, 'id'); + } + else { + drupal_write_record($table, $record); + } +} + +/** + * Returns user name by user id. + * + * @param $uid + * Integer specifying the user id. + * + * @return string + * Returns user name or 'User does not exist'. + */ +function guestbook_name_by_id($uid) { + if ($uid) { + $query = db_select('users', 't') + ->fields('t', array('name')) + ->condition('t.uid', $uid) + ->execute(); + $value = $query->fetchAssoc(); + $name = $value['name']; + } + else { + $name = t('User does not exist'); + } + + return $name; +} + +/** + * Deletes message. + * + * @param $id + * $id contains message id. + */ +function guestbook_message_delete($id) { + db_delete('guestbook_drupal') + ->condition('id', $id) + ->execute(); + drupal_set_message(t('Message deleted!')); + $params = drupal_get_query_parameters(); + drupal_goto('guestbook-page', array('query' => $params)); +} + +/** + * Gets info by message id. + * + * @param $mid + * Integer specifying the message id. + * + * @return array + * A fully-loaded array of message info ('id', 'uid', 'sid', 'date', 'message'). + * - id: message id; + * - uid: user id; + * - sid: session id; + * - date: message creation date; + * - message: message text. + */ +function guestbook_info_by_mid($mid) { + $query = db_select('guestbook_drupal', 't') + ->fields('t', array('id', 'uid', 'sid', 'date', 'message')) + ->condition('t.id', $mid) + ->execute(); + $value = $query->fetchAssoc(); + + return $value; +} diff --git a/include/guestbook.form.inc b/include/guestbook.form.inc new file mode 100644 index 0000000..1eb299e --- /dev/null +++ b/include/guestbook.form.inc @@ -0,0 +1,149 @@ + 'value', + '#value' => $value, + ); + } + + $path = drupal_get_path('module', 'guestbook'); + $form['#attached']['css'][] = $path . '/css/guestbook.css'; + + // Show messages if it exists. + $variables = guestbook_read_db('guestbook_drupal', 'id', 'DESC', '10'); + $form['message_window'] = array( + '#theme' => 'guestbook_message_template', + '#body' => $variables, + ); + + // Show area for input text if user is logged. + if ($user->uid) { + $form['message'] = array( + '#type' => 'textarea', + '#title' => t('message'), + '#size' => 1000, + '#default_value' => $text_edit, + '#element_validate' => array('guestbook_message_validate'), + ); + + // Show save or edit button. + $form['submit'] = array( + '#type' => 'submit', + '#attributes' => array( + 'class' => array('guestbook-button'), + ), + '#value' => isset($value['id']) ? t('Edit') : t('Save'), + ); + + // Show or hide the cancel button. + if (isset($value['id'])) { + $form['cancel_button'] = array( + '#type' => 'link', + '#title' => t('Cancel'), + '#href' => 'guestbook-page', + '#options' => array( + 'query' => drupal_get_query_parameters(), + ), + '#attributes' => array( + 'class' => array('guestbook-button'), + ), + ); + } + } + + return $form; +} + +/** + * Validates guestbook_page_form. + */ +function guestbook_message_validate($element, $form, &$form_state) { + if (empty($element['#value'] || drupal_strlen($element['#value']) > 1000)) { + form_error($element, t("Field '@fieldname' must be less than @c + chars and can't be empty.", + array( + '@fieldname' => t('message'), + '@c' => 1000, + ) + ) + ); + } +} + +/** + * Submit callback for guestbook_page_form. + */ +function guestbook_page_form_submit($form, &$form_state) { + guestbook_save_edit_db($form_state); + $form_state['redirect'] = array( + 'guestbook-page', array( + 'query' => drupal_get_query_parameters(), + ) + ); +} + +/** + * Form constructor for the message deletion confirmation form. + * + * @param $form + * An associative array containing the structure of the form. + * @param $form_state + * An associative array containing the current state of the form. + * @param $value + * Contains array('id', 'uid', 'sid', 'date', 'message'). + * + * @return array + * Return form. + */ +function guestbook_message_form_delete($form, &$form_state, $value) { + $form = array(); + $form['id'] = array( + '#type' => 'value', + '#value' => $value['id'], + ); + $query = drupal_get_query_parameters(); + $path = array( + 'path' => 'guestbook-page', + 'query' => $query, + ); + $question = t('Are you sure you want to delete message?'); + $undone = t('This action cannot be undone.'); + $delete = t('Delete'); + $cancel = t('Cancel'); + + return confirm_form($form, $question, $path, $undone, $delete, $cancel); +} + +/** + * Submit callback for guestbook_message_form_delete. + */ +function guestbook_message_form_delete_submit($form, &$form_state) { + $id = $form_state['values']['id']; + guestbook_message_delete($id); +} diff --git a/include/guestbook.theme.inc b/include/guestbook.theme.inc new file mode 100644 index 0000000..406d984 --- /dev/null +++ b/include/guestbook.theme.inc @@ -0,0 +1,35 @@ + array( + 'class' => array('guestbook-button'), + ), + 'query' => $params, + ); + foreach ($variables['body'] as $value){ + $links = l(t('edit'), 'guestbook-page/' . $value['id'] . '/edit', $options); + $links .= l(t('delete'), 'guestbook-page/' . $value['id'] . '/delete', $options); + $variables['body'][$i] += array( + 'links' => $links, + ); + $i++; + } +} diff --git a/templates/guestbook_message_template.tpl.php b/templates/guestbook_message_template.tpl.php new file mode 100644 index 0000000..a247d13 --- /dev/null +++ b/templates/guestbook_message_template.tpl.php @@ -0,0 +1,54 @@ + + + + + + +
+ +
+
+ + +
+ +
+ +
+ + + uid && $value['sid'] == $user->sid): ?> +
+ +
+ +
+ +
+ +
+ +
diff --git a/templates/guestbook_weather_template.tpl.php b/templates/guestbook_weather_template.tpl.php new file mode 100644 index 0000000..7d4a4b2 --- /dev/null +++ b/templates/guestbook_weather_template.tpl.php @@ -0,0 +1,42 @@ + + +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
diff --git a/weather.xml b/weather.xml new file mode 100644 index 0000000..1a0f604 --- /dev/null +++ b/weather.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +