/** * Rebuilds the master 0 skin from the PHP files in /cache/{master_skin_dir}/ * * @access public * @param int Set ID to rebuild from * @return array Array of messages * <code> * Exception Codes: * NOT_MASTER_SKIN: Set ID is not linked to a master skin directory * NO_SUCH_DIR: {master_skin_dir} directory cannot be found * CANNOT_READ: cannot read the {master_skin_dir} directory * </code> */ public function rebuildMasterFromPHP($setId = 0) { //----------------------------------------- // INIT //----------------------------------------- $setId = is_numeric($setId) ? intval($setId) : trim($setId); $script_token = 0; $script_jump = 0; $skin_dir = IPS_CACHE_PATH . "cache/skin_cache/" . $this->remapData['templates'][$setId]; $flag = 0; $messages = array(); $templates = array(); /* Got the master skin dir? */ if (!$this->remapData['templates'][$setId]) { throw new Exception("NOT_MASTER_SKIN"); } if (!is_dir($skin_dir)) { throw new Exception("NO_SUCH_DIR"); } if (!is_readable($skin_dir)) { throw new Exception("CANNOT_READ"); } /* Remove current templates... */ if (is_numeric($setId)) { $this->DB->delete('skin_templates', 'template_set_id=' . $setId); } else { $this->DB->delete('skin_templates', 'template_master_key=\'' . $setId . '\''); } /* Fetch all template bits. NOW */ if (is_numeric($setId) and $setId > 0) { $templates = $this->fetchTemplates($setId, 'allTemplates'); } //----------------------------------------- // Set key and ID //----------------------------------------- $set_id = is_numeric($setId) ? $setId : $this->fetchSetIdByKey($setId); $set_key = ''; if ($this->isMasterSet($setId)) { $set_key = is_numeric($setId) ? $this->fetchSetKeyById($setId) : $setId; } /* Loop through the directory */ try { foreach (new DirectoryIterator($skin_dir) as $file) { if (!$file->isDot() and !$file->isDir()) { $_name = $file->getFileName(); if (substr($_name, -4) == '.php') { $name = substr($_name, 0, -4); $fdata = @file_get_contents($skin_dir . "/" . $_name); if (!$fdata) { $messages[] = sprintf($this->lang->words['couldnotopenfile'], $_name); continue; } $fdata = str_replace("\r", "\n", $fdata); $fdata = str_replace("\n\n", "\n", $fdata); if (!preg_match("/\n/", $fdata)) { $messages[] = sprintf($this->lang->words['couldnotfindlineeol'], $_name); continue; } $farray = explode("\n", $fdata); $functions = array(); $added = 0; $updated = 0; foreach ($farray as $f) { //----------------------------------------- // Skip javascript functions... //----------------------------------------- if (stristr($f, '<script')) { $script_token = 1; $script_jump = 0; } if (stristr($f, '</script>')) { $script_token = 0; $script_jump = 0; } //----------------------------------------- // If, in the middle? //----------------------------------------- if ($script_token and $script_jump == 0) { if (preg_match('#<if test=[\'\\"]#', $f)) { $script_jump = 1; $script_token = 0; } } if ($script_token == 0 and $script_jump == 1) { if (preg_match("#</if>#", $f)) { $script_jump = 0; $script_token = 1; } } //----------------------------------------- // NOT IN JS //----------------------------------------- if (!$script_token) { if (preg_match('/^function\\s*([\\w\\_]+)\\s*\\((.*)\\)/i', $f, $matches)) { $functions[$matches[1]] = ''; $config[$matches[1]] = $matches[2]; $flag = $matches[1]; continue; } } else { # Make JS safe (UBE - Ugly, but effective) $f = preg_replace('#if\\s+?\\(#is', "i~f~(~", $f); $f = str_ireplace('else', "e~lse~", $f); $f = preg_replace('#else\\s+?if#is', "e~lse~i~f", $f); } if ($flag) { $functions[$flag] .= $f . "\n"; continue; } } $final = ""; $flag = 0; foreach ($functions as $fname => $ftext) { preg_match("#//--starthtml--//(.+?)//--endhtml--//#s", $ftext, $matches); $content = $this->registry->templateEngine->convertPhpToHtml($matches[1]); //----------------------------------------- // Unconvert JS //----------------------------------------- $content = str_replace("i~f~(~", "if (", $content); $content = str_replace("e~lse~", "else", $content); $content = str_replace("e~lse~i~f", "else if", $content); /* Encode */ $content = IPSText::encodeForXml($content); /* Build array */ $array = array('template_set_id' => $set_id, 'template_group' => $name, 'template_content' => $content, 'template_name' => $fname, 'template_data' => trim($config[$fname]), 'template_updated' => time(), 'template_removable' => (is_numeric($setId) and $setId) ? 1 : 0, 'template_master_key' => $set_key, 'template_added_to' => $set_id); if (!$setId) { $added++; /* All new bits go to 'master' skin */ $array['template_set_id'] = 0; $array['template_added_to'] = 0; $array['template_master_key'] = 'root'; $this->DB->insert('skin_templates', $array); } else { /* Compare for changes? */ if (IPSText::contentToMd5($templates[$name][strtolower($fname)]['template_content']) != IPSText::contentToMd5($content)) { /* It's changed, so update. We create a new row as it might be inherited */ $updated++; $this->DB->insert('skin_templates', $array); } } } $messages[] = sprintf($this->lang->words['tplbitimported'], $name, $added, $updated); $functions = array(); } } } } catch (Exception $e) { } /* Recache */ if (is_numeric($setId) and $setId) { $this->rebuildPHPTemplates($setId); $this->removeDeadPHPCaches($setId); $this->cache->putWithCacheLib('Skin_Store_' . $setId, array(), 1); } if ($set_key == 'mobile') { $this->rebuildMobileSkinUserAgentsFromSetDataXml(); } /* Return */ $messages[] = $this->lang->words['cpltrebuildfromcaches']; return $messages; }
/** * Create a status update for a member * * @param array [Array of member data for member updating their status - will use ->getAuthor() if null] * @param array [Array of member data for owner of status update. If null and StatusOwner empty, getAuthor will be used] * @return array Status information */ public function create($author = null, $owner = null) { $author = $author === null ? $this->getAuthor() : $author; $_owner = $this->getStatusOwner(); $owner = $owner === null ? !empty($_owner['member_id']) ? $_owner : $author : $owner; $data = array(); if ($this->canCreate($author, $owner)) { if ($this->getContent()) { $content = $this->_cleanContent($this->getContent()); $hash = IPSText::contentToMd5($content); /* Check for this status update already created */ $test = $this->fetchByHash($owner['member_id'], $hash); if ($test['status_id']) { /* Already imported this one */ return FALSE; } $data = array('status_member_id' => $owner['member_id'], 'status_author_id' => $author['member_id'], 'status_date' => time(), 'status_content' => $this->_parseContent($content, $this->_internalData['Creator']), 'status_hash' => $hash, 'status_replies' => 0, 'status_author_ip' => $this->member->ip_address, 'status_approved' => $owner['pp_setting_moderate_comments'] && $owner['member_id'] != $author['member_id'] || IPSMember::isOnModQueue($author['member_id']) ? 0 : $this->getIsApproved(), 'status_imported' => intval($this->_internalData['IsImport']), 'status_creator' => trim(addslashes($this->_internalData['Creator'])), 'status_last_ids' => ''); /* Data Hook Location */ IPSLib::doDataHooks($data, 'statusUpdateNew'); $this->DB->insert('member_status_updates', $data); $status_id = $this->DB->getInsertId(); $data['status_id'] = $status_id; if ($owner['member_id'] != $author['member_id']) { $this->_sendCommentNotification($author, $owner, $data); } else { $this->_recordAction('new', $author, $data); $this->rebuildOwnerLatest($owner); /* Fire off external updates */ $eU = $this->getExternalUpdates(); if (!$this->_internalData['IsImport'] and is_array($eU)) { $this->_triggerExternalUpdates($eU, $status_id, $owner, $content); } //----------------------------------------- // Notify owner's friends as configured //----------------------------------------- $friends = array(); if ($this->settings['friends_enabled'] and $author['member_id'] == $owner['member_id']) { $this->DB->build(array('select' => 'friends_member_id, friends_approved', 'from' => 'profile_friends', 'where' => 'friends_friend_id=' . $owner['member_id'])); $this->DB->execute(); while ($_friend = $this->DB->fetch()) { if ($_friend['friends_approved']) { $friends[$_friend['friends_member_id']] = $_friend['friends_member_id']; } } } if (count($friends)) { //----------------------------------------- // Notifications library //----------------------------------------- $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . '/sources/classes/member/notifications.php', 'notifications'); $notifyLibrary = new $classToLoad($this->registry); $friends = IPSMember::load($friends); $statusUrl = $this->registry->output->buildSEOUrl('app=members&module=profile&section=status&type=single&status_id=' . $status_id, 'publicNoSession', array($owner['member_id'], $owner['members_seo_name']), 'members_status_single'); /* Build message as few times as possible */ $ndata = array('NAME' => '#friend.name#', 'OWNER' => $owner['members_display_name'], 'STATUS' => $data['status_content'], 'URL' => $this->registry->output->buildSEOUrl('app=core&module=usercp&tab=core&area=notifications', 'publicNoSession')); /* Get languages */ $langMessages = array(); foreach ($friends as $friend) { if (!isset($langMessages[$friend['language']])) { IPSText::getTextClass('email')->getTemplate('new_status', $friend['language']); IPSText::getTextClass('email')->buildMessage($ndata); $_subject = sprintf(IPSText::getTextClass('email')->subject, $this->registry->output->buildSEOUrl('showuser='******'member_id'], 'publicNoSession', $owner['members_seo_name'], 'showuser'), $owner['members_display_name'], $statusUrl); $langMessages[$friend['language']] = array('subject' => $_subject, 'message' => IPSText::getTextClass('email')->message); } } foreach ($friends as $friend) { $message = $langMessages[$friend['language']]['message']; $message = str_replace('#friend.name#', $friend['members_display_name'], $message); $notifyLibrary->setMember($friend); $notifyLibrary->setFrom($author); $notifyLibrary->setNotificationKey('friend_status_update'); $notifyLibrary->setNotificationUrl($statusUrl); $notifyLibrary->setNotificationText($message); $notifyLibrary->setNotificationTitle($langMessages[$friend['language']]['subject']); try { $notifyLibrary->sendNotification(); } catch (Exception $e) { } } } } } return $data; } return FALSE; }
/** * Rebuilds the master 0 skin from the PHP files in /cache/{master_skin_dir}/ * * @access public * @param int Set ID to rebuild from * @return array Array of messages * <code> * Exception Codes: * NOT_MASTER_SKIN: Set ID is not linked to a master skin directory * NO_SUCH_DIR: {master_skin_dir} directory cannot be found * CANNOT_READ: cannot read the {master_skin_dir} directory * </code> */ public function rebuildMasterFromPHP($setId = 0) { //----------------------------------------- // INIT //----------------------------------------- $setId = intval($setId); $script_token = 0; $script_jump = 0; $skin_dir = IPS_CACHE_PATH . "cache/skin_cache/" . $this->remapData['templates'][$setId]; $flag = 0; $messages = array(); $templates = array(); /* Got the master skin dir? */ if (!$this->remapData['templates'][$setId]) { throw new Exception("NOT_MASTER_SKIN"); } if (!file_exists($skin_dir)) { throw new Exception("NO_SUCH_DIR"); } if (!is_readable($skin_dir)) { throw new Exception("CANNOT_READ"); } /* Remove current templates... */ $this->DB->delete('skin_templates', 'template_set_id=' . $setId); /* Fetch all template bits. NOW */ if ($setId > 0) { $templates = $this->fetchTemplates($setId, 'allTemplates'); } /* Loop through the directory */ try { foreach (new DirectoryIterator($skin_dir) as $file) { if (!$file->isDot() and !$file->isDir()) { $_name = $file->getFileName(); if (substr($_name, -4) == '.php') { $name = substr($_name, 0, -4); $fdata = @file_get_contents($skin_dir . "/" . $_name); if (!$fdata) { $messages[] = "Could not open {$_name} for reading, skipping file..."; continue; } $fdata = str_replace("\r", "\n", $fdata); $fdata = str_replace("\n\n", "\n", $fdata); if (!preg_match("/\n/", $fdata)) { $messages[] = "Could not find any line endings in {$_name}, skipping file..."; continue; } $farray = explode("\n", $fdata); $functions = array(); $added = 0; $updated = 0; foreach ($farray as $f) { //----------------------------------------- // Skip javascript functions... //----------------------------------------- if (stristr($f, '<script')) { $script_token = 1; $script_jump = 0; } if (stristr($f, '</script>')) { $script_token = 0; $script_jump = 0; } //----------------------------------------- // If, in the middle? //----------------------------------------- if ($script_token and $script_jump == 0) { if (preg_match("#<if test=[\\'\"]#", $f)) { $script_jump = 1; $script_token = 0; } } if ($script_token == 0 and $script_jump == 1) { if (preg_match("#</if>#", $f)) { $script_jump = 0; $script_token = 1; } } //----------------------------------------- // NOT IN JS //----------------------------------------- if (!$script_token) { if (preg_match("/^function\\s*([\\w\\_]+)\\s*\\((.*)\\)/i", $f, $matches)) { $functions[$matches[1]] = ''; $config[$matches[1]] = $matches[2]; $flag = $matches[1]; continue; } } else { # Make JS safe (UBE - Ugly, but effective) $f = preg_replace("#if\\s+?\\(#is", "i~f~(~", $f); $f = str_ireplace("else", "e~lse~", $f); $f = preg_replace("#else\\s+?if#is", "e~lse~i~f", $f); } if ($flag) { $functions[$flag] .= $f . "\n"; continue; } } $final = ""; $flag = 0; foreach ($functions as $fname => $ftext) { preg_match("#//--starthtml--//(.+?)//--endhtml--//#s", $ftext, $matches); $content = $this->registry->templateEngine->convertPhpToHtml($matches[1]); //----------------------------------------- // Unconvert JS //----------------------------------------- $content = str_replace("i~f~(~", "if (", $content); $content = str_replace("e~lse~", "else", $content); $content = str_replace("e~lse~i~f", "else if", $content); /* Encode */ $content = IPSText::encodeForXml($content); /* Build array */ $array = array('template_set_id' => $setId, 'template_group' => $name, 'template_content' => $content, 'template_name' => $fname, 'template_data' => trim($config[$fname]), 'template_updated' => time(), 'template_removable' => $setId ? 1 : 0, 'template_added_to' => $setId); if (!$setId or !$templates[$name][strtolower($fname)]) { $added++; /* All new bits go to 'master' skin */ $array['template_set_id'] = 0; $array['template_added_to'] = 0; $this->DB->insert('skin_templates', $array); } else { /* Compare for changes? */ if (IPSText::contentToMd5($templates[$name][strtolower($fname)]['template_content']) != IPSText::contentToMd5($content)) { /* It's changed, so update. We create a new row as it might be inherited */ $updated++; $this->DB->insert('skin_templates', $array); } } } $messages[] = "{$name} imported (Added " . $added . "; updated " . $updated . " template bits)"; $functions = array(); } } } } catch (Exception $e) { } /* Recache */ if ($setId) { $this->rebuildPHPTemplates($setId); $this->removeDeadPHPCaches($setId); } /* Return */ $messages[] = "Completed database rebuild from PHP cache files."; return $messages; }