Showing posts with label PHP. Show all posts
Showing posts with label PHP. Show all posts

Sunday, August 23, 2015

Use WordPress as CMS

WordPress is a popular blogging software. It has a lot of nice-looking themes. It will be very nice if it can be used as the framework of a website.

For this purpose, one should be able to create custom roles (user groups), members of such roles may or may not be able to post blogs, but can access custom pages once log in. Several things are crucial:

1) create custom role(s).
2) check if a user is logged in, and access user profile such as ID, login name, user name, email, user type. Based on this, one can add custom database tables and build whatever function that is desired.
3) make use of WordPress theme in custom page.

A study on these requirements proves fruitful. Over the weekend, I was able to build a member page for 4 WordPress themes. It's easy to extend to more themes.

The files are prepared and will be uploaded to github. See:

https://github.com/chenx/WordPress_Extension


Summary:
  • Shows how to check if a user is logged in, and retrieval user information.
  • Shows how to include header/footer of current theme.
  • To add custom links, go to Appearance -> Menus -> Custom Links
  • To allow user register, see [3] below.
    It seems Wordpress allows each user to have one role only. That's less flexible than .NET membership, which allows each user to have any roles.
  • To change default user registeration email, see [4].
  • To allow manage user roles, use the Members plugin [5].
  • To disable comments/discussion on a per-page basis:
    On Edit Page, click Screen Options and check the Discussion box. Then in Discussion section, uncheck "Allow comments".
  • To add a forum, see .
  • Note: installed themes are in wp-content/themes/
  • Note: to imitate other page's layout, see theme's page.php.
  • Note: to customize page title, see wp-includes/post-template.php function get_the_title().
References:
  1. http://codex.wordpress.org/Function_Reference/wp_get_current_user
  2. https://web-design-weekly.com/snippets/load-a-different-header-in-wordpress/
  3. http://www.wpbeginner.com/beginners-guide/how-to-allow-user-registration-on-your-wordpress-site/
  4. https://wordpress.org/plugins/welcome-email-editor/
  5. https://wordpress.org/plugins/members/
  6. wordpress - redirect to target page after log in 

Tuesday, July 16, 2013

Essential PHP security

Essential PHP security. By Chris Shflett. 2006.

Nice book. Basic rules can apply to sites built in other languages.


Tuesday, February 12, 2013

SOAP in PHP


See: http://www.perl.com/pub/2001/01/soap.html
SOAP server: server.cgi
#!/usr/bin/perl -w
use SOAP::Transport::HTTP;

SOAP::Transport::HTTP::CGI     
    -> dispatch_to('Demo')       
    -> handle;

package Demo;

sub hi {                       
    return "hello, world\n";       
}

sub languages {                
    return ("Perl", "C", "sh");  
}

SOAP client: client.pl
#!/usr/bin/perl -w
use SOAP::Lite;

$s = SOAP::Lite
    -> uri('http://localhost/Demo')
    -> proxy('http://localhost/DFetch_stamp/tmp/hibye.cgi')
    -> hi()
    -> result; # can use result() too.
print $s;
 
Now run: perl client.pl, you can see the output.

Other notes:
- multiple line comments in perl: start with "=pod", end with "=cut".

Tuesday, November 22, 2011

Escape special char

When transferring data, special characters may be used as separators of records, e.g., row or record separators. In that case you need to escape the special characters from the data, and recover them at the data receiving side. Here is PHP code for this purpose:

test("\.");

function test($s) {
$t = encode($s);
$o = decode($t);
p("s = [$s], encode(s) = [$t], decode(encode(s)) = [$o]. " . (($o == $s) ? "passed" : "failed !!!"));
}

//
// Escape row separator "\n" in a string.
// Encoding scheme:
// \ -> \\
// \n -> \.
//
function encode($s) {
return str_replace(",", "\;", str_replace("\\", "\\\\", $s));
}

//
// Decoding scheme:
// \. -> \n
// \\ -> \
// Note: can't use the following:
// return str_replace("\\\\", "\\", str_replace("\.", "\n", $s));
// because it fails for the below case:
// s = "\.". encode(s) = "\\.", decode(encode(s)) = "\n".
//
function decode($s) {
// Use "===", since "==" treats 0 as false. See http://www.php.net/manual/en/function.strpos.php
if (strpos($s, "\\") === false) return $s;

$t = "";
$len = strlen($s);
for ($i = 0; $i < $len; $i ++) {
$c = $s[$i];
if ($c == "\\") {
$d = $s[$i + 1];
if ($d == "\\") { $t .= "\\"; $i ++; }
else if ($d == ".") { $t .= "\n"; $i ++; }
else { $t .= "(error)"; } // This shouldn't happen.
}
else { $t .= $c; }
}
return $t;
}

function p($s) {
print str_replace("\n", "<br>", $s) . "<br>";
}

Saturday, July 2, 2011

Call a C program from php and read output

Use shell_exec() command:

$output = shell_exec('/path/to/your/program'); // $output contains whatever program prints.

This is great. It makes possible writing C code for computation intensive part and pass result back to php.

Thursday, June 16, 2011

wsdl cache, count_big

PHP web service, cache files are stored in /tmp as "wsdl-..." files. After update web service, you need to delete these files to clear the cache so the changes are reflected.

"select count(*) from tbl" would time out and says: "Arithmetic overflow error converting expression to data type int.". This site has it that you should use "select COUNT_BIG(*) from tbl" instead. Also see MSDN at Transact-SQL reference or COUNT_BIG.

Thursday, May 26, 2011

PHP class to do paging

This code can be easily ported to other languages. Note that the database used here is MSSQL, it has a paging function starting from version 2005 [1][2]. In MySQL, this can be achieved using 'Limit'.

<html>
<head><title>Test</title></head>
<body>
<h1>Test Paging</h1>
<?php
// General variables for navBar.
$paging = new PagingClass( getService('getDataCount', array()), $_REQUEST['pg'] );

// Get data according to range.
$data = getService('getData', array('RangeStart' => $paging->getStart(), 'RangeEnd' => $paging->getEnd()));

// Output navBar and data.
print $paging->writeNavBar();
print Service2Table($data);
print $paging->writeNavBar();
?>


<?php

//
// @Author: HomeTom
// @Date: 5/26/2011
//
class PagingClass {

private $pageSize;
private $pageButtonCount;
private $totalCount;
private $pageCount;
private $currentPage;
private $BaseUrl;

//
// Parameters:
// $totalCount: Total number of rows/records.
// $curPage: Current page index (usually passed as request parameter).
// Preassumption: No parameter uses the name "pg", which is used for paging.
//
public function __construct($totalCount, $curPage) {
$this->pageSize = 3; // Default page size.
$this->pageButtonCount = 4; // Default number of paging buttons.

$this->totalCount = $totalCount;
$this->pageCount = ceil($totalCount / $this->pageSize);

$this->currentPage = $curPage;
if ($this->currentPage == "") { $this->currentPage = 1; }
else if ($this->currentPage < 0) { $this->currentPage = 0; }
else if ($this->currentPage >= $this->pageCount) { $this->currentPage = $this->pageCount - 1; }

// Base URL used by page links. Page parameter should be at the end. E.g. "index.php?pg="
$baseUrl = $_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING'];
if (preg_match("#pg=[0-9]*$#", $baseUrl) > 0) {
$this->BaseUrl = preg_replace("#pg=[0-9]*$#", "", $baseUrl) . "pg=";
} else if ( empty($_SERVER['QUERY_STRING']) ) {
$this->BaseUrl = $baseUrl . "pg=";
} else {
$this->BaseUrl = $baseUrl . "&pg=";
}
}

// Get start and end row/record number in current page.
public function getStart() { return $this->currentPage * $this->pageSize + 1; }
public function getEnd() { return (1 + $this->currentPage) * $this->pageSize; }

//
// Parameters:
// $PageCount: Total number of pages.
// $CurrentPageIndex: Current page index.
// $PageButtonCount: Number of page buttons to show on one page.
//
public function writeNavBar() {
$PageCount = $this->pageCount;
$CurrentPageIndex = $this->currentPage;
$PageButtonCount = $this->pageButtonCount;
$baseUrl = $this->BaseUrl; //"index.php?pg=";

$DEBUG = 0;
$lblNext = "Next";
$lblPrev = "Prev";
$lblFirst = "First";
$lblLast = "Last";

$s = "";

if ($DEBUG) {
print "pagecount: $PageCount, currentPageIndex: $CurrentPageIndex, ";
print "PageButtonCount: $PageButtonCount<br>";
}

$startPage = (floor(($CurrentPageIndex)/$PageButtonCount) * $PageButtonCount);
if ($DEBUG) print "startpage = $startPage<br>";

$tmp = $PageCount - $PageButtonCount;
if ($tmp > 0 && $tmp < $startPage) { $startPage = $tmp; }

// First.
if ($CurrentPageIndex == 0) { $s .= $lblFirst . " "; }
else { $s .= "<a href=\"" . $baseUrl . "0\">" . $lblFirst . "</a> "; }

// Prev.
if ($CurrentPageIndex == 0) { $s .= $lblPrev . " "; }
else
{
$j = $CurrentPageIndex - 1;
$s .= "<a href=\"" . $baseUrl . $j . "\">" . $lblPrev . "</a> ";
}

// ...
if ($startPage > 0) { $s .= "<a href=\"" . $baseUrl . ($startPage - 1) . "\">...</a> "; }

for ($i = 0; $i < $PageCount; $i ++) {
if ($i < $startPage || $i >= $startPage + $PageButtonCount) { continue; }
if ($i == $CurrentPageIndex) { $s .= " " . (1 + $i); }
else { $s .= " <a href='" . $baseUrl . $i . "'>". (1 + $i) . "</a>"; }
}

// ...
if ($startPage + $PageButtonCount <= $PageCount - 1) {
$j = $PageButtonCount + $startPage;
$s .= " <a href=\"" . $baseUrl . $j . "\">...</a> ";
}

// Next.
if ($CurrentPageIndex >= $PageCount - 1) { $s .= " " . $lblNext; }
else
{
$j = $CurrentPageIndex + 1;
$s .= " <a href=\"" . $baseUrl . $j . "\">" . $lblNext . "</a>";
}

// Last.
if ($CurrentPageIndex >= $PageCount - 1) { $s .= " " . $lblLast; }
else { $s .= " <a href=\"" . $baseUrl . ($PageCount - 1) . "\">" . $lblLast . "</a>"; }

return $s;
}
}

//
// This function retrieves a web service return result.
// http://www.php.net/manual/en/soapclient.soapcall.php
//
// Parameters:
// $func: Name of the web service function.
// $params: Array of parameters used by this function.
//
function getService($func, $params) {
try {
$url = "http://localhost/test/TestService.asmx?WSDL";
$client = new SoapClient($url);
$result = $client->$func($params);
//reset($result); // 'reset' sets the array pointer to the start of the array.
// 'each' gets the current key/value pair into a separate array.
list($key, $val) = each($result);
//print $key . ": " . $val . "<br>";
return $val;
} catch (Exception $e) {
die ("<br><font color='red'>getService() error: " . $e->getMessage() . "</font><br>");
}
}


//
// This function converts web service return result into a table.
//
// rows are delimited by '\n',
// cols are delimited by '\t'.
//
// explode() v.s. split():
// Biggest difference is explode() takes a delimiter to split by,
// while split() takes a regular expression. explode is faster.
//
function Service2Table($val) {
$row_delimiter = "\n";
$col_delimiter = "\t";
$DEBUG = 0;

$v = "";
$v_row = "";
$rows = explode($row_delimiter, $val);
$row_count = count($rows);
if ($DEBUG) print "<br>row count: " . $row_count . "<br>";
for ($i = 0; $i < $row_count; $i ++) {
$s = $rows[$i];
if ($s != "") {
if ($DEBUG) print "$i. $s<br>";
$cols = explode($col_delimiter, $s);
$col_count = count($cols);
$v_row = "";
for ($j = 0; $j < $col_count; $j ++) {
$v_row .= "<td>" . $cols[$j] . " </td>";
}
$v .= "<tr>$v_row</tr>";
}
}
$v = "<table border=1>$v</table>";
return $v;
}

?>

</body>
</html>

On server side, the web service function (in C#) looks like this:

[WebMethod]
public string getData(int RangeStart, int RangeEnd) {
string row_delimiter = "\n";
string col_delimiter = "\t";

string s = "";

string connStr = ConfigurationManager.ConnectionStrings["LocalDB"].ConnectionString;
SqlConnection conn = new SqlConnection(connStr);
conn.Open();
string sql = @"with TmpDataTable AS
(SELECT *, ROW_NUMBER() OVER (ORDER BY JobID) as 'RowNum' FROM DataTable)
SELECT * FROM TmpDataTable WHERE RowNum between " + RangeStart + " and " + RangeEnd;
SqlCommand cmd = new SqlCommand(sql, conn);
SqlDataReader sdr = cmd.ExecuteReader();

int fieldCount = sdr.VisibleFieldCount;

// get column names.
s = sdr.GetName(0);
for (int i = 1; i < fieldCount; i++)
{
s += col_delimiter + formatStr(sdr.GetName(i));
}
s += row_delimiter;

if (sdr.HasRows) {
// get column values.
while (sdr.Read()) {
s += sdr[0];
for (int i = 1; i < fieldCount; i++) {
s += col_delimiter + formatStr(sdr[i]);
}
s += row_delimiter;
}
}
conn.Close();

return s.Trim();
}

[1] Pagination in SQL Server
[2] retrieve specific range of rows in a SQL Server table

Tuesday, May 24, 2011

PHP upload size limit

Default PHP upload size limit is 2MB. That's too small.

A place to change this limit is in php.ini. Change "upload_max_filesize" and "post_max_size" bigger should save it [1][2]. Another place to increase this is in .htaccess [2]. If PHP SOAP client gives "Error Fetching http headers" warning, then you need to increase default_socket_timeout in php.ini to fix it [3].

[1] Howto optimize your PHP installation to handle large file uploads
[2] PHP Increase Upload File Size Limit
[3] PHP SOAP client giving "Error Fetching http headers"

Friday, June 18, 2010

Adding PHP snippets through the Drupal user interface

Enable PHP input filter: Go to Administer -> Site building -> Modules, and check PHP Filter under core - optional. Now when create new content, a PHP option will appear under input formats - select this to paste a PHP code snippet. This opens a powerful door to creating dynamic content on a Drupal site.

See Drupal: A beginner's guide to using snippets.

Often a PHP snippet is written inside a drupal module block. What if you want to access Drupal database from an external PHP file? Below is an example. See here for reference.

<?php
// Root path of drupal site, can be obtained using getcwd().
$path = "/web/1/www.hawaii.edu/drupalc/";
chdir($path);

// include needed files
include_once('includes/bootstrap.inc');
include_once('includes/database.inc');
//include_once('includes/database.mysql.inc'); // Disable this for drupal 6.

// Launch drupal start: configuration and database bootstrap
conf_init();
drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);

// Page start. Output page as an Excel file download.
header("Content-type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=\"excel_download.xls\"");
header("Pragma: no-cache");
header("Expires: 0");

// table header
echo "<table border='1'>";
db_query("SELECT * FROM users"); // access to database.
// more processing ...
echo "</table>";

?>

Blog Archive

Followers