Thursday, June 30, 2011

Internationalization for LampCMS using XLIFF

My Question on Support site for LampCMS project

I was researching the topic of Internationalization and was considering different solutions.
I was more inclined to store translation strings right in the Mongo Database.

But then after looking at what other projects are using I came across something interesting. Symfony2 uses XLIFF as preferred method to store translated strings. So I looked at that XLIFF format, and I really like it. At first it looked like it would be complicated for users to create their xml files. But then I found that there are several GUI editors for XLIFF files. One of them is a plugin for Eclipse. I use Eclipse all the time anyway, that's my preferred IDE.

There is also a web-based program that allows you to setup a translation project, define desired languages and let volunteers to contribute translations and at the end it creates valid XLIFF flies.

I think it's really cool. So am thinking now if to use Symfony's existing Translator class or to write my own which will be more lightweight (Symfony is great but as always it can do alot more that I need for this project and most importantly it does not have one feature I really like to see). I will try to get in touch with Symfony developers and see if that can add that extra small feature I want. If it does not work out then I'll write my own Translator class.

Click here to post your reply


Tuesday, June 28, 2011

My answer to "Is there any way to include images in my post?"

This is my answer to a Question on Support site for LampCMS project


There are some posts with images on this site. I am not sure how they did it. There is no support to actually save an image to the server but there is a way to just include an img tag that points to image hosted somewhere else. 

Sunday, June 26, 2011

Added LinkedIn API Integration

My Question on Support site for LampCMS project

I am finished with the LinkedINAPI module.
It's done and pushed to github.

It's now possible to add "Login with LinkedIn" button to the list of existing buttons.
Also when posting Question or Answer there is an option to also post to LinkedIn. The link to your Question or Answer will then be sent to LinkedIn and will be visible by people on your network on LinkedIn.

This is similar to "Sharing" on Twitter.

As with other social sites it's also possible to add LinkedIn to your existing account from the Viewing your profile page while logged in to site.

Also if you check the "Post to LInkedIn" checkbox on the "Ask" or "Answer" form and your account is not connected to LinkedIn, the small window will popup starting the "Connect to LinkedIn" process.

The new section [LINKEDIN] is added to the !config.ini.dist (which you rename to !config.ini)
Instructions on how to get your LinkedInAPI key are in that section.

Click here to post your reply


Sunday, June 19, 2011

My answer to "Removing Copyright Message"

This is my answer to a Question on Support site for LampCMS project


The free version of Lampcms will always have this attribution requirement. The commercial license will be available when the program is ready for stable release version 1.0. Commercial license will not have any such attribution requirements.

At least one more important feature has to be added before version 1.0 can be released - I18N module. It will take probably one more month before everything is ready, probably more like 2-3 months.

Friday, June 17, 2011

Working on LinkedIn integration

My Question on Support site for LampCMS project

Just a heads up. I am working on "Login with LinkedIN" and also a way to connect "LinkedIn" account to your existing Lampcms account.

It will be very similar to Signin with Twitter. You will be able to also post links to your questions/Answers to your LinkedIn as an "Update"

It will be ready in a few days. The "Signin with LInkedIn" is almost done.

Click here to post your reply


Thursday, June 16, 2011

My answer to "Application details don't register"

This is my answer to a Question on Support site for LampCMS project


I found the bug and fixed it. Please try again on this site.

Lampcms Write API

My Question on Support site for LampCMS project

I said before that OAuth2 (or Oauth1) based API will not be free. This is still true.
But I also decided to still write a write API, based on Basic Auth. Basic Auth is a simple authentication where username and password are sent in request headers. This is the old standard. When Twitter API first came out it was based on Basic Auth, then for some time it was still available even after they released OAuth api, then finally they discontinued it.

Basic Auth in not secure but can still be OK if used with https urls.

Some (maybe even many) APIs out there still support Basic Auth, for example github API has such support.

Anyway, I added the support for Basic Auth and wrote 2 write API controllers: addquestion and addanswer

I am still testing the addanswer but addquestion already works.

This all means that you can start writing apps for Lampcms, for example maybe an Android app or web app.
More write API controllers will be added soon, like retag, edit, addcomment, vote, acceptanswer, delete, flag, close

You should ask questions here if you need more details on how to write apps for Lampcms and how to use API in general.

Click here to post your reply


My answer to "MySQL, why not Sqlite3?"

This is my answer to a Question on Support site for LampCMS project


It will be easy to add other types of databases. MySQL is used only for the search feature. Ideally no database will be needed at all when we start using real search engine like Lucene or Sphinx.

If you want to write sqlite plugin then you need to implement 2 interfaces: Search and Indexer
Then edit SearchFactory class to return your own objects that implement these 2.

The class for creating tables if tables don't exists is just a helper class specifically for mysql. You are not required to implement it but then you will be required to pre-create all your SQLite tables in advance. I prefer when there is that helper class that detects that table does not exist and creates it.

Later I should probably refactory this a little so that every search provider is in its own namespace, for example
\Lampcms\Modules\Search\Mysql\Indexer.php and \Lampcms\Modules\Search\Mysql\Search.php

Then it will be easy to define your prefered search provider in !config.ini by just defining the name of search provider.

My answer to "Application details don't register"

This is my answer to a Question on Support site for LampCMS project


It will be easy to add other types of databases. MySQL is used only for the search feature. Ideally no database will be needed at all when we start using real search engine like Lucene or Sphinx.

If you want to write sqlite plugin then you need to implement 2 interfaces: Search and Indexer
Then edit SearchFactory class to return your own objects that implement these 2.

The class for creating tables if tables don't exists is just a helper class specifically for mysql. You are not required to implement it but then you will be required to pre-create all your SQLite tables in advance. I prefer when there is that helper class that detects that table does not exist and creates it.

Later I should probably refactory this a little so that every search provider is in its own namespace, for example
\Lampcms\Modules\Search\Mysql\Indexer.php and \Lampcms\Modules\Search\Mysql\Search.php

Then it will be easy to define your prefered search provider in !config.ini by just defining the name of search provider.

Monday, June 13, 2011

My answer to "Big improvement to comments system - now comments can have replies!"

This is my answer to a Question on Support site for LampCMS project


Everything looked good, I also updated the Email Notifier script to notify original commentor when someone replies to their comment.
I pushed all the updates to github today, you can try it now.

Sunday, June 12, 2011

Big improvement to comments system - now comments can have replies!

My Question on Support site for LampCMS project

This is a pretty big update to the comments system.
Here is the deal: Often a comment is a reply to another comment. It's not easy to keep track of these replies.
On most other site like StackOverflow for example, the best one can do is to include the @user in the beginning
of a comment to indicate that this is a reply.

But this only tells that it's a reply to a comment by @userA. It is not very helpful when userA made more than one comment. How do you know which one of these comments this reply is referring to?

I thought I can do better. Here is goes: Now every comment has a "reply" link. Want to reply to a comment - just use that magic link. No need to manually type @userA - the system will figure out that this is a reply to @userA and more importantly which one of @userA comments

Then when looking at comments all the replies will automatically include @user - and these are underscored with a dashed line.

Now the best part - when you mouse over these @user labels - the comment for which this is a reply will become highlighted - you in case instantly see the message for this this is a reply. You can even click on that @user label in which case BOTH - the original and this reply are highlighted. Clicking it again will toggle the highlighing on/off

And now I'm going to post a simple comment and a reply, and you are welcome to also post replies to comments and just test it out. If this works well, I'll push it to github soon.

I don't think you'll find this feature anywhere else because I thought of it myself. I think it's pretty useful addition.

Click here to post your reply


Friday, June 10, 2011

My answer to "Dmitri: is this agile development? do you have your idea / plan documents?"

This is my answer to a Question on Support site for LampCMS project


One more programming tip I can share, but this is a top secret trick, dont tell anyone.

Sometimes I just create an new blank php file, give it the name of class it's going to be, then just write some comments in the comments block describing what it's going to do, including as much details as possible and then just save it and it will just sit there for awhile.
I may even include a few methods with no body, just comment blocks.

For example

protected function main(){
        $this->getInput()
        ->parseData()
        ->validate()
        ->saveData()
        ->updateUser()
        ->sendEmails();
}


This could be all I need to later take it from there. This is actually the important part, the actual methods can be written later but the main() methods I have to write as I think about the steps involved in this one feature. This is called a top-down design. This may be a true secret to being a good programmer. This is certainly what separates a good programmer from a beginner. Beginners don't do a top-down design, they tend to do the opposite - sometimes refereed to as bottom-up design, which is the wrong way of doing things

A little blank php file, not doing anything but waiting for me to implement it when I get to it.

My answer to "Dmitri: is this agile development? do you have your idea / plan documents?"

This is my answer to a Question on Support site for LampCMS project


Once I wrote the base classes and basically wrote the framework, adding new features is not that hard, actually quite fast. It probably took me about 6 months or so before I even released the first commit to github, but it goes much faster now that all the base classes are solid and "bulllet-proof", I mean bug-free and have test cases.

Also abandoning MySQL and going with Mongo resulted in much faster development, and also alot of unpleasant parts of defining new tables and modifying existing tables and thinking of complex table joins are gone.

Yes, I did have all written down in a simple text file, like a todo list.

Also when I have another idea I now adding it to github issue tracker as a "todo" item, sometimes even including some implementation details. Often when I think of some new feature I also think of how this feature is going to be done, what classes, what database model has to be added. I now if I don't write it down I will forget all the details.

So right now there are a few things on the "todo" list and I don't really want to even adding new ideas before at least some of the "todo" items are completed.

Important items now are "Internationalization" class. I am thinking of the best way to implement it right now.

Also want to add option the "reply" to comment so that it will be clear that a comment is a reply to @user
On StackOverflow you have to explicitely type @user when you replying. I want to simple add a "reply" link and then it will automatically add the @user and maybe even visually indicate that comment B is a reply to comment A

At the same time I am not in the process of writing the API. Most of read API is already done. Next I want to start writing OAuth2 based write API. I've never done this before, so it may not be as fast.

It's perfectly fine for me to switch tasks and just write the comments reply feature for now and then come back to OAuth API thing. I find this task switching is easier on my brain sometimes.


I know there are many more features I want to add, but I also see that the "todo" features list is not infinite. I pretty much know what else has to be done before I can call this a finished program.

These other things are "messaging system" that would include sending system and private user-to-user messages and also a custom SESSION storage class so that a large site that has multiple front-end servers can store session data somewhere on a dedicated server. Also SESSION class will make it easy to show "who's online" and "what they are doing now"

Agile is slightly different. TDD is also different. I mean, I do write test cases but usually not before the classes. In TDD you write test case first, then write code untill it passes your test. I don't do this yet, maybe in the future I will. I don't have any plans to use UnitTests for the documentation. This is a whole other pattern and I don't really like it. I like to just add descriptive comments to all my classes and methods. This is then easy for new developers and also for me to go back and read my own documentation in case I forget what I was thinking at the time I wrote something.

Lampcms REST API update

My Question on Support site for LampCMS project

Hello!
Just want to share some progress of the LampCMS API work:

Any good API must have a way for developers to quickly register their APP and get a unique API KEY.

I have added this feature. This is how it works: most api calls can be made without the API KEY but the daily rate limit will be low without the key. With the valid API KEY the daily limit is much higher. All these limits are configures from !config.ini

So this is how it works: If you want to add API to your Lampcms powered site you need to tell developers how to register their app. All you do is point them to /viewapps/ url
If use does not have any apps yet, then user is redirected to the form to create new app, otherwise user sees the list of all registered apps and can view and edit any app.

You are welcome to try it here http://support.lampcms.com/viewapps/

Once you have the api key you just add &apikey=somekey to all the API requests

For example: http://support.lampcms.com/api/api.php?a=questions&tags=feature&starttime=1306360958&apikey=yourkey

Replace "youkey" with your new valid key or you will get an error, just as you should in case of invalid api key

Several api controllers are ready. Controllers are identiried by the value of the 'a' param which stands for "action"

So in previous example url the "a" is "Questions"

Other controllers are "users" - get info on any user(s) by passing comma-separated values of "uids" param
You can also just call /api/api.php?a=users with no params to get all users and can user pageID and limit params to paginate results. Results can also be sorted using sort= and dir=
for example sort=i_rep&dir=desc to sort by reputation in descending order

Another controllers:


"tags" to get tags data,

"relatedtags" to get related tags - pass tag=sometag to get related data of "sometag"

"usertags" to get tags user's active tags. Pass userID in uid param

"isfollowing" to check if user identified by uid is following another user (or tag or question) identified by "val"
For example: /api/api.php?a=isfollowing&uid=3&t=q&val=125
Will return is_following = true if user with id 3
is following question with id 125

For example /api/api.php?a=isfollowing&uid=3&t=u&val=23
Will return is_following = true IF user with id 3 IS FOLLOWING
user with id 23 (false if not following)

I will push all the latest stuff to github soon so you can examine the API controllers for yourself.





Click here to post your reply


Thursday, June 9, 2011

My answer to "This is a multi-browser test for tag auto-compete"

This is my answer to a Question on Support site for LampCMS project


This is strange. What you describing is a buggy behaviour of the orifinal widget.
You can see it on the original widget demo page

http://rgrove.github.com/node-tokeninput/examples/example-autocomplete.html

(try apple, banana, cherry)

But since I applied a fix the bug is gone, you can select the autosuggested tag with a mouse (or with keyboard) now. I mean it works for me on this site using Chrome on Windows.

I am not sure about other browsers. Maybe it's different on Mac?

Have you reloaded the "Ask" page while holding down the shift key to update browser cache? I mean, is it possible that you were still using the old version of javascript file?

Wednesday, June 8, 2011

Autocomplete for tags added

My Question on Support site for LampCMS project

OK, as per some requests I added the autocomplete for tags
After applying a quick fix to YUI tag widget it works well now.

You can try it here for yourself here, post some question with some existing tags.

If everything works well and there are not more bugs discovered here then I'll push this to github.

Click here to post your reply


Tuesday, June 7, 2011

My answer to "xml markup in editor and (maybe) preview"

This is my answer to a Question on Support site for LampCMS project


There are no limitations. Your users can even use Code highleghter to treat your code snippets as XML, for examle like this: (just highlight code and select "Code style" in the editor


<xsl:template match="/">
        <xsl:element name="plaintext">
                <xsl:apply-templates />
        </xsl:element>
</xsl:template>

My answer to "What attachments beyond images and YouTube are supported?"

This is my answer to a Question on Support site for LampCMS project


Text file? Why don't you just post it as text?
Right now there is no option to attach any files. Even image and youtube options are not really an attachments but simply point to external images or video.

I plan on adding uploader option to the RTE editor but was only going to allow image uploads, have not thought about attachments really.


Monday, June 6, 2011

My answer to "Is there any way to include images in my post?"

This is my answer to a Question on Support site for LampCMS project


There are some posts with images on this site. I am not sure how they did it. There is no support to actually save an image to the server but there is a way to just include an img tag that points to image hosted somewhere else. 

Sunday, June 5, 2011

Lampcms REST API preview

My Question on Support site for LampCMS project

Hello!

Just want to let you know the status of the API work. Here is what I wrote so far:

Wrote base class for the API, wrote a new type of class called Output. This represents the content that is ready to be sent out to the client and it specific to the output format. Concrete classes representing the output format like Json or XML or Jsonp extend this class.

Wrote the Response class - it represents the body and headers ready to be sent to the client (usually browser but any API client really)

Added a new section to !config.ini called [API]

It has these params:
; Maximum results an API can return per page
MAX_RESULTS = 100
; Dalily access limit for not logged in users
DAILY_LIMIT_ANON = 150
; Daily access limit for logged in users
DAILY_LIMIT_APP = 3000
; Daily limit for authenticated user
DAILY_LIMIT_USER = 10000


Using these settings you can completely restring the access to API to only your partner sites by settings DAILY_LIMIT_ANON = 0
It will prevent any access by anonymous clients


API already supports these basic features: makes use of Http response headers and specific HTTP status codes. For example 404 when content not fount or 406 when the value of request parameter is invalid or 500 in case of error in API

Support for custom headers to indicate client's daily rate limit:
X-RateLimit-Limit
X-RateLimit-Remaining
X-RateLimit-Reset
The X-RateLimit-Reset is the timestamp of the next time limit is reset which is usually the beginning of the next day since rate limit is per day.

API currently supports 2 output formats: JSON and JSONP
support for XML can easily be added by just writing the custom OutputXML class. No changes to other classes will be necessary.

API has support for versioning. This is how most good APIs work - when new version of API is released the old ones still work, so your client programs are not broken. You can just pass the v (version id) in request and start using the new version of API. Current version is 1

Currently I wrote 2 API controllers: questions and question

This is how you use it:
Example URL for api is: domain/api/api.php?v=1&a=questions&start_id=5&limit=1&sort=i_votes&dir=desc&alt=json

Here is the explanation of params:

v = version of API, optional, defaults to 1, so for now you can omit it as 1 is the only version

a = "action" Currently completed controllers for "questions" and "question" actions

limit = number of results to return per API call. Think of it as a per-page number on the website.
sort = sort results by this param. For "questions" allowed values are i_votes to sort by votes,
i_lm_ts to sort by "last modified timestamp",
_id to sort by question id,
i_ans to sort by number of answers

dir = direction of sorting. Allowed values are asc for ascending or desc for descending (default)

start_id = show questions with id greated than this (but not including this) id.

max_id = show questions with id less than but not including this id

starttime = unix timestamp in GMT. Show questions posted after this time

tags = space separated tags. Request must be urlencoded so space char should be replaced with %20
show only questions with these tags

match = when tags value is set you can use this param to set to "all" or "any" to match questions with any of the tags or to return questions that must contain all of the tags

uid = userID. Return only questions posted by this user.

type = Return only questions of this type. Allowed values are: "unans" to return only questions with no answers,
"answrd" to return questions with answers by not with "Accepted" answer, "accptd" to return only questions that have an "Accepted" answer.

Extra params: comments=yes to also include comments (by default comments not included)
body=yes to also include full body of question. By default only the "intro", a short text-only version of the first 150 chars of question is included

You can mix these params. For example you can easily get only unanswered questions that have certain tags and posted after certain time.


Question controller.

This controller returns data for one question specified by the qid param.
Example : domain/api/api.php?a=question&qid=5&sort=i_votes&limit=4

Here the limit applies to number of Answers included in response.
For Question controller you can also sort by "accepted", for example: sort=accepted&limit=1
will return only 1 answer that is an "Accepted" answer.


For both questions and question controllers the returned data includes number of total results and the pageID.
Default pageid = 1, you can pass the pageID in request in order to get questions that did not fit in the per-page limit and you know that are more results. In such cases you use the pagination by passing pageID value


You can review the source files for more info. API classes are in /lib/Lampcms/Api/ folder

More API controllers will be released soon: tags, tag, users, user, answers
As well as web controller to register the client and to get clientID.







Click here to post your reply


Saturday, June 4, 2011

My answer to "autocomplete search not including tags"

This is my answer to a Question on Support site for LampCMS project


Yes, definetely I want to add autocomplete for the tags field too. In fact if you dig through my Javascript code you will find that it was actually added but then commented out.
The reason for that is that autocomplete for tags has a bug. I use the YUI tag widget written by one of the YUI team member and when I discovered that bug in autocomplete I contacted him and he basically promised to fix it. So as soon as it's fixed I will add auto complete for tags back.

My answer to "two word tags"

This is my answer to a Question on Support site for LampCMS project


I personally think 2-word tags is not a good idea. I thought about it but I don't remember exact reason why I decided the 2-words tags are bad idea, but at that time there was a good reason for that. One reason is it makes it easier for end-user to enter tags and now worry about forgetting to include comma.

As far as comma separated - yes, currently comma could be used as well as space.
For 2-word tags you would have to use underscore or dashed between words.

The Good thing about tags on this site is that any char is allowed in tags, including UTF-8 char, so even non-English alphabet could be used in tags. This support for Unicode chars in tags is a big deal, this feature is not supported on many other Q&A sites. Also even non-letters like % are allowed in tags, so a 100% would be a valid tag.