{"id":21202644,"url":"https://github.com/cundd/pop","last_synced_at":"2025-03-14T22:28:24.590Z","repository":{"id":3302697,"uuid":"4344454","full_name":"cundd/pop","owner":"cundd","description":"Controlling Cocoa from PHP","archived":false,"fork":false,"pushed_at":"2012-10-01T18:16:54.000Z","size":13292,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-21T15:11:39.939Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cundd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-05-16T07:16:56.000Z","updated_at":"2014-06-16T19:54:30.000Z","dependencies_parsed_at":"2022-09-04T02:11:54.971Z","dependency_job_id":null,"html_url":"https://github.com/cundd/pop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cundd%2Fpop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cundd%2Fpop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cundd%2Fpop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cundd%2Fpop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cundd","download_url":"https://codeload.github.com/cundd/pop/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243655817,"owners_count":20326148,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-20T20:17:29.841Z","updated_at":"2025-03-14T22:28:24.569Z","avatar_url":"https://github.com/cundd.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"POP - Cocoa with vitamin P\n==========================\n\nIntroduction\n------------\n\nAs a PHP developer and Mac user you may be jealous of Ruby and Python programmers, which can use [MacRuby](http://macruby.org/) or [PyObjC](http://pyobjc.sourceforge.net/). pop and it's counterpart qoq now offers you the ability to let your Cocoa application communicate with the PHP application and vice versa.\n\nPOP isn't a real PHP Objective-C Bridge, like it's the aim of the [php-objc project](http://wezfurlong.org/blog/2007/nov/php-objective-c-bridge/), which doesn't seem to work on Mac OS X Lion. POP utilizes the flexibility of Objective-C to perform tasks given by a string. These strings (called command) are sent from PHP using it's standard output. To test these commands POP offers a very simple interactive console.\n\n    {path/to/your/executable} -a\n\npop vs. qoq\n-----------\n\nThe POP system consists of two parts:\n- POP: The Cocoa application that listens for commands sent from PHP\n- QOQ: The PHP framework that provides the runtime of the PHP task\n\nIf the functionality of QOQ doesn't meet your needs, you may replace it with your own PHP runtime.\n\nInstallation\n------------\n\nTo use POP simply add the PopServer.h and PopServer.m files to your project and let your Cocoa delegate extend the PopServer.\n\n    @interface CDAppDelegate : PopServer \u003cNSApplicationDelegate\u003e {\n    }\n\nOn startup the delegate will launch a PHP task with the script path defined in the taskScriptPath property, which defaults to \"path/to/the/app/resources/qoq/run.php\". This path can be easily overwritten in the -taskScriptPath method of your delegate.\n\nCommands / Communicate with POP\n-------------------------------\n\nThe PHP script communicates with the POP server through the PHP tasks standard output. So everything PHP writes to that pipe through echo(), print(), printf(), fwrite(STDOUT, \"some command\"), or similar will be evaluated by POP.\n\nCommands consist of the different parts:\n\n    {signal} {part1} {part2} … {partN} ;\n\nIt starts with a signal, that describes the task to perform, and is followed by the parts/arguments needed to perform the task. The different parts of a command are separated by a whitespace character (\" \") and the command itself is delimited by a newline character or a semicolon (\";\").\n\n\n### Comments\n\n    // This is a comment until a semicolon (\";\") or a newline occurs\n    # This is also a comment until a semicolon (\";\") or a newline occurs\n    \u003e At the moment this is a comment, but this may be removed in future versions\nCurrently these three comment styles are available.\n\n### alloc\n\n    alloc {class} {identifier}\nAllocates a new instance of the given {class} and safes it with the name {identifier}.\n\n### new\n\n    new {class} {identifier} {noInit}\nAllocates a new instance of the given {class}, safes it with the name {identifier} and invokes it's -init method.\nIf {noInit} is set the -init method will not be called (this is the same as the alloc command).\n\n### exec\n\n    exec {identifier} {name:of:the:method:} {argument1}, … {argumentN}\nInvokes the method {name:of:the:method:} of the object with the identifier {identifier} and the given arguments.\n\n    {identifier} {name:of:the:method:} {argument1}, … {argumentN}\nThe short version of the exec command.\n\n### set\n\n    set {identifier} {identifierOfTheNewValue}\nReplaces the variable {identifier} with the value of {identifierOfTheNewValue}.\n\n### get\n\n    get {identifier}\nThe POP server exports the value of {identifier} to the PHP script.\n\n### echo\n\n    echo {identifier}\nLogs the value of {identifier} to the console.\n\n### printf\n\n    printf {identifier} {format}\nLogs the value of {identifier} with the format {format} to the console.\n\n### throw\n\n    throw {name} {message} [{userInfo}]\nThrows an Objective-C exception with the name {name} and reason {message}. \nIf the optional {userInfo} is given, the value of {userInfo} will be used as the exception's userInfo.\n\n### Command examples\n\n#### Close the delegate's window\n\n    echo \"exec window close;\";\n\nYou may omit 'exec'.\n\n    echo \"window close;\";\n\n#### Change the title of the delegate's window\n\n    echo 'window setTitle: @\"NewTitle\";';\n\nWhitespaces are used to separate the parts of a command, therefore you have to replace whitespaces with \"\u0026_\".\n    \n    echo 'window setTitle: @\"Hello\u0026_how\u0026_are\u0026_you?\";';\n\n#### Create a new window\n    echo \"new NSWindow theIdentifier noInit;\";\n    echo \"exec theIdentifier initWithContentRect:styleMask:backing:defer: @NSMakeRect(0,0,200,200) (uint)13 (uint)2 (int)1;\";\n    echo \"exec theIdentifier makeKeyAndOrderFront: nil;\";\n\n### Casting\nThe Objective-C arguments that need to be of a distinct data type, have to be preceded with a syntax that is similar to the one of casts.\n\n- `(int)` signals an integer\n- `(uint)` signals an unsigned integer\n\nCommunicate with QOQ\n--------------------\n\nA one way communication would not be enough to create useful applications. This is what QOQ is created for. It provides a runtime that manages the runloop and the basic communication with the POP server. So your PHP application is able to receive commands from Cocoa, that as an example signal the click of a button.\n\nOn startup POP creates a pipe with the path defined in the qoqPipeName property, which defaults to \"/tmp/qoq_pipe\". The server exports data and commands through this pipe and QOQ is configured to read new commands from this pipe. \n\n### Principe of retrieving values\n- The PHP task sends the command ```get window.title```.\n- POP receives the command, evaluates it and retrieves the title of the delegate's window property\n- POP writes the window's title string to the QOQ pipe\n- The PHP script has to wait until this data has been written to the pipe\n- The PHP script can use the received value\n\n### Retrieving values with QOQ\nTo retrieve values with QOQ you can use the runtime directly\n\n    \\Qoq\\QoqRuntime::getValueForKeyPath('window.title');\n\nor even simpler, create a subclass of the AbstractController\n\n    use \\Qoq\\Controller\\AbstractController;\n    class StandardController extends AbstractController {\n    \tpublic function handle($command){\n            $oldTitle = $this-\u003egetValueForKeyPath('window.title');\n        }\n    }\n\n### Using the Proxy Object\nThe QOQ system provides the \\Qoq\\ProxyObject class that may be used to communicate in an object oriented way. The proxy translates method calls to commands for the POP server, so the commands don't have to be created manually.\n\n    $window = \\Qoq\\QoqRuntime::makeInstance('NSWindow', TRUE);\n    $window-\u003einitWithContentRect_styleMask_backing_defer('@NSMakeRect(0,200,800,600)', uint(13), uint(2), (int)1);\n    $window-\u003emakeKeyAndOrderFront(nil());\n\nThe example also shows the usage of value object functions like `uint()` or `int()`. These functions return value object instances like \\Qoq\\Uint, that will be converted to casted argument strings (see \"Casting\").\n\nExposing your Cocoa code through Plugins\n----------------------------------------\n\nSometimes one would like to define custom commands and signals to enhance the abilities of POP, or to create shortcuts that invoke multiple methods at once. Here Plugins step into the breach. You can register your own classes and methods to be invoked when a specified command is parsed.\n\nWhen the POP server receives a command, which has no built-in route, the server will check if a handler is registered for the given command. If at least one handler is registered POP will post a notification which triggers the invocation of the handler's method.\n\n### Registering a Plugin\nThe PopServer's method +sharedInstance may be used to retrieve the shared server instance.\n\n    [[PopServer sharedInstance] addPlugin:{handler} \n                                selector:@selector({method:}) \n                                forCommand:@\"{command}\"];\n\n### Definition of a Plugin method\nThe methods that should handle the command will receive a notification object that contains the original command's data.\n\n    -(void)theHandlerMethod: (NSNotification *)notification{\n        // notification.userInfo holds the command's data\n    }\n\nThe userInfo dictionary contains the command parts as a NSArray object for the key \"commandParts\" and the signal for key \"signal\".\n\n    NSDictionary * userInfo = [NSDictionary dictionaryWithObjectsAndKeys:\n                            commandParts, @\"commandParts\", \n                            signal, @\"command\",\n                            nil];\n\nIssues and Todos\n----------------\n\n- POP cannot invoke Objective-C class (static) methods.\n- POP cannot export non-scalar Objective-C objects (maybe include a JSON library).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcundd%2Fpop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcundd%2Fpop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcundd%2Fpop/lists"}